10b57cec5SDimitry Andric //===- llvm-stress.cpp - Generate random LL files to stress-test LLVM -----===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This program is a utility that generates random .ll files to stress-test
100b57cec5SDimitry Andric // different components in LLVM.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric 
140b57cec5SDimitry Andric #include "llvm/ADT/APFloat.h"
150b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
160b57cec5SDimitry Andric #include "llvm/ADT/ArrayRef.h"
170b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
180b57cec5SDimitry Andric #include "llvm/ADT/StringRef.h"
190b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
200b57cec5SDimitry Andric #include "llvm/IR/BasicBlock.h"
210b57cec5SDimitry Andric #include "llvm/IR/CallingConv.h"
220b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
230b57cec5SDimitry Andric #include "llvm/IR/DataLayout.h"
240b57cec5SDimitry Andric #include "llvm/IR/DerivedTypes.h"
250b57cec5SDimitry Andric #include "llvm/IR/Function.h"
260b57cec5SDimitry Andric #include "llvm/IR/GlobalValue.h"
270b57cec5SDimitry Andric #include "llvm/IR/InstrTypes.h"
280b57cec5SDimitry Andric #include "llvm/IR/Instruction.h"
290b57cec5SDimitry Andric #include "llvm/IR/Instructions.h"
300b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
310b57cec5SDimitry Andric #include "llvm/IR/Module.h"
320b57cec5SDimitry Andric #include "llvm/IR/Type.h"
330b57cec5SDimitry Andric #include "llvm/IR/Value.h"
340b57cec5SDimitry Andric #include "llvm/IR/Verifier.h"
350b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
360b57cec5SDimitry Andric #include "llvm/Support/CommandLine.h"
370b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
380b57cec5SDimitry Andric #include "llvm/Support/FileSystem.h"
39e8d8bef9SDimitry Andric #include "llvm/Support/InitLLVM.h"
400b57cec5SDimitry Andric #include "llvm/Support/ToolOutputFile.h"
4104eeddc0SDimitry Andric #include "llvm/Support/WithColor.h"
421fd87a68SDimitry Andric #include "llvm/Support/raw_ostream.h"
430b57cec5SDimitry Andric #include <algorithm>
440b57cec5SDimitry Andric #include <cassert>
450b57cec5SDimitry Andric #include <cstddef>
460b57cec5SDimitry Andric #include <cstdint>
470b57cec5SDimitry Andric #include <memory>
480b57cec5SDimitry Andric #include <string>
490b57cec5SDimitry Andric #include <system_error>
500b57cec5SDimitry Andric #include <vector>
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric namespace llvm {
530b57cec5SDimitry Andric 
54fe6060f1SDimitry Andric static cl::OptionCategory StressCategory("Stress Options");
550b57cec5SDimitry Andric 
56fe6060f1SDimitry Andric static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"),
57fe6060f1SDimitry Andric                                 cl::init(0), cl::cat(StressCategory));
58fe6060f1SDimitry Andric 
59fe6060f1SDimitry Andric static cl::opt<unsigned> SizeCL(
60fe6060f1SDimitry Andric     "size",
610b57cec5SDimitry Andric     cl::desc("The estimated size of the generated function (# of instrs)"),
62fe6060f1SDimitry Andric     cl::init(100), cl::cat(StressCategory));
630b57cec5SDimitry Andric 
64fe6060f1SDimitry Andric static cl::opt<std::string> OutputFilename("o",
65fe6060f1SDimitry Andric                                            cl::desc("Override output filename"),
66fe6060f1SDimitry Andric                                            cl::value_desc("filename"),
67fe6060f1SDimitry Andric                                            cl::cat(StressCategory));
680b57cec5SDimitry Andric 
6981ad6265SDimitry Andric static cl::list<StringRef> AdditionalScalarTypes(
7081ad6265SDimitry Andric     "types", cl::CommaSeparated,
710b57cec5SDimitry Andric     cl::desc("Additional IR scalar types "
720b57cec5SDimitry Andric              "(always includes i1, i8, i16, i32, i64, float and double)"));
730b57cec5SDimitry Andric 
74bdd1243dSDimitry Andric static cl::opt<bool> EnableScalableVectors(
75bdd1243dSDimitry Andric     "enable-scalable-vectors",
76bdd1243dSDimitry Andric     cl::desc("Generate IR involving scalable vector types"),
77bdd1243dSDimitry Andric     cl::init(false), cl::cat(StressCategory));
78bdd1243dSDimitry Andric 
79bdd1243dSDimitry Andric 
800b57cec5SDimitry Andric namespace {
810b57cec5SDimitry Andric 
820b57cec5SDimitry Andric /// A utility class to provide a pseudo-random number generator which is
830b57cec5SDimitry Andric /// the same across all platforms. This is somewhat close to the libc
840b57cec5SDimitry Andric /// implementation. Note: This is not a cryptographically secure pseudorandom
850b57cec5SDimitry Andric /// number generator.
860b57cec5SDimitry Andric class Random {
870b57cec5SDimitry Andric public:
880b57cec5SDimitry Andric   /// C'tor
Random(unsigned _seed)890b57cec5SDimitry Andric   Random(unsigned _seed):Seed(_seed) {}
900b57cec5SDimitry Andric 
910b57cec5SDimitry Andric   /// Return a random integer, up to a
920b57cec5SDimitry Andric   /// maximum of 2**19 - 1.
Rand()930b57cec5SDimitry Andric   uint32_t Rand() {
940b57cec5SDimitry Andric     uint32_t Val = Seed + 0x000b07a1;
950b57cec5SDimitry Andric     Seed = (Val * 0x3c7c0ac1);
960b57cec5SDimitry Andric     // Only lowest 19 bits are random-ish.
970b57cec5SDimitry Andric     return Seed & 0x7ffff;
980b57cec5SDimitry Andric   }
990b57cec5SDimitry Andric 
1000b57cec5SDimitry Andric   /// Return a random 64 bit integer.
Rand64()1010b57cec5SDimitry Andric   uint64_t Rand64() {
1020b57cec5SDimitry Andric     uint64_t Val = Rand() & 0xffff;
1030b57cec5SDimitry Andric     Val |= uint64_t(Rand() & 0xffff) << 16;
1040b57cec5SDimitry Andric     Val |= uint64_t(Rand() & 0xffff) << 32;
1050b57cec5SDimitry Andric     Val |= uint64_t(Rand() & 0xffff) << 48;
1060b57cec5SDimitry Andric     return Val;
1070b57cec5SDimitry Andric   }
1080b57cec5SDimitry Andric 
1090b57cec5SDimitry Andric   /// Rand operator for STL algorithms.
operator ()(ptrdiff_t y)1100b57cec5SDimitry Andric   ptrdiff_t operator()(ptrdiff_t y) {
1110b57cec5SDimitry Andric     return  Rand64() % y;
1120b57cec5SDimitry Andric   }
1130b57cec5SDimitry Andric 
1140b57cec5SDimitry Andric   /// Make this like a C++11 random device
1150b57cec5SDimitry Andric   using result_type = uint32_t ;
1160b57cec5SDimitry Andric 
min()1170b57cec5SDimitry Andric   static constexpr result_type min() { return 0; }
max()1180b57cec5SDimitry Andric   static constexpr result_type max() { return 0x7ffff; }
1190b57cec5SDimitry Andric 
operator ()()1200b57cec5SDimitry Andric   uint32_t operator()() {
1210b57cec5SDimitry Andric     uint32_t Val = Rand();
1220b57cec5SDimitry Andric     assert(Val <= max() && "Random value out of range");
1230b57cec5SDimitry Andric     return Val;
1240b57cec5SDimitry Andric   }
1250b57cec5SDimitry Andric 
1260b57cec5SDimitry Andric private:
1270b57cec5SDimitry Andric   unsigned Seed;
1280b57cec5SDimitry Andric };
1290b57cec5SDimitry Andric 
1300b57cec5SDimitry Andric /// Generate an empty function with a default argument list.
GenEmptyFunction(Module * M)1310b57cec5SDimitry Andric Function *GenEmptyFunction(Module *M) {
1320b57cec5SDimitry Andric   // Define a few arguments
1330b57cec5SDimitry Andric   LLVMContext &Context = M->getContext();
1340b57cec5SDimitry Andric   Type* ArgsTy[] = {
1355f757f3fSDimitry Andric     PointerType::get(Context, 0),
1365f757f3fSDimitry Andric     PointerType::get(Context, 0),
1375f757f3fSDimitry Andric     PointerType::get(Context, 0),
1380b57cec5SDimitry Andric     Type::getInt32Ty(Context),
1390b57cec5SDimitry Andric     Type::getInt64Ty(Context),
1400b57cec5SDimitry Andric     Type::getInt8Ty(Context)
1410b57cec5SDimitry Andric   };
1420b57cec5SDimitry Andric 
1430b57cec5SDimitry Andric   auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false);
1440b57cec5SDimitry Andric   // Pick a unique name to describe the input parameters
1450b57cec5SDimitry Andric   Twine Name = "autogen_SD" + Twine{SeedCL};
1460b57cec5SDimitry Andric   auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M);
1470b57cec5SDimitry Andric   Func->setCallingConv(CallingConv::C);
1480b57cec5SDimitry Andric   return Func;
1490b57cec5SDimitry Andric }
1500b57cec5SDimitry Andric 
1510b57cec5SDimitry Andric /// A base class, implementing utilities needed for
1520b57cec5SDimitry Andric /// modifying and adding new random instructions.
1530b57cec5SDimitry Andric struct Modifier {
1540b57cec5SDimitry Andric   /// Used to store the randomly generated values.
1550b57cec5SDimitry Andric   using PieceTable = std::vector<Value *>;
1560b57cec5SDimitry Andric 
1570b57cec5SDimitry Andric public:
1580b57cec5SDimitry Andric   /// C'tor
Modifierllvm::__anon31e928f90111::Modifier1590b57cec5SDimitry Andric   Modifier(BasicBlock *Block, PieceTable *PT, Random *R)
16081ad6265SDimitry Andric       : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {
16181ad6265SDimitry Andric     ScalarTypes.assign({Type::getInt1Ty(Context), Type::getInt8Ty(Context),
16281ad6265SDimitry Andric                         Type::getInt16Ty(Context), Type::getInt32Ty(Context),
16381ad6265SDimitry Andric                         Type::getInt64Ty(Context), Type::getFloatTy(Context),
16481ad6265SDimitry Andric                         Type::getDoubleTy(Context)});
16581ad6265SDimitry Andric 
16681ad6265SDimitry Andric     for (auto &Arg : AdditionalScalarTypes) {
16781ad6265SDimitry Andric       Type *Ty = nullptr;
16881ad6265SDimitry Andric       if (Arg == "half")
16981ad6265SDimitry Andric         Ty = Type::getHalfTy(Context);
17081ad6265SDimitry Andric       else if (Arg == "fp128")
17181ad6265SDimitry Andric         Ty = Type::getFP128Ty(Context);
17281ad6265SDimitry Andric       else if (Arg == "x86_fp80")
17381ad6265SDimitry Andric         Ty = Type::getX86_FP80Ty(Context);
17481ad6265SDimitry Andric       else if (Arg == "ppc_fp128")
17581ad6265SDimitry Andric         Ty = Type::getPPC_FP128Ty(Context);
17681ad6265SDimitry Andric       else if (Arg == "x86_mmx")
17781ad6265SDimitry Andric         Ty = Type::getX86_MMXTy(Context);
1785f757f3fSDimitry Andric       else if (Arg.starts_with("i")) {
17981ad6265SDimitry Andric         unsigned N = 0;
18081ad6265SDimitry Andric         Arg.drop_front().getAsInteger(10, N);
18181ad6265SDimitry Andric         if (N > 0)
18281ad6265SDimitry Andric           Ty = Type::getIntNTy(Context, N);
18381ad6265SDimitry Andric       }
18481ad6265SDimitry Andric       if (!Ty) {
18581ad6265SDimitry Andric         errs() << "Invalid IR scalar type: '" << Arg << "'!\n";
18681ad6265SDimitry Andric         exit(1);
18781ad6265SDimitry Andric       }
18881ad6265SDimitry Andric 
18981ad6265SDimitry Andric       ScalarTypes.push_back(Ty);
19081ad6265SDimitry Andric     }
19181ad6265SDimitry Andric   }
1920b57cec5SDimitry Andric 
1930b57cec5SDimitry Andric   /// virtual D'tor to silence warnings.
1940b57cec5SDimitry Andric   virtual ~Modifier() = default;
1950b57cec5SDimitry Andric 
1960b57cec5SDimitry Andric   /// Add a new instruction.
1970b57cec5SDimitry Andric   virtual void Act() = 0;
1980b57cec5SDimitry Andric 
1990b57cec5SDimitry Andric   /// Add N new instructions,
ActNllvm::__anon31e928f90111::Modifier2000b57cec5SDimitry Andric   virtual void ActN(unsigned n) {
2010b57cec5SDimitry Andric     for (unsigned i=0; i<n; ++i)
2020b57cec5SDimitry Andric       Act();
2030b57cec5SDimitry Andric   }
2040b57cec5SDimitry Andric 
2050b57cec5SDimitry Andric protected:
2060b57cec5SDimitry Andric   /// Return a random integer.
getRandomllvm::__anon31e928f90111::Modifier2070b57cec5SDimitry Andric   uint32_t getRandom() {
2080b57cec5SDimitry Andric     return Ran->Rand();
2090b57cec5SDimitry Andric   }
2100b57cec5SDimitry Andric 
2110b57cec5SDimitry Andric   /// Return a random value from the list of known values.
getRandomValllvm::__anon31e928f90111::Modifier2120b57cec5SDimitry Andric   Value *getRandomVal() {
2130b57cec5SDimitry Andric     assert(PT->size());
2140b57cec5SDimitry Andric     return PT->at(getRandom() % PT->size());
2150b57cec5SDimitry Andric   }
2160b57cec5SDimitry Andric 
getRandomConstantllvm::__anon31e928f90111::Modifier2170b57cec5SDimitry Andric   Constant *getRandomConstant(Type *Tp) {
2180b57cec5SDimitry Andric     if (Tp->isIntegerTy()) {
2190b57cec5SDimitry Andric       if (getRandom() & 1)
2200b57cec5SDimitry Andric         return ConstantInt::getAllOnesValue(Tp);
2210b57cec5SDimitry Andric       return ConstantInt::getNullValue(Tp);
2220b57cec5SDimitry Andric     } else if (Tp->isFloatingPointTy()) {
2230b57cec5SDimitry Andric       if (getRandom() & 1)
2240b57cec5SDimitry Andric         return ConstantFP::getAllOnesValue(Tp);
22506c3fb27SDimitry Andric       return ConstantFP::getZero(Tp);
2260b57cec5SDimitry Andric     }
2270b57cec5SDimitry Andric     return UndefValue::get(Tp);
2280b57cec5SDimitry Andric   }
2290b57cec5SDimitry Andric 
2300b57cec5SDimitry Andric   /// Return a random value with a known type.
getRandomValuellvm::__anon31e928f90111::Modifier2310b57cec5SDimitry Andric   Value *getRandomValue(Type *Tp) {
2320b57cec5SDimitry Andric     unsigned index = getRandom();
2330b57cec5SDimitry Andric     for (unsigned i=0; i<PT->size(); ++i) {
2340b57cec5SDimitry Andric       Value *V = PT->at((index + i) % PT->size());
2350b57cec5SDimitry Andric       if (V->getType() == Tp)
2360b57cec5SDimitry Andric         return V;
2370b57cec5SDimitry Andric     }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric     // If the requested type was not found, generate a constant value.
2400b57cec5SDimitry Andric     if (Tp->isIntegerTy()) {
2410b57cec5SDimitry Andric       if (getRandom() & 1)
2420b57cec5SDimitry Andric         return ConstantInt::getAllOnesValue(Tp);
2430b57cec5SDimitry Andric       return ConstantInt::getNullValue(Tp);
2440b57cec5SDimitry Andric     } else if (Tp->isFloatingPointTy()) {
2450b57cec5SDimitry Andric       if (getRandom() & 1)
2460b57cec5SDimitry Andric         return ConstantFP::getAllOnesValue(Tp);
24706c3fb27SDimitry Andric       return ConstantFP::getZero(Tp);
248bdd1243dSDimitry Andric     } else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) {
2490b57cec5SDimitry Andric       std::vector<Constant*> TempValues;
2500b57cec5SDimitry Andric       TempValues.reserve(VTp->getNumElements());
2510b57cec5SDimitry Andric       for (unsigned i = 0; i < VTp->getNumElements(); ++i)
2520b57cec5SDimitry Andric         TempValues.push_back(getRandomConstant(VTp->getScalarType()));
2530b57cec5SDimitry Andric 
2540b57cec5SDimitry Andric       ArrayRef<Constant*> VectorValue(TempValues);
2550b57cec5SDimitry Andric       return ConstantVector::get(VectorValue);
2560b57cec5SDimitry Andric     }
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric     return UndefValue::get(Tp);
2590b57cec5SDimitry Andric   }
2600b57cec5SDimitry Andric 
2610b57cec5SDimitry Andric   /// Return a random value of any pointer type.
getRandomPointerValuellvm::__anon31e928f90111::Modifier2620b57cec5SDimitry Andric   Value *getRandomPointerValue() {
2630b57cec5SDimitry Andric     unsigned index = getRandom();
2640b57cec5SDimitry Andric     for (unsigned i=0; i<PT->size(); ++i) {
2650b57cec5SDimitry Andric       Value *V = PT->at((index + i) % PT->size());
2660b57cec5SDimitry Andric       if (V->getType()->isPointerTy())
2670b57cec5SDimitry Andric         return V;
2680b57cec5SDimitry Andric     }
2690b57cec5SDimitry Andric     return UndefValue::get(pickPointerType());
2700b57cec5SDimitry Andric   }
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric   /// Return a random value of any vector type.
getRandomVectorValuellvm::__anon31e928f90111::Modifier2730b57cec5SDimitry Andric   Value *getRandomVectorValue() {
2740b57cec5SDimitry Andric     unsigned index = getRandom();
2750b57cec5SDimitry Andric     for (unsigned i=0; i<PT->size(); ++i) {
2760b57cec5SDimitry Andric       Value *V = PT->at((index + i) % PT->size());
2770b57cec5SDimitry Andric       if (V->getType()->isVectorTy())
2780b57cec5SDimitry Andric         return V;
2790b57cec5SDimitry Andric     }
2800b57cec5SDimitry Andric     return UndefValue::get(pickVectorType());
2810b57cec5SDimitry Andric   }
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   /// Pick a random type.
pickTypellvm::__anon31e928f90111::Modifier2840b57cec5SDimitry Andric   Type *pickType() {
2850b57cec5SDimitry Andric     return (getRandom() & 1) ? pickVectorType() : pickScalarType();
2860b57cec5SDimitry Andric   }
2870b57cec5SDimitry Andric 
2880b57cec5SDimitry Andric   /// Pick a random pointer type.
pickPointerTypellvm::__anon31e928f90111::Modifier2890b57cec5SDimitry Andric   Type *pickPointerType() {
2900b57cec5SDimitry Andric     Type *Ty = pickType();
2910b57cec5SDimitry Andric     return PointerType::get(Ty, 0);
2920b57cec5SDimitry Andric   }
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   /// Pick a random vector type.
pickVectorTypellvm::__anon31e928f90111::Modifier295bdd1243dSDimitry Andric   Type *pickVectorType(VectorType *VTy = nullptr) {
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric     // Vectors of x86mmx are illegal; keep trying till we get something else.
298bdd1243dSDimitry Andric     Type *Ty;
2990b57cec5SDimitry Andric     do {
3000b57cec5SDimitry Andric       Ty = pickScalarType();
3010b57cec5SDimitry Andric     } while (Ty->isX86_MMXTy());
3020b57cec5SDimitry Andric 
303bdd1243dSDimitry Andric     if (VTy)
304bdd1243dSDimitry Andric       return VectorType::get(Ty, VTy->getElementCount());
305bdd1243dSDimitry Andric 
306bdd1243dSDimitry Andric     // Select either fixed length or scalable vectors with 50% probability
307bdd1243dSDimitry Andric     // (only if scalable vectors are enabled)
308bdd1243dSDimitry Andric     bool Scalable = EnableScalableVectors && getRandom() & 1;
309bdd1243dSDimitry Andric 
310bdd1243dSDimitry Andric     // Pick a random vector width in the range 2**0 to 2**4.
311bdd1243dSDimitry Andric     // by adding two randoms we are generating a normal-like distribution
312bdd1243dSDimitry Andric     // around 2**3.
313bdd1243dSDimitry Andric     unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));
314bdd1243dSDimitry Andric     return VectorType::get(Ty, width, Scalable);
3150b57cec5SDimitry Andric   }
3160b57cec5SDimitry Andric 
3170b57cec5SDimitry Andric   /// Pick a random scalar type.
pickScalarTypellvm::__anon31e928f90111::Modifier3180b57cec5SDimitry Andric   Type *pickScalarType() {
3190b57cec5SDimitry Andric     return ScalarTypes[getRandom() % ScalarTypes.size()];
3200b57cec5SDimitry Andric   }
3210b57cec5SDimitry Andric 
3220b57cec5SDimitry Andric   /// Basic block to populate
3230b57cec5SDimitry Andric   BasicBlock *BB;
3240b57cec5SDimitry Andric 
3250b57cec5SDimitry Andric   /// Value table
3260b57cec5SDimitry Andric   PieceTable *PT;
3270b57cec5SDimitry Andric 
3280b57cec5SDimitry Andric   /// Random number generator
3290b57cec5SDimitry Andric   Random *Ran;
3300b57cec5SDimitry Andric 
3310b57cec5SDimitry Andric   /// Context
3320b57cec5SDimitry Andric   LLVMContext &Context;
33381ad6265SDimitry Andric 
33481ad6265SDimitry Andric   std::vector<Type *> ScalarTypes;
3350b57cec5SDimitry Andric };
3360b57cec5SDimitry Andric 
3370b57cec5SDimitry Andric struct LoadModifier: public Modifier {
LoadModifierllvm::__anon31e928f90111::LoadModifier3380b57cec5SDimitry Andric   LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R)
3390b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
3400b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::LoadModifier3410b57cec5SDimitry Andric   void Act() override {
3420b57cec5SDimitry Andric     // Try to use predefined pointers. If non-exist, use undef pointer value;
3430b57cec5SDimitry Andric     Value *Ptr = getRandomPointerValue();
34406c3fb27SDimitry Andric     Type *Ty = pickType();
34581ad6265SDimitry Andric     Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator());
3460b57cec5SDimitry Andric     PT->push_back(V);
3470b57cec5SDimitry Andric   }
3480b57cec5SDimitry Andric };
3490b57cec5SDimitry Andric 
3500b57cec5SDimitry Andric struct StoreModifier: public Modifier {
StoreModifierllvm::__anon31e928f90111::StoreModifier3510b57cec5SDimitry Andric   StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R)
3520b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
3530b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::StoreModifier3540b57cec5SDimitry Andric   void Act() override {
3550b57cec5SDimitry Andric     // Try to use predefined pointers. If non-exist, use undef pointer value;
3560b57cec5SDimitry Andric     Value *Ptr = getRandomPointerValue();
35706c3fb27SDimitry Andric     Type *ValTy = pickType();
3580b57cec5SDimitry Andric 
3590b57cec5SDimitry Andric     // Do not store vectors of i1s because they are unsupported
3600b57cec5SDimitry Andric     // by the codegen.
3610b57cec5SDimitry Andric     if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1)
3620b57cec5SDimitry Andric       return;
3630b57cec5SDimitry Andric 
36481ad6265SDimitry Andric     Value *Val = getRandomValue(ValTy);
3650b57cec5SDimitry Andric     new StoreInst(Val, Ptr, BB->getTerminator());
3660b57cec5SDimitry Andric   }
3670b57cec5SDimitry Andric };
3680b57cec5SDimitry Andric 
3690b57cec5SDimitry Andric struct BinModifier: public Modifier {
BinModifierllvm::__anon31e928f90111::BinModifier3700b57cec5SDimitry Andric   BinModifier(BasicBlock *BB, PieceTable *PT, Random *R)
3710b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
3720b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::BinModifier3730b57cec5SDimitry Andric   void Act() override {
3740b57cec5SDimitry Andric     Value *Val0 = getRandomVal();
3750b57cec5SDimitry Andric     Value *Val1 = getRandomValue(Val0->getType());
3760b57cec5SDimitry Andric 
3770b57cec5SDimitry Andric     // Don't handle pointer types.
3780b57cec5SDimitry Andric     if (Val0->getType()->isPointerTy() ||
3790b57cec5SDimitry Andric         Val1->getType()->isPointerTy())
3800b57cec5SDimitry Andric       return;
3810b57cec5SDimitry Andric 
3820b57cec5SDimitry Andric     // Don't handle i1 types.
3830b57cec5SDimitry Andric     if (Val0->getType()->getScalarSizeInBits() == 1)
3840b57cec5SDimitry Andric       return;
3850b57cec5SDimitry Andric 
3860b57cec5SDimitry Andric     bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy();
3870b57cec5SDimitry Andric     Instruction* Term = BB->getTerminator();
3880b57cec5SDimitry Andric     unsigned R = getRandom() % (isFloat ? 7 : 13);
3890b57cec5SDimitry Andric     Instruction::BinaryOps Op;
3900b57cec5SDimitry Andric 
3910b57cec5SDimitry Andric     switch (R) {
3920b57cec5SDimitry Andric     default: llvm_unreachable("Invalid BinOp");
3930b57cec5SDimitry Andric     case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; }
3940b57cec5SDimitry Andric     case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; }
3950b57cec5SDimitry Andric     case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; }
3960b57cec5SDimitry Andric     case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; }
3970b57cec5SDimitry Andric     case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; }
3980b57cec5SDimitry Andric     case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; }
3990b57cec5SDimitry Andric     case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; }
4000b57cec5SDimitry Andric     case 7: {Op = Instruction::Shl;  break; }
4010b57cec5SDimitry Andric     case 8: {Op = Instruction::LShr; break; }
4020b57cec5SDimitry Andric     case 9: {Op = Instruction::AShr; break; }
4030b57cec5SDimitry Andric     case 10:{Op = Instruction::And;  break; }
4040b57cec5SDimitry Andric     case 11:{Op = Instruction::Or;   break; }
4050b57cec5SDimitry Andric     case 12:{Op = Instruction::Xor;  break; }
4060b57cec5SDimitry Andric     }
4070b57cec5SDimitry Andric 
4080b57cec5SDimitry Andric     PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term));
4090b57cec5SDimitry Andric   }
4100b57cec5SDimitry Andric };
4110b57cec5SDimitry Andric 
4120b57cec5SDimitry Andric /// Generate constant values.
4130b57cec5SDimitry Andric struct ConstModifier: public Modifier {
ConstModifierllvm::__anon31e928f90111::ConstModifier4140b57cec5SDimitry Andric   ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R)
4150b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
4160b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::ConstModifier4170b57cec5SDimitry Andric   void Act() override {
4180b57cec5SDimitry Andric     Type *Ty = pickType();
4190b57cec5SDimitry Andric 
4200b57cec5SDimitry Andric     if (Ty->isVectorTy()) {
4210b57cec5SDimitry Andric       switch (getRandom() % 2) {
4220b57cec5SDimitry Andric       case 0: if (Ty->isIntOrIntVectorTy())
4230b57cec5SDimitry Andric                 return PT->push_back(ConstantVector::getAllOnesValue(Ty));
4240b57cec5SDimitry Andric               break;
4250b57cec5SDimitry Andric       case 1: if (Ty->isIntOrIntVectorTy())
4260b57cec5SDimitry Andric                 return PT->push_back(ConstantVector::getNullValue(Ty));
4270b57cec5SDimitry Andric       }
4280b57cec5SDimitry Andric     }
4290b57cec5SDimitry Andric 
4300b57cec5SDimitry Andric     if (Ty->isFloatingPointTy()) {
4310b57cec5SDimitry Andric       // Generate 128 random bits, the size of the (currently)
4320b57cec5SDimitry Andric       // largest floating-point types.
4330b57cec5SDimitry Andric       uint64_t RandomBits[2];
4340b57cec5SDimitry Andric       for (unsigned i = 0; i < 2; ++i)
4350b57cec5SDimitry Andric         RandomBits[i] = Ran->Rand64();
4360b57cec5SDimitry Andric 
437bdd1243dSDimitry Andric       APInt RandomInt(Ty->getPrimitiveSizeInBits(), ArrayRef(RandomBits));
4380b57cec5SDimitry Andric       APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
4390b57cec5SDimitry Andric 
4400b57cec5SDimitry Andric       if (getRandom() & 1)
44106c3fb27SDimitry Andric         return PT->push_back(ConstantFP::getZero(Ty));
4420b57cec5SDimitry Andric       return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));
4430b57cec5SDimitry Andric     }
4440b57cec5SDimitry Andric 
4450b57cec5SDimitry Andric     if (Ty->isIntegerTy()) {
4460b57cec5SDimitry Andric       switch (getRandom() % 7) {
4470b57cec5SDimitry Andric       case 0:
4480b57cec5SDimitry Andric         return PT->push_back(ConstantInt::get(
449349cc55cSDimitry Andric             Ty, APInt::getAllOnes(Ty->getPrimitiveSizeInBits())));
4500b57cec5SDimitry Andric       case 1:
451349cc55cSDimitry Andric         return PT->push_back(
452349cc55cSDimitry Andric             ConstantInt::get(Ty, APInt::getZero(Ty->getPrimitiveSizeInBits())));
4530b57cec5SDimitry Andric       case 2:
4540b57cec5SDimitry Andric       case 3:
4550b57cec5SDimitry Andric       case 4:
4560b57cec5SDimitry Andric       case 5:
4570b57cec5SDimitry Andric       case 6:
4580b57cec5SDimitry Andric         PT->push_back(ConstantInt::get(Ty, getRandom()));
4590b57cec5SDimitry Andric       }
4600b57cec5SDimitry Andric     }
4610b57cec5SDimitry Andric   }
4620b57cec5SDimitry Andric };
4630b57cec5SDimitry Andric 
4640b57cec5SDimitry Andric struct AllocaModifier: public Modifier {
AllocaModifierllvm::__anon31e928f90111::AllocaModifier4650b57cec5SDimitry Andric   AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R)
4660b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
4670b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::AllocaModifier4680b57cec5SDimitry Andric   void Act() override {
4690b57cec5SDimitry Andric     Type *Tp = pickType();
4700b57cec5SDimitry Andric     const DataLayout &DL = BB->getModule()->getDataLayout();
4710b57cec5SDimitry Andric     PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(),
4720b57cec5SDimitry Andric                                  "A", BB->getFirstNonPHI()));
4730b57cec5SDimitry Andric   }
4740b57cec5SDimitry Andric };
4750b57cec5SDimitry Andric 
4760b57cec5SDimitry Andric struct ExtractElementModifier: public Modifier {
ExtractElementModifierllvm::__anon31e928f90111::ExtractElementModifier4770b57cec5SDimitry Andric   ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
4780b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
4790b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::ExtractElementModifier4800b57cec5SDimitry Andric   void Act() override {
4810b57cec5SDimitry Andric     Value *Val0 = getRandomVectorValue();
482e8d8bef9SDimitry Andric     Value *V = ExtractElementInst::Create(
483e8d8bef9SDimitry Andric         Val0,
484bdd1243dSDimitry Andric         getRandomValue(Type::getInt32Ty(BB->getContext())),
4850b57cec5SDimitry Andric         "E", BB->getTerminator());
4860b57cec5SDimitry Andric     return PT->push_back(V);
4870b57cec5SDimitry Andric   }
4880b57cec5SDimitry Andric };
4890b57cec5SDimitry Andric 
4900b57cec5SDimitry Andric struct ShuffModifier: public Modifier {
ShuffModifierllvm::__anon31e928f90111::ShuffModifier4910b57cec5SDimitry Andric   ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R)
4920b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
4930b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::ShuffModifier4940b57cec5SDimitry Andric   void Act() override {
4950b57cec5SDimitry Andric     Value *Val0 = getRandomVectorValue();
4960b57cec5SDimitry Andric     Value *Val1 = getRandomValue(Val0->getType());
4970b57cec5SDimitry Andric 
498bdd1243dSDimitry Andric     // Can't express arbitrary shufflevectors for scalable vectors
499bdd1243dSDimitry Andric     if (isa<ScalableVectorType>(Val0->getType()))
500bdd1243dSDimitry Andric       return;
501bdd1243dSDimitry Andric 
502e8d8bef9SDimitry Andric     unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements();
5030b57cec5SDimitry Andric     std::vector<Constant*> Idxs;
5040b57cec5SDimitry Andric 
5050b57cec5SDimitry Andric     Type *I32 = Type::getInt32Ty(BB->getContext());
5060b57cec5SDimitry Andric     for (unsigned i=0; i<Width; ++i) {
5070b57cec5SDimitry Andric       Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2));
5080b57cec5SDimitry Andric       // Pick some undef values.
5090b57cec5SDimitry Andric       if (!(getRandom() % 5))
5100b57cec5SDimitry Andric         CI = UndefValue::get(I32);
5110b57cec5SDimitry Andric       Idxs.push_back(CI);
5120b57cec5SDimitry Andric     }
5130b57cec5SDimitry Andric 
5140b57cec5SDimitry Andric     Constant *Mask = ConstantVector::get(Idxs);
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric     Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff",
5170b57cec5SDimitry Andric                                      BB->getTerminator());
5180b57cec5SDimitry Andric     PT->push_back(V);
5190b57cec5SDimitry Andric   }
5200b57cec5SDimitry Andric };
5210b57cec5SDimitry Andric 
5220b57cec5SDimitry Andric struct InsertElementModifier: public Modifier {
InsertElementModifierllvm::__anon31e928f90111::InsertElementModifier5230b57cec5SDimitry Andric   InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
5240b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
5250b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::InsertElementModifier5260b57cec5SDimitry Andric   void Act() override {
5270b57cec5SDimitry Andric     Value *Val0 = getRandomVectorValue();
5280b57cec5SDimitry Andric     Value *Val1 = getRandomValue(Val0->getType()->getScalarType());
5290b57cec5SDimitry Andric 
530e8d8bef9SDimitry Andric     Value *V = InsertElementInst::Create(
531e8d8bef9SDimitry Andric         Val0, Val1,
532bdd1243dSDimitry Andric         getRandomValue(Type::getInt32Ty(BB->getContext())),
5330b57cec5SDimitry Andric         "I", BB->getTerminator());
5340b57cec5SDimitry Andric     return PT->push_back(V);
5350b57cec5SDimitry Andric   }
5360b57cec5SDimitry Andric };
5370b57cec5SDimitry Andric 
5380b57cec5SDimitry Andric struct CastModifier: public Modifier {
CastModifierllvm::__anon31e928f90111::CastModifier5390b57cec5SDimitry Andric   CastModifier(BasicBlock *BB, PieceTable *PT, Random *R)
5400b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
5410b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::CastModifier5420b57cec5SDimitry Andric   void Act() override {
5430b57cec5SDimitry Andric     Value *V = getRandomVal();
5440b57cec5SDimitry Andric     Type *VTy = V->getType();
5450b57cec5SDimitry Andric     Type *DestTy = pickScalarType();
5460b57cec5SDimitry Andric 
5470b57cec5SDimitry Andric     // Handle vector casts vectors.
548bdd1243dSDimitry Andric     if (VTy->isVectorTy())
549bdd1243dSDimitry Andric       DestTy = pickVectorType(cast<VectorType>(VTy));
5500b57cec5SDimitry Andric 
5510b57cec5SDimitry Andric     // no need to cast.
5520b57cec5SDimitry Andric     if (VTy == DestTy) return;
5530b57cec5SDimitry Andric 
5540b57cec5SDimitry Andric     // Pointers:
5550b57cec5SDimitry Andric     if (VTy->isPointerTy()) {
5560b57cec5SDimitry Andric       if (!DestTy->isPointerTy())
5570b57cec5SDimitry Andric         DestTy = PointerType::get(DestTy, 0);
5580b57cec5SDimitry Andric       return PT->push_back(
5590b57cec5SDimitry Andric         new BitCastInst(V, DestTy, "PC", BB->getTerminator()));
5600b57cec5SDimitry Andric     }
5610b57cec5SDimitry Andric 
5620b57cec5SDimitry Andric     unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits();
5630b57cec5SDimitry Andric     unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits();
5640b57cec5SDimitry Andric 
5650b57cec5SDimitry Andric     // Generate lots of bitcasts.
5660b57cec5SDimitry Andric     if ((getRandom() & 1) && VSize == DestSize) {
5670b57cec5SDimitry Andric       return PT->push_back(
5680b57cec5SDimitry Andric         new BitCastInst(V, DestTy, "BC", BB->getTerminator()));
5690b57cec5SDimitry Andric     }
5700b57cec5SDimitry Andric 
5710b57cec5SDimitry Andric     // Both types are integers:
5720b57cec5SDimitry Andric     if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) {
5730b57cec5SDimitry Andric       if (VSize > DestSize) {
5740b57cec5SDimitry Andric         return PT->push_back(
5750b57cec5SDimitry Andric           new TruncInst(V, DestTy, "Tr", BB->getTerminator()));
5760b57cec5SDimitry Andric       } else {
5770b57cec5SDimitry Andric         assert(VSize < DestSize && "Different int types with the same size?");
5780b57cec5SDimitry Andric         if (getRandom() & 1)
5790b57cec5SDimitry Andric           return PT->push_back(
5800b57cec5SDimitry Andric             new ZExtInst(V, DestTy, "ZE", BB->getTerminator()));
5810b57cec5SDimitry Andric         return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator()));
5820b57cec5SDimitry Andric       }
5830b57cec5SDimitry Andric     }
5840b57cec5SDimitry Andric 
5850b57cec5SDimitry Andric     // Fp to int.
5860b57cec5SDimitry Andric     if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) {
5870b57cec5SDimitry Andric       if (getRandom() & 1)
5880b57cec5SDimitry Andric         return PT->push_back(
5890b57cec5SDimitry Andric           new FPToSIInst(V, DestTy, "FC", BB->getTerminator()));
5900b57cec5SDimitry Andric       return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator()));
5910b57cec5SDimitry Andric     }
5920b57cec5SDimitry Andric 
5930b57cec5SDimitry Andric     // Int to fp.
5940b57cec5SDimitry Andric     if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) {
5950b57cec5SDimitry Andric       if (getRandom() & 1)
5960b57cec5SDimitry Andric         return PT->push_back(
5970b57cec5SDimitry Andric           new SIToFPInst(V, DestTy, "FC", BB->getTerminator()));
5980b57cec5SDimitry Andric       return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator()));
5990b57cec5SDimitry Andric     }
6000b57cec5SDimitry Andric 
6010b57cec5SDimitry Andric     // Both floats.
6020b57cec5SDimitry Andric     if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) {
6030b57cec5SDimitry Andric       if (VSize > DestSize) {
6040b57cec5SDimitry Andric         return PT->push_back(
6050b57cec5SDimitry Andric           new FPTruncInst(V, DestTy, "Tr", BB->getTerminator()));
6060b57cec5SDimitry Andric       } else if (VSize < DestSize) {
6070b57cec5SDimitry Andric         return PT->push_back(
6080b57cec5SDimitry Andric           new FPExtInst(V, DestTy, "ZE", BB->getTerminator()));
6090b57cec5SDimitry Andric       }
6100b57cec5SDimitry Andric       // If VSize == DestSize, then the two types must be fp128 and ppc_fp128,
6110b57cec5SDimitry Andric       // for which there is no defined conversion. So do nothing.
6120b57cec5SDimitry Andric     }
6130b57cec5SDimitry Andric   }
6140b57cec5SDimitry Andric };
6150b57cec5SDimitry Andric 
6160b57cec5SDimitry Andric struct SelectModifier: public Modifier {
SelectModifierllvm::__anon31e928f90111::SelectModifier6170b57cec5SDimitry Andric   SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R)
6180b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
6190b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::SelectModifier6200b57cec5SDimitry Andric   void Act() override {
6210b57cec5SDimitry Andric     // Try a bunch of different select configuration until a valid one is found.
6220b57cec5SDimitry Andric     Value *Val0 = getRandomVal();
6230b57cec5SDimitry Andric     Value *Val1 = getRandomValue(Val0->getType());
6240b57cec5SDimitry Andric 
6250b57cec5SDimitry Andric     Type *CondTy = Type::getInt1Ty(Context);
6260b57cec5SDimitry Andric 
6270b57cec5SDimitry Andric     // If the value type is a vector, and we allow vector select, then in 50%
6280b57cec5SDimitry Andric     // of the cases generate a vector select.
629bdd1243dSDimitry Andric     if (auto *VTy = dyn_cast<VectorType>(Val0->getType()))
630bdd1243dSDimitry Andric       if (getRandom() & 1)
631bdd1243dSDimitry Andric         CondTy = VectorType::get(CondTy, VTy->getElementCount());
6320b57cec5SDimitry Andric 
6330b57cec5SDimitry Andric     Value *Cond = getRandomValue(CondTy);
6340b57cec5SDimitry Andric     Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator());
6350b57cec5SDimitry Andric     return PT->push_back(V);
6360b57cec5SDimitry Andric   }
6370b57cec5SDimitry Andric };
6380b57cec5SDimitry Andric 
6390b57cec5SDimitry Andric struct CmpModifier: public Modifier {
CmpModifierllvm::__anon31e928f90111::CmpModifier6400b57cec5SDimitry Andric   CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R)
6410b57cec5SDimitry Andric       : Modifier(BB, PT, R) {}
6420b57cec5SDimitry Andric 
Actllvm::__anon31e928f90111::CmpModifier6430b57cec5SDimitry Andric   void Act() override {
6440b57cec5SDimitry Andric     Value *Val0 = getRandomVal();
6450b57cec5SDimitry Andric     Value *Val1 = getRandomValue(Val0->getType());
6460b57cec5SDimitry Andric 
6470b57cec5SDimitry Andric     if (Val0->getType()->isPointerTy()) return;
6480b57cec5SDimitry Andric     bool fp = Val0->getType()->getScalarType()->isFloatingPointTy();
6490b57cec5SDimitry Andric 
6500b57cec5SDimitry Andric     int op;
6510b57cec5SDimitry Andric     if (fp) {
6520b57cec5SDimitry Andric       op = getRandom() %
6530b57cec5SDimitry Andric       (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) +
6540b57cec5SDimitry Andric        CmpInst::FIRST_FCMP_PREDICATE;
6550b57cec5SDimitry Andric     } else {
6560b57cec5SDimitry Andric       op = getRandom() %
6570b57cec5SDimitry Andric       (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) +
6580b57cec5SDimitry Andric        CmpInst::FIRST_ICMP_PREDICATE;
6590b57cec5SDimitry Andric     }
6600b57cec5SDimitry Andric 
6610b57cec5SDimitry Andric     Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp,
6620b57cec5SDimitry Andric                                (CmpInst::Predicate)op, Val0, Val1, "Cmp",
6630b57cec5SDimitry Andric                                BB->getTerminator());
6640b57cec5SDimitry Andric     return PT->push_back(V);
6650b57cec5SDimitry Andric   }
6660b57cec5SDimitry Andric };
6670b57cec5SDimitry Andric 
6680b57cec5SDimitry Andric } // end anonymous namespace
6690b57cec5SDimitry Andric 
FillFunction(Function * F,Random & R)6700b57cec5SDimitry Andric static void FillFunction(Function *F, Random &R) {
6710b57cec5SDimitry Andric   // Create a legal entry block.
6720b57cec5SDimitry Andric   BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F);
6730b57cec5SDimitry Andric   ReturnInst::Create(F->getContext(), BB);
6740b57cec5SDimitry Andric 
6750b57cec5SDimitry Andric   // Create the value table.
6760b57cec5SDimitry Andric   Modifier::PieceTable PT;
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric   // Consider arguments as legal values.
6790b57cec5SDimitry Andric   for (auto &arg : F->args())
6800b57cec5SDimitry Andric     PT.push_back(&arg);
6810b57cec5SDimitry Andric 
6820b57cec5SDimitry Andric   // List of modifiers which add new random instructions.
6830b57cec5SDimitry Andric   std::vector<std::unique_ptr<Modifier>> Modifiers;
6840b57cec5SDimitry Andric   Modifiers.emplace_back(new LoadModifier(BB, &PT, &R));
6850b57cec5SDimitry Andric   Modifiers.emplace_back(new StoreModifier(BB, &PT, &R));
6860b57cec5SDimitry Andric   auto SM = Modifiers.back().get();
6870b57cec5SDimitry Andric   Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R));
6880b57cec5SDimitry Andric   Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R));
6890b57cec5SDimitry Andric   Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R));
6900b57cec5SDimitry Andric   Modifiers.emplace_back(new BinModifier(BB, &PT, &R));
6910b57cec5SDimitry Andric   Modifiers.emplace_back(new CastModifier(BB, &PT, &R));
6920b57cec5SDimitry Andric   Modifiers.emplace_back(new SelectModifier(BB, &PT, &R));
6930b57cec5SDimitry Andric   Modifiers.emplace_back(new CmpModifier(BB, &PT, &R));
6940b57cec5SDimitry Andric 
6950b57cec5SDimitry Andric   // Generate the random instructions
6960b57cec5SDimitry Andric   AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas
6970b57cec5SDimitry Andric   ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants
6980b57cec5SDimitry Andric 
6990b57cec5SDimitry Andric   for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i)
7000b57cec5SDimitry Andric     for (auto &Mod : Modifiers)
7010b57cec5SDimitry Andric       Mod->Act();
7020b57cec5SDimitry Andric 
7030b57cec5SDimitry Andric   SM->ActN(5); // Throw in a few stores.
7040b57cec5SDimitry Andric }
7050b57cec5SDimitry Andric 
IntroduceControlFlow(Function * F,Random & R)7060b57cec5SDimitry Andric static void IntroduceControlFlow(Function *F, Random &R) {
7070b57cec5SDimitry Andric   std::vector<Instruction*> BoolInst;
7080b57cec5SDimitry Andric   for (auto &Instr : F->front()) {
7090b57cec5SDimitry Andric     if (Instr.getType() == IntegerType::getInt1Ty(F->getContext()))
7100b57cec5SDimitry Andric       BoolInst.push_back(&Instr);
7110b57cec5SDimitry Andric   }
7120b57cec5SDimitry Andric 
713fe6060f1SDimitry Andric   llvm::shuffle(BoolInst.begin(), BoolInst.end(), R);
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric   for (auto *Instr : BoolInst) {
7160b57cec5SDimitry Andric     BasicBlock *Curr = Instr->getParent();
7170b57cec5SDimitry Andric     BasicBlock::iterator Loc = Instr->getIterator();
7180b57cec5SDimitry Andric     BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF");
7190b57cec5SDimitry Andric     Instr->moveBefore(Curr->getTerminator());
7200b57cec5SDimitry Andric     if (Curr != &F->getEntryBlock()) {
7210b57cec5SDimitry Andric       BranchInst::Create(Curr, Next, Instr, Curr->getTerminator());
7220b57cec5SDimitry Andric       Curr->getTerminator()->eraseFromParent();
7230b57cec5SDimitry Andric     }
7240b57cec5SDimitry Andric   }
7250b57cec5SDimitry Andric }
7260b57cec5SDimitry Andric 
7270b57cec5SDimitry Andric } // end namespace llvm
7280b57cec5SDimitry Andric 
main(int argc,char ** argv)7290b57cec5SDimitry Andric int main(int argc, char **argv) {
7300b57cec5SDimitry Andric   using namespace llvm;
7310b57cec5SDimitry Andric 
732e8d8bef9SDimitry Andric   InitLLVM X(argc, argv);
733fe6060f1SDimitry Andric   cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()});
7340b57cec5SDimitry Andric   cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
7350b57cec5SDimitry Andric 
73681ad6265SDimitry Andric   LLVMContext Context;
7378bcb0991SDimitry Andric   auto M = std::make_unique<Module>("/tmp/autogen.bc", Context);
7380b57cec5SDimitry Andric   Function *F = GenEmptyFunction(M.get());
7390b57cec5SDimitry Andric 
7400b57cec5SDimitry Andric   // Pick an initial seed value
7410b57cec5SDimitry Andric   Random R(SeedCL);
7420b57cec5SDimitry Andric   // Generate lots of random instructions inside a single basic block.
7430b57cec5SDimitry Andric   FillFunction(F, R);
7440b57cec5SDimitry Andric   // Break the basic block into many loops.
7450b57cec5SDimitry Andric   IntroduceControlFlow(F, R);
7460b57cec5SDimitry Andric 
7470b57cec5SDimitry Andric   // Figure out what stream we are supposed to write to...
7480b57cec5SDimitry Andric   std::unique_ptr<ToolOutputFile> Out;
7490b57cec5SDimitry Andric   // Default to standard output.
7500b57cec5SDimitry Andric   if (OutputFilename.empty())
7510b57cec5SDimitry Andric     OutputFilename = "-";
7520b57cec5SDimitry Andric 
7530b57cec5SDimitry Andric   std::error_code EC;
7548bcb0991SDimitry Andric   Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
7550b57cec5SDimitry Andric   if (EC) {
7560b57cec5SDimitry Andric     errs() << EC.message() << '\n';
7570b57cec5SDimitry Andric     return 1;
7580b57cec5SDimitry Andric   }
7590b57cec5SDimitry Andric 
760bdd1243dSDimitry Andric   // Check that the generated module is accepted by the verifier.
761bdd1243dSDimitry Andric   if (verifyModule(*M.get(), &Out->os()))
762bdd1243dSDimitry Andric     report_fatal_error("Broken module found, compilation aborted!");
763bdd1243dSDimitry Andric 
764bdd1243dSDimitry Andric   // Output textual IR.
765bdd1243dSDimitry Andric   M->print(Out->os(), nullptr);
766bdd1243dSDimitry Andric 
7670b57cec5SDimitry Andric   Out->keep();
7680b57cec5SDimitry Andric 
7690b57cec5SDimitry Andric   return 0;
7700b57cec5SDimitry Andric }
771