1 //===- llvm-stress.cpp - Generate random LL files to stress-test LLVM -----===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 // 9 // This program is a utility that generates random .ll files to stress-test 10 // different components in LLVM. 11 // 12 //===----------------------------------------------------------------------===// 13 14 #include "llvm/ADT/APFloat.h" 15 #include "llvm/ADT/APInt.h" 16 #include "llvm/ADT/ArrayRef.h" 17 #include "llvm/ADT/STLExtras.h" 18 #include "llvm/ADT/StringRef.h" 19 #include "llvm/ADT/Twine.h" 20 #include "llvm/IR/BasicBlock.h" 21 #include "llvm/IR/CallingConv.h" 22 #include "llvm/IR/Constants.h" 23 #include "llvm/IR/DataLayout.h" 24 #include "llvm/IR/DerivedTypes.h" 25 #include "llvm/IR/Function.h" 26 #include "llvm/IR/GlobalValue.h" 27 #include "llvm/IR/InstrTypes.h" 28 #include "llvm/IR/Instruction.h" 29 #include "llvm/IR/Instructions.h" 30 #include "llvm/IR/LLVMContext.h" 31 #include "llvm/IR/Module.h" 32 #include "llvm/IR/Type.h" 33 #include "llvm/IR/Value.h" 34 #include "llvm/IR/Verifier.h" 35 #include "llvm/Support/Casting.h" 36 #include "llvm/Support/CommandLine.h" 37 #include "llvm/Support/ErrorHandling.h" 38 #include "llvm/Support/FileSystem.h" 39 #include "llvm/Support/InitLLVM.h" 40 #include "llvm/Support/ToolOutputFile.h" 41 #include "llvm/Support/WithColor.h" 42 #include "llvm/Support/raw_ostream.h" 43 #include <algorithm> 44 #include <cassert> 45 #include <cstddef> 46 #include <cstdint> 47 #include <memory> 48 #include <string> 49 #include <system_error> 50 #include <vector> 51 52 namespace llvm { 53 54 static cl::OptionCategory StressCategory("Stress Options"); 55 56 static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"), 57 cl::init(0), cl::cat(StressCategory)); 58 59 static cl::opt<unsigned> SizeCL( 60 "size", 61 cl::desc("The estimated size of the generated function (# of instrs)"), 62 cl::init(100), cl::cat(StressCategory)); 63 64 static cl::opt<std::string> OutputFilename("o", 65 cl::desc("Override output filename"), 66 cl::value_desc("filename"), 67 cl::cat(StressCategory)); 68 69 static cl::list<StringRef> AdditionalScalarTypes( 70 "types", cl::CommaSeparated, 71 cl::desc("Additional IR scalar types " 72 "(always includes i1, i8, i16, i32, i64, float and double)")); 73 74 static cl::opt<bool> EnableScalableVectors( 75 "enable-scalable-vectors", 76 cl::desc("Generate IR involving scalable vector types"), 77 cl::init(false), cl::cat(StressCategory)); 78 79 80 namespace { 81 82 /// A utility class to provide a pseudo-random number generator which is 83 /// the same across all platforms. This is somewhat close to the libc 84 /// implementation. Note: This is not a cryptographically secure pseudorandom 85 /// number generator. 86 class Random { 87 public: 88 /// C'tor 89 Random(unsigned _seed):Seed(_seed) {} 90 91 /// Return a random integer, up to a 92 /// maximum of 2**19 - 1. 93 uint32_t Rand() { 94 uint32_t Val = Seed + 0x000b07a1; 95 Seed = (Val * 0x3c7c0ac1); 96 // Only lowest 19 bits are random-ish. 97 return Seed & 0x7ffff; 98 } 99 100 /// Return a random 64 bit integer. 101 uint64_t Rand64() { 102 uint64_t Val = Rand() & 0xffff; 103 Val |= uint64_t(Rand() & 0xffff) << 16; 104 Val |= uint64_t(Rand() & 0xffff) << 32; 105 Val |= uint64_t(Rand() & 0xffff) << 48; 106 return Val; 107 } 108 109 /// Rand operator for STL algorithms. 110 ptrdiff_t operator()(ptrdiff_t y) { 111 return Rand64() % y; 112 } 113 114 /// Make this like a C++11 random device 115 using result_type = uint32_t ; 116 117 static constexpr result_type min() { return 0; } 118 static constexpr result_type max() { return 0x7ffff; } 119 120 uint32_t operator()() { 121 uint32_t Val = Rand(); 122 assert(Val <= max() && "Random value out of range"); 123 return Val; 124 } 125 126 private: 127 unsigned Seed; 128 }; 129 130 /// Generate an empty function with a default argument list. 131 Function *GenEmptyFunction(Module *M) { 132 // Define a few arguments 133 LLVMContext &Context = M->getContext(); 134 Type* ArgsTy[] = { 135 Type::getInt8PtrTy(Context), 136 Type::getInt32PtrTy(Context), 137 Type::getInt64PtrTy(Context), 138 Type::getInt32Ty(Context), 139 Type::getInt64Ty(Context), 140 Type::getInt8Ty(Context) 141 }; 142 143 auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false); 144 // Pick a unique name to describe the input parameters 145 Twine Name = "autogen_SD" + Twine{SeedCL}; 146 auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M); 147 Func->setCallingConv(CallingConv::C); 148 return Func; 149 } 150 151 /// A base class, implementing utilities needed for 152 /// modifying and adding new random instructions. 153 struct Modifier { 154 /// Used to store the randomly generated values. 155 using PieceTable = std::vector<Value *>; 156 157 public: 158 /// C'tor 159 Modifier(BasicBlock *Block, PieceTable *PT, Random *R) 160 : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) { 161 ScalarTypes.assign({Type::getInt1Ty(Context), Type::getInt8Ty(Context), 162 Type::getInt16Ty(Context), Type::getInt32Ty(Context), 163 Type::getInt64Ty(Context), Type::getFloatTy(Context), 164 Type::getDoubleTy(Context)}); 165 166 for (auto &Arg : AdditionalScalarTypes) { 167 Type *Ty = nullptr; 168 if (Arg == "half") 169 Ty = Type::getHalfTy(Context); 170 else if (Arg == "fp128") 171 Ty = Type::getFP128Ty(Context); 172 else if (Arg == "x86_fp80") 173 Ty = Type::getX86_FP80Ty(Context); 174 else if (Arg == "ppc_fp128") 175 Ty = Type::getPPC_FP128Ty(Context); 176 else if (Arg == "x86_mmx") 177 Ty = Type::getX86_MMXTy(Context); 178 else if (Arg.startswith("i")) { 179 unsigned N = 0; 180 Arg.drop_front().getAsInteger(10, N); 181 if (N > 0) 182 Ty = Type::getIntNTy(Context, N); 183 } 184 if (!Ty) { 185 errs() << "Invalid IR scalar type: '" << Arg << "'!\n"; 186 exit(1); 187 } 188 189 ScalarTypes.push_back(Ty); 190 } 191 } 192 193 /// virtual D'tor to silence warnings. 194 virtual ~Modifier() = default; 195 196 /// Add a new instruction. 197 virtual void Act() = 0; 198 199 /// Add N new instructions, 200 virtual void ActN(unsigned n) { 201 for (unsigned i=0; i<n; ++i) 202 Act(); 203 } 204 205 protected: 206 /// Return a random integer. 207 uint32_t getRandom() { 208 return Ran->Rand(); 209 } 210 211 /// Return a random value from the list of known values. 212 Value *getRandomVal() { 213 assert(PT->size()); 214 return PT->at(getRandom() % PT->size()); 215 } 216 217 Constant *getRandomConstant(Type *Tp) { 218 if (Tp->isIntegerTy()) { 219 if (getRandom() & 1) 220 return ConstantInt::getAllOnesValue(Tp); 221 return ConstantInt::getNullValue(Tp); 222 } else if (Tp->isFloatingPointTy()) { 223 if (getRandom() & 1) 224 return ConstantFP::getAllOnesValue(Tp); 225 return ConstantFP::getNullValue(Tp); 226 } 227 return UndefValue::get(Tp); 228 } 229 230 /// Return a random value with a known type. 231 Value *getRandomValue(Type *Tp) { 232 unsigned index = getRandom(); 233 for (unsigned i=0; i<PT->size(); ++i) { 234 Value *V = PT->at((index + i) % PT->size()); 235 if (V->getType() == Tp) 236 return V; 237 } 238 239 // If the requested type was not found, generate a constant value. 240 if (Tp->isIntegerTy()) { 241 if (getRandom() & 1) 242 return ConstantInt::getAllOnesValue(Tp); 243 return ConstantInt::getNullValue(Tp); 244 } else if (Tp->isFloatingPointTy()) { 245 if (getRandom() & 1) 246 return ConstantFP::getAllOnesValue(Tp); 247 return ConstantFP::getNullValue(Tp); 248 } else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) { 249 std::vector<Constant*> TempValues; 250 TempValues.reserve(VTp->getNumElements()); 251 for (unsigned i = 0; i < VTp->getNumElements(); ++i) 252 TempValues.push_back(getRandomConstant(VTp->getScalarType())); 253 254 ArrayRef<Constant*> VectorValue(TempValues); 255 return ConstantVector::get(VectorValue); 256 } 257 258 return UndefValue::get(Tp); 259 } 260 261 /// Return a random value of any pointer type. 262 Value *getRandomPointerValue() { 263 unsigned index = getRandom(); 264 for (unsigned i=0; i<PT->size(); ++i) { 265 Value *V = PT->at((index + i) % PT->size()); 266 if (V->getType()->isPointerTy()) 267 return V; 268 } 269 return UndefValue::get(pickPointerType()); 270 } 271 272 /// Return a random value of any vector type. 273 Value *getRandomVectorValue() { 274 unsigned index = getRandom(); 275 for (unsigned i=0; i<PT->size(); ++i) { 276 Value *V = PT->at((index + i) % PT->size()); 277 if (V->getType()->isVectorTy()) 278 return V; 279 } 280 return UndefValue::get(pickVectorType()); 281 } 282 283 /// Pick a random type. 284 Type *pickType() { 285 return (getRandom() & 1) ? pickVectorType() : pickScalarType(); 286 } 287 288 /// Pick a random pointer type. 289 Type *pickPointerType() { 290 Type *Ty = pickType(); 291 return PointerType::get(Ty, 0); 292 } 293 294 /// Pick a random vector type. 295 Type *pickVectorType(VectorType *VTy = nullptr) { 296 297 // Vectors of x86mmx are illegal; keep trying till we get something else. 298 Type *Ty; 299 do { 300 Ty = pickScalarType(); 301 } while (Ty->isX86_MMXTy()); 302 303 if (VTy) 304 return VectorType::get(Ty, VTy->getElementCount()); 305 306 // Select either fixed length or scalable vectors with 50% probability 307 // (only if scalable vectors are enabled) 308 bool Scalable = EnableScalableVectors && getRandom() & 1; 309 310 // Pick a random vector width in the range 2**0 to 2**4. 311 // by adding two randoms we are generating a normal-like distribution 312 // around 2**3. 313 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3)); 314 return VectorType::get(Ty, width, Scalable); 315 } 316 317 /// Pick a random scalar type. 318 Type *pickScalarType() { 319 return ScalarTypes[getRandom() % ScalarTypes.size()]; 320 } 321 322 /// Basic block to populate 323 BasicBlock *BB; 324 325 /// Value table 326 PieceTable *PT; 327 328 /// Random number generator 329 Random *Ran; 330 331 /// Context 332 LLVMContext &Context; 333 334 std::vector<Type *> ScalarTypes; 335 }; 336 337 struct LoadModifier: public Modifier { 338 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R) 339 : Modifier(BB, PT, R) {} 340 341 void Act() override { 342 // Try to use predefined pointers. If non-exist, use undef pointer value; 343 Value *Ptr = getRandomPointerValue(); 344 Type *Ty = Ptr->getType()->isOpaquePointerTy() 345 ? pickType() 346 : Ptr->getType()->getNonOpaquePointerElementType(); 347 Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator()); 348 PT->push_back(V); 349 } 350 }; 351 352 struct StoreModifier: public Modifier { 353 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R) 354 : Modifier(BB, PT, R) {} 355 356 void Act() override { 357 // Try to use predefined pointers. If non-exist, use undef pointer value; 358 Value *Ptr = getRandomPointerValue(); 359 Type *ValTy = Ptr->getType()->isOpaquePointerTy() 360 ? pickType() 361 : Ptr->getType()->getNonOpaquePointerElementType(); 362 363 // Do not store vectors of i1s because they are unsupported 364 // by the codegen. 365 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1) 366 return; 367 368 Value *Val = getRandomValue(ValTy); 369 new StoreInst(Val, Ptr, BB->getTerminator()); 370 } 371 }; 372 373 struct BinModifier: public Modifier { 374 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R) 375 : Modifier(BB, PT, R) {} 376 377 void Act() override { 378 Value *Val0 = getRandomVal(); 379 Value *Val1 = getRandomValue(Val0->getType()); 380 381 // Don't handle pointer types. 382 if (Val0->getType()->isPointerTy() || 383 Val1->getType()->isPointerTy()) 384 return; 385 386 // Don't handle i1 types. 387 if (Val0->getType()->getScalarSizeInBits() == 1) 388 return; 389 390 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy(); 391 Instruction* Term = BB->getTerminator(); 392 unsigned R = getRandom() % (isFloat ? 7 : 13); 393 Instruction::BinaryOps Op; 394 395 switch (R) { 396 default: llvm_unreachable("Invalid BinOp"); 397 case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; } 398 case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; } 399 case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; } 400 case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; } 401 case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; } 402 case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; } 403 case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; } 404 case 7: {Op = Instruction::Shl; break; } 405 case 8: {Op = Instruction::LShr; break; } 406 case 9: {Op = Instruction::AShr; break; } 407 case 10:{Op = Instruction::And; break; } 408 case 11:{Op = Instruction::Or; break; } 409 case 12:{Op = Instruction::Xor; break; } 410 } 411 412 PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term)); 413 } 414 }; 415 416 /// Generate constant values. 417 struct ConstModifier: public Modifier { 418 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R) 419 : Modifier(BB, PT, R) {} 420 421 void Act() override { 422 Type *Ty = pickType(); 423 424 if (Ty->isVectorTy()) { 425 switch (getRandom() % 2) { 426 case 0: if (Ty->isIntOrIntVectorTy()) 427 return PT->push_back(ConstantVector::getAllOnesValue(Ty)); 428 break; 429 case 1: if (Ty->isIntOrIntVectorTy()) 430 return PT->push_back(ConstantVector::getNullValue(Ty)); 431 } 432 } 433 434 if (Ty->isFloatingPointTy()) { 435 // Generate 128 random bits, the size of the (currently) 436 // largest floating-point types. 437 uint64_t RandomBits[2]; 438 for (unsigned i = 0; i < 2; ++i) 439 RandomBits[i] = Ran->Rand64(); 440 441 APInt RandomInt(Ty->getPrimitiveSizeInBits(), ArrayRef(RandomBits)); 442 APFloat RandomFloat(Ty->getFltSemantics(), RandomInt); 443 444 if (getRandom() & 1) 445 return PT->push_back(ConstantFP::getNullValue(Ty)); 446 return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat)); 447 } 448 449 if (Ty->isIntegerTy()) { 450 switch (getRandom() % 7) { 451 case 0: 452 return PT->push_back(ConstantInt::get( 453 Ty, APInt::getAllOnes(Ty->getPrimitiveSizeInBits()))); 454 case 1: 455 return PT->push_back( 456 ConstantInt::get(Ty, APInt::getZero(Ty->getPrimitiveSizeInBits()))); 457 case 2: 458 case 3: 459 case 4: 460 case 5: 461 case 6: 462 PT->push_back(ConstantInt::get(Ty, getRandom())); 463 } 464 } 465 } 466 }; 467 468 struct AllocaModifier: public Modifier { 469 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R) 470 : Modifier(BB, PT, R) {} 471 472 void Act() override { 473 Type *Tp = pickType(); 474 const DataLayout &DL = BB->getModule()->getDataLayout(); 475 PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(), 476 "A", BB->getFirstNonPHI())); 477 } 478 }; 479 480 struct ExtractElementModifier: public Modifier { 481 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 482 : Modifier(BB, PT, R) {} 483 484 void Act() override { 485 Value *Val0 = getRandomVectorValue(); 486 Value *V = ExtractElementInst::Create( 487 Val0, 488 getRandomValue(Type::getInt32Ty(BB->getContext())), 489 "E", BB->getTerminator()); 490 return PT->push_back(V); 491 } 492 }; 493 494 struct ShuffModifier: public Modifier { 495 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R) 496 : Modifier(BB, PT, R) {} 497 498 void Act() override { 499 Value *Val0 = getRandomVectorValue(); 500 Value *Val1 = getRandomValue(Val0->getType()); 501 502 // Can't express arbitrary shufflevectors for scalable vectors 503 if (isa<ScalableVectorType>(Val0->getType())) 504 return; 505 506 unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements(); 507 std::vector<Constant*> Idxs; 508 509 Type *I32 = Type::getInt32Ty(BB->getContext()); 510 for (unsigned i=0; i<Width; ++i) { 511 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2)); 512 // Pick some undef values. 513 if (!(getRandom() % 5)) 514 CI = UndefValue::get(I32); 515 Idxs.push_back(CI); 516 } 517 518 Constant *Mask = ConstantVector::get(Idxs); 519 520 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", 521 BB->getTerminator()); 522 PT->push_back(V); 523 } 524 }; 525 526 struct InsertElementModifier: public Modifier { 527 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 528 : Modifier(BB, PT, R) {} 529 530 void Act() override { 531 Value *Val0 = getRandomVectorValue(); 532 Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); 533 534 Value *V = InsertElementInst::Create( 535 Val0, Val1, 536 getRandomValue(Type::getInt32Ty(BB->getContext())), 537 "I", BB->getTerminator()); 538 return PT->push_back(V); 539 } 540 }; 541 542 struct CastModifier: public Modifier { 543 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R) 544 : Modifier(BB, PT, R) {} 545 546 void Act() override { 547 Value *V = getRandomVal(); 548 Type *VTy = V->getType(); 549 Type *DestTy = pickScalarType(); 550 551 // Handle vector casts vectors. 552 if (VTy->isVectorTy()) 553 DestTy = pickVectorType(cast<VectorType>(VTy)); 554 555 // no need to cast. 556 if (VTy == DestTy) return; 557 558 // Pointers: 559 if (VTy->isPointerTy()) { 560 if (!DestTy->isPointerTy()) 561 DestTy = PointerType::get(DestTy, 0); 562 return PT->push_back( 563 new BitCastInst(V, DestTy, "PC", BB->getTerminator())); 564 } 565 566 unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits(); 567 unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits(); 568 569 // Generate lots of bitcasts. 570 if ((getRandom() & 1) && VSize == DestSize) { 571 return PT->push_back( 572 new BitCastInst(V, DestTy, "BC", BB->getTerminator())); 573 } 574 575 // Both types are integers: 576 if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) { 577 if (VSize > DestSize) { 578 return PT->push_back( 579 new TruncInst(V, DestTy, "Tr", BB->getTerminator())); 580 } else { 581 assert(VSize < DestSize && "Different int types with the same size?"); 582 if (getRandom() & 1) 583 return PT->push_back( 584 new ZExtInst(V, DestTy, "ZE", BB->getTerminator())); 585 return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator())); 586 } 587 } 588 589 // Fp to int. 590 if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) { 591 if (getRandom() & 1) 592 return PT->push_back( 593 new FPToSIInst(V, DestTy, "FC", BB->getTerminator())); 594 return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator())); 595 } 596 597 // Int to fp. 598 if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) { 599 if (getRandom() & 1) 600 return PT->push_back( 601 new SIToFPInst(V, DestTy, "FC", BB->getTerminator())); 602 return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator())); 603 } 604 605 // Both floats. 606 if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) { 607 if (VSize > DestSize) { 608 return PT->push_back( 609 new FPTruncInst(V, DestTy, "Tr", BB->getTerminator())); 610 } else if (VSize < DestSize) { 611 return PT->push_back( 612 new FPExtInst(V, DestTy, "ZE", BB->getTerminator())); 613 } 614 // If VSize == DestSize, then the two types must be fp128 and ppc_fp128, 615 // for which there is no defined conversion. So do nothing. 616 } 617 } 618 }; 619 620 struct SelectModifier: public Modifier { 621 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R) 622 : Modifier(BB, PT, R) {} 623 624 void Act() override { 625 // Try a bunch of different select configuration until a valid one is found. 626 Value *Val0 = getRandomVal(); 627 Value *Val1 = getRandomValue(Val0->getType()); 628 629 Type *CondTy = Type::getInt1Ty(Context); 630 631 // If the value type is a vector, and we allow vector select, then in 50% 632 // of the cases generate a vector select. 633 if (auto *VTy = dyn_cast<VectorType>(Val0->getType())) 634 if (getRandom() & 1) 635 CondTy = VectorType::get(CondTy, VTy->getElementCount()); 636 637 Value *Cond = getRandomValue(CondTy); 638 Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator()); 639 return PT->push_back(V); 640 } 641 }; 642 643 struct CmpModifier: public Modifier { 644 CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R) 645 : Modifier(BB, PT, R) {} 646 647 void Act() override { 648 Value *Val0 = getRandomVal(); 649 Value *Val1 = getRandomValue(Val0->getType()); 650 651 if (Val0->getType()->isPointerTy()) return; 652 bool fp = Val0->getType()->getScalarType()->isFloatingPointTy(); 653 654 int op; 655 if (fp) { 656 op = getRandom() % 657 (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) + 658 CmpInst::FIRST_FCMP_PREDICATE; 659 } else { 660 op = getRandom() % 661 (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) + 662 CmpInst::FIRST_ICMP_PREDICATE; 663 } 664 665 Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp, 666 (CmpInst::Predicate)op, Val0, Val1, "Cmp", 667 BB->getTerminator()); 668 return PT->push_back(V); 669 } 670 }; 671 672 } // end anonymous namespace 673 674 static void FillFunction(Function *F, Random &R) { 675 // Create a legal entry block. 676 BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F); 677 ReturnInst::Create(F->getContext(), BB); 678 679 // Create the value table. 680 Modifier::PieceTable PT; 681 682 // Consider arguments as legal values. 683 for (auto &arg : F->args()) 684 PT.push_back(&arg); 685 686 // List of modifiers which add new random instructions. 687 std::vector<std::unique_ptr<Modifier>> Modifiers; 688 Modifiers.emplace_back(new LoadModifier(BB, &PT, &R)); 689 Modifiers.emplace_back(new StoreModifier(BB, &PT, &R)); 690 auto SM = Modifiers.back().get(); 691 Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R)); 692 Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R)); 693 Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R)); 694 Modifiers.emplace_back(new BinModifier(BB, &PT, &R)); 695 Modifiers.emplace_back(new CastModifier(BB, &PT, &R)); 696 Modifiers.emplace_back(new SelectModifier(BB, &PT, &R)); 697 Modifiers.emplace_back(new CmpModifier(BB, &PT, &R)); 698 699 // Generate the random instructions 700 AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas 701 ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants 702 703 for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i) 704 for (auto &Mod : Modifiers) 705 Mod->Act(); 706 707 SM->ActN(5); // Throw in a few stores. 708 } 709 710 static void IntroduceControlFlow(Function *F, Random &R) { 711 std::vector<Instruction*> BoolInst; 712 for (auto &Instr : F->front()) { 713 if (Instr.getType() == IntegerType::getInt1Ty(F->getContext())) 714 BoolInst.push_back(&Instr); 715 } 716 717 llvm::shuffle(BoolInst.begin(), BoolInst.end(), R); 718 719 for (auto *Instr : BoolInst) { 720 BasicBlock *Curr = Instr->getParent(); 721 BasicBlock::iterator Loc = Instr->getIterator(); 722 BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); 723 Instr->moveBefore(Curr->getTerminator()); 724 if (Curr != &F->getEntryBlock()) { 725 BranchInst::Create(Curr, Next, Instr, Curr->getTerminator()); 726 Curr->getTerminator()->eraseFromParent(); 727 } 728 } 729 } 730 731 } // end namespace llvm 732 733 int main(int argc, char **argv) { 734 using namespace llvm; 735 736 InitLLVM X(argc, argv); 737 cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()}); 738 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); 739 740 LLVMContext Context; 741 auto M = std::make_unique<Module>("/tmp/autogen.bc", Context); 742 Function *F = GenEmptyFunction(M.get()); 743 744 // Pick an initial seed value 745 Random R(SeedCL); 746 // Generate lots of random instructions inside a single basic block. 747 FillFunction(F, R); 748 // Break the basic block into many loops. 749 IntroduceControlFlow(F, R); 750 751 // Figure out what stream we are supposed to write to... 752 std::unique_ptr<ToolOutputFile> Out; 753 // Default to standard output. 754 if (OutputFilename.empty()) 755 OutputFilename = "-"; 756 757 std::error_code EC; 758 Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); 759 if (EC) { 760 errs() << EC.message() << '\n'; 761 return 1; 762 } 763 764 // Check that the generated module is accepted by the verifier. 765 if (verifyModule(*M.get(), &Out->os())) 766 report_fatal_error("Broken module found, compilation aborted!"); 767 768 // Output textual IR. 769 M->print(Out->os(), nullptr); 770 771 Out->keep(); 772 773 return 0; 774 } 775