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