1 //===- llvm-stress.cpp - Generate random LL files to stress-test LLVM -----===//
2 //
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 //===----------------------------------------------------------------------===//
14
15 #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"
23 #include "llvm/IR/Constants.h"
24 #include "llvm/IR/DataLayout.h"
25 #include "llvm/IR/DerivedTypes.h"
26 #include "llvm/IR/Function.h"
27 #include "llvm/IR/GlobalValue.h"
28 #include "llvm/IR/IRPrintingPasses.h"
29 #include "llvm/IR/InstrTypes.h"
30 #include "llvm/IR/Instruction.h"
31 #include "llvm/IR/Instructions.h"
32 #include "llvm/IR/LLVMContext.h"
33 #include "llvm/IR/LegacyPassManager.h"
34 #include "llvm/IR/Module.h"
35 #include "llvm/IR/Type.h"
36 #include "llvm/IR/Value.h"
37 #include "llvm/IR/Verifier.h"
38 #include "llvm/Support/Casting.h"
39 #include "llvm/Support/CommandLine.h"
40 #include "llvm/Support/ErrorHandling.h"
41 #include "llvm/Support/FileSystem.h"
42 #include "llvm/Support/ManagedStatic.h"
43 #include "llvm/Support/PrettyStackTrace.h"
44 #include "llvm/Support/ToolOutputFile.h"
45 #include "llvm/Support/raw_ostream.h"
46 #include <algorithm>
47 #include <cassert>
48 #include <cstddef>
49 #include <cstdint>
50 #include <memory>
51 #include <string>
52 #include <system_error>
53 #include <vector>
54
55 namespace llvm {
56
57 static cl::opt<unsigned> SeedCL("seed",
58 cl::desc("Seed used for randomness"), cl::init(0));
59
60 static cl::opt<unsigned> SizeCL("size",
61 cl::desc("The estimated size of the generated function (# of instrs)"),
62 cl::init(100));
63
64 static cl::opt<std::string>
65 OutputFilename("o", cl::desc("Override output filename"),
66 cl::value_desc("filename"));
67
68 static LLVMContext Context;
69
70 namespace cl {
71
72 template <> class parser<Type*> final : public basic_parser<Type*> {
73 public:
parser(Option & O)74 parser(Option &O) : basic_parser(O) {}
75
76 // Parse options as IR types. Return true on error.
parse(Option & O,StringRef,StringRef Arg,Type * & Value)77 bool parse(Option &O, StringRef, StringRef Arg, Type *&Value) {
78 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
getValueName() const95 StringRef getValueName() const override { return "IR scalar type"; }
96 };
97
98 } // end namespace cl
99
100 static 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)"));
103
104 namespace {
105
106 /// 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.
110 class Random {
111 public:
112 /// C'tor
Random(unsigned _seed)113 Random(unsigned _seed):Seed(_seed) {}
114
115 /// Return a random integer, up to a
116 /// maximum of 2**19 - 1.
Rand()117 uint32_t Rand() {
118 uint32_t Val = Seed + 0x000b07a1;
119 Seed = (Val * 0x3c7c0ac1);
120 // Only lowest 19 bits are random-ish.
121 return Seed & 0x7ffff;
122 }
123
124 /// Return a random 64 bit integer.
Rand64()125 uint64_t Rand64() {
126 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;
131 }
132
133 /// Rand operator for STL algorithms.
operator ()(ptrdiff_t y)134 ptrdiff_t operator()(ptrdiff_t y) {
135 return Rand64() % y;
136 }
137
138 /// Make this like a C++11 random device
139 using result_type = uint32_t ;
140
min()141 static constexpr result_type min() { return 0; }
max()142 static constexpr result_type max() { return 0x7ffff; }
143
operator ()()144 uint32_t operator()() {
145 uint32_t Val = Rand();
146 assert(Val <= max() && "Random value out of range");
147 return Val;
148 }
149
150 private:
151 unsigned Seed;
152 };
153
154 /// Generate an empty function with a default argument list.
GenEmptyFunction(Module * M)155 Function *GenEmptyFunction(Module *M) {
156 // Define a few arguments
157 LLVMContext &Context = M->getContext();
158 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 };
166
167 auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false);
168 // Pick a unique name to describe the input parameters
169 Twine Name = "autogen_SD" + Twine{SeedCL};
170 auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M);
171 Func->setCallingConv(CallingConv::C);
172 return Func;
173 }
174
175 /// A base class, implementing utilities needed for
176 /// modifying and adding new random instructions.
177 struct Modifier {
178 /// Used to store the randomly generated values.
179 using PieceTable = std::vector<Value *>;
180
181 public:
182 /// C'tor
Modifierllvm::__anon21a8b58b0111::Modifier183 Modifier(BasicBlock *Block, PieceTable *PT, Random *R)
184 : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {}
185
186 /// virtual D'tor to silence warnings.
187 virtual ~Modifier() = default;
188
189 /// Add a new instruction.
190 virtual void Act() = 0;
191
192 /// Add N new instructions,
ActNllvm::__anon21a8b58b0111::Modifier193 virtual void ActN(unsigned n) {
194 for (unsigned i=0; i<n; ++i)
195 Act();
196 }
197
198 protected:
199 /// Return a random integer.
getRandomllvm::__anon21a8b58b0111::Modifier200 uint32_t getRandom() {
201 return Ran->Rand();
202 }
203
204 /// Return a random value from the list of known values.
getRandomValllvm::__anon21a8b58b0111::Modifier205 Value *getRandomVal() {
206 assert(PT->size());
207 return PT->at(getRandom() % PT->size());
208 }
209
getRandomConstantllvm::__anon21a8b58b0111::Modifier210 Constant *getRandomConstant(Type *Tp) {
211 if (Tp->isIntegerTy()) {
212 if (getRandom() & 1)
213 return ConstantInt::getAllOnesValue(Tp);
214 return ConstantInt::getNullValue(Tp);
215 } else if (Tp->isFloatingPointTy()) {
216 if (getRandom() & 1)
217 return ConstantFP::getAllOnesValue(Tp);
218 return ConstantFP::getNullValue(Tp);
219 }
220 return UndefValue::get(Tp);
221 }
222
223 /// Return a random value with a known type.
getRandomValuellvm::__anon21a8b58b0111::Modifier224 Value *getRandomValue(Type *Tp) {
225 unsigned index = getRandom();
226 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()) {
234 if (getRandom() & 1)
235 return ConstantInt::getAllOnesValue(Tp);
236 return ConstantInt::getNullValue(Tp);
237 } else if (Tp->isFloatingPointTy()) {
238 if (getRandom() & 1)
239 return ConstantFP::getAllOnesValue(Tp);
240 return ConstantFP::getNullValue(Tp);
241 } 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);
251 }
252
253 return UndefValue::get(Tp);
254 }
255
256 /// Return a random value of any pointer type.
getRandomPointerValuellvm::__anon21a8b58b0111::Modifier257 Value *getRandomPointerValue() {
258 unsigned index = getRandom();
259 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.
getRandomVectorValuellvm::__anon21a8b58b0111::Modifier268 Value *getRandomVectorValue() {
269 unsigned index = getRandom();
270 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.
pickTypellvm::__anon21a8b58b0111::Modifier279 Type *pickType() {
280 return (getRandom() & 1 ? pickVectorType() : pickScalarType());
281 }
282
283 /// Pick a random pointer type.
pickPointerTypellvm::__anon21a8b58b0111::Modifier284 Type *pickPointerType() {
285 Type *Ty = pickType();
286 return PointerType::get(Ty, 0);
287 }
288
289 /// Pick a random vector type.
pickVectorTypellvm::__anon21a8b58b0111::Modifier290 Type *pickVectorType(unsigned len = (unsigned)-1) {
291 // 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.
294 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));
295 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
302 if (len != (unsigned)-1)
303 width = len;
304 return VectorType::get(Ty, width);
305 }
306
307 /// Pick a random scalar type.
pickScalarTypellvm::__anon21a8b58b0111::Modifier308 Type *pickScalarType() {
309 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 }
323
324 return ScalarTypes[getRandom() % ScalarTypes.size()];
325 }
326
327 /// Basic block to populate
328 BasicBlock *BB;
329
330 /// Value table
331 PieceTable *PT;
332
333 /// Random number generator
334 Random *Ran;
335
336 /// Context
337 LLVMContext &Context;
338 };
339
340 struct LoadModifier: public Modifier {
LoadModifierllvm::__anon21a8b58b0111::LoadModifier341 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R)
342 : Modifier(BB, PT, R) {}
343
Actllvm::__anon21a8b58b0111::LoadModifier344 void Act() override {
345 // Try to use predefined pointers. If non-exist, use undef pointer value;
346 Value *Ptr = getRandomPointerValue();
347 Value *V = new LoadInst(Ptr, "L", BB->getTerminator());
348 PT->push_back(V);
349 }
350 };
351
352 struct StoreModifier: public Modifier {
StoreModifierllvm::__anon21a8b58b0111::StoreModifier353 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R)
354 : Modifier(BB, PT, R) {}
355
Actllvm::__anon21a8b58b0111::StoreModifier356 void Act() override {
357 // Try to use predefined pointers. If non-exist, use undef pointer value;
358 Value *Ptr = getRandomPointerValue();
359 Type *Tp = Ptr->getType();
360 Value *Val = getRandomValue(Tp->getContainedType(0));
361 Type *ValTy = Val->getType();
362
363 // Do not store vectors of i1s because they are unsupported
364 // by the codegen.
365 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1)
366 return;
367
368 new StoreInst(Val, Ptr, BB->getTerminator());
369 }
370 };
371
372 struct BinModifier: public Modifier {
BinModifierllvm::__anon21a8b58b0111::BinModifier373 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R)
374 : Modifier(BB, PT, R) {}
375
Actllvm::__anon21a8b58b0111::BinModifier376 void Act() override {
377 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
389 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy();
390 Instruction* Term = BB->getTerminator();
391 unsigned R = getRandom() % (isFloat ? 7 : 13);
392 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.
416 struct ConstModifier: public Modifier {
ConstModifierllvm::__anon21a8b58b0111::ConstModifier417 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R)
418 : Modifier(BB, PT, R) {}
419
Actllvm::__anon21a8b58b0111::ConstModifier420 void Act() override {
421 Type *Ty = pickType();
422
423 if (Ty->isVectorTy()) {
424 switch (getRandom() % 2) {
425 case 0: if (Ty->isIntOrIntVectorTy())
426 return PT->push_back(ConstantVector::getAllOnesValue(Ty));
427 break;
428 case 1: if (Ty->isIntOrIntVectorTy())
429 return PT->push_back(ConstantVector::getNullValue(Ty));
430 }
431 }
432
433 if (Ty->isFloatingPointTy()) {
434 // 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));
441 APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
442
443 if (getRandom() & 1)
444 return PT->push_back(ConstantFP::getNullValue(Ty));
445 return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));
446 }
447
448 if (Ty->isIntegerTy()) {
449 switch (getRandom() % 7) {
450 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())));
456 case 2:
457 case 3:
458 case 4:
459 case 5:
460 case 6:
461 PT->push_back(ConstantInt::get(Ty, getRandom()));
462 }
463 }
464 }
465 };
466
467 struct AllocaModifier: public Modifier {
AllocaModifierllvm::__anon21a8b58b0111::AllocaModifier468 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R)
469 : Modifier(BB, PT, R) {}
470
Actllvm::__anon21a8b58b0111::AllocaModifier471 void Act() override {
472 Type *Tp = pickType();
473 const DataLayout &DL = BB->getModule()->getDataLayout();
474 PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(),
475 "A", BB->getFirstNonPHI()));
476 }
477 };
478
479 struct ExtractElementModifier: public Modifier {
ExtractElementModifierllvm::__anon21a8b58b0111::ExtractElementModifier480 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
481 : Modifier(BB, PT, R) {}
482
Actllvm::__anon21a8b58b0111::ExtractElementModifier483 void Act() override {
484 Value *Val0 = getRandomVectorValue();
485 Value *V = ExtractElementInst::Create(Val0,
486 ConstantInt::get(Type::getInt32Ty(BB->getContext()),
487 getRandom() % cast<VectorType>(Val0->getType())->getNumElements()),
488 "E", BB->getTerminator());
489 return PT->push_back(V);
490 }
491 };
492
493 struct ShuffModifier: public Modifier {
ShuffModifierllvm::__anon21a8b58b0111::ShuffModifier494 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R)
495 : Modifier(BB, PT, R) {}
496
Actllvm::__anon21a8b58b0111::ShuffModifier497 void Act() override {
498 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) {
506 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2));
507 // Pick some undef values.
508 if (!(getRandom() % 5))
509 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
521 struct InsertElementModifier: public Modifier {
InsertElementModifierllvm::__anon21a8b58b0111::InsertElementModifier522 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
523 : Modifier(BB, PT, R) {}
524
Actllvm::__anon21a8b58b0111::InsertElementModifier525 void Act() override {
526 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()),
531 getRandom() % cast<VectorType>(Val0->getType())->getNumElements()),
532 "I", BB->getTerminator());
533 return PT->push_back(V);
534 }
535 };
536
537 struct CastModifier: public Modifier {
CastModifierllvm::__anon21a8b58b0111::CastModifier538 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R)
539 : Modifier(BB, PT, R) {}
540
Actllvm::__anon21a8b58b0111::CastModifier541 void Act() override {
542 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
552 // no need to cast.
553 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
563 unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits();
564 unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits();
565
566 // Generate lots of bitcasts.
567 if ((getRandom() & 1) && VSize == DestSize) {
568 return PT->push_back(
569 new BitCastInst(V, DestTy, "BC", BB->getTerminator()));
570 }
571
572 // Both types are integers:
573 if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) {
574 if (VSize > DestSize) {
575 return PT->push_back(
576 new TruncInst(V, DestTy, "Tr", BB->getTerminator()));
577 } else {
578 assert(VSize < DestSize && "Different int types with the same size?");
579 if (getRandom() & 1)
580 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.
587 if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) {
588 if (getRandom() & 1)
589 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.
595 if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) {
596 if (getRandom() & 1)
597 return PT->push_back(
598 new SIToFPInst(V, DestTy, "FC", BB->getTerminator()));
599 return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator()));
600 }
601
602 // Both floats.
603 if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) {
604 if (VSize > DestSize) {
605 return PT->push_back(
606 new FPTruncInst(V, DestTy, "Tr", BB->getTerminator()));
607 } else if (VSize < DestSize) {
608 return PT->push_back(
609 new FPExtInst(V, DestTy, "ZE", BB->getTerminator()));
610 }
611 // If VSize == DestSize, then the two types must be fp128 and ppc_fp128,
612 // for which there is no defined conversion. So do nothing.
613 }
614 }
615 };
616
617 struct SelectModifier: public Modifier {
SelectModifierllvm::__anon21a8b58b0111::SelectModifier618 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R)
619 : Modifier(BB, PT, R) {}
620
Actllvm::__anon21a8b58b0111::SelectModifier621 void Act() override {
622 // Try a bunch of different select configuration until a valid one is found.
623 Value *Val0 = getRandomVal();
624 Value *Val1 = getRandomValue(Val0->getType());
625
626 Type *CondTy = Type::getInt1Ty(Context);
627
628 // 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 }
634
635 Value *Cond = getRandomValue(CondTy);
636 Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator());
637 return PT->push_back(V);
638 }
639 };
640
641 struct CmpModifier: public Modifier {
CmpModifierllvm::__anon21a8b58b0111::CmpModifier642 CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R)
643 : Modifier(BB, PT, R) {}
644
Actllvm::__anon21a8b58b0111::CmpModifier645 void Act() override {
646 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) {
654 op = getRandom() %
655 (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) +
656 CmpInst::FIRST_FCMP_PREDICATE;
657 } else {
658 op = getRandom() %
659 (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,
664 (CmpInst::Predicate)op, Val0, Val1, "Cmp",
665 BB->getTerminator());
666 return PT->push_back(V);
667 }
668 };
669
670 } // end anonymous namespace
671
FillFunction(Function * F,Random & R)672 static void FillFunction(Function *F, Random &R) {
673 // 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;
679
680 // Consider arguments as legal values.
681 for (auto &arg : F->args())
682 PT.push_back(&arg);
683
684 // List of modifiers which add new random instructions.
685 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));
696
697 // Generate the random instructions
698 AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas
699 ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants
700
701 for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i)
702 for (auto &Mod : Modifiers)
703 Mod->Act();
704
705 SM->ActN(5); // Throw in a few stores.
706 }
707
IntroduceControlFlow(Function * F,Random & R)708 static void IntroduceControlFlow(Function *F, Random &R) {
709 std::vector<Instruction*> BoolInst;
710 for (auto &Instr : F->front()) {
711 if (Instr.getType() == IntegerType::getInt1Ty(F->getContext()))
712 BoolInst.push_back(&Instr);
713 }
714
715 std::shuffle(BoolInst.begin(), BoolInst.end(), R);
716
717 for (auto *Instr : BoolInst) {
718 BasicBlock *Curr = Instr->getParent();
719 BasicBlock::iterator Loc = Instr->getIterator();
720 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
729 } // end namespace llvm
730
main(int argc,char ** argv)731 int main(int argc, char **argv) {
732 using namespace llvm;
733
734 // Init LLVM, call llvm_shutdown() on exit, parse args, etc.
735 PrettyStackTraceProgram X(argc, argv);
736 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
737 llvm_shutdown_obj Y;
738
739 auto M = llvm::make_unique<Module>("/tmp/autogen.bc", Context);
740 Function *F = GenEmptyFunction(M.get());
741
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);
748
749 // Figure out what stream we are supposed to write to...
750 std::unique_ptr<ToolOutputFile> Out;
751 // Default to standard output.
752 if (OutputFilename.empty())
753 OutputFilename = "-";
754
755 std::error_code EC;
756 Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::F_None));
757 if (EC) {
758 errs() << EC.message() << '\n';
759 return 1;
760 }
761
762 legacy::PassManager Passes;
763 Passes.add(createVerifierPass());
764 Passes.add(createPrintModulePass(Out->os()));
765 Passes.run(*M.get());
766 Out->keep();
767
768 return 0;
769 }
770