1234285Sdim//===-- llvm-stress.cpp - Generate random LL files to stress-test LLVM ----===// 2234285Sdim// 3234285Sdim// The LLVM Compiler Infrastructure 4234285Sdim// 5234285Sdim// This file is distributed under the University of Illinois Open Source 6234285Sdim// License. See LICENSE.TXT for details. 7234285Sdim// 8234285Sdim//===----------------------------------------------------------------------===// 9234285Sdim// 10234285Sdim// This program is a utility that generates random .ll files to stress-test 11234285Sdim// different components in LLVM. 12234285Sdim// 13234285Sdim//===----------------------------------------------------------------------===// 14252723Sdim#include "llvm/IR/LLVMContext.h" 15252723Sdim#include "llvm/ADT/OwningPtr.h" 16252723Sdim#include "llvm/Analysis/CallGraphSCCPass.h" 17252723Sdim#include "llvm/Analysis/Verifier.h" 18252723Sdim#include "llvm/Assembly/PrintModulePass.h" 19252723Sdim#include "llvm/IR/Constants.h" 20252723Sdim#include "llvm/IR/Instruction.h" 21252723Sdim#include "llvm/IR/Module.h" 22234285Sdim#include "llvm/PassManager.h" 23234285Sdim#include "llvm/Support/Debug.h" 24234285Sdim#include "llvm/Support/ManagedStatic.h" 25252723Sdim#include "llvm/Support/PassNameParser.h" 26234285Sdim#include "llvm/Support/PluginLoader.h" 27234285Sdim#include "llvm/Support/PrettyStackTrace.h" 28234285Sdim#include "llvm/Support/ToolOutputFile.h" 29252723Sdim#include <algorithm> 30252723Sdim#include <set> 31234285Sdim#include <sstream> 32234285Sdim#include <vector> 33234285Sdimusing namespace llvm; 34234285Sdim 35234285Sdimstatic cl::opt<unsigned> SeedCL("seed", 36234285Sdim cl::desc("Seed used for randomness"), cl::init(0)); 37234285Sdimstatic cl::opt<unsigned> SizeCL("size", 38234285Sdim cl::desc("The estimated size of the generated function (# of instrs)"), 39234285Sdim cl::init(100)); 40234285Sdimstatic cl::opt<std::string> 41234285SdimOutputFilename("o", cl::desc("Override output filename"), 42234285Sdim cl::value_desc("filename")); 43234285Sdim 44234285Sdimstatic cl::opt<bool> GenHalfFloat("generate-half-float", 45234285Sdim cl::desc("Generate half-length floating-point values"), cl::init(false)); 46234285Sdimstatic cl::opt<bool> GenX86FP80("generate-x86-fp80", 47234285Sdim cl::desc("Generate 80-bit X86 floating-point values"), cl::init(false)); 48234285Sdimstatic cl::opt<bool> GenFP128("generate-fp128", 49234285Sdim cl::desc("Generate 128-bit floating-point values"), cl::init(false)); 50234285Sdimstatic cl::opt<bool> GenPPCFP128("generate-ppc-fp128", 51234285Sdim cl::desc("Generate 128-bit PPC floating-point values"), cl::init(false)); 52234285Sdimstatic cl::opt<bool> GenX86MMX("generate-x86-mmx", 53234285Sdim cl::desc("Generate X86 MMX floating-point values"), cl::init(false)); 54234285Sdim 55263509Sdimnamespace { 56234285Sdim/// A utility class to provide a pseudo-random number generator which is 57234285Sdim/// the same across all platforms. This is somewhat close to the libc 58234285Sdim/// implementation. Note: This is not a cryptographically secure pseudorandom 59234285Sdim/// number generator. 60234285Sdimclass Random { 61234285Sdimpublic: 62234285Sdim /// C'tor 63234285Sdim Random(unsigned _seed):Seed(_seed) {} 64234285Sdim 65234285Sdim /// Return a random integer, up to a 66234285Sdim /// maximum of 2**19 - 1. 67234285Sdim uint32_t Rand() { 68234285Sdim uint32_t Val = Seed + 0x000b07a1; 69234285Sdim Seed = (Val * 0x3c7c0ac1); 70234285Sdim // Only lowest 19 bits are random-ish. 71234285Sdim return Seed & 0x7ffff; 72234285Sdim } 73234285Sdim 74234285Sdim /// Return a random 32 bit integer. 75234285Sdim uint32_t Rand32() { 76234285Sdim uint32_t Val = Rand(); 77234285Sdim Val &= 0xffff; 78234285Sdim return Val | (Rand() << 16); 79234285Sdim } 80234285Sdim 81234285Sdim /// Return a random 64 bit integer. 82234285Sdim uint64_t Rand64() { 83234285Sdim uint64_t Val = Rand32(); 84234285Sdim return Val | (uint64_t(Rand32()) << 32); 85234285Sdim } 86245431Sdim 87245431Sdim /// Rand operator for STL algorithms. 88245431Sdim ptrdiff_t operator()(ptrdiff_t y) { 89245431Sdim return Rand64() % y; 90245431Sdim } 91245431Sdim 92234285Sdimprivate: 93234285Sdim unsigned Seed; 94234285Sdim}; 95234285Sdim 96234285Sdim/// Generate an empty function with a default argument list. 97234285SdimFunction *GenEmptyFunction(Module *M) { 98234285Sdim // Type Definitions 99234285Sdim std::vector<Type*> ArgsTy; 100234285Sdim // Define a few arguments 101234285Sdim LLVMContext &Context = M->getContext(); 102234285Sdim ArgsTy.push_back(PointerType::get(IntegerType::getInt8Ty(Context), 0)); 103234285Sdim ArgsTy.push_back(PointerType::get(IntegerType::getInt32Ty(Context), 0)); 104234285Sdim ArgsTy.push_back(PointerType::get(IntegerType::getInt64Ty(Context), 0)); 105234285Sdim ArgsTy.push_back(IntegerType::getInt32Ty(Context)); 106234285Sdim ArgsTy.push_back(IntegerType::getInt64Ty(Context)); 107234285Sdim ArgsTy.push_back(IntegerType::getInt8Ty(Context)); 108234285Sdim 109234285Sdim FunctionType *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, 0); 110234285Sdim // Pick a unique name to describe the input parameters 111234285Sdim std::stringstream ss; 112234285Sdim ss<<"autogen_SD"<<SeedCL; 113234285Sdim Function *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, 114234285Sdim ss.str(), M); 115234285Sdim 116234285Sdim Func->setCallingConv(CallingConv::C); 117234285Sdim return Func; 118234285Sdim} 119234285Sdim 120234285Sdim/// A base class, implementing utilities needed for 121234285Sdim/// modifying and adding new random instructions. 122234285Sdimstruct Modifier { 123234285Sdim /// Used to store the randomly generated values. 124234285Sdim typedef std::vector<Value*> PieceTable; 125234285Sdim 126234285Sdimpublic: 127234285Sdim /// C'tor 128234285Sdim Modifier(BasicBlock *Block, PieceTable *PT, Random *R): 129234285Sdim BB(Block),PT(PT),Ran(R),Context(BB->getContext()) {} 130245431Sdim 131245431Sdim /// virtual D'tor to silence warnings. 132245431Sdim virtual ~Modifier() {} 133245431Sdim 134234285Sdim /// Add a new instruction. 135234285Sdim virtual void Act() = 0; 136234285Sdim /// Add N new instructions, 137234285Sdim virtual void ActN(unsigned n) { 138234285Sdim for (unsigned i=0; i<n; ++i) 139234285Sdim Act(); 140234285Sdim } 141234285Sdim 142234285Sdimprotected: 143234285Sdim /// Return a random value from the list of known values. 144234285Sdim Value *getRandomVal() { 145234285Sdim assert(PT->size()); 146234285Sdim return PT->at(Ran->Rand() % PT->size()); 147234285Sdim } 148234285Sdim 149234285Sdim Constant *getRandomConstant(Type *Tp) { 150234285Sdim if (Tp->isIntegerTy()) { 151234285Sdim if (Ran->Rand() & 1) 152234285Sdim return ConstantInt::getAllOnesValue(Tp); 153234285Sdim return ConstantInt::getNullValue(Tp); 154234285Sdim } else if (Tp->isFloatingPointTy()) { 155234285Sdim if (Ran->Rand() & 1) 156234285Sdim return ConstantFP::getAllOnesValue(Tp); 157234285Sdim return ConstantFP::getNullValue(Tp); 158234285Sdim } 159234285Sdim return UndefValue::get(Tp); 160234285Sdim } 161234285Sdim 162234285Sdim /// Return a random value with a known type. 163234285Sdim Value *getRandomValue(Type *Tp) { 164234285Sdim unsigned index = Ran->Rand(); 165234285Sdim for (unsigned i=0; i<PT->size(); ++i) { 166234285Sdim Value *V = PT->at((index + i) % PT->size()); 167234285Sdim if (V->getType() == Tp) 168234285Sdim return V; 169234285Sdim } 170234285Sdim 171234285Sdim // If the requested type was not found, generate a constant value. 172234285Sdim if (Tp->isIntegerTy()) { 173234285Sdim if (Ran->Rand() & 1) 174234285Sdim return ConstantInt::getAllOnesValue(Tp); 175234285Sdim return ConstantInt::getNullValue(Tp); 176234285Sdim } else if (Tp->isFloatingPointTy()) { 177234285Sdim if (Ran->Rand() & 1) 178234285Sdim return ConstantFP::getAllOnesValue(Tp); 179234285Sdim return ConstantFP::getNullValue(Tp); 180234285Sdim } else if (Tp->isVectorTy()) { 181234285Sdim VectorType *VTp = cast<VectorType>(Tp); 182234285Sdim 183234285Sdim std::vector<Constant*> TempValues; 184234285Sdim TempValues.reserve(VTp->getNumElements()); 185234285Sdim for (unsigned i = 0; i < VTp->getNumElements(); ++i) 186234285Sdim TempValues.push_back(getRandomConstant(VTp->getScalarType())); 187234285Sdim 188234285Sdim ArrayRef<Constant*> VectorValue(TempValues); 189234285Sdim return ConstantVector::get(VectorValue); 190234285Sdim } 191234285Sdim 192234285Sdim return UndefValue::get(Tp); 193234285Sdim } 194234285Sdim 195234285Sdim /// Return a random value of any pointer type. 196234285Sdim Value *getRandomPointerValue() { 197234285Sdim unsigned index = Ran->Rand(); 198234285Sdim for (unsigned i=0; i<PT->size(); ++i) { 199234285Sdim Value *V = PT->at((index + i) % PT->size()); 200234285Sdim if (V->getType()->isPointerTy()) 201234285Sdim return V; 202234285Sdim } 203234285Sdim return UndefValue::get(pickPointerType()); 204234285Sdim } 205234285Sdim 206234285Sdim /// Return a random value of any vector type. 207234285Sdim Value *getRandomVectorValue() { 208234285Sdim unsigned index = Ran->Rand(); 209234285Sdim for (unsigned i=0; i<PT->size(); ++i) { 210234285Sdim Value *V = PT->at((index + i) % PT->size()); 211234285Sdim if (V->getType()->isVectorTy()) 212234285Sdim return V; 213234285Sdim } 214234285Sdim return UndefValue::get(pickVectorType()); 215234285Sdim } 216234285Sdim 217234285Sdim /// Pick a random type. 218234285Sdim Type *pickType() { 219234285Sdim return (Ran->Rand() & 1 ? pickVectorType() : pickScalarType()); 220234285Sdim } 221234285Sdim 222234285Sdim /// Pick a random pointer type. 223234285Sdim Type *pickPointerType() { 224234285Sdim Type *Ty = pickType(); 225234285Sdim return PointerType::get(Ty, 0); 226234285Sdim } 227234285Sdim 228234285Sdim /// Pick a random vector type. 229234285Sdim Type *pickVectorType(unsigned len = (unsigned)-1) { 230234285Sdim // Pick a random vector width in the range 2**0 to 2**4. 231234285Sdim // by adding two randoms we are generating a normal-like distribution 232234285Sdim // around 2**3. 233234285Sdim unsigned width = 1<<((Ran->Rand() % 3) + (Ran->Rand() % 3)); 234234285Sdim Type *Ty; 235234285Sdim 236234285Sdim // Vectors of x86mmx are illegal; keep trying till we get something else. 237234285Sdim do { 238234285Sdim Ty = pickScalarType(); 239234285Sdim } while (Ty->isX86_MMXTy()); 240234285Sdim 241234285Sdim if (len != (unsigned)-1) 242234285Sdim width = len; 243234285Sdim return VectorType::get(Ty, width); 244234285Sdim } 245234285Sdim 246234285Sdim /// Pick a random scalar type. 247234285Sdim Type *pickScalarType() { 248234285Sdim Type *t = 0; 249234285Sdim do { 250234285Sdim switch (Ran->Rand() % 30) { 251234285Sdim case 0: t = Type::getInt1Ty(Context); break; 252234285Sdim case 1: t = Type::getInt8Ty(Context); break; 253234285Sdim case 2: t = Type::getInt16Ty(Context); break; 254234285Sdim case 3: case 4: 255234285Sdim case 5: t = Type::getFloatTy(Context); break; 256234285Sdim case 6: case 7: 257234285Sdim case 8: t = Type::getDoubleTy(Context); break; 258234285Sdim case 9: case 10: 259234285Sdim case 11: t = Type::getInt32Ty(Context); break; 260234285Sdim case 12: case 13: 261234285Sdim case 14: t = Type::getInt64Ty(Context); break; 262234285Sdim case 15: case 16: 263234285Sdim case 17: if (GenHalfFloat) t = Type::getHalfTy(Context); break; 264234285Sdim case 18: case 19: 265234285Sdim case 20: if (GenX86FP80) t = Type::getX86_FP80Ty(Context); break; 266234285Sdim case 21: case 22: 267234285Sdim case 23: if (GenFP128) t = Type::getFP128Ty(Context); break; 268234285Sdim case 24: case 25: 269234285Sdim case 26: if (GenPPCFP128) t = Type::getPPC_FP128Ty(Context); break; 270234285Sdim case 27: case 28: 271234285Sdim case 29: if (GenX86MMX) t = Type::getX86_MMXTy(Context); break; 272234285Sdim default: llvm_unreachable("Invalid scalar value"); 273234285Sdim } 274234285Sdim } while (t == 0); 275234285Sdim 276234285Sdim return t; 277234285Sdim } 278234285Sdim 279234285Sdim /// Basic block to populate 280234285Sdim BasicBlock *BB; 281234285Sdim /// Value table 282234285Sdim PieceTable *PT; 283234285Sdim /// Random number generator 284234285Sdim Random *Ran; 285234285Sdim /// Context 286234285Sdim LLVMContext &Context; 287234285Sdim}; 288234285Sdim 289234285Sdimstruct LoadModifier: public Modifier { 290234285Sdim LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 291234285Sdim virtual void Act() { 292234285Sdim // Try to use predefined pointers. If non exist, use undef pointer value; 293234285Sdim Value *Ptr = getRandomPointerValue(); 294234285Sdim Value *V = new LoadInst(Ptr, "L", BB->getTerminator()); 295234285Sdim PT->push_back(V); 296234285Sdim } 297234285Sdim}; 298234285Sdim 299234285Sdimstruct StoreModifier: public Modifier { 300234285Sdim StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 301234285Sdim virtual void Act() { 302234285Sdim // Try to use predefined pointers. If non exist, use undef pointer value; 303234285Sdim Value *Ptr = getRandomPointerValue(); 304234285Sdim Type *Tp = Ptr->getType(); 305234285Sdim Value *Val = getRandomValue(Tp->getContainedType(0)); 306234285Sdim Type *ValTy = Val->getType(); 307234285Sdim 308234285Sdim // Do not store vectors of i1s because they are unsupported 309234285Sdim // by the codegen. 310234285Sdim if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1) 311234285Sdim return; 312234285Sdim 313234285Sdim new StoreInst(Val, Ptr, BB->getTerminator()); 314234285Sdim } 315234285Sdim}; 316234285Sdim 317234285Sdimstruct BinModifier: public Modifier { 318234285Sdim BinModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 319234285Sdim 320234285Sdim virtual void Act() { 321234285Sdim Value *Val0 = getRandomVal(); 322234285Sdim Value *Val1 = getRandomValue(Val0->getType()); 323234285Sdim 324234285Sdim // Don't handle pointer types. 325234285Sdim if (Val0->getType()->isPointerTy() || 326234285Sdim Val1->getType()->isPointerTy()) 327234285Sdim return; 328234285Sdim 329234285Sdim // Don't handle i1 types. 330234285Sdim if (Val0->getType()->getScalarSizeInBits() == 1) 331234285Sdim return; 332234285Sdim 333234285Sdim 334234285Sdim bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy(); 335234285Sdim Instruction* Term = BB->getTerminator(); 336234285Sdim unsigned R = Ran->Rand() % (isFloat ? 7 : 13); 337234285Sdim Instruction::BinaryOps Op; 338234285Sdim 339234285Sdim switch (R) { 340234285Sdim default: llvm_unreachable("Invalid BinOp"); 341234285Sdim case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; } 342234285Sdim case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; } 343234285Sdim case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; } 344234285Sdim case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; } 345234285Sdim case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; } 346234285Sdim case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; } 347234285Sdim case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; } 348234285Sdim case 7: {Op = Instruction::Shl; break; } 349234285Sdim case 8: {Op = Instruction::LShr; break; } 350234285Sdim case 9: {Op = Instruction::AShr; break; } 351234285Sdim case 10:{Op = Instruction::And; break; } 352234285Sdim case 11:{Op = Instruction::Or; break; } 353234285Sdim case 12:{Op = Instruction::Xor; break; } 354234285Sdim } 355234285Sdim 356234285Sdim PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term)); 357234285Sdim } 358234285Sdim}; 359234285Sdim 360234285Sdim/// Generate constant values. 361234285Sdimstruct ConstModifier: public Modifier { 362234285Sdim ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 363234285Sdim virtual void Act() { 364234285Sdim Type *Ty = pickType(); 365234285Sdim 366234285Sdim if (Ty->isVectorTy()) { 367234285Sdim switch (Ran->Rand() % 2) { 368234285Sdim case 0: if (Ty->getScalarType()->isIntegerTy()) 369234285Sdim return PT->push_back(ConstantVector::getAllOnesValue(Ty)); 370234285Sdim case 1: if (Ty->getScalarType()->isIntegerTy()) 371234285Sdim return PT->push_back(ConstantVector::getNullValue(Ty)); 372234285Sdim } 373234285Sdim } 374234285Sdim 375234285Sdim if (Ty->isFloatingPointTy()) { 376234285Sdim // Generate 128 random bits, the size of the (currently) 377234285Sdim // largest floating-point types. 378234285Sdim uint64_t RandomBits[2]; 379234285Sdim for (unsigned i = 0; i < 2; ++i) 380234285Sdim RandomBits[i] = Ran->Rand64(); 381234285Sdim 382234285Sdim APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits)); 383252723Sdim APFloat RandomFloat(Ty->getFltSemantics(), RandomInt); 384234285Sdim 385234285Sdim if (Ran->Rand() & 1) 386234285Sdim return PT->push_back(ConstantFP::getNullValue(Ty)); 387234285Sdim return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat)); 388234285Sdim } 389234285Sdim 390234285Sdim if (Ty->isIntegerTy()) { 391234285Sdim switch (Ran->Rand() % 7) { 392234285Sdim case 0: if (Ty->isIntegerTy()) 393234285Sdim return PT->push_back(ConstantInt::get(Ty, 394234285Sdim APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits()))); 395234285Sdim case 1: if (Ty->isIntegerTy()) 396234285Sdim return PT->push_back(ConstantInt::get(Ty, 397234285Sdim APInt::getNullValue(Ty->getPrimitiveSizeInBits()))); 398234285Sdim case 2: case 3: case 4: case 5: 399234285Sdim case 6: if (Ty->isIntegerTy()) 400234285Sdim PT->push_back(ConstantInt::get(Ty, Ran->Rand())); 401234285Sdim } 402234285Sdim } 403234285Sdim 404234285Sdim } 405234285Sdim}; 406234285Sdim 407234285Sdimstruct AllocaModifier: public Modifier { 408234285Sdim AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R){} 409234285Sdim 410234285Sdim virtual void Act() { 411234285Sdim Type *Tp = pickType(); 412234285Sdim PT->push_back(new AllocaInst(Tp, "A", BB->getFirstNonPHI())); 413234285Sdim } 414234285Sdim}; 415234285Sdim 416234285Sdimstruct ExtractElementModifier: public Modifier { 417234285Sdim ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R): 418234285Sdim Modifier(BB, PT, R) {} 419234285Sdim 420234285Sdim virtual void Act() { 421234285Sdim Value *Val0 = getRandomVectorValue(); 422234285Sdim Value *V = ExtractElementInst::Create(Val0, 423234285Sdim ConstantInt::get(Type::getInt32Ty(BB->getContext()), 424235633Sdim Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), 425234285Sdim "E", BB->getTerminator()); 426234285Sdim return PT->push_back(V); 427234285Sdim } 428234285Sdim}; 429234285Sdim 430234285Sdimstruct ShuffModifier: public Modifier { 431234285Sdim ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 432234285Sdim virtual void Act() { 433234285Sdim 434234285Sdim Value *Val0 = getRandomVectorValue(); 435234285Sdim Value *Val1 = getRandomValue(Val0->getType()); 436234285Sdim 437234285Sdim unsigned Width = cast<VectorType>(Val0->getType())->getNumElements(); 438234285Sdim std::vector<Constant*> Idxs; 439234285Sdim 440234285Sdim Type *I32 = Type::getInt32Ty(BB->getContext()); 441234285Sdim for (unsigned i=0; i<Width; ++i) { 442234285Sdim Constant *CI = ConstantInt::get(I32, Ran->Rand() % (Width*2)); 443234285Sdim // Pick some undef values. 444234285Sdim if (!(Ran->Rand() % 5)) 445234285Sdim CI = UndefValue::get(I32); 446234285Sdim Idxs.push_back(CI); 447234285Sdim } 448234285Sdim 449234285Sdim Constant *Mask = ConstantVector::get(Idxs); 450234285Sdim 451234285Sdim Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff", 452234285Sdim BB->getTerminator()); 453234285Sdim PT->push_back(V); 454234285Sdim } 455234285Sdim}; 456234285Sdim 457234285Sdimstruct InsertElementModifier: public Modifier { 458234285Sdim InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R): 459234285Sdim Modifier(BB, PT, R) {} 460234285Sdim 461234285Sdim virtual void Act() { 462234285Sdim Value *Val0 = getRandomVectorValue(); 463234285Sdim Value *Val1 = getRandomValue(Val0->getType()->getScalarType()); 464234285Sdim 465234285Sdim Value *V = InsertElementInst::Create(Val0, Val1, 466234285Sdim ConstantInt::get(Type::getInt32Ty(BB->getContext()), 467234285Sdim Ran->Rand() % cast<VectorType>(Val0->getType())->getNumElements()), 468234285Sdim "I", BB->getTerminator()); 469234285Sdim return PT->push_back(V); 470234285Sdim } 471234285Sdim 472234285Sdim}; 473234285Sdim 474234285Sdimstruct CastModifier: public Modifier { 475234285Sdim CastModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 476234285Sdim virtual void Act() { 477234285Sdim 478234285Sdim Value *V = getRandomVal(); 479234285Sdim Type *VTy = V->getType(); 480234285Sdim Type *DestTy = pickScalarType(); 481234285Sdim 482234285Sdim // Handle vector casts vectors. 483234285Sdim if (VTy->isVectorTy()) { 484234285Sdim VectorType *VecTy = cast<VectorType>(VTy); 485234285Sdim DestTy = pickVectorType(VecTy->getNumElements()); 486234285Sdim } 487234285Sdim 488235633Sdim // no need to cast. 489234285Sdim if (VTy == DestTy) return; 490234285Sdim 491234285Sdim // Pointers: 492234285Sdim if (VTy->isPointerTy()) { 493234285Sdim if (!DestTy->isPointerTy()) 494234285Sdim DestTy = PointerType::get(DestTy, 0); 495234285Sdim return PT->push_back( 496234285Sdim new BitCastInst(V, DestTy, "PC", BB->getTerminator())); 497234285Sdim } 498234285Sdim 499235633Sdim unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits(); 500235633Sdim unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits(); 501235633Sdim 502234285Sdim // Generate lots of bitcasts. 503235633Sdim if ((Ran->Rand() & 1) && VSize == DestSize) { 504234285Sdim return PT->push_back( 505234285Sdim new BitCastInst(V, DestTy, "BC", BB->getTerminator())); 506234285Sdim } 507234285Sdim 508234285Sdim // Both types are integers: 509234285Sdim if (VTy->getScalarType()->isIntegerTy() && 510234285Sdim DestTy->getScalarType()->isIntegerTy()) { 511235633Sdim if (VSize > DestSize) { 512234285Sdim return PT->push_back( 513234285Sdim new TruncInst(V, DestTy, "Tr", BB->getTerminator())); 514234285Sdim } else { 515235633Sdim assert(VSize < DestSize && "Different int types with the same size?"); 516234285Sdim if (Ran->Rand() & 1) 517234285Sdim return PT->push_back( 518234285Sdim new ZExtInst(V, DestTy, "ZE", BB->getTerminator())); 519234285Sdim return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator())); 520234285Sdim } 521234285Sdim } 522234285Sdim 523234285Sdim // Fp to int. 524234285Sdim if (VTy->getScalarType()->isFloatingPointTy() && 525234285Sdim DestTy->getScalarType()->isIntegerTy()) { 526234285Sdim if (Ran->Rand() & 1) 527234285Sdim return PT->push_back( 528234285Sdim new FPToSIInst(V, DestTy, "FC", BB->getTerminator())); 529234285Sdim return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator())); 530234285Sdim } 531234285Sdim 532234285Sdim // Int to fp. 533234285Sdim if (VTy->getScalarType()->isIntegerTy() && 534234285Sdim DestTy->getScalarType()->isFloatingPointTy()) { 535234285Sdim if (Ran->Rand() & 1) 536234285Sdim return PT->push_back( 537234285Sdim new SIToFPInst(V, DestTy, "FC", BB->getTerminator())); 538234285Sdim return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator())); 539234285Sdim 540234285Sdim } 541234285Sdim 542234285Sdim // Both floats. 543234285Sdim if (VTy->getScalarType()->isFloatingPointTy() && 544234285Sdim DestTy->getScalarType()->isFloatingPointTy()) { 545235633Sdim if (VSize > DestSize) { 546234285Sdim return PT->push_back( 547234285Sdim new FPTruncInst(V, DestTy, "Tr", BB->getTerminator())); 548235633Sdim } else if (VSize < DestSize) { 549234285Sdim return PT->push_back( 550234285Sdim new FPExtInst(V, DestTy, "ZE", BB->getTerminator())); 551234285Sdim } 552235633Sdim // If VSize == DestSize, then the two types must be fp128 and ppc_fp128, 553235633Sdim // for which there is no defined conversion. So do nothing. 554234285Sdim } 555234285Sdim } 556234285Sdim 557234285Sdim}; 558234285Sdim 559234285Sdimstruct SelectModifier: public Modifier { 560234285Sdim SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R): 561234285Sdim Modifier(BB, PT, R) {} 562234285Sdim 563234285Sdim virtual void Act() { 564234285Sdim // Try a bunch of different select configuration until a valid one is found. 565234285Sdim Value *Val0 = getRandomVal(); 566234285Sdim Value *Val1 = getRandomValue(Val0->getType()); 567234285Sdim 568234285Sdim Type *CondTy = Type::getInt1Ty(Context); 569234285Sdim 570234285Sdim // If the value type is a vector, and we allow vector select, then in 50% 571234285Sdim // of the cases generate a vector select. 572234285Sdim if (Val0->getType()->isVectorTy() && (Ran->Rand() % 1)) { 573234285Sdim unsigned NumElem = cast<VectorType>(Val0->getType())->getNumElements(); 574234285Sdim CondTy = VectorType::get(CondTy, NumElem); 575234285Sdim } 576234285Sdim 577234285Sdim Value *Cond = getRandomValue(CondTy); 578234285Sdim Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator()); 579234285Sdim return PT->push_back(V); 580234285Sdim } 581234285Sdim}; 582234285Sdim 583234285Sdim 584234285Sdimstruct CmpModifier: public Modifier { 585234285Sdim CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R):Modifier(BB, PT, R) {} 586234285Sdim virtual void Act() { 587234285Sdim 588234285Sdim Value *Val0 = getRandomVal(); 589234285Sdim Value *Val1 = getRandomValue(Val0->getType()); 590234285Sdim 591234285Sdim if (Val0->getType()->isPointerTy()) return; 592234285Sdim bool fp = Val0->getType()->getScalarType()->isFloatingPointTy(); 593234285Sdim 594234285Sdim int op; 595234285Sdim if (fp) { 596234285Sdim op = Ran->Rand() % 597234285Sdim (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) + 598234285Sdim CmpInst::FIRST_FCMP_PREDICATE; 599234285Sdim } else { 600234285Sdim op = Ran->Rand() % 601234285Sdim (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) + 602234285Sdim CmpInst::FIRST_ICMP_PREDICATE; 603234285Sdim } 604234285Sdim 605234285Sdim Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp, 606234285Sdim op, Val0, Val1, "Cmp", BB->getTerminator()); 607234285Sdim return PT->push_back(V); 608234285Sdim } 609234285Sdim}; 610234285Sdim 611263509Sdim} // end anonymous namespace 612263509Sdim 613263509Sdimstatic void FillFunction(Function *F, Random &R) { 614234285Sdim // Create a legal entry block. 615234285Sdim BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F); 616234285Sdim ReturnInst::Create(F->getContext(), BB); 617234285Sdim 618234285Sdim // Create the value table. 619234285Sdim Modifier::PieceTable PT; 620234285Sdim 621234285Sdim // Consider arguments as legal values. 622234285Sdim for (Function::arg_iterator it = F->arg_begin(), e = F->arg_end(); 623234285Sdim it != e; ++it) 624234285Sdim PT.push_back(it); 625234285Sdim 626234285Sdim // List of modifiers which add new random instructions. 627234285Sdim std::vector<Modifier*> Modifiers; 628252723Sdim OwningPtr<Modifier> LM(new LoadModifier(BB, &PT, &R)); 629252723Sdim OwningPtr<Modifier> SM(new StoreModifier(BB, &PT, &R)); 630252723Sdim OwningPtr<Modifier> EE(new ExtractElementModifier(BB, &PT, &R)); 631252723Sdim OwningPtr<Modifier> SHM(new ShuffModifier(BB, &PT, &R)); 632252723Sdim OwningPtr<Modifier> IE(new InsertElementModifier(BB, &PT, &R)); 633252723Sdim OwningPtr<Modifier> BM(new BinModifier(BB, &PT, &R)); 634252723Sdim OwningPtr<Modifier> CM(new CastModifier(BB, &PT, &R)); 635252723Sdim OwningPtr<Modifier> SLM(new SelectModifier(BB, &PT, &R)); 636252723Sdim OwningPtr<Modifier> PM(new CmpModifier(BB, &PT, &R)); 637234285Sdim Modifiers.push_back(LM.get()); 638234285Sdim Modifiers.push_back(SM.get()); 639234285Sdim Modifiers.push_back(EE.get()); 640234285Sdim Modifiers.push_back(SHM.get()); 641234285Sdim Modifiers.push_back(IE.get()); 642234285Sdim Modifiers.push_back(BM.get()); 643234285Sdim Modifiers.push_back(CM.get()); 644234285Sdim Modifiers.push_back(SLM.get()); 645234285Sdim Modifiers.push_back(PM.get()); 646234285Sdim 647234285Sdim // Generate the random instructions 648234285Sdim AllocaModifier AM(BB, &PT, &R); AM.ActN(5); // Throw in a few allocas 649234285Sdim ConstModifier COM(BB, &PT, &R); COM.ActN(40); // Throw in a few constants 650234285Sdim 651234285Sdim for (unsigned i=0; i< SizeCL / Modifiers.size(); ++i) 652234285Sdim for (std::vector<Modifier*>::iterator it = Modifiers.begin(), 653234285Sdim e = Modifiers.end(); it != e; ++it) { 654234285Sdim (*it)->Act(); 655234285Sdim } 656234285Sdim 657234285Sdim SM->ActN(5); // Throw in a few stores. 658234285Sdim} 659234285Sdim 660263509Sdimstatic void IntroduceControlFlow(Function *F, Random &R) { 661245431Sdim std::vector<Instruction*> BoolInst; 662234285Sdim for (BasicBlock::iterator it = F->begin()->begin(), 663234285Sdim e = F->begin()->end(); it != e; ++it) { 664234285Sdim if (it->getType() == IntegerType::getInt1Ty(F->getContext())) 665245431Sdim BoolInst.push_back(it); 666234285Sdim } 667234285Sdim 668245431Sdim std::random_shuffle(BoolInst.begin(), BoolInst.end(), R); 669245431Sdim 670245431Sdim for (std::vector<Instruction*>::iterator it = BoolInst.begin(), 671234285Sdim e = BoolInst.end(); it != e; ++it) { 672234285Sdim Instruction *Instr = *it; 673234285Sdim BasicBlock *Curr = Instr->getParent(); 674234285Sdim BasicBlock::iterator Loc= Instr; 675234285Sdim BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF"); 676234285Sdim Instr->moveBefore(Curr->getTerminator()); 677234285Sdim if (Curr != &F->getEntryBlock()) { 678234285Sdim BranchInst::Create(Curr, Next, Instr, Curr->getTerminator()); 679234285Sdim Curr->getTerminator()->eraseFromParent(); 680234285Sdim } 681234285Sdim } 682234285Sdim} 683234285Sdim 684234285Sdimint main(int argc, char **argv) { 685234285Sdim // Init LLVM, call llvm_shutdown() on exit, parse args, etc. 686234285Sdim llvm::PrettyStackTraceProgram X(argc, argv); 687234285Sdim cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n"); 688234285Sdim llvm_shutdown_obj Y; 689234285Sdim 690252723Sdim OwningPtr<Module> M(new Module("/tmp/autogen.bc", getGlobalContext())); 691234285Sdim Function *F = GenEmptyFunction(M.get()); 692234285Sdim 693245431Sdim // Pick an initial seed value 694245431Sdim Random R(SeedCL); 695245431Sdim // Generate lots of random instructions inside a single basic block. 696245431Sdim FillFunction(F, R); 697245431Sdim // Break the basic block into many loops. 698245431Sdim IntroduceControlFlow(F, R); 699245431Sdim 700234285Sdim // Figure out what stream we are supposed to write to... 701234285Sdim OwningPtr<tool_output_file> Out; 702234285Sdim // Default to standard output. 703234285Sdim if (OutputFilename.empty()) 704234285Sdim OutputFilename = "-"; 705234285Sdim 706234285Sdim std::string ErrorInfo; 707234285Sdim Out.reset(new tool_output_file(OutputFilename.c_str(), ErrorInfo, 708263509Sdim sys::fs::F_Binary)); 709234285Sdim if (!ErrorInfo.empty()) { 710234285Sdim errs() << ErrorInfo << '\n'; 711234285Sdim return 1; 712234285Sdim } 713234285Sdim 714234285Sdim PassManager Passes; 715234285Sdim Passes.add(createVerifierPass()); 716234285Sdim Passes.add(createPrintModulePass(&Out->os())); 717234285Sdim Passes.run(*M.get()); 718234285Sdim Out->keep(); 719234285Sdim 720234285Sdim return 0; 721234285Sdim} 722