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