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 PointerType::get(Context, 0), 136 PointerType::get(Context, 0), 137 PointerType::get(Context, 0), 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.starts_with("i")) { 177 unsigned N = 0; 178 Arg.drop_front().getAsInteger(10, N); 179 if (N > 0) 180 Ty = Type::getIntNTy(Context, N); 181 } 182 if (!Ty) { 183 errs() << "Invalid IR scalar type: '" << Arg << "'!\n"; 184 exit(1); 185 } 186 187 ScalarTypes.push_back(Ty); 188 } 189 } 190 191 /// virtual D'tor to silence warnings. 192 virtual ~Modifier() = default; 193 194 /// Add a new instruction. 195 virtual void Act() = 0; 196 197 /// Add N new instructions, 198 virtual void ActN(unsigned n) { 199 for (unsigned i=0; i<n; ++i) 200 Act(); 201 } 202 203 protected: 204 /// Return a random integer. 205 uint32_t getRandom() { 206 return Ran->Rand(); 207 } 208 209 /// Return a random value from the list of known values. 210 Value *getRandomVal() { 211 assert(PT->size()); 212 return PT->at(getRandom() % PT->size()); 213 } 214 215 Constant *getRandomConstant(Type *Tp) { 216 if (Tp->isIntegerTy()) { 217 if (getRandom() & 1) 218 return ConstantInt::getAllOnesValue(Tp); 219 return ConstantInt::getNullValue(Tp); 220 } else if (Tp->isFloatingPointTy()) { 221 if (getRandom() & 1) 222 return ConstantFP::getAllOnesValue(Tp); 223 return ConstantFP::getZero(Tp); 224 } 225 return UndefValue::get(Tp); 226 } 227 228 /// Return a random value with a known type. 229 Value *getRandomValue(Type *Tp) { 230 unsigned index = getRandom(); 231 for (unsigned i=0; i<PT->size(); ++i) { 232 Value *V = PT->at((index + i) % PT->size()); 233 if (V->getType() == Tp) 234 return V; 235 } 236 237 // If the requested type was not found, generate a constant value. 238 if (Tp->isIntegerTy()) { 239 if (getRandom() & 1) 240 return ConstantInt::getAllOnesValue(Tp); 241 return ConstantInt::getNullValue(Tp); 242 } else if (Tp->isFloatingPointTy()) { 243 if (getRandom() & 1) 244 return ConstantFP::getAllOnesValue(Tp); 245 return ConstantFP::getZero(Tp); 246 } else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) { 247 std::vector<Constant*> TempValues; 248 TempValues.reserve(VTp->getNumElements()); 249 for (unsigned i = 0; i < VTp->getNumElements(); ++i) 250 TempValues.push_back(getRandomConstant(VTp->getScalarType())); 251 252 ArrayRef<Constant*> VectorValue(TempValues); 253 return ConstantVector::get(VectorValue); 254 } 255 256 return UndefValue::get(Tp); 257 } 258 259 /// Return a random value of any pointer type. 260 Value *getRandomPointerValue() { 261 unsigned index = getRandom(); 262 for (unsigned i=0; i<PT->size(); ++i) { 263 Value *V = PT->at((index + i) % PT->size()); 264 if (V->getType()->isPointerTy()) 265 return V; 266 } 267 return UndefValue::get(PointerType::get(Context, 0)); 268 } 269 270 /// Return a random value of any vector type. 271 Value *getRandomVectorValue() { 272 unsigned index = getRandom(); 273 for (unsigned i=0; i<PT->size(); ++i) { 274 Value *V = PT->at((index + i) % PT->size()); 275 if (V->getType()->isVectorTy()) 276 return V; 277 } 278 return UndefValue::get(pickVectorType()); 279 } 280 281 /// Pick a random type. 282 Type *pickType() { 283 return (getRandom() & 1) ? pickVectorType() : pickScalarType(); 284 } 285 286 /// Pick a random vector type. 287 Type *pickVectorType(VectorType *VTy = nullptr) { 288 289 Type *Ty = pickScalarType(); 290 291 if (VTy) 292 return VectorType::get(Ty, VTy->getElementCount()); 293 294 // Select either fixed length or scalable vectors with 50% probability 295 // (only if scalable vectors are enabled) 296 bool Scalable = EnableScalableVectors && getRandom() & 1; 297 298 // Pick a random vector width in the range 2**0 to 2**4. 299 // by adding two randoms we are generating a normal-like distribution 300 // around 2**3. 301 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3)); 302 return VectorType::get(Ty, width, Scalable); 303 } 304 305 /// Pick a random scalar type. 306 Type *pickScalarType() { 307 return ScalarTypes[getRandom() % ScalarTypes.size()]; 308 } 309 310 /// Basic block to populate 311 BasicBlock *BB; 312 313 /// Value table 314 PieceTable *PT; 315 316 /// Random number generator 317 Random *Ran; 318 319 /// Context 320 LLVMContext &Context; 321 322 std::vector<Type *> ScalarTypes; 323 }; 324 325 struct LoadModifier: public Modifier { 326 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R) 327 : Modifier(BB, PT, R) {} 328 329 void Act() override { 330 // Try to use predefined pointers. If non-exist, use undef pointer value; 331 Value *Ptr = getRandomPointerValue(); 332 Type *Ty = pickType(); 333 Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator()->getIterator()); 334 PT->push_back(V); 335 } 336 }; 337 338 struct StoreModifier: public Modifier { 339 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R) 340 : Modifier(BB, PT, R) {} 341 342 void Act() override { 343 // Try to use predefined pointers. If non-exist, use undef pointer value; 344 Value *Ptr = getRandomPointerValue(); 345 Type *ValTy = pickType(); 346 347 // Do not store vectors of i1s because they are unsupported 348 // by the codegen. 349 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1) 350 return; 351 352 Value *Val = getRandomValue(ValTy); 353 new StoreInst(Val, Ptr, BB->getTerminator()->getIterator()); 354 } 355 }; 356 357 struct BinModifier: public Modifier { 358 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R) 359 : Modifier(BB, PT, R) {} 360 361 void Act() override { 362 Value *Val0 = getRandomVal(); 363 Value *Val1 = getRandomValue(Val0->getType()); 364 365 // Don't handle pointer types. 366 if (Val0->getType()->isPointerTy() || 367 Val1->getType()->isPointerTy()) 368 return; 369 370 // Don't handle i1 types. 371 if (Val0->getType()->getScalarSizeInBits() == 1) 372 return; 373 374 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy(); 375 Instruction* Term = BB->getTerminator(); 376 unsigned R = getRandom() % (isFloat ? 7 : 13); 377 Instruction::BinaryOps Op; 378 379 switch (R) { 380 default: llvm_unreachable("Invalid BinOp"); 381 case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; } 382 case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; } 383 case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; } 384 case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; } 385 case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; } 386 case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; } 387 case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; } 388 case 7: {Op = Instruction::Shl; break; } 389 case 8: {Op = Instruction::LShr; break; } 390 case 9: {Op = Instruction::AShr; break; } 391 case 10:{Op = Instruction::And; break; } 392 case 11:{Op = Instruction::Or; break; } 393 case 12:{Op = Instruction::Xor; break; } 394 } 395 396 PT->push_back( 397 BinaryOperator::Create(Op, Val0, Val1, "B", Term->getIterator())); 398 } 399 }; 400 401 /// Generate constant values. 402 struct ConstModifier: public Modifier { 403 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R) 404 : Modifier(BB, PT, R) {} 405 406 void Act() override { 407 Type *Ty = pickType(); 408 409 if (Ty->isVectorTy()) { 410 switch (getRandom() % 2) { 411 case 0: if (Ty->isIntOrIntVectorTy()) 412 return PT->push_back(ConstantVector::getAllOnesValue(Ty)); 413 break; 414 case 1: if (Ty->isIntOrIntVectorTy()) 415 return PT->push_back(ConstantVector::getNullValue(Ty)); 416 } 417 } 418 419 if (Ty->isFloatingPointTy()) { 420 // Generate 128 random bits, the size of the (currently) 421 // largest floating-point types. 422 uint64_t RandomBits[2]; 423 for (unsigned i = 0; i < 2; ++i) 424 RandomBits[i] = Ran->Rand64(); 425 426 APInt RandomInt(Ty->getPrimitiveSizeInBits(), ArrayRef(RandomBits)); 427 APFloat RandomFloat(Ty->getFltSemantics(), RandomInt); 428 429 if (getRandom() & 1) 430 return PT->push_back(ConstantFP::getZero(Ty)); 431 return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat)); 432 } 433 434 if (Ty->isIntegerTy()) { 435 switch (getRandom() % 7) { 436 case 0: 437 return PT->push_back(ConstantInt::get( 438 Ty, APInt::getAllOnes(Ty->getPrimitiveSizeInBits()))); 439 case 1: 440 return PT->push_back( 441 ConstantInt::get(Ty, APInt::getZero(Ty->getPrimitiveSizeInBits()))); 442 case 2: 443 case 3: 444 case 4: 445 case 5: 446 case 6: 447 PT->push_back(ConstantInt::get(Ty, getRandom())); 448 } 449 } 450 } 451 }; 452 453 struct AllocaModifier: public Modifier { 454 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R) 455 : Modifier(BB, PT, R) {} 456 457 void Act() override { 458 Type *Tp = pickType(); 459 const DataLayout &DL = BB->getDataLayout(); 460 PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(), "A", 461 BB->getFirstNonPHIIt())); 462 } 463 }; 464 465 struct ExtractElementModifier: public Modifier { 466 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 467 : Modifier(BB, PT, R) {} 468 469 void Act() override { 470 Value *Val0 = getRandomVectorValue(); 471 Value *V = ExtractElementInst::Create( 472 Val0, getRandomValue(Type::getInt32Ty(BB->getContext())), "E", 473 BB->getTerminator()->getIterator()); 474 return PT->push_back(V); 475 } 476 }; 477 478 struct ShuffModifier: public Modifier { 479 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R) 480 : Modifier(BB, PT, R) {} 481 482 void Act() override { 483 Value *Val0 = getRandomVectorValue(); 484 Value *Val1 = getRandomValue(Val0->getType()); 485 486 // Can't express arbitrary shufflevectors for scalable vectors 487 if (isa<ScalableVectorType>(Val0->getType())) 488 return; 489 490 unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements(); 491 std::vector<Constant*> Idxs; 492 493 Type *I32 = Type::getInt32Ty(BB->getContext()); 494 for (unsigned i=0; i<Width; ++i) { 495 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2)); 496 // Pick some undef values. 497 if (!(getRandom() % 5)) 498 CI = UndefValue::get(I32); 499 Idxs.push_back(CI); 500 } 501 502 Constant *Mask = ConstantVector::get(Idxs); 503 504 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", 505 BB->getTerminator()->getIterator()); 506 PT->push_back(V); 507 } 508 }; 509 510 struct InsertElementModifier: public Modifier { 511 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 512 : Modifier(BB, PT, R) {} 513 514 void Act() override { 515 Value *Val0 = getRandomVectorValue(); 516 Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); 517 518 Value *V = InsertElementInst::Create( 519 Val0, Val1, getRandomValue(Type::getInt32Ty(BB->getContext())), "I", 520 BB->getTerminator()->getIterator()); 521 return PT->push_back(V); 522 } 523 }; 524 525 struct CastModifier: public Modifier { 526 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R) 527 : Modifier(BB, PT, R) {} 528 529 void Act() override { 530 Value *V = getRandomVal(); 531 Type *VTy = V->getType(); 532 Type *DestTy = pickScalarType(); 533 534 // Handle vector casts vectors. 535 if (VTy->isVectorTy()) 536 DestTy = pickVectorType(cast<VectorType>(VTy)); 537 538 // no need to cast. 539 if (VTy == DestTy) return; 540 541 // Pointers: 542 if (VTy->isPointerTy()) { 543 if (!DestTy->isPointerTy()) 544 DestTy = PointerType::get(Context, 0); 545 return PT->push_back( 546 new BitCastInst(V, DestTy, "PC", BB->getTerminator()->getIterator())); 547 } 548 549 unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits(); 550 unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits(); 551 552 // Generate lots of bitcasts. 553 if ((getRandom() & 1) && VSize == DestSize) { 554 return PT->push_back( 555 new BitCastInst(V, DestTy, "BC", BB->getTerminator()->getIterator())); 556 } 557 558 // Both types are integers: 559 if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) { 560 if (VSize > DestSize) { 561 return PT->push_back( 562 new TruncInst(V, DestTy, "Tr", BB->getTerminator()->getIterator())); 563 } else { 564 assert(VSize < DestSize && "Different int types with the same size?"); 565 if (getRandom() & 1) 566 return PT->push_back(new ZExtInst( 567 V, DestTy, "ZE", BB->getTerminator()->getIterator())); 568 return PT->push_back( 569 new SExtInst(V, DestTy, "Se", BB->getTerminator()->getIterator())); 570 } 571 } 572 573 // Fp to int. 574 if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) { 575 if (getRandom() & 1) 576 return PT->push_back(new FPToSIInst( 577 V, DestTy, "FC", BB->getTerminator()->getIterator())); 578 return PT->push_back( 579 new FPToUIInst(V, DestTy, "FC", BB->getTerminator()->getIterator())); 580 } 581 582 // Int to fp. 583 if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) { 584 if (getRandom() & 1) 585 return PT->push_back(new SIToFPInst( 586 V, DestTy, "FC", BB->getTerminator()->getIterator())); 587 return PT->push_back( 588 new UIToFPInst(V, DestTy, "FC", BB->getTerminator()->getIterator())); 589 } 590 591 // Both floats. 592 if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) { 593 if (VSize > DestSize) { 594 return PT->push_back(new FPTruncInst( 595 V, DestTy, "Tr", BB->getTerminator()->getIterator())); 596 } else if (VSize < DestSize) { 597 return PT->push_back( 598 new FPExtInst(V, DestTy, "ZE", BB->getTerminator()->getIterator())); 599 } 600 // If VSize == DestSize, then the two types must be fp128 and ppc_fp128, 601 // for which there is no defined conversion. So do nothing. 602 } 603 } 604 }; 605 606 struct SelectModifier: public Modifier { 607 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R) 608 : Modifier(BB, PT, R) {} 609 610 void Act() override { 611 // Try a bunch of different select configuration until a valid one is found. 612 Value *Val0 = getRandomVal(); 613 Value *Val1 = getRandomValue(Val0->getType()); 614 615 Type *CondTy = Type::getInt1Ty(Context); 616 617 // If the value type is a vector, and we allow vector select, then in 50% 618 // of the cases generate a vector select. 619 if (auto *VTy = dyn_cast<VectorType>(Val0->getType())) 620 if (getRandom() & 1) 621 CondTy = VectorType::get(CondTy, VTy->getElementCount()); 622 623 Value *Cond = getRandomValue(CondTy); 624 Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", 625 BB->getTerminator()->getIterator()); 626 return PT->push_back(V); 627 } 628 }; 629 630 struct CmpModifier: public Modifier { 631 CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R) 632 : Modifier(BB, PT, R) {} 633 634 void Act() override { 635 Value *Val0 = getRandomVal(); 636 Value *Val1 = getRandomValue(Val0->getType()); 637 638 if (Val0->getType()->isPointerTy()) return; 639 bool fp = Val0->getType()->getScalarType()->isFloatingPointTy(); 640 641 int op; 642 if (fp) { 643 op = getRandom() % 644 (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) + 645 CmpInst::FIRST_FCMP_PREDICATE; 646 } else { 647 op = getRandom() % 648 (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) + 649 CmpInst::FIRST_ICMP_PREDICATE; 650 } 651 652 Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp, 653 (CmpInst::Predicate)op, Val0, Val1, "Cmp", 654 BB->getTerminator()->getIterator()); 655 return PT->push_back(V); 656 } 657 }; 658 659 } // end anonymous namespace 660 661 static void FillFunction(Function *F, Random &R) { 662 // Create a legal entry block. 663 BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F); 664 ReturnInst::Create(F->getContext(), BB); 665 666 // Create the value table. 667 Modifier::PieceTable PT; 668 669 // Consider arguments as legal values. 670 for (auto &arg : F->args()) 671 PT.push_back(&arg); 672 673 // List of modifiers which add new random instructions. 674 std::vector<std::unique_ptr<Modifier>> Modifiers; 675 Modifiers.emplace_back(new LoadModifier(BB, &PT, &R)); 676 Modifiers.emplace_back(new StoreModifier(BB, &PT, &R)); 677 auto SM = Modifiers.back().get(); 678 Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R)); 679 Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R)); 680 Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R)); 681 Modifiers.emplace_back(new BinModifier(BB, &PT, &R)); 682 Modifiers.emplace_back(new CastModifier(BB, &PT, &R)); 683 Modifiers.emplace_back(new SelectModifier(BB, &PT, &R)); 684 Modifiers.emplace_back(new CmpModifier(BB, &PT, &R)); 685 686 // Generate the random instructions 687 AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas 688 ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants 689 690 for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i) 691 for (auto &Mod : Modifiers) 692 Mod->Act(); 693 694 SM->ActN(5); // Throw in a few stores. 695 } 696 697 static void IntroduceControlFlow(Function *F, Random &R) { 698 std::vector<Instruction*> BoolInst; 699 for (auto &Instr : F->front()) { 700 if (Instr.getType() == IntegerType::getInt1Ty(F->getContext())) 701 BoolInst.push_back(&Instr); 702 } 703 704 llvm::shuffle(BoolInst.begin(), BoolInst.end(), R); 705 706 for (auto *Instr : BoolInst) { 707 BasicBlock *Curr = Instr->getParent(); 708 BasicBlock::iterator Loc = Instr->getIterator(); 709 BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); 710 Instr->moveBefore(Curr->getTerminator()->getIterator()); 711 if (Curr != &F->getEntryBlock()) { 712 BranchInst::Create(Curr, Next, Instr, 713 Curr->getTerminator()->getIterator()); 714 Curr->getTerminator()->eraseFromParent(); 715 } 716 } 717 } 718 719 } // end namespace llvm 720 721 int main(int argc, char **argv) { 722 using namespace llvm; 723 724 InitLLVM X(argc, argv); 725 cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()}); 726 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); 727 728 LLVMContext Context; 729 auto M = std::make_unique<Module>("/tmp/autogen.bc", Context); 730 Function *F = GenEmptyFunction(M.get()); 731 732 // Pick an initial seed value 733 Random R(SeedCL); 734 // Generate lots of random instructions inside a single basic block. 735 FillFunction(F, R); 736 // Break the basic block into many loops. 737 IntroduceControlFlow(F, R); 738 739 // Figure out what stream we are supposed to write to... 740 std::unique_ptr<ToolOutputFile> Out; 741 // Default to standard output. 742 if (OutputFilename.empty()) 743 OutputFilename = "-"; 744 745 std::error_code EC; 746 Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); 747 if (EC) { 748 errs() << EC.message() << '\n'; 749 return 1; 750 } 751 752 // Check that the generated module is accepted by the verifier. 753 if (verifyModule(*M.get(), &Out->os())) 754 report_fatal_error("Broken module found, compilation aborted!"); 755 756 // Output textual IR. 757 M->print(Out->os(), nullptr); 758 759 Out->keep(); 760 761 return 0; 762 } 763