blob: c29b7a7f7e461636cbe1d918af2bce7894216474 [file] [log] [blame]
Eugene Zelenko046ca042017-08-31 21:56:16 +00001//===- llvm-stress.cpp - Generate random LL files to stress-test LLVM -----===//
Nadav Rotemfdc309c2012-02-26 08:35:53 +00002//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9//
10// This program is a utility that generates random .ll files to stress-test
11// different components in LLVM.
12//
13//===----------------------------------------------------------------------===//
Ahmed Charlesf4ccd112014-03-06 05:51:42 +000014
Eugene Zelenko046ca042017-08-31 21:56:16 +000015#include "llvm/ADT/APFloat.h"
16#include "llvm/ADT/APInt.h"
17#include "llvm/ADT/ArrayRef.h"
18#include "llvm/ADT/STLExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"
21#include "llvm/IR/BasicBlock.h"
22#include "llvm/IR/CallingConv.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000023#include "llvm/IR/Constants.h"
Eugene Zelenko046ca042017-08-31 21:56:16 +000024#include "llvm/IR/DataLayout.h"
25#include "llvm/IR/DerivedTypes.h"
26#include "llvm/IR/Function.h"
27#include "llvm/IR/GlobalValue.h"
Chandler Carruth8a5351f2014-01-12 11:10:32 +000028#include "llvm/IR/IRPrintingPasses.h"
Eugene Zelenko046ca042017-08-31 21:56:16 +000029#include "llvm/IR/InstrTypes.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000030#include "llvm/IR/Instruction.h"
Eugene Zelenko046ca042017-08-31 21:56:16 +000031#include "llvm/IR/Instructions.h"
Chandler Carruth8a5351f2014-01-12 11:10:32 +000032#include "llvm/IR/LLVMContext.h"
Mehdi Aminif6071e12016-04-18 09:17:29 +000033#include "llvm/IR/LegacyPassManager.h"
Chandler Carruth0b8c9a82013-01-02 11:36:10 +000034#include "llvm/IR/Module.h"
Eugene Zelenko046ca042017-08-31 21:56:16 +000035#include "llvm/IR/Type.h"
36#include "llvm/IR/Value.h"
Chandler Carruth56e13942014-01-13 09:26:24 +000037#include "llvm/IR/Verifier.h"
Eugene Zelenko046ca042017-08-31 21:56:16 +000038#include "llvm/Support/Casting.h"
39#include "llvm/Support/CommandLine.h"
40#include "llvm/Support/ErrorHandling.h"
Benjamin Kramer7259f142014-04-29 23:26:49 +000041#include "llvm/Support/FileSystem.h"
Nadav Rotemfdc309c2012-02-26 08:35:53 +000042#include "llvm/Support/ManagedStatic.h"
Nadav Rotemfdc309c2012-02-26 08:35:53 +000043#include "llvm/Support/PrettyStackTrace.h"
44#include "llvm/Support/ToolOutputFile.h"
Eugene Zelenko046ca042017-08-31 21:56:16 +000045#include "llvm/Support/raw_ostream.h"
Nadav Rotemfdc309c2012-02-26 08:35:53 +000046#include <algorithm>
Eugene Zelenko046ca042017-08-31 21:56:16 +000047#include <cassert>
48#include <cstddef>
49#include <cstdint>
50#include <memory>
51#include <string>
52#include <system_error>
Chandler Carruthf010c462012-12-04 10:44:52 +000053#include <vector>
Pawel Bylica8229e332015-07-10 10:01:47 +000054
55namespace llvm {
Nadav Rotemfdc309c2012-02-26 08:35:53 +000056
57static cl::opt<unsigned> SeedCL("seed",
58 cl::desc("Seed used for randomness"), cl::init(0));
Eugene Zelenko046ca042017-08-31 21:56:16 +000059
Nadav Rotemfdc309c2012-02-26 08:35:53 +000060static cl::opt<unsigned> SizeCL("size",
61 cl::desc("The estimated size of the generated function (# of instrs)"),
62 cl::init(100));
Eugene Zelenko046ca042017-08-31 21:56:16 +000063
Nadav Rotemfdc309c2012-02-26 08:35:53 +000064static cl::opt<std::string>
65OutputFilename("o", cl::desc("Override output filename"),
66 cl::value_desc("filename"));
67
Mehdi Amini8be77072016-04-14 21:59:01 +000068static LLVMContext Context;
69
Pawel Bylica8229e332015-07-10 10:01:47 +000070namespace cl {
Eugene Zelenko046ca042017-08-31 21:56:16 +000071
Pawel Bylica8229e332015-07-10 10:01:47 +000072template <> class parser<Type*> final : public basic_parser<Type*> {
73public:
74 parser(Option &O) : basic_parser(O) {}
75
76 // Parse options as IR types. Return true on error.
77 bool parse(Option &O, StringRef, StringRef Arg, Type *&Value) {
Pawel Bylica8229e332015-07-10 10:01:47 +000078 if (Arg == "half") Value = Type::getHalfTy(Context);
79 else if (Arg == "fp128") Value = Type::getFP128Ty(Context);
80 else if (Arg == "x86_fp80") Value = Type::getX86_FP80Ty(Context);
81 else if (Arg == "ppc_fp128") Value = Type::getPPC_FP128Ty(Context);
82 else if (Arg == "x86_mmx") Value = Type::getX86_MMXTy(Context);
83 else if (Arg.startswith("i")) {
84 unsigned N = 0;
85 Arg.drop_front().getAsInteger(10, N);
86 if (N > 0)
87 Value = Type::getIntNTy(Context, N);
88 }
89
90 if (!Value)
91 return O.error("Invalid IR scalar type: '" + Arg + "'!");
92 return false;
93 }
94
Mehdi Aminib7d8ee42016-10-01 03:43:20 +000095 StringRef getValueName() const override { return "IR scalar type"; }
Pawel Bylica8229e332015-07-10 10:01:47 +000096};
Pawel Bylica8229e332015-07-10 10:01:47 +000097
Eugene Zelenko046ca042017-08-31 21:56:16 +000098} // end namespace cl
Pawel Bylica8229e332015-07-10 10:01:47 +000099
100static cl::list<Type*> AdditionalScalarTypes("types", cl::CommaSeparated,
101 cl::desc("Additional IR scalar types "
102 "(always includes i1, i8, i16, i32, i64, float and double)"));
Hal Finkel2cff6172012-02-27 23:59:33 +0000103
Juergen Ributzkaba0f9912013-11-19 03:08:35 +0000104namespace {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000105
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000106/// A utility class to provide a pseudo-random number generator which is
107/// the same across all platforms. This is somewhat close to the libc
108/// implementation. Note: This is not a cryptographically secure pseudorandom
109/// number generator.
110class Random {
111public:
112 /// C'tor
113 Random(unsigned _seed):Seed(_seed) {}
Dylan Noblesmith83f17f22012-04-10 22:44:51 +0000114
115 /// Return a random integer, up to a
116 /// maximum of 2**19 - 1.
117 uint32_t Rand() {
118 uint32_t Val = Seed + 0x000b07a1;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000119 Seed = (Val * 0x3c7c0ac1);
120 // Only lowest 19 bits are random-ish.
121 return Seed & 0x7ffff;
122 }
123
Dylan Noblesmith83f17f22012-04-10 22:44:51 +0000124 /// Return a random 64 bit integer.
125 uint64_t Rand64() {
Simon Pilgrim151f40d2017-06-26 13:17:36 +0000126 uint64_t Val = Rand() & 0xffff;
127 Val |= uint64_t(Rand() & 0xffff) << 16;
128 Val |= uint64_t(Rand() & 0xffff) << 32;
129 Val |= uint64_t(Rand() & 0xffff) << 48;
130 return Val;
Dylan Noblesmith83f17f22012-04-10 22:44:51 +0000131 }
Nadav Rotem70602212012-06-21 08:58:15 +0000132
133 /// Rand operator for STL algorithms.
134 ptrdiff_t operator()(ptrdiff_t y) {
135 return Rand64() % y;
136 }
137
Marshall Clowbdbb2952017-02-16 14:37:03 +0000138 /// Make this like a C++11 random device
Eugene Zelenko046ca042017-08-31 21:56:16 +0000139 using result_type = uint32_t ;
140
Marshall Clowbdbb2952017-02-16 14:37:03 +0000141 static constexpr result_type min() { return 0; }
142 static constexpr result_type max() { return 0x7ffff; }
Eugene Zelenko046ca042017-08-31 21:56:16 +0000143
Simon Pilgrim2e6fc832017-06-26 10:16:34 +0000144 uint32_t operator()() {
145 uint32_t Val = Rand();
146 assert(Val <= max() && "Random value out of range");
147 return Val;
148 }
149
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000150private:
151 unsigned Seed;
152};
153
154/// Generate an empty function with a default argument list.
155Function *GenEmptyFunction(Module *M) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000156 // Define a few arguments
157 LLVMContext &Context = M->getContext();
Pawel Bylica611e4932015-06-24 11:49:44 +0000158 Type* ArgsTy[] = {
159 Type::getInt8PtrTy(Context),
160 Type::getInt32PtrTy(Context),
161 Type::getInt64PtrTy(Context),
162 Type::getInt32Ty(Context),
163 Type::getInt64Ty(Context),
164 Type::getInt8Ty(Context)
165 };
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000166
Pawel Bylica611e4932015-06-24 11:49:44 +0000167 auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000168 // Pick a unique name to describe the input parameters
Pawel Bylica611e4932015-06-24 11:49:44 +0000169 Twine Name = "autogen_SD" + Twine{SeedCL};
170 auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000171 Func->setCallingConv(CallingConv::C);
172 return Func;
173}
174
175/// A base class, implementing utilities needed for
176/// modifying and adding new random instructions.
177struct Modifier {
178 /// Used to store the randomly generated values.
Eugene Zelenko046ca042017-08-31 21:56:16 +0000179 using PieceTable = std::vector<Value *>;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000180
181public:
182 /// C'tor
Eugene Zelenko046ca042017-08-31 21:56:16 +0000183 Modifier(BasicBlock *Block, PieceTable *PT, Random *R)
184 : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {}
Andrew Trick67076a92012-09-19 05:08:30 +0000185
186 /// virtual D'tor to silence warnings.
Eugene Zelenko046ca042017-08-31 21:56:16 +0000187 virtual ~Modifier() = default;
Andrew Trick67076a92012-09-19 05:08:30 +0000188
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000189 /// Add a new instruction.
190 virtual void Act() = 0;
Eugene Zelenko046ca042017-08-31 21:56:16 +0000191
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000192 /// Add N new instructions,
193 virtual void ActN(unsigned n) {
194 for (unsigned i=0; i<n; ++i)
195 Act();
196 }
197
198protected:
Simon Pilgrim7c162602017-06-26 15:41:36 +0000199 /// Return a random integer.
200 uint32_t getRandom() {
201 return Ran->Rand();
202 }
203
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000204 /// Return a random value from the list of known values.
205 Value *getRandomVal() {
206 assert(PT->size());
Simon Pilgrim7c162602017-06-26 15:41:36 +0000207 return PT->at(getRandom() % PT->size());
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000208 }
209
Nadav Rotembfb7dfa2012-02-26 13:56:18 +0000210 Constant *getRandomConstant(Type *Tp) {
211 if (Tp->isIntegerTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000212 if (getRandom() & 1)
Nadav Rotembfb7dfa2012-02-26 13:56:18 +0000213 return ConstantInt::getAllOnesValue(Tp);
214 return ConstantInt::getNullValue(Tp);
215 } else if (Tp->isFloatingPointTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000216 if (getRandom() & 1)
Nadav Rotembfb7dfa2012-02-26 13:56:18 +0000217 return ConstantFP::getAllOnesValue(Tp);
218 return ConstantFP::getNullValue(Tp);
219 }
220 return UndefValue::get(Tp);
221 }
222
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000223 /// Return a random value with a known type.
224 Value *getRandomValue(Type *Tp) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000225 unsigned index = getRandom();
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000226 for (unsigned i=0; i<PT->size(); ++i) {
227 Value *V = PT->at((index + i) % PT->size());
228 if (V->getType() == Tp)
229 return V;
230 }
231
232 // If the requested type was not found, generate a constant value.
233 if (Tp->isIntegerTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000234 if (getRandom() & 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000235 return ConstantInt::getAllOnesValue(Tp);
236 return ConstantInt::getNullValue(Tp);
237 } else if (Tp->isFloatingPointTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000238 if (getRandom() & 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000239 return ConstantFP::getAllOnesValue(Tp);
240 return ConstantFP::getNullValue(Tp);
Nadav Rotembfb7dfa2012-02-26 13:56:18 +0000241 } else if (Tp->isVectorTy()) {
242 VectorType *VTp = cast<VectorType>(Tp);
243
244 std::vector<Constant*> TempValues;
245 TempValues.reserve(VTp->getNumElements());
246 for (unsigned i = 0; i < VTp->getNumElements(); ++i)
247 TempValues.push_back(getRandomConstant(VTp->getScalarType()));
248
249 ArrayRef<Constant*> VectorValue(TempValues);
250 return ConstantVector::get(VectorValue);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000251 }
252
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000253 return UndefValue::get(Tp);
254 }
255
256 /// Return a random value of any pointer type.
257 Value *getRandomPointerValue() {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000258 unsigned index = getRandom();
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000259 for (unsigned i=0; i<PT->size(); ++i) {
260 Value *V = PT->at((index + i) % PT->size());
261 if (V->getType()->isPointerTy())
262 return V;
263 }
264 return UndefValue::get(pickPointerType());
265 }
266
267 /// Return a random value of any vector type.
268 Value *getRandomVectorValue() {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000269 unsigned index = getRandom();
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000270 for (unsigned i=0; i<PT->size(); ++i) {
271 Value *V = PT->at((index + i) % PT->size());
272 if (V->getType()->isVectorTy())
273 return V;
274 }
275 return UndefValue::get(pickVectorType());
276 }
277
278 /// Pick a random type.
279 Type *pickType() {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000280 return (getRandom() & 1 ? pickVectorType() : pickScalarType());
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000281 }
282
283 /// Pick a random pointer type.
284 Type *pickPointerType() {
285 Type *Ty = pickType();
286 return PointerType::get(Ty, 0);
287 }
288
289 /// Pick a random vector type.
290 Type *pickVectorType(unsigned len = (unsigned)-1) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000291 // Pick a random vector width in the range 2**0 to 2**4.
292 // by adding two randoms we are generating a normal-like distribution
293 // around 2**3.
Simon Pilgrim7c162602017-06-26 15:41:36 +0000294 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));
Dylan Noblesmith701de8f2012-04-10 22:44:49 +0000295 Type *Ty;
296
297 // Vectors of x86mmx are illegal; keep trying till we get something else.
298 do {
299 Ty = pickScalarType();
300 } while (Ty->isX86_MMXTy());
301
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000302 if (len != (unsigned)-1)
303 width = len;
304 return VectorType::get(Ty, width);
305 }
306
307 /// Pick a random scalar type.
308 Type *pickScalarType() {
Pawel Bylica8229e332015-07-10 10:01:47 +0000309 static std::vector<Type*> ScalarTypes;
310 if (ScalarTypes.empty()) {
311 ScalarTypes.assign({
312 Type::getInt1Ty(Context),
313 Type::getInt8Ty(Context),
314 Type::getInt16Ty(Context),
315 Type::getInt32Ty(Context),
316 Type::getInt64Ty(Context),
317 Type::getFloatTy(Context),
318 Type::getDoubleTy(Context)
319 });
320 ScalarTypes.insert(ScalarTypes.end(),
321 AdditionalScalarTypes.begin(), AdditionalScalarTypes.end());
322 }
Hal Finkel2cff6172012-02-27 23:59:33 +0000323
Simon Pilgrim7c162602017-06-26 15:41:36 +0000324 return ScalarTypes[getRandom() % ScalarTypes.size()];
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000325 }
326
327 /// Basic block to populate
328 BasicBlock *BB;
Eugene Zelenko046ca042017-08-31 21:56:16 +0000329
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000330 /// Value table
331 PieceTable *PT;
Eugene Zelenko046ca042017-08-31 21:56:16 +0000332
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000333 /// Random number generator
334 Random *Ran;
Eugene Zelenko046ca042017-08-31 21:56:16 +0000335
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000336 /// Context
337 LLVMContext &Context;
338};
339
340struct LoadModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000341 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R)
342 : Modifier(BB, PT, R) {}
343
Craig Topperc83e68f2014-03-08 08:27:28 +0000344 void Act() override {
Alp Toker087ab612013-12-05 05:44:44 +0000345 // Try to use predefined pointers. If non-exist, use undef pointer value;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000346 Value *Ptr = getRandomPointerValue();
347 Value *V = new LoadInst(Ptr, "L", BB->getTerminator());
348 PT->push_back(V);
349 }
350};
351
352struct StoreModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000353 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R)
354 : Modifier(BB, PT, R) {}
355
Craig Topperc83e68f2014-03-08 08:27:28 +0000356 void Act() override {
Alp Toker087ab612013-12-05 05:44:44 +0000357 // Try to use predefined pointers. If non-exist, use undef pointer value;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000358 Value *Ptr = getRandomPointerValue();
James Y Knightd2ea65b2019-01-10 16:43:26 +0000359 PointerType *Tp = cast<PointerType>(Ptr->getType());
James Y Knight719df2e2019-01-10 16:07:20 +0000360 Value *Val = getRandomValue(Tp->getElementType());
Nadav Rotem2e851a92012-02-26 12:00:22 +0000361 Type *ValTy = Val->getType();
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000362
363 // Do not store vectors of i1s because they are unsupported
Nadav Rotem794c16a2012-02-26 12:34:17 +0000364 // by the codegen.
365 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000366 return;
367
368 new StoreInst(Val, Ptr, BB->getTerminator());
369 }
370};
371
372struct BinModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000373 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R)
374 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000375
Craig Topperc83e68f2014-03-08 08:27:28 +0000376 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000377 Value *Val0 = getRandomVal();
378 Value *Val1 = getRandomValue(Val0->getType());
379
380 // Don't handle pointer types.
381 if (Val0->getType()->isPointerTy() ||
382 Val1->getType()->isPointerTy())
383 return;
384
385 // Don't handle i1 types.
386 if (Val0->getType()->getScalarSizeInBits() == 1)
387 return;
388
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000389 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy();
390 Instruction* Term = BB->getTerminator();
Simon Pilgrim7c162602017-06-26 15:41:36 +0000391 unsigned R = getRandom() % (isFloat ? 7 : 13);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000392 Instruction::BinaryOps Op;
393
394 switch (R) {
395 default: llvm_unreachable("Invalid BinOp");
396 case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; }
397 case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; }
398 case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; }
399 case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; }
400 case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; }
401 case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; }
402 case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; }
403 case 7: {Op = Instruction::Shl; break; }
404 case 8: {Op = Instruction::LShr; break; }
405 case 9: {Op = Instruction::AShr; break; }
406 case 10:{Op = Instruction::And; break; }
407 case 11:{Op = Instruction::Or; break; }
408 case 12:{Op = Instruction::Xor; break; }
409 }
410
411 PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term));
412 }
413};
414
415/// Generate constant values.
416struct ConstModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000417 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R)
418 : Modifier(BB, PT, R) {}
419
Craig Topperc83e68f2014-03-08 08:27:28 +0000420 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000421 Type *Ty = pickType();
422
423 if (Ty->isVectorTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000424 switch (getRandom() % 2) {
Craig Topper10600822017-07-09 07:04:00 +0000425 case 0: if (Ty->isIntOrIntVectorTy())
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000426 return PT->push_back(ConstantVector::getAllOnesValue(Ty));
Galina Kistanova831f8f82017-06-10 18:26:19 +0000427 break;
Craig Topper10600822017-07-09 07:04:00 +0000428 case 1: if (Ty->isIntOrIntVectorTy())
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000429 return PT->push_back(ConstantVector::getNullValue(Ty));
430 }
431 }
432
433 if (Ty->isFloatingPointTy()) {
Dylan Noblesmith83f17f22012-04-10 22:44:51 +0000434 // Generate 128 random bits, the size of the (currently)
435 // largest floating-point types.
436 uint64_t RandomBits[2];
437 for (unsigned i = 0; i < 2; ++i)
438 RandomBits[i] = Ran->Rand64();
439
440 APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits));
Tim Northoverf65dc6e2013-01-22 10:18:26 +0000441 APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
Dylan Noblesmith83f17f22012-04-10 22:44:51 +0000442
Simon Pilgrim7c162602017-06-26 15:41:36 +0000443 if (getRandom() & 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000444 return PT->push_back(ConstantFP::getNullValue(Ty));
Dylan Noblesmith83f17f22012-04-10 22:44:51 +0000445 return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000446 }
447
448 if (Ty->isIntegerTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000449 switch (getRandom() % 7) {
David Blaikiefd2310e2017-06-12 20:09:53 +0000450 case 0:
451 return PT->push_back(ConstantInt::get(
452 Ty, APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits())));
453 case 1:
454 return PT->push_back(ConstantInt::get(
455 Ty, APInt::getNullValue(Ty->getPrimitiveSizeInBits())));
David Blaikie833be192017-06-21 15:20:46 +0000456 case 2:
457 case 3:
458 case 4:
459 case 5:
David Blaikiefd2310e2017-06-12 20:09:53 +0000460 case 6:
Simon Pilgrim7c162602017-06-26 15:41:36 +0000461 PT->push_back(ConstantInt::get(Ty, getRandom()));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000462 }
463 }
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000464 }
465};
466
467struct AllocaModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000468 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R)
469 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000470
Craig Topperc83e68f2014-03-08 08:27:28 +0000471 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000472 Type *Tp = pickType();
Matt Arsenaulte0b3c332017-04-10 22:27:50 +0000473 const DataLayout &DL = BB->getModule()->getDataLayout();
474 PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(),
475 "A", BB->getFirstNonPHI()));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000476 }
477};
478
479struct ExtractElementModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000480 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
481 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000482
Craig Topperc83e68f2014-03-08 08:27:28 +0000483 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000484 Value *Val0 = getRandomVectorValue();
485 Value *V = ExtractElementInst::Create(Val0,
486 ConstantInt::get(Type::getInt32Ty(BB->getContext()),
Simon Pilgrim7c162602017-06-26 15:41:36 +0000487 getRandom() % cast<VectorType>(Val0->getType())->getNumElements()),
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000488 "E", BB->getTerminator());
489 return PT->push_back(V);
490 }
491};
492
493struct ShuffModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000494 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R)
495 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000496
Eugene Zelenko046ca042017-08-31 21:56:16 +0000497 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000498 Value *Val0 = getRandomVectorValue();
499 Value *Val1 = getRandomValue(Val0->getType());
500
501 unsigned Width = cast<VectorType>(Val0->getType())->getNumElements();
502 std::vector<Constant*> Idxs;
503
504 Type *I32 = Type::getInt32Ty(BB->getContext());
505 for (unsigned i=0; i<Width; ++i) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000506 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000507 // Pick some undef values.
Simon Pilgrim7c162602017-06-26 15:41:36 +0000508 if (!(getRandom() % 5))
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000509 CI = UndefValue::get(I32);
510 Idxs.push_back(CI);
511 }
512
513 Constant *Mask = ConstantVector::get(Idxs);
514
515 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff",
516 BB->getTerminator());
517 PT->push_back(V);
518 }
519};
520
521struct InsertElementModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000522 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
523 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000524
Craig Topperc83e68f2014-03-08 08:27:28 +0000525 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000526 Value *Val0 = getRandomVectorValue();
527 Value *Val1 = getRandomValue(Val0->getType()->getScalarType());
528
529 Value *V = InsertElementInst::Create(Val0, Val1,
530 ConstantInt::get(Type::getInt32Ty(BB->getContext()),
Simon Pilgrim7c162602017-06-26 15:41:36 +0000531 getRandom() % cast<VectorType>(Val0->getType())->getNumElements()),
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000532 "I", BB->getTerminator());
533 return PT->push_back(V);
534 }
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000535};
536
537struct CastModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000538 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R)
539 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000540
Eugene Zelenko046ca042017-08-31 21:56:16 +0000541 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000542 Value *V = getRandomVal();
543 Type *VTy = V->getType();
544 Type *DestTy = pickScalarType();
545
546 // Handle vector casts vectors.
547 if (VTy->isVectorTy()) {
548 VectorType *VecTy = cast<VectorType>(VTy);
549 DestTy = pickVectorType(VecTy->getNumElements());
550 }
551
Nadav Rotem7d719a52012-04-15 20:17:14 +0000552 // no need to cast.
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000553 if (VTy == DestTy) return;
554
555 // Pointers:
556 if (VTy->isPointerTy()) {
557 if (!DestTy->isPointerTy())
558 DestTy = PointerType::get(DestTy, 0);
559 return PT->push_back(
560 new BitCastInst(V, DestTy, "PC", BB->getTerminator()));
561 }
562
Nadav Rotem7d719a52012-04-15 20:17:14 +0000563 unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits();
564 unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits();
565
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000566 // Generate lots of bitcasts.
Simon Pilgrim7c162602017-06-26 15:41:36 +0000567 if ((getRandom() & 1) && VSize == DestSize) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000568 return PT->push_back(
569 new BitCastInst(V, DestTy, "BC", BB->getTerminator()));
570 }
571
572 // Both types are integers:
Craig Topper10600822017-07-09 07:04:00 +0000573 if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) {
Nadav Rotem7d719a52012-04-15 20:17:14 +0000574 if (VSize > DestSize) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000575 return PT->push_back(
576 new TruncInst(V, DestTy, "Tr", BB->getTerminator()));
577 } else {
Nadav Rotem7d719a52012-04-15 20:17:14 +0000578 assert(VSize < DestSize && "Different int types with the same size?");
Simon Pilgrim7c162602017-06-26 15:41:36 +0000579 if (getRandom() & 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000580 return PT->push_back(
581 new ZExtInst(V, DestTy, "ZE", BB->getTerminator()));
582 return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator()));
583 }
584 }
585
586 // Fp to int.
Craig Topper10600822017-07-09 07:04:00 +0000587 if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000588 if (getRandom() & 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000589 return PT->push_back(
590 new FPToSIInst(V, DestTy, "FC", BB->getTerminator()));
591 return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator()));
592 }
593
594 // Int to fp.
Craig Topper10600822017-07-09 07:04:00 +0000595 if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000596 if (getRandom() & 1)
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000597 return PT->push_back(
598 new SIToFPInst(V, DestTy, "FC", BB->getTerminator()));
599 return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator()));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000600 }
601
602 // Both floats.
Craig Topper10600822017-07-09 07:04:00 +0000603 if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) {
Nadav Rotem7d719a52012-04-15 20:17:14 +0000604 if (VSize > DestSize) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000605 return PT->push_back(
606 new FPTruncInst(V, DestTy, "Tr", BB->getTerminator()));
Nadav Rotem7d719a52012-04-15 20:17:14 +0000607 } else if (VSize < DestSize) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000608 return PT->push_back(
609 new FPExtInst(V, DestTy, "ZE", BB->getTerminator()));
610 }
Nadav Rotem7d719a52012-04-15 20:17:14 +0000611 // If VSize == DestSize, then the two types must be fp128 and ppc_fp128,
612 // for which there is no defined conversion. So do nothing.
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000613 }
614 }
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000615};
616
617struct SelectModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000618 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R)
619 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000620
Craig Topperc83e68f2014-03-08 08:27:28 +0000621 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000622 // Try a bunch of different select configuration until a valid one is found.
Eugene Zelenko046ca042017-08-31 21:56:16 +0000623 Value *Val0 = getRandomVal();
624 Value *Val1 = getRandomValue(Val0->getType());
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000625
Eugene Zelenko046ca042017-08-31 21:56:16 +0000626 Type *CondTy = Type::getInt1Ty(Context);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000627
Eugene Zelenko046ca042017-08-31 21:56:16 +0000628 // If the value type is a vector, and we allow vector select, then in 50%
629 // of the cases generate a vector select.
630 if (Val0->getType()->isVectorTy() && (getRandom() % 1)) {
631 unsigned NumElem = cast<VectorType>(Val0->getType())->getNumElements();
632 CondTy = VectorType::get(CondTy, NumElem);
633 }
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000634
Eugene Zelenko046ca042017-08-31 21:56:16 +0000635 Value *Cond = getRandomValue(CondTy);
636 Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator());
637 return PT->push_back(V);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000638 }
639};
640
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000641struct CmpModifier: public Modifier {
Eugene Zelenko046ca042017-08-31 21:56:16 +0000642 CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R)
643 : Modifier(BB, PT, R) {}
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000644
Eugene Zelenko046ca042017-08-31 21:56:16 +0000645 void Act() override {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000646 Value *Val0 = getRandomVal();
647 Value *Val1 = getRandomValue(Val0->getType());
648
649 if (Val0->getType()->isPointerTy()) return;
650 bool fp = Val0->getType()->getScalarType()->isFloatingPointTy();
651
652 int op;
653 if (fp) {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000654 op = getRandom() %
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000655 (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) +
656 CmpInst::FIRST_FCMP_PREDICATE;
657 } else {
Simon Pilgrim7c162602017-06-26 15:41:36 +0000658 op = getRandom() %
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000659 (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) +
660 CmpInst::FIRST_ICMP_PREDICATE;
661 }
662
663 Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp,
Craig Topper240b0e12015-12-15 06:11:33 +0000664 (CmpInst::Predicate)op, Val0, Val1, "Cmp",
665 BB->getTerminator());
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000666 return PT->push_back(V);
667 }
668};
669
Juergen Ributzkaba0f9912013-11-19 03:08:35 +0000670} // end anonymous namespace
Juergen Ributzka35436252013-11-19 00:57:56 +0000671
Juergen Ributzkaba0f9912013-11-19 03:08:35 +0000672static void FillFunction(Function *F, Random &R) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000673 // Create a legal entry block.
674 BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F);
675 ReturnInst::Create(F->getContext(), BB);
676
677 // Create the value table.
678 Modifier::PieceTable PT;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000679
680 // Consider arguments as legal values.
Pawel Bylica611e4932015-06-24 11:49:44 +0000681 for (auto &arg : F->args())
682 PT.push_back(&arg);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000683
684 // List of modifiers which add new random instructions.
Pawel Bylica611e4932015-06-24 11:49:44 +0000685 std::vector<std::unique_ptr<Modifier>> Modifiers;
686 Modifiers.emplace_back(new LoadModifier(BB, &PT, &R));
687 Modifiers.emplace_back(new StoreModifier(BB, &PT, &R));
688 auto SM = Modifiers.back().get();
689 Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R));
690 Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R));
691 Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R));
692 Modifiers.emplace_back(new BinModifier(BB, &PT, &R));
693 Modifiers.emplace_back(new CastModifier(BB, &PT, &R));
694 Modifiers.emplace_back(new SelectModifier(BB, &PT, &R));
695 Modifiers.emplace_back(new CmpModifier(BB, &PT, &R));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000696
697 // Generate the random instructions
Pawel Bylica611e4932015-06-24 11:49:44 +0000698 AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas
699 ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000700
Pawel Bylica611e4932015-06-24 11:49:44 +0000701 for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i)
702 for (auto &Mod : Modifiers)
703 Mod->Act();
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000704
705 SM->ActN(5); // Throw in a few stores.
706}
707
Juergen Ributzkaba0f9912013-11-19 03:08:35 +0000708static void IntroduceControlFlow(Function *F, Random &R) {
Nadav Rotem70602212012-06-21 08:58:15 +0000709 std::vector<Instruction*> BoolInst;
Pawel Bylica611e4932015-06-24 11:49:44 +0000710 for (auto &Instr : F->front()) {
711 if (Instr.getType() == IntegerType::getInt1Ty(F->getContext()))
712 BoolInst.push_back(&Instr);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000713 }
714
Marshall Clowbdbb2952017-02-16 14:37:03 +0000715 std::shuffle(BoolInst.begin(), BoolInst.end(), R);
Nadav Rotem70602212012-06-21 08:58:15 +0000716
Pawel Bylica611e4932015-06-24 11:49:44 +0000717 for (auto *Instr : BoolInst) {
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000718 BasicBlock *Curr = Instr->getParent();
Duncan P. N. Exon Smith5013c512015-11-07 00:01:16 +0000719 BasicBlock::iterator Loc = Instr->getIterator();
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000720 BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF");
721 Instr->moveBefore(Curr->getTerminator());
722 if (Curr != &F->getEntryBlock()) {
723 BranchInst::Create(Curr, Next, Instr, Curr->getTerminator());
724 Curr->getTerminator()->eraseFromParent();
725 }
726 }
727}
728
Eugene Zelenko046ca042017-08-31 21:56:16 +0000729} // end namespace llvm
Pawel Bylica8229e332015-07-10 10:01:47 +0000730
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000731int main(int argc, char **argv) {
Pawel Bylica8229e332015-07-10 10:01:47 +0000732 using namespace llvm;
733
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000734 // Init LLVM, call llvm_shutdown() on exit, parse args, etc.
Pawel Bylicac1a7ff92015-07-13 11:25:56 +0000735 PrettyStackTraceProgram X(argc, argv);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000736 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
737 llvm_shutdown_obj Y;
738
Eugene Zelenko046ca042017-08-31 21:56:16 +0000739 auto M = llvm::make_unique<Module>("/tmp/autogen.bc", Context);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000740 Function *F = GenEmptyFunction(M.get());
Nadav Rotem70602212012-06-21 08:58:15 +0000741
742 // Pick an initial seed value
743 Random R(SeedCL);
744 // Generate lots of random instructions inside a single basic block.
745 FillFunction(F, R);
746 // Break the basic block into many loops.
747 IntroduceControlFlow(F, R);
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000748
749 // Figure out what stream we are supposed to write to...
Reid Kleckner97ca9642017-09-23 01:03:17 +0000750 std::unique_ptr<ToolOutputFile> Out;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000751 // Default to standard output.
752 if (OutputFilename.empty())
753 OutputFilename = "-";
754
Rafael Espindola8c968622014-08-25 18:16:47 +0000755 std::error_code EC;
Reid Kleckner97ca9642017-09-23 01:03:17 +0000756 Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::F_None));
Rafael Espindola8c968622014-08-25 18:16:47 +0000757 if (EC) {
758 errs() << EC.message() << '\n';
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000759 return 1;
760 }
761
Chandler Carruth417c5c12015-02-13 10:01:29 +0000762 legacy::PassManager Passes;
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000763 Passes.add(createVerifierPass());
Chandler Carruthb6458b62014-01-12 11:39:04 +0000764 Passes.add(createPrintModulePass(Out->os()));
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000765 Passes.run(*M.get());
Nadav Rotemfdc309c2012-02-26 08:35:53 +0000766 Out->keep();
767
768 return 0;
769}