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/ManagedStatic.h" 42 #include "llvm/Support/PrettyStackTrace.h" 43 #include "llvm/Support/ToolOutputFile.h" 44 #include "llvm/Support/raw_ostream.h" 45 #include <algorithm> 46 #include <cassert> 47 #include <cstddef> 48 #include <cstdint> 49 #include <memory> 50 #include <string> 51 #include <system_error> 52 #include <vector> 53 54 namespace llvm { 55 56 static cl::opt<unsigned> SeedCL("seed", 57 cl::desc("Seed used for randomness"), cl::init(0)); 58 59 static cl::opt<unsigned> SizeCL("size", 60 cl::desc("The estimated size of the generated function (# of instrs)"), 61 cl::init(100)); 62 63 static cl::opt<std::string> 64 OutputFilename("o", cl::desc("Override output filename"), 65 cl::value_desc("filename")); 66 67 static LLVMContext Context; 68 69 namespace cl { 70 71 template <> class parser<Type*> final : public basic_parser<Type*> { 72 public: 73 parser(Option &O) : basic_parser(O) {} 74 75 // Parse options as IR types. Return true on error. 76 bool parse(Option &O, StringRef, StringRef Arg, Type *&Value) { 77 if (Arg == "half") Value = Type::getHalfTy(Context); 78 else if (Arg == "fp128") Value = Type::getFP128Ty(Context); 79 else if (Arg == "x86_fp80") Value = Type::getX86_FP80Ty(Context); 80 else if (Arg == "ppc_fp128") Value = Type::getPPC_FP128Ty(Context); 81 else if (Arg == "x86_mmx") Value = Type::getX86_MMXTy(Context); 82 else if (Arg.startswith("i")) { 83 unsigned N = 0; 84 Arg.drop_front().getAsInteger(10, N); 85 if (N > 0) 86 Value = Type::getIntNTy(Context, N); 87 } 88 89 if (!Value) 90 return O.error("Invalid IR scalar type: '" + Arg + "'!"); 91 return false; 92 } 93 94 StringRef getValueName() const override { return "IR scalar type"; } 95 }; 96 97 } // end namespace cl 98 99 static cl::list<Type*> AdditionalScalarTypes("types", cl::CommaSeparated, 100 cl::desc("Additional IR scalar types " 101 "(always includes i1, i8, i16, i32, i64, float and double)")); 102 103 namespace { 104 105 /// A utility class to provide a pseudo-random number generator which is 106 /// the same across all platforms. This is somewhat close to the libc 107 /// implementation. Note: This is not a cryptographically secure pseudorandom 108 /// number generator. 109 class Random { 110 public: 111 /// C'tor 112 Random(unsigned _seed):Seed(_seed) {} 113 114 /// Return a random integer, up to a 115 /// maximum of 2**19 - 1. 116 uint32_t Rand() { 117 uint32_t Val = Seed + 0x000b07a1; 118 Seed = (Val * 0x3c7c0ac1); 119 // Only lowest 19 bits are random-ish. 120 return Seed & 0x7ffff; 121 } 122 123 /// Return a random 64 bit integer. 124 uint64_t Rand64() { 125 uint64_t Val = Rand() & 0xffff; 126 Val |= uint64_t(Rand() & 0xffff) << 16; 127 Val |= uint64_t(Rand() & 0xffff) << 32; 128 Val |= uint64_t(Rand() & 0xffff) << 48; 129 return Val; 130 } 131 132 /// Rand operator for STL algorithms. 133 ptrdiff_t operator()(ptrdiff_t y) { 134 return Rand64() % y; 135 } 136 137 /// Make this like a C++11 random device 138 using result_type = uint32_t ; 139 140 static constexpr result_type min() { return 0; } 141 static constexpr result_type max() { return 0x7ffff; } 142 143 uint32_t operator()() { 144 uint32_t Val = Rand(); 145 assert(Val <= max() && "Random value out of range"); 146 return Val; 147 } 148 149 private: 150 unsigned Seed; 151 }; 152 153 /// Generate an empty function with a default argument list. 154 Function *GenEmptyFunction(Module *M) { 155 // Define a few arguments 156 LLVMContext &Context = M->getContext(); 157 Type* ArgsTy[] = { 158 Type::getInt8PtrTy(Context), 159 Type::getInt32PtrTy(Context), 160 Type::getInt64PtrTy(Context), 161 Type::getInt32Ty(Context), 162 Type::getInt64Ty(Context), 163 Type::getInt8Ty(Context) 164 }; 165 166 auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false); 167 // Pick a unique name to describe the input parameters 168 Twine Name = "autogen_SD" + Twine{SeedCL}; 169 auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M); 170 Func->setCallingConv(CallingConv::C); 171 return Func; 172 } 173 174 /// A base class, implementing utilities needed for 175 /// modifying and adding new random instructions. 176 struct Modifier { 177 /// Used to store the randomly generated values. 178 using PieceTable = std::vector<Value *>; 179 180 public: 181 /// C'tor 182 Modifier(BasicBlock *Block, PieceTable *PT, Random *R) 183 : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {} 184 185 /// virtual D'tor to silence warnings. 186 virtual ~Modifier() = default; 187 188 /// Add a new instruction. 189 virtual void Act() = 0; 190 191 /// Add N new instructions, 192 virtual void ActN(unsigned n) { 193 for (unsigned i=0; i<n; ++i) 194 Act(); 195 } 196 197 protected: 198 /// Return a random integer. 199 uint32_t getRandom() { 200 return Ran->Rand(); 201 } 202 203 /// Return a random value from the list of known values. 204 Value *getRandomVal() { 205 assert(PT->size()); 206 return PT->at(getRandom() % PT->size()); 207 } 208 209 Constant *getRandomConstant(Type *Tp) { 210 if (Tp->isIntegerTy()) { 211 if (getRandom() & 1) 212 return ConstantInt::getAllOnesValue(Tp); 213 return ConstantInt::getNullValue(Tp); 214 } else if (Tp->isFloatingPointTy()) { 215 if (getRandom() & 1) 216 return ConstantFP::getAllOnesValue(Tp); 217 return ConstantFP::getNullValue(Tp); 218 } 219 return UndefValue::get(Tp); 220 } 221 222 /// Return a random value with a known type. 223 Value *getRandomValue(Type *Tp) { 224 unsigned index = getRandom(); 225 for (unsigned i=0; i<PT->size(); ++i) { 226 Value *V = PT->at((index + i) % PT->size()); 227 if (V->getType() == Tp) 228 return V; 229 } 230 231 // If the requested type was not found, generate a constant value. 232 if (Tp->isIntegerTy()) { 233 if (getRandom() & 1) 234 return ConstantInt::getAllOnesValue(Tp); 235 return ConstantInt::getNullValue(Tp); 236 } else if (Tp->isFloatingPointTy()) { 237 if (getRandom() & 1) 238 return ConstantFP::getAllOnesValue(Tp); 239 return ConstantFP::getNullValue(Tp); 240 } else if (Tp->isVectorTy()) { 241 VectorType *VTp = cast<VectorType>(Tp); 242 243 std::vector<Constant*> TempValues; 244 TempValues.reserve(VTp->getNumElements()); 245 for (unsigned i = 0; i < VTp->getNumElements(); ++i) 246 TempValues.push_back(getRandomConstant(VTp->getScalarType())); 247 248 ArrayRef<Constant*> VectorValue(TempValues); 249 return ConstantVector::get(VectorValue); 250 } 251 252 return UndefValue::get(Tp); 253 } 254 255 /// Return a random value of any pointer type. 256 Value *getRandomPointerValue() { 257 unsigned index = getRandom(); 258 for (unsigned i=0; i<PT->size(); ++i) { 259 Value *V = PT->at((index + i) % PT->size()); 260 if (V->getType()->isPointerTy()) 261 return V; 262 } 263 return UndefValue::get(pickPointerType()); 264 } 265 266 /// Return a random value of any vector type. 267 Value *getRandomVectorValue() { 268 unsigned index = getRandom(); 269 for (unsigned i=0; i<PT->size(); ++i) { 270 Value *V = PT->at((index + i) % PT->size()); 271 if (V->getType()->isVectorTy()) 272 return V; 273 } 274 return UndefValue::get(pickVectorType()); 275 } 276 277 /// Pick a random type. 278 Type *pickType() { 279 return (getRandom() & 1) ? pickVectorType() : pickScalarType(); 280 } 281 282 /// Pick a random pointer type. 283 Type *pickPointerType() { 284 Type *Ty = pickType(); 285 return PointerType::get(Ty, 0); 286 } 287 288 /// Pick a random vector type. 289 Type *pickVectorType(unsigned len = (unsigned)-1) { 290 // Pick a random vector width in the range 2**0 to 2**4. 291 // by adding two randoms we are generating a normal-like distribution 292 // around 2**3. 293 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3)); 294 Type *Ty; 295 296 // Vectors of x86mmx are illegal; keep trying till we get something else. 297 do { 298 Ty = pickScalarType(); 299 } while (Ty->isX86_MMXTy()); 300 301 if (len != (unsigned)-1) 302 width = len; 303 return FixedVectorType::get(Ty, width); 304 } 305 306 /// Pick a random scalar type. 307 Type *pickScalarType() { 308 static std::vector<Type*> ScalarTypes; 309 if (ScalarTypes.empty()) { 310 ScalarTypes.assign({ 311 Type::getInt1Ty(Context), 312 Type::getInt8Ty(Context), 313 Type::getInt16Ty(Context), 314 Type::getInt32Ty(Context), 315 Type::getInt64Ty(Context), 316 Type::getFloatTy(Context), 317 Type::getDoubleTy(Context) 318 }); 319 ScalarTypes.insert(ScalarTypes.end(), 320 AdditionalScalarTypes.begin(), AdditionalScalarTypes.end()); 321 } 322 323 return ScalarTypes[getRandom() % ScalarTypes.size()]; 324 } 325 326 /// Basic block to populate 327 BasicBlock *BB; 328 329 /// Value table 330 PieceTable *PT; 331 332 /// Random number generator 333 Random *Ran; 334 335 /// Context 336 LLVMContext &Context; 337 }; 338 339 struct LoadModifier: public Modifier { 340 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R) 341 : Modifier(BB, PT, R) {} 342 343 void Act() override { 344 // Try to use predefined pointers. If non-exist, use undef pointer value; 345 Value *Ptr = getRandomPointerValue(); 346 PointerType *Tp = cast<PointerType>(Ptr->getType()); 347 Value *V = new LoadInst(Tp->getElementType(), Ptr, "L", 348 BB->getTerminator()); 349 PT->push_back(V); 350 } 351 }; 352 353 struct StoreModifier: public Modifier { 354 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R) 355 : Modifier(BB, PT, R) {} 356 357 void Act() override { 358 // Try to use predefined pointers. If non-exist, use undef pointer value; 359 Value *Ptr = getRandomPointerValue(); 360 PointerType *Tp = cast<PointerType>(Ptr->getType()); 361 Value *Val = getRandomValue(Tp->getElementType()); 362 Type *ValTy = Val->getType(); 363 364 // Do not store vectors of i1s because they are unsupported 365 // by the codegen. 366 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1) 367 return; 368 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(), makeArrayRef(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::getAllOnesValue(Ty->getPrimitiveSizeInBits()))); 454 case 1: 455 return PT->push_back(ConstantInt::get( 456 Ty, APInt::getNullValue(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(Val0, 487 ConstantInt::get(Type::getInt32Ty(BB->getContext()), 488 getRandom() % cast<VectorType>(Val0->getType())->getNumElements()), 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 unsigned Width = cast<VectorType>(Val0->getType())->getNumElements(); 503 std::vector<Constant*> Idxs; 504 505 Type *I32 = Type::getInt32Ty(BB->getContext()); 506 for (unsigned i=0; i<Width; ++i) { 507 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2)); 508 // Pick some undef values. 509 if (!(getRandom() % 5)) 510 CI = UndefValue::get(I32); 511 Idxs.push_back(CI); 512 } 513 514 Constant *Mask = ConstantVector::get(Idxs); 515 516 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", 517 BB->getTerminator()); 518 PT->push_back(V); 519 } 520 }; 521 522 struct InsertElementModifier: public Modifier { 523 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 524 : Modifier(BB, PT, R) {} 525 526 void Act() override { 527 Value *Val0 = getRandomVectorValue(); 528 Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); 529 530 Value *V = InsertElementInst::Create(Val0, Val1, 531 ConstantInt::get(Type::getInt32Ty(BB->getContext()), 532 getRandom() % cast<VectorType>(Val0->getType())->getNumElements()), 533 "I", BB->getTerminator()); 534 return PT->push_back(V); 535 } 536 }; 537 538 struct CastModifier: public Modifier { 539 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R) 540 : Modifier(BB, PT, R) {} 541 542 void Act() override { 543 Value *V = getRandomVal(); 544 Type *VTy = V->getType(); 545 Type *DestTy = pickScalarType(); 546 547 // Handle vector casts vectors. 548 if (VTy->isVectorTy()) { 549 VectorType *VecTy = cast<VectorType>(VTy); 550 DestTy = pickVectorType(VecTy->getNumElements()); 551 } 552 553 // no need to cast. 554 if (VTy == DestTy) return; 555 556 // Pointers: 557 if (VTy->isPointerTy()) { 558 if (!DestTy->isPointerTy()) 559 DestTy = PointerType::get(DestTy, 0); 560 return PT->push_back( 561 new BitCastInst(V, DestTy, "PC", BB->getTerminator())); 562 } 563 564 unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits(); 565 unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits(); 566 567 // Generate lots of bitcasts. 568 if ((getRandom() & 1) && VSize == DestSize) { 569 return PT->push_back( 570 new BitCastInst(V, DestTy, "BC", BB->getTerminator())); 571 } 572 573 // Both types are integers: 574 if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) { 575 if (VSize > DestSize) { 576 return PT->push_back( 577 new TruncInst(V, DestTy, "Tr", BB->getTerminator())); 578 } else { 579 assert(VSize < DestSize && "Different int types with the same size?"); 580 if (getRandom() & 1) 581 return PT->push_back( 582 new ZExtInst(V, DestTy, "ZE", BB->getTerminator())); 583 return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator())); 584 } 585 } 586 587 // Fp to int. 588 if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) { 589 if (getRandom() & 1) 590 return PT->push_back( 591 new FPToSIInst(V, DestTy, "FC", BB->getTerminator())); 592 return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator())); 593 } 594 595 // Int to fp. 596 if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) { 597 if (getRandom() & 1) 598 return PT->push_back( 599 new SIToFPInst(V, DestTy, "FC", BB->getTerminator())); 600 return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator())); 601 } 602 603 // Both floats. 604 if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) { 605 if (VSize > DestSize) { 606 return PT->push_back( 607 new FPTruncInst(V, DestTy, "Tr", BB->getTerminator())); 608 } else if (VSize < DestSize) { 609 return PT->push_back( 610 new FPExtInst(V, DestTy, "ZE", BB->getTerminator())); 611 } 612 // If VSize == DestSize, then the two types must be fp128 and ppc_fp128, 613 // for which there is no defined conversion. So do nothing. 614 } 615 } 616 }; 617 618 struct SelectModifier: public Modifier { 619 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R) 620 : Modifier(BB, PT, R) {} 621 622 void Act() override { 623 // Try a bunch of different select configuration until a valid one is found. 624 Value *Val0 = getRandomVal(); 625 Value *Val1 = getRandomValue(Val0->getType()); 626 627 Type *CondTy = Type::getInt1Ty(Context); 628 629 // If the value type is a vector, and we allow vector select, then in 50% 630 // of the cases generate a vector select. 631 if (isa<FixedVectorType>(Val0->getType()) && (getRandom() % 1)) { 632 unsigned NumElem = 633 cast<FixedVectorType>(Val0->getType())->getNumElements(); 634 CondTy = FixedVectorType::get(CondTy, NumElem); 635 } 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 std::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 // Init LLVM, call llvm_shutdown() on exit, parse args, etc. 737 PrettyStackTraceProgram X(argc, argv); 738 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); 739 llvm_shutdown_obj Y; 740 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 legacy::PassManager Passes; 765 Passes.add(createVerifierPass()); 766 Passes.add(createPrintModulePass(Out->os())); 767 Passes.run(*M.get()); 768 Out->keep(); 769 770 return 0; 771 } 772