brintos

brintos / llvm-project-archived public Read only

0
0
Text · 23.6 KiB · 2fe5d6b Raw
762 lines · cpp
1//===- llvm-stress.cpp - Generate random LL files to stress-test LLVM -----===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8//9// This program is a utility that generates random .ll files to stress-test10// different components in LLVM.11//12//===----------------------------------------------------------------------===//13 14#include "llvm/ADT/APFloat.h"15#include "llvm/ADT/APInt.h"16#include "llvm/ADT/ArrayRef.h"17#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/StringRef.h"19#include "llvm/ADT/Twine.h"20#include "llvm/IR/BasicBlock.h"21#include "llvm/IR/CallingConv.h"22#include "llvm/IR/Constants.h"23#include "llvm/IR/DataLayout.h"24#include "llvm/IR/DerivedTypes.h"25#include "llvm/IR/Function.h"26#include "llvm/IR/GlobalValue.h"27#include "llvm/IR/InstrTypes.h"28#include "llvm/IR/Instruction.h"29#include "llvm/IR/Instructions.h"30#include "llvm/IR/LLVMContext.h"31#include "llvm/IR/Module.h"32#include "llvm/IR/Type.h"33#include "llvm/IR/Value.h"34#include "llvm/IR/Verifier.h"35#include "llvm/Support/Casting.h"36#include "llvm/Support/CommandLine.h"37#include "llvm/Support/ErrorHandling.h"38#include "llvm/Support/FileSystem.h"39#include "llvm/Support/InitLLVM.h"40#include "llvm/Support/ToolOutputFile.h"41#include "llvm/Support/WithColor.h"42#include "llvm/Support/raw_ostream.h"43#include <cassert>44#include <cstddef>45#include <cstdint>46#include <memory>47#include <string>48#include <system_error>49#include <vector>50 51namespace llvm {52 53static cl::OptionCategory StressCategory("Stress Options");54 55static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"),56                                cl::init(0), cl::cat(StressCategory));57 58static cl::opt<unsigned> SizeCL(59    "size",60    cl::desc("The estimated size of the generated function (# of instrs)"),61    cl::init(100), cl::cat(StressCategory));62 63static cl::opt<std::string> OutputFilename("o",64                                           cl::desc("Override output filename"),65                                           cl::value_desc("filename"),66                                           cl::cat(StressCategory));67 68static cl::list<StringRef> AdditionalScalarTypes(69    "types", cl::CommaSeparated,70    cl::desc("Additional IR scalar types "71             "(always includes i1, i8, i16, i32, i64, float and double)"));72 73static cl::opt<bool> EnableScalableVectors(74    "enable-scalable-vectors",75    cl::desc("Generate IR involving scalable vector types"),76    cl::init(false), cl::cat(StressCategory));77 78 79namespace {80 81/// A utility class to provide a pseudo-random number generator which is82/// the same across all platforms. This is somewhat close to the libc83/// implementation. Note: This is not a cryptographically secure pseudorandom84/// number generator.85class Random {86public:87  /// C'tor88  Random(unsigned _seed):Seed(_seed) {}89 90  /// Return a random integer, up to a91  /// maximum of 2**19 - 1.92  uint32_t Rand() {93    uint32_t Val = Seed + 0x000b07a1;94    Seed = (Val * 0x3c7c0ac1);95    // Only lowest 19 bits are random-ish.96    return Seed & 0x7ffff;97  }98 99  /// Return a random 64 bit integer.100  uint64_t Rand64() {101    uint64_t Val = Rand() & 0xffff;102    Val |= uint64_t(Rand() & 0xffff) << 16;103    Val |= uint64_t(Rand() & 0xffff) << 32;104    Val |= uint64_t(Rand() & 0xffff) << 48;105    return Val;106  }107 108  /// Rand operator for STL algorithms.109  ptrdiff_t operator()(ptrdiff_t y) {110    return  Rand64() % y;111  }112 113  /// Make this like a C++11 random device114  using result_type = uint32_t ;115 116  static constexpr result_type min() { return 0; }117  static constexpr result_type max() { return 0x7ffff; }118 119  uint32_t operator()() {120    uint32_t Val = Rand();121    assert(Val <= max() && "Random value out of range");122    return Val;123  }124 125private:126  unsigned Seed;127};128 129/// Generate an empty function with a default argument list.130Function *GenEmptyFunction(Module *M) {131  // Define a few arguments132  LLVMContext &Context = M->getContext();133  Type* ArgsTy[] = {134    PointerType::get(Context, 0),135    PointerType::get(Context, 0),136    PointerType::get(Context, 0),137    Type::getInt32Ty(Context),138    Type::getInt64Ty(Context),139    Type::getInt8Ty(Context)140  };141 142  auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false);143  // Pick a unique name to describe the input parameters144  Twine Name = "autogen_SD" + Twine{SeedCL};145  auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M);146  Func->setCallingConv(CallingConv::C);147  return Func;148}149 150/// A base class, implementing utilities needed for151/// modifying and adding new random instructions.152struct Modifier {153  /// Used to store the randomly generated values.154  using PieceTable = std::vector<Value *>;155 156public:157  /// C'tor158  Modifier(BasicBlock *Block, PieceTable *PT, Random *R)159      : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {160    ScalarTypes.assign({Type::getInt1Ty(Context), Type::getInt8Ty(Context),161                        Type::getInt16Ty(Context), Type::getInt32Ty(Context),162                        Type::getInt64Ty(Context), Type::getFloatTy(Context),163                        Type::getDoubleTy(Context)});164 165    for (auto &Arg : AdditionalScalarTypes) {166      Type *Ty = nullptr;167      if (Arg == "half")168        Ty = Type::getHalfTy(Context);169      else if (Arg == "fp128")170        Ty = Type::getFP128Ty(Context);171      else if (Arg == "x86_fp80")172        Ty = Type::getX86_FP80Ty(Context);173      else if (Arg == "ppc_fp128")174        Ty = Type::getPPC_FP128Ty(Context);175      else if (Arg.starts_with("i")) {176        unsigned N = 0;177        Arg.drop_front().getAsInteger(10, N);178        if (N > 0)179          Ty = Type::getIntNTy(Context, N);180      }181      if (!Ty) {182        errs() << "Invalid IR scalar type: '" << Arg << "'!\n";183        exit(1);184      }185 186      ScalarTypes.push_back(Ty);187    }188  }189 190  /// virtual D'tor to silence warnings.191  virtual ~Modifier() = default;192 193  /// Add a new instruction.194  virtual void Act() = 0;195 196  /// Add N new instructions,197  virtual void ActN(unsigned n) {198    for (unsigned i=0; i<n; ++i)199      Act();200  }201 202protected:203  /// Return a random integer.204  uint32_t getRandom() {205    return Ran->Rand();206  }207 208  /// Return a random value from the list of known values.209  Value *getRandomVal() {210    assert(PT->size());211    return PT->at(getRandom() % PT->size());212  }213 214  Constant *getRandomConstant(Type *Tp) {215    if (Tp->isIntegerTy()) {216      if (getRandom() & 1)217        return ConstantInt::getAllOnesValue(Tp);218      return ConstantInt::getNullValue(Tp);219    } else if (Tp->isFloatingPointTy()) {220      if (getRandom() & 1)221        return ConstantFP::getAllOnesValue(Tp);222      return ConstantFP::getZero(Tp);223    }224    return UndefValue::get(Tp);225  }226 227  /// Return a random value with a known type.228  Value *getRandomValue(Type *Tp) {229    unsigned index = getRandom();230    for (unsigned i=0; i<PT->size(); ++i) {231      Value *V = PT->at((index + i) % PT->size());232      if (V->getType() == Tp)233        return V;234    }235 236    // If the requested type was not found, generate a constant value.237    if (Tp->isIntegerTy()) {238      if (getRandom() & 1)239        return ConstantInt::getAllOnesValue(Tp);240      return ConstantInt::getNullValue(Tp);241    } else if (Tp->isFloatingPointTy()) {242      if (getRandom() & 1)243        return ConstantFP::getAllOnesValue(Tp);244      return ConstantFP::getZero(Tp);245    } else if (auto *VTp = dyn_cast<FixedVectorType>(Tp)) {246      std::vector<Constant*> TempValues;247      TempValues.reserve(VTp->getNumElements());248      for (unsigned i = 0; i < VTp->getNumElements(); ++i)249        TempValues.push_back(getRandomConstant(VTp->getScalarType()));250 251      ArrayRef<Constant*> VectorValue(TempValues);252      return ConstantVector::get(VectorValue);253    }254 255    return UndefValue::get(Tp);256  }257 258  /// Return a random value of any pointer type.259  Value *getRandomPointerValue() {260    unsigned index = getRandom();261    for (unsigned i=0; i<PT->size(); ++i) {262      Value *V = PT->at((index + i) % PT->size());263      if (V->getType()->isPointerTy())264        return V;265    }266    return UndefValue::get(PointerType::get(Context, 0));267  }268 269  /// Return a random value of any vector type.270  Value *getRandomVectorValue() {271    unsigned index = getRandom();272    for (unsigned i=0; i<PT->size(); ++i) {273      Value *V = PT->at((index + i) % PT->size());274      if (V->getType()->isVectorTy())275        return V;276    }277    return UndefValue::get(pickVectorType());278  }279 280  /// Pick a random type.281  Type *pickType() {282    return (getRandom() & 1) ? pickVectorType() : pickScalarType();283  }284 285  /// Pick a random vector type.286  Type *pickVectorType(VectorType *VTy = nullptr) {287 288    Type *Ty = pickScalarType();289 290    if (VTy)291      return VectorType::get(Ty, VTy->getElementCount());292 293    // Select either fixed length or scalable vectors with 50% probability294    // (only if scalable vectors are enabled)295    bool Scalable = EnableScalableVectors && getRandom() & 1;296 297    // Pick a random vector width in the range 2**0 to 2**4.298    // by adding two randoms we are generating a normal-like distribution299    // around 2**3.300    unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));301    return VectorType::get(Ty, width, Scalable);302  }303 304  /// Pick a random scalar type.305  Type *pickScalarType() {306    return ScalarTypes[getRandom() % ScalarTypes.size()];307  }308 309  /// Basic block to populate310  BasicBlock *BB;311 312  /// Value table313  PieceTable *PT;314 315  /// Random number generator316  Random *Ran;317 318  /// Context319  LLVMContext &Context;320 321  std::vector<Type *> ScalarTypes;322};323 324struct LoadModifier: public Modifier {325  LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R)326      : Modifier(BB, PT, R) {}327 328  void Act() override {329    // Try to use predefined pointers. If non-exist, use undef pointer value;330    Value *Ptr = getRandomPointerValue();331    Type *Ty = pickType();332    Value *V = new LoadInst(Ty, Ptr, "L", BB->getTerminator()->getIterator());333    PT->push_back(V);334  }335};336 337struct StoreModifier: public Modifier {338  StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R)339      : Modifier(BB, PT, R) {}340 341  void Act() override {342    // Try to use predefined pointers. If non-exist, use undef pointer value;343    Value *Ptr = getRandomPointerValue();344    Type *ValTy = pickType();345 346    // Do not store vectors of i1s because they are unsupported347    // by the codegen.348    if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1)349      return;350 351    Value *Val = getRandomValue(ValTy);352    new StoreInst(Val, Ptr, BB->getTerminator()->getIterator());353  }354};355 356struct BinModifier: public Modifier {357  BinModifier(BasicBlock *BB, PieceTable *PT, Random *R)358      : Modifier(BB, PT, R) {}359 360  void Act() override {361    Value *Val0 = getRandomVal();362    Value *Val1 = getRandomValue(Val0->getType());363 364    // Don't handle pointer types.365    if (Val0->getType()->isPointerTy() ||366        Val1->getType()->isPointerTy())367      return;368 369    // Don't handle i1 types.370    if (Val0->getType()->getScalarSizeInBits() == 1)371      return;372 373    bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy();374    Instruction* Term = BB->getTerminator();375    unsigned R = getRandom() % (isFloat ? 7 : 13);376    Instruction::BinaryOps Op;377 378    switch (R) {379    default: llvm_unreachable("Invalid BinOp");380    case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; }381    case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; }382    case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; }383    case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; }384    case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; }385    case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; }386    case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; }387    case 7: {Op = Instruction::Shl;  break; }388    case 8: {Op = Instruction::LShr; break; }389    case 9: {Op = Instruction::AShr; break; }390    case 10:{Op = Instruction::And;  break; }391    case 11:{Op = Instruction::Or;   break; }392    case 12:{Op = Instruction::Xor;  break; }393    }394 395    PT->push_back(396        BinaryOperator::Create(Op, Val0, Val1, "B", Term->getIterator()));397  }398};399 400/// Generate constant values.401struct ConstModifier: public Modifier {402  ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R)403      : Modifier(BB, PT, R) {}404 405  void Act() override {406    Type *Ty = pickType();407 408    if (Ty->isVectorTy()) {409      switch (getRandom() % 2) {410      case 0: if (Ty->isIntOrIntVectorTy())411                return PT->push_back(ConstantVector::getAllOnesValue(Ty));412              break;413      case 1: if (Ty->isIntOrIntVectorTy())414                return PT->push_back(ConstantVector::getNullValue(Ty));415      }416    }417 418    if (Ty->isFloatingPointTy()) {419      // Generate 128 random bits, the size of the (currently)420      // largest floating-point types.421      uint64_t RandomBits[2];422      for (unsigned i = 0; i < 2; ++i)423        RandomBits[i] = Ran->Rand64();424 425      APInt RandomInt(Ty->getPrimitiveSizeInBits(), ArrayRef(RandomBits));426      APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);427 428      if (getRandom() & 1)429        return PT->push_back(ConstantFP::getZero(Ty));430      return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));431    }432 433    if (Ty->isIntegerTy()) {434      switch (getRandom() % 7) {435      case 0:436        return PT->push_back(ConstantInt::get(437            Ty, APInt::getAllOnes(Ty->getPrimitiveSizeInBits())));438      case 1:439        return PT->push_back(440            ConstantInt::get(Ty, APInt::getZero(Ty->getPrimitiveSizeInBits())));441      case 2:442      case 3:443      case 4:444      case 5:445      case 6:446        PT->push_back(ConstantInt::get(Ty, getRandom()));447      }448    }449  }450};451 452struct AllocaModifier: public Modifier {453  AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R)454      : Modifier(BB, PT, R) {}455 456  void Act() override {457    Type *Tp = pickType();458    const DataLayout &DL = BB->getDataLayout();459    PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(), "A",460                                 BB->getFirstNonPHIIt()));461  }462};463 464struct ExtractElementModifier: public Modifier {465  ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)466      : Modifier(BB, PT, R) {}467 468  void Act() override {469    Value *Val0 = getRandomVectorValue();470    Value *V = ExtractElementInst::Create(471        Val0, getRandomValue(Type::getInt32Ty(BB->getContext())), "E",472        BB->getTerminator()->getIterator());473    return PT->push_back(V);474  }475};476 477struct ShuffModifier: public Modifier {478  ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R)479      : Modifier(BB, PT, R) {}480 481  void Act() override {482    Value *Val0 = getRandomVectorValue();483    Value *Val1 = getRandomValue(Val0->getType());484 485    // Can't express arbitrary shufflevectors for scalable vectors486    if (isa<ScalableVectorType>(Val0->getType()))487      return;488 489    unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements();490    std::vector<Constant*> Idxs;491 492    Type *I32 = Type::getInt32Ty(BB->getContext());493    for (unsigned i=0; i<Width; ++i) {494      Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2));495      // Pick some undef values.496      if (!(getRandom() % 5))497        CI = UndefValue::get(I32);498      Idxs.push_back(CI);499    }500 501    Constant *Mask = ConstantVector::get(Idxs);502 503    Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff",504                                     BB->getTerminator()->getIterator());505    PT->push_back(V);506  }507};508 509struct InsertElementModifier: public Modifier {510  InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)511      : Modifier(BB, PT, R) {}512 513  void Act() override {514    Value *Val0 = getRandomVectorValue();515    Value *Val1 = getRandomValue(Val0->getType()->getScalarType());516 517    Value *V = InsertElementInst::Create(518        Val0, Val1, getRandomValue(Type::getInt32Ty(BB->getContext())), "I",519        BB->getTerminator()->getIterator());520    return PT->push_back(V);521  }522};523 524struct CastModifier: public Modifier {525  CastModifier(BasicBlock *BB, PieceTable *PT, Random *R)526      : Modifier(BB, PT, R) {}527 528  void Act() override {529    Value *V = getRandomVal();530    Type *VTy = V->getType();531    Type *DestTy = pickScalarType();532 533    // Handle vector casts vectors.534    if (VTy->isVectorTy())535      DestTy = pickVectorType(cast<VectorType>(VTy));536 537    // no need to cast.538    if (VTy == DestTy) return;539 540    // Pointers:541    if (VTy->isPointerTy()) {542      if (!DestTy->isPointerTy())543        DestTy = PointerType::get(Context, 0);544      return PT->push_back(545          new BitCastInst(V, DestTy, "PC", BB->getTerminator()->getIterator()));546    }547 548    unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits();549    unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits();550 551    // Generate lots of bitcasts.552    if ((getRandom() & 1) && VSize == DestSize) {553      return PT->push_back(554          new BitCastInst(V, DestTy, "BC", BB->getTerminator()->getIterator()));555    }556 557    // Both types are integers:558    if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) {559      if (VSize > DestSize) {560        return PT->push_back(561            new TruncInst(V, DestTy, "Tr", BB->getTerminator()->getIterator()));562      } else {563        assert(VSize < DestSize && "Different int types with the same size?");564        if (getRandom() & 1)565          return PT->push_back(new ZExtInst(566              V, DestTy, "ZE", BB->getTerminator()->getIterator()));567        return PT->push_back(568            new SExtInst(V, DestTy, "Se", BB->getTerminator()->getIterator()));569      }570    }571 572    // Fp to int.573    if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) {574      if (getRandom() & 1)575        return PT->push_back(new FPToSIInst(576            V, DestTy, "FC", BB->getTerminator()->getIterator()));577      return PT->push_back(578          new FPToUIInst(V, DestTy, "FC", BB->getTerminator()->getIterator()));579    }580 581    // Int to fp.582    if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) {583      if (getRandom() & 1)584        return PT->push_back(new SIToFPInst(585            V, DestTy, "FC", BB->getTerminator()->getIterator()));586      return PT->push_back(587          new UIToFPInst(V, DestTy, "FC", BB->getTerminator()->getIterator()));588    }589 590    // Both floats.591    if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) {592      if (VSize > DestSize) {593        return PT->push_back(new FPTruncInst(594            V, DestTy, "Tr", BB->getTerminator()->getIterator()));595      } else if (VSize < DestSize) {596        return PT->push_back(597            new FPExtInst(V, DestTy, "ZE", BB->getTerminator()->getIterator()));598      }599      // If VSize == DestSize, then the two types must be fp128 and ppc_fp128,600      // for which there is no defined conversion. So do nothing.601    }602  }603};604 605struct SelectModifier: public Modifier {606  SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R)607      : Modifier(BB, PT, R) {}608 609  void Act() override {610    // Try a bunch of different select configuration until a valid one is found.611    Value *Val0 = getRandomVal();612    Value *Val1 = getRandomValue(Val0->getType());613 614    Type *CondTy = Type::getInt1Ty(Context);615 616    // If the value type is a vector, and we allow vector select, then in 50%617    // of the cases generate a vector select.618    if (auto *VTy = dyn_cast<VectorType>(Val0->getType()))619      if (getRandom() & 1)620        CondTy = VectorType::get(CondTy, VTy->getElementCount());621 622    Value *Cond = getRandomValue(CondTy);623    Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl",624                                  BB->getTerminator()->getIterator());625    return PT->push_back(V);626  }627};628 629struct CmpModifier: public Modifier {630  CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R)631      : Modifier(BB, PT, R) {}632 633  void Act() override {634    Value *Val0 = getRandomVal();635    Value *Val1 = getRandomValue(Val0->getType());636 637    if (Val0->getType()->isPointerTy()) return;638    bool fp = Val0->getType()->getScalarType()->isFloatingPointTy();639 640    int op;641    if (fp) {642      op = getRandom() %643      (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) +644       CmpInst::FIRST_FCMP_PREDICATE;645    } else {646      op = getRandom() %647      (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) +648       CmpInst::FIRST_ICMP_PREDICATE;649    }650 651    Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp,652                               (CmpInst::Predicate)op, Val0, Val1, "Cmp",653                               BB->getTerminator()->getIterator());654    return PT->push_back(V);655  }656};657 658} // end anonymous namespace659 660static void FillFunction(Function *F, Random &R) {661  // Create a legal entry block.662  BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F);663  ReturnInst::Create(F->getContext(), BB);664 665  // Create the value table.666  Modifier::PieceTable PT;667 668  // Consider arguments as legal values.669  for (auto &arg : F->args())670    PT.push_back(&arg);671 672  // List of modifiers which add new random instructions.673  std::vector<std::unique_ptr<Modifier>> Modifiers;674  Modifiers.emplace_back(new LoadModifier(BB, &PT, &R));675  Modifiers.emplace_back(new StoreModifier(BB, &PT, &R));676  auto SM = Modifiers.back().get();677  Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R));678  Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R));679  Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R));680  Modifiers.emplace_back(new BinModifier(BB, &PT, &R));681  Modifiers.emplace_back(new CastModifier(BB, &PT, &R));682  Modifiers.emplace_back(new SelectModifier(BB, &PT, &R));683  Modifiers.emplace_back(new CmpModifier(BB, &PT, &R));684 685  // Generate the random instructions686  AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas687  ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants688 689  for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i)690    for (auto &Mod : Modifiers)691      Mod->Act();692 693  SM->ActN(5); // Throw in a few stores.694}695 696static void IntroduceControlFlow(Function *F, Random &R) {697  std::vector<Instruction*> BoolInst;698  for (auto &Instr : F->front()) {699    if (Instr.getType() == IntegerType::getInt1Ty(F->getContext()))700      BoolInst.push_back(&Instr);701  }702 703  llvm::shuffle(BoolInst.begin(), BoolInst.end(), R);704 705  for (auto *Instr : BoolInst) {706    BasicBlock *Curr = Instr->getParent();707    BasicBlock::iterator Loc = Instr->getIterator();708    BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF");709    Instr->moveBefore(Curr->getTerminator()->getIterator());710    if (Curr != &F->getEntryBlock()) {711      BranchInst::Create(Curr, Next, Instr,712                         Curr->getTerminator()->getIterator());713      Curr->getTerminator()->eraseFromParent();714    }715  }716}717 718} // end namespace llvm719 720int main(int argc, char **argv) {721  using namespace llvm;722 723  InitLLVM X(argc, argv);724  cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()});725  cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");726 727  LLVMContext Context;728  auto M = std::make_unique<Module>("/tmp/autogen.bc", Context);729  Function *F = GenEmptyFunction(M.get());730 731  // Pick an initial seed value732  Random R(SeedCL);733  // Generate lots of random instructions inside a single basic block.734  FillFunction(F, R);735  // Break the basic block into many loops.736  IntroduceControlFlow(F, R);737 738  // Figure out what stream we are supposed to write to...739  std::unique_ptr<ToolOutputFile> Out;740  // Default to standard output.741  if (OutputFilename.empty())742    OutputFilename = "-";743 744  std::error_code EC;745  Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));746  if (EC) {747    errs() << EC.message() << '\n';748    return 1;749  }750 751  // Check that the generated module is accepted by the verifier.752  if (verifyModule(*M.get(), &Out->os()))753    report_fatal_error("Broken module found, compilation aborted!");754 755  // Output textual IR.756  M->print(Out->os(), nullptr);757 758  Out->keep();759 760  return 0;761}762