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