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