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/Pass.h" 38 #include "llvm/Support/Casting.h" 39 #include "llvm/Support/CommandLine.h" 40 #include "llvm/Support/ErrorHandling.h" 41 #include "llvm/Support/FileSystem.h" 42 #include "llvm/Support/InitLLVM.h" 43 #include "llvm/Support/ToolOutputFile.h" 44 #include "llvm/Support/WithColor.h" 45 #include "llvm/Support/raw_ostream.h" 46 #include <algorithm> 47 #include <cassert> 48 #include <cstddef> 49 #include <cstdint> 50 #include <memory> 51 #include <string> 52 #include <system_error> 53 #include <vector> 54 55 namespace llvm { 56 57 static cl::OptionCategory StressCategory("Stress Options"); 58 59 static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"), 60 cl::init(0), cl::cat(StressCategory)); 61 62 static cl::opt<unsigned> SizeCL( 63 "size", 64 cl::desc("The estimated size of the generated function (# of instrs)"), 65 cl::init(100), cl::cat(StressCategory)); 66 67 static cl::opt<std::string> OutputFilename("o", 68 cl::desc("Override output filename"), 69 cl::value_desc("filename"), 70 cl::cat(StressCategory)); 71 72 static cl::list<StringRef> AdditionalScalarTypes( 73 "types", cl::CommaSeparated, 74 cl::desc("Additional IR scalar types " 75 "(always includes i1, i8, i16, i32, i64, float and double)")); 76 77 namespace { 78 79 /// A utility class to provide a pseudo-random number generator which is 80 /// the same across all platforms. This is somewhat close to the libc 81 /// implementation. Note: This is not a cryptographically secure pseudorandom 82 /// number generator. 83 class Random { 84 public: 85 /// C'tor 86 Random(unsigned _seed):Seed(_seed) {} 87 88 /// Return a random integer, up to a 89 /// maximum of 2**19 - 1. 90 uint32_t Rand() { 91 uint32_t Val = Seed + 0x000b07a1; 92 Seed = (Val * 0x3c7c0ac1); 93 // Only lowest 19 bits are random-ish. 94 return Seed & 0x7ffff; 95 } 96 97 /// Return a random 64 bit integer. 98 uint64_t Rand64() { 99 uint64_t Val = Rand() & 0xffff; 100 Val |= uint64_t(Rand() & 0xffff) << 16; 101 Val |= uint64_t(Rand() & 0xffff) << 32; 102 Val |= uint64_t(Rand() & 0xffff) << 48; 103 return Val; 104 } 105 106 /// Rand operator for STL algorithms. 107 ptrdiff_t operator()(ptrdiff_t y) { 108 return Rand64() % y; 109 } 110 111 /// Make this like a C++11 random device 112 using result_type = uint32_t ; 113 114 static constexpr result_type min() { return 0; } 115 static constexpr result_type max() { return 0x7ffff; } 116 117 uint32_t operator()() { 118 uint32_t Val = Rand(); 119 assert(Val <= max() && "Random value out of range"); 120 return Val; 121 } 122 123 private: 124 unsigned Seed; 125 }; 126 127 /// Generate an empty function with a default argument list. 128 Function *GenEmptyFunction(Module *M) { 129 // Define a few arguments 130 LLVMContext &Context = M->getContext(); 131 Type* ArgsTy[] = { 132 Type::getInt8PtrTy(Context), 133 Type::getInt32PtrTy(Context), 134 Type::getInt64PtrTy(Context), 135 Type::getInt32Ty(Context), 136 Type::getInt64Ty(Context), 137 Type::getInt8Ty(Context) 138 }; 139 140 auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false); 141 // Pick a unique name to describe the input parameters 142 Twine Name = "autogen_SD" + Twine{SeedCL}; 143 auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M); 144 Func->setCallingConv(CallingConv::C); 145 return Func; 146 } 147 148 /// A base class, implementing utilities needed for 149 /// modifying and adding new random instructions. 150 struct Modifier { 151 /// Used to store the randomly generated values. 152 using PieceTable = std::vector<Value *>; 153 154 public: 155 /// C'tor 156 Modifier(BasicBlock *Block, PieceTable *PT, Random *R) 157 : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) { 158 ScalarTypes.assign({Type::getInt1Ty(Context), Type::getInt8Ty(Context), 159 Type::getInt16Ty(Context), Type::getInt32Ty(Context), 160 Type::getInt64Ty(Context), Type::getFloatTy(Context), 161 Type::getDoubleTy(Context)}); 162 163 for (auto &Arg : AdditionalScalarTypes) { 164 Type *Ty = nullptr; 165 if (Arg == "half") 166 Ty = Type::getHalfTy(Context); 167 else if (Arg == "fp128") 168 Ty = Type::getFP128Ty(Context); 169 else if (Arg == "x86_fp80") 170 Ty = Type::getX86_FP80Ty(Context); 171 else if (Arg == "ppc_fp128") 172 Ty = Type::getPPC_FP128Ty(Context); 173 else if (Arg == "x86_mmx") 174 Ty = Type::getX86_MMXTy(Context); 175 else if (Arg.startswith("i")) { 176 unsigned N = 0; 177 Arg.drop_front().getAsInteger(10, N); 178 if (N > 0) 179 Ty = Type::getIntNTy(Context, N); 180 } 181 if (!Ty) { 182 errs() << "Invalid IR scalar type: '" << Arg << "'!\n"; 183 exit(1); 184 } 185 186 ScalarTypes.push_back(Ty); 187 } 188 } 189 190 /// virtual D'tor to silence warnings. 191 virtual ~Modifier() = default; 192 193 /// Add a new instruction. 194 virtual void Act() = 0; 195 196 /// Add N new instructions, 197 virtual void ActN(unsigned n) { 198 for (unsigned i=0; i<n; ++i) 199 Act(); 200 } 201 202 protected: 203 /// Return a random integer. 204 uint32_t getRandom() { 205 return Ran->Rand(); 206 } 207 208 /// Return a random value from the list of known values. 209 Value *getRandomVal() { 210 assert(PT->size()); 211 return PT->at(getRandom() % PT->size()); 212 } 213 214 Constant *getRandomConstant(Type *Tp) { 215 if (Tp->isIntegerTy()) { 216 if (getRandom() & 1) 217 return ConstantInt::getAllOnesValue(Tp); 218 return ConstantInt::getNullValue(Tp); 219 } else if (Tp->isFloatingPointTy()) { 220 if (getRandom() & 1) 221 return ConstantFP::getAllOnesValue(Tp); 222 return ConstantFP::getNullValue(Tp); 223 } 224 return UndefValue::get(Tp); 225 } 226 227 /// Return a random value with a known type. 228 Value *getRandomValue(Type *Tp) { 229 unsigned index = getRandom(); 230 for (unsigned i=0; i<PT->size(); ++i) { 231 Value *V = PT->at((index + i) % PT->size()); 232 if (V->getType() == Tp) 233 return V; 234 } 235 236 // If the requested type was not found, generate a constant value. 237 if (Tp->isIntegerTy()) { 238 if (getRandom() & 1) 239 return ConstantInt::getAllOnesValue(Tp); 240 return ConstantInt::getNullValue(Tp); 241 } else if (Tp->isFloatingPointTy()) { 242 if (getRandom() & 1) 243 return ConstantFP::getAllOnesValue(Tp); 244 return ConstantFP::getNullValue(Tp); 245 } else if (Tp->isVectorTy()) { 246 auto *VTp = cast<FixedVectorType>(Tp); 247 248 std::vector<Constant*> TempValues; 249 TempValues.reserve(VTp->getNumElements()); 250 for (unsigned i = 0; i < VTp->getNumElements(); ++i) 251 TempValues.push_back(getRandomConstant(VTp->getScalarType())); 252 253 ArrayRef<Constant*> VectorValue(TempValues); 254 return ConstantVector::get(VectorValue); 255 } 256 257 return UndefValue::get(Tp); 258 } 259 260 /// Return a random value of any pointer type. 261 Value *getRandomPointerValue() { 262 unsigned index = getRandom(); 263 for (unsigned i=0; i<PT->size(); ++i) { 264 Value *V = PT->at((index + i) % PT->size()); 265 if (V->getType()->isPointerTy()) 266 return V; 267 } 268 return UndefValue::get(pickPointerType()); 269 } 270 271 /// Return a random value of any vector type. 272 Value *getRandomVectorValue() { 273 unsigned index = getRandom(); 274 for (unsigned i=0; i<PT->size(); ++i) { 275 Value *V = PT->at((index + i) % PT->size()); 276 if (V->getType()->isVectorTy()) 277 return V; 278 } 279 return UndefValue::get(pickVectorType()); 280 } 281 282 /// Pick a random type. 283 Type *pickType() { 284 return (getRandom() & 1) ? pickVectorType() : pickScalarType(); 285 } 286 287 /// Pick a random pointer type. 288 Type *pickPointerType() { 289 Type *Ty = pickType(); 290 return PointerType::get(Ty, 0); 291 } 292 293 /// Pick a random vector type. 294 Type *pickVectorType(unsigned len = (unsigned)-1) { 295 // Pick a random vector width in the range 2**0 to 2**4. 296 // by adding two randoms we are generating a normal-like distribution 297 // around 2**3. 298 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3)); 299 Type *Ty; 300 301 // Vectors of x86mmx are illegal; keep trying till we get something else. 302 do { 303 Ty = pickScalarType(); 304 } while (Ty->isX86_MMXTy()); 305 306 if (len != (unsigned)-1) 307 width = len; 308 return FixedVectorType::get(Ty, width); 309 } 310 311 /// Pick a random scalar type. 312 Type *pickScalarType() { 313 return ScalarTypes[getRandom() % ScalarTypes.size()]; 314 } 315 316 /// Basic block to populate 317 BasicBlock *BB; 318 319 /// Value table 320 PieceTable *PT; 321 322 /// Random number generator 323 Random *Ran; 324 325 /// Context 326 LLVMContext &Context; 327 328 std::vector<Type *> ScalarTypes; 329 }; 330 331 struct LoadModifier: public Modifier { 332 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R) 333 : Modifier(BB, PT, R) {} 334 335 void Act() override { 336 // Try to use predefined pointers. If non-exist, use undef pointer value; 337 Value *Ptr = getRandomPointerValue(); 338 Type *Ty = Ptr->getType()->isOpaquePointerTy() 339 ? pickType() 340 : Ptr->getType()->getNonOpaquePointerElementType(); 341 Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator()); 342 PT->push_back(V); 343 } 344 }; 345 346 struct StoreModifier: public Modifier { 347 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R) 348 : Modifier(BB, PT, R) {} 349 350 void Act() override { 351 // Try to use predefined pointers. If non-exist, use undef pointer value; 352 Value *Ptr = getRandomPointerValue(); 353 Type *ValTy = Ptr->getType()->isOpaquePointerTy() 354 ? pickType() 355 : Ptr->getType()->getNonOpaquePointerElementType(); 356 357 // Do not store vectors of i1s because they are unsupported 358 // by the codegen. 359 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1) 360 return; 361 362 Value *Val = getRandomValue(ValTy); 363 new StoreInst(Val, Ptr, BB->getTerminator()); 364 } 365 }; 366 367 struct BinModifier: public Modifier { 368 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R) 369 : Modifier(BB, PT, R) {} 370 371 void Act() override { 372 Value *Val0 = getRandomVal(); 373 Value *Val1 = getRandomValue(Val0->getType()); 374 375 // Don't handle pointer types. 376 if (Val0->getType()->isPointerTy() || 377 Val1->getType()->isPointerTy()) 378 return; 379 380 // Don't handle i1 types. 381 if (Val0->getType()->getScalarSizeInBits() == 1) 382 return; 383 384 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy(); 385 Instruction* Term = BB->getTerminator(); 386 unsigned R = getRandom() % (isFloat ? 7 : 13); 387 Instruction::BinaryOps Op; 388 389 switch (R) { 390 default: llvm_unreachable("Invalid BinOp"); 391 case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; } 392 case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; } 393 case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; } 394 case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; } 395 case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; } 396 case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; } 397 case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; } 398 case 7: {Op = Instruction::Shl; break; } 399 case 8: {Op = Instruction::LShr; break; } 400 case 9: {Op = Instruction::AShr; break; } 401 case 10:{Op = Instruction::And; break; } 402 case 11:{Op = Instruction::Or; break; } 403 case 12:{Op = Instruction::Xor; break; } 404 } 405 406 PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term)); 407 } 408 }; 409 410 /// Generate constant values. 411 struct ConstModifier: public Modifier { 412 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R) 413 : Modifier(BB, PT, R) {} 414 415 void Act() override { 416 Type *Ty = pickType(); 417 418 if (Ty->isVectorTy()) { 419 switch (getRandom() % 2) { 420 case 0: if (Ty->isIntOrIntVectorTy()) 421 return PT->push_back(ConstantVector::getAllOnesValue(Ty)); 422 break; 423 case 1: if (Ty->isIntOrIntVectorTy()) 424 return PT->push_back(ConstantVector::getNullValue(Ty)); 425 } 426 } 427 428 if (Ty->isFloatingPointTy()) { 429 // Generate 128 random bits, the size of the (currently) 430 // largest floating-point types. 431 uint64_t RandomBits[2]; 432 for (unsigned i = 0; i < 2; ++i) 433 RandomBits[i] = Ran->Rand64(); 434 435 APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits)); 436 APFloat RandomFloat(Ty->getFltSemantics(), RandomInt); 437 438 if (getRandom() & 1) 439 return PT->push_back(ConstantFP::getNullValue(Ty)); 440 return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat)); 441 } 442 443 if (Ty->isIntegerTy()) { 444 switch (getRandom() % 7) { 445 case 0: 446 return PT->push_back(ConstantInt::get( 447 Ty, APInt::getAllOnes(Ty->getPrimitiveSizeInBits()))); 448 case 1: 449 return PT->push_back( 450 ConstantInt::get(Ty, APInt::getZero(Ty->getPrimitiveSizeInBits()))); 451 case 2: 452 case 3: 453 case 4: 454 case 5: 455 case 6: 456 PT->push_back(ConstantInt::get(Ty, getRandom())); 457 } 458 } 459 } 460 }; 461 462 struct AllocaModifier: public Modifier { 463 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R) 464 : Modifier(BB, PT, R) {} 465 466 void Act() override { 467 Type *Tp = pickType(); 468 const DataLayout &DL = BB->getModule()->getDataLayout(); 469 PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(), 470 "A", BB->getFirstNonPHI())); 471 } 472 }; 473 474 struct ExtractElementModifier: public Modifier { 475 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 476 : Modifier(BB, PT, R) {} 477 478 void Act() override { 479 Value *Val0 = getRandomVectorValue(); 480 Value *V = ExtractElementInst::Create( 481 Val0, 482 ConstantInt::get( 483 Type::getInt32Ty(BB->getContext()), 484 getRandom() % 485 cast<FixedVectorType>(Val0->getType())->getNumElements()), 486 "E", BB->getTerminator()); 487 return PT->push_back(V); 488 } 489 }; 490 491 struct ShuffModifier: public Modifier { 492 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R) 493 : Modifier(BB, PT, R) {} 494 495 void Act() override { 496 Value *Val0 = getRandomVectorValue(); 497 Value *Val1 = getRandomValue(Val0->getType()); 498 499 unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements(); 500 std::vector<Constant*> Idxs; 501 502 Type *I32 = Type::getInt32Ty(BB->getContext()); 503 for (unsigned i=0; i<Width; ++i) { 504 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2)); 505 // Pick some undef values. 506 if (!(getRandom() % 5)) 507 CI = UndefValue::get(I32); 508 Idxs.push_back(CI); 509 } 510 511 Constant *Mask = ConstantVector::get(Idxs); 512 513 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", 514 BB->getTerminator()); 515 PT->push_back(V); 516 } 517 }; 518 519 struct InsertElementModifier: public Modifier { 520 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R) 521 : Modifier(BB, PT, R) {} 522 523 void Act() override { 524 Value *Val0 = getRandomVectorValue(); 525 Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); 526 527 Value *V = InsertElementInst::Create( 528 Val0, Val1, 529 ConstantInt::get( 530 Type::getInt32Ty(BB->getContext()), 531 getRandom() % 532 cast<FixedVectorType>(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 auto *VecTy = cast<FixedVectorType>(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 llvm::shuffle(BoolInst.begin(), BoolInst.end(), R); 718 719 for (auto *Instr : BoolInst) { 720 BasicBlock *Curr = Instr->getParent(); 721 BasicBlock::iterator Loc = Instr->getIterator(); 722 BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); 723 Instr->moveBefore(Curr->getTerminator()); 724 if (Curr != &F->getEntryBlock()) { 725 BranchInst::Create(Curr, Next, Instr, Curr->getTerminator()); 726 Curr->getTerminator()->eraseFromParent(); 727 } 728 } 729 } 730 731 } // end namespace llvm 732 733 int main(int argc, char **argv) { 734 using namespace llvm; 735 736 InitLLVM X(argc, argv); 737 cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()}); 738 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); 739 740 LLVMContext Context; 741 auto M = std::make_unique<Module>("/tmp/autogen.bc", Context); 742 Function *F = GenEmptyFunction(M.get()); 743 744 // Pick an initial seed value 745 Random R(SeedCL); 746 // Generate lots of random instructions inside a single basic block. 747 FillFunction(F, R); 748 // Break the basic block into many loops. 749 IntroduceControlFlow(F, R); 750 751 // Figure out what stream we are supposed to write to... 752 std::unique_ptr<ToolOutputFile> Out; 753 // Default to standard output. 754 if (OutputFilename.empty()) 755 OutputFilename = "-"; 756 757 std::error_code EC; 758 Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None)); 759 if (EC) { 760 errs() << EC.message() << '\n'; 761 return 1; 762 } 763 764 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