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-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This program is a utility that generates random .ll files to stress-test
10 // 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/IRPrintingPasses.h"
28 #include "llvm/IR/InstrTypes.h"
29 #include "llvm/IR/Instruction.h"
30 #include "llvm/IR/Instructions.h"
31 #include "llvm/IR/LLVMContext.h"
32 #include "llvm/IR/LegacyPassManager.h"
33 #include "llvm/IR/Module.h"
34 #include "llvm/IR/Type.h"
35 #include "llvm/IR/Value.h"
36 #include "llvm/IR/Verifier.h"
37 #include "llvm/Support/Casting.h"
38 #include "llvm/Support/CommandLine.h"
39 #include "llvm/Support/ErrorHandling.h"
40 #include "llvm/Support/FileSystem.h"
41 #include "llvm/Support/InitLLVM.h"
42 #include "llvm/Support/ToolOutputFile.h"
43 #include "llvm/Support/raw_ostream.h"
44 #include <algorithm>
45 #include <cassert>
46 #include <cstddef>
47 #include <cstdint>
48 #include <memory>
49 #include <string>
50 #include <system_error>
51 #include <vector>
52
53 namespace llvm {
54
55 static cl::OptionCategory StressCategory("Stress Options");
56
57 static cl::opt<unsigned> SeedCL("seed", cl::desc("Seed used for randomness"),
58 cl::init(0), cl::cat(StressCategory));
59
60 static cl::opt<unsigned> SizeCL(
61 "size",
62 cl::desc("The estimated size of the generated function (# of instrs)"),
63 cl::init(100), cl::cat(StressCategory));
64
65 static cl::opt<std::string> OutputFilename("o",
66 cl::desc("Override output filename"),
67 cl::value_desc("filename"),
68 cl::cat(StressCategory));
69
70 static LLVMContext Context;
71
72 namespace cl {
73
74 template <> class parser<Type*> final : public basic_parser<Type*> {
75 public:
parser(Option & O)76 parser(Option &O) : basic_parser(O) {}
77
78 // Parse options as IR types. Return true on error.
parse(Option & O,StringRef,StringRef Arg,Type * & Value)79 bool parse(Option &O, StringRef, StringRef Arg, Type *&Value) {
80 if (Arg == "half") Value = Type::getHalfTy(Context);
81 else if (Arg == "fp128") Value = Type::getFP128Ty(Context);
82 else if (Arg == "x86_fp80") Value = Type::getX86_FP80Ty(Context);
83 else if (Arg == "ppc_fp128") Value = Type::getPPC_FP128Ty(Context);
84 else if (Arg == "x86_mmx") Value = Type::getX86_MMXTy(Context);
85 else if (Arg.startswith("i")) {
86 unsigned N = 0;
87 Arg.drop_front().getAsInteger(10, N);
88 if (N > 0)
89 Value = Type::getIntNTy(Context, N);
90 }
91
92 if (!Value)
93 return O.error("Invalid IR scalar type: '" + Arg + "'!");
94 return false;
95 }
96
getValueName() const97 StringRef getValueName() const override { return "IR scalar type"; }
98 };
99
100 } // end namespace cl
101
102 static cl::list<Type*> AdditionalScalarTypes("types", cl::CommaSeparated,
103 cl::desc("Additional IR scalar types "
104 "(always includes i1, i8, i16, i32, i64, float and double)"));
105
106 namespace {
107
108 /// A utility class to provide a pseudo-random number generator which is
109 /// the same across all platforms. This is somewhat close to the libc
110 /// implementation. Note: This is not a cryptographically secure pseudorandom
111 /// number generator.
112 class Random {
113 public:
114 /// C'tor
Random(unsigned _seed)115 Random(unsigned _seed):Seed(_seed) {}
116
117 /// Return a random integer, up to a
118 /// maximum of 2**19 - 1.
Rand()119 uint32_t Rand() {
120 uint32_t Val = Seed + 0x000b07a1;
121 Seed = (Val * 0x3c7c0ac1);
122 // Only lowest 19 bits are random-ish.
123 return Seed & 0x7ffff;
124 }
125
126 /// Return a random 64 bit integer.
Rand64()127 uint64_t Rand64() {
128 uint64_t Val = Rand() & 0xffff;
129 Val |= uint64_t(Rand() & 0xffff) << 16;
130 Val |= uint64_t(Rand() & 0xffff) << 32;
131 Val |= uint64_t(Rand() & 0xffff) << 48;
132 return Val;
133 }
134
135 /// Rand operator for STL algorithms.
operator ()(ptrdiff_t y)136 ptrdiff_t operator()(ptrdiff_t y) {
137 return Rand64() % y;
138 }
139
140 /// Make this like a C++11 random device
141 using result_type = uint32_t ;
142
min()143 static constexpr result_type min() { return 0; }
max()144 static constexpr result_type max() { return 0x7ffff; }
145
operator ()()146 uint32_t operator()() {
147 uint32_t Val = Rand();
148 assert(Val <= max() && "Random value out of range");
149 return Val;
150 }
151
152 private:
153 unsigned Seed;
154 };
155
156 /// Generate an empty function with a default argument list.
GenEmptyFunction(Module * M)157 Function *GenEmptyFunction(Module *M) {
158 // Define a few arguments
159 LLVMContext &Context = M->getContext();
160 Type* ArgsTy[] = {
161 Type::getInt8PtrTy(Context),
162 Type::getInt32PtrTy(Context),
163 Type::getInt64PtrTy(Context),
164 Type::getInt32Ty(Context),
165 Type::getInt64Ty(Context),
166 Type::getInt8Ty(Context)
167 };
168
169 auto *FuncTy = FunctionType::get(Type::getVoidTy(Context), ArgsTy, false);
170 // Pick a unique name to describe the input parameters
171 Twine Name = "autogen_SD" + Twine{SeedCL};
172 auto *Func = Function::Create(FuncTy, GlobalValue::ExternalLinkage, Name, M);
173 Func->setCallingConv(CallingConv::C);
174 return Func;
175 }
176
177 /// A base class, implementing utilities needed for
178 /// modifying and adding new random instructions.
179 struct Modifier {
180 /// Used to store the randomly generated values.
181 using PieceTable = std::vector<Value *>;
182
183 public:
184 /// C'tor
Modifierllvm::__anond0a2ce370111::Modifier185 Modifier(BasicBlock *Block, PieceTable *PT, Random *R)
186 : BB(Block), PT(PT), Ran(R), Context(BB->getContext()) {}
187
188 /// virtual D'tor to silence warnings.
189 virtual ~Modifier() = default;
190
191 /// Add a new instruction.
192 virtual void Act() = 0;
193
194 /// Add N new instructions,
ActNllvm::__anond0a2ce370111::Modifier195 virtual void ActN(unsigned n) {
196 for (unsigned i=0; i<n; ++i)
197 Act();
198 }
199
200 protected:
201 /// Return a random integer.
getRandomllvm::__anond0a2ce370111::Modifier202 uint32_t getRandom() {
203 return Ran->Rand();
204 }
205
206 /// Return a random value from the list of known values.
getRandomValllvm::__anond0a2ce370111::Modifier207 Value *getRandomVal() {
208 assert(PT->size());
209 return PT->at(getRandom() % PT->size());
210 }
211
getRandomConstantllvm::__anond0a2ce370111::Modifier212 Constant *getRandomConstant(Type *Tp) {
213 if (Tp->isIntegerTy()) {
214 if (getRandom() & 1)
215 return ConstantInt::getAllOnesValue(Tp);
216 return ConstantInt::getNullValue(Tp);
217 } else if (Tp->isFloatingPointTy()) {
218 if (getRandom() & 1)
219 return ConstantFP::getAllOnesValue(Tp);
220 return ConstantFP::getNullValue(Tp);
221 }
222 return UndefValue::get(Tp);
223 }
224
225 /// Return a random value with a known type.
getRandomValuellvm::__anond0a2ce370111::Modifier226 Value *getRandomValue(Type *Tp) {
227 unsigned index = getRandom();
228 for (unsigned i=0; i<PT->size(); ++i) {
229 Value *V = PT->at((index + i) % PT->size());
230 if (V->getType() == Tp)
231 return V;
232 }
233
234 // If the requested type was not found, generate a constant value.
235 if (Tp->isIntegerTy()) {
236 if (getRandom() & 1)
237 return ConstantInt::getAllOnesValue(Tp);
238 return ConstantInt::getNullValue(Tp);
239 } else if (Tp->isFloatingPointTy()) {
240 if (getRandom() & 1)
241 return ConstantFP::getAllOnesValue(Tp);
242 return ConstantFP::getNullValue(Tp);
243 } else if (Tp->isVectorTy()) {
244 auto *VTp = cast<FixedVectorType>(Tp);
245
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.
getRandomPointerValuellvm::__anond0a2ce370111::Modifier259 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(pickPointerType());
267 }
268
269 /// Return a random value of any vector type.
getRandomVectorValuellvm::__anond0a2ce370111::Modifier270 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.
pickTypellvm::__anond0a2ce370111::Modifier281 Type *pickType() {
282 return (getRandom() & 1) ? pickVectorType() : pickScalarType();
283 }
284
285 /// Pick a random pointer type.
pickPointerTypellvm::__anond0a2ce370111::Modifier286 Type *pickPointerType() {
287 Type *Ty = pickType();
288 return PointerType::get(Ty, 0);
289 }
290
291 /// Pick a random vector type.
pickVectorTypellvm::__anond0a2ce370111::Modifier292 Type *pickVectorType(unsigned len = (unsigned)-1) {
293 // Pick a random vector width in the range 2**0 to 2**4.
294 // by adding two randoms we are generating a normal-like distribution
295 // around 2**3.
296 unsigned width = 1<<((getRandom() % 3) + (getRandom() % 3));
297 Type *Ty;
298
299 // Vectors of x86mmx are illegal; keep trying till we get something else.
300 do {
301 Ty = pickScalarType();
302 } while (Ty->isX86_MMXTy());
303
304 if (len != (unsigned)-1)
305 width = len;
306 return FixedVectorType::get(Ty, width);
307 }
308
309 /// Pick a random scalar type.
pickScalarTypellvm::__anond0a2ce370111::Modifier310 Type *pickScalarType() {
311 static std::vector<Type*> ScalarTypes;
312 if (ScalarTypes.empty()) {
313 ScalarTypes.assign({
314 Type::getInt1Ty(Context),
315 Type::getInt8Ty(Context),
316 Type::getInt16Ty(Context),
317 Type::getInt32Ty(Context),
318 Type::getInt64Ty(Context),
319 Type::getFloatTy(Context),
320 Type::getDoubleTy(Context)
321 });
322 llvm::append_range(ScalarTypes, AdditionalScalarTypes);
323 }
324
325 return ScalarTypes[getRandom() % ScalarTypes.size()];
326 }
327
328 /// Basic block to populate
329 BasicBlock *BB;
330
331 /// Value table
332 PieceTable *PT;
333
334 /// Random number generator
335 Random *Ran;
336
337 /// Context
338 LLVMContext &Context;
339 };
340
341 struct LoadModifier: public Modifier {
LoadModifierllvm::__anond0a2ce370111::LoadModifier342 LoadModifier(BasicBlock *BB, PieceTable *PT, Random *R)
343 : Modifier(BB, PT, R) {}
344
Actllvm::__anond0a2ce370111::LoadModifier345 void Act() override {
346 // Try to use predefined pointers. If non-exist, use undef pointer value;
347 Value *Ptr = getRandomPointerValue();
348 PointerType *Tp = cast<PointerType>(Ptr->getType());
349 Value *V = new LoadInst(Tp->getElementType(), Ptr, "L",
350 BB->getTerminator());
351 PT->push_back(V);
352 }
353 };
354
355 struct StoreModifier: public Modifier {
StoreModifierllvm::__anond0a2ce370111::StoreModifier356 StoreModifier(BasicBlock *BB, PieceTable *PT, Random *R)
357 : Modifier(BB, PT, R) {}
358
Actllvm::__anond0a2ce370111::StoreModifier359 void Act() override {
360 // Try to use predefined pointers. If non-exist, use undef pointer value;
361 Value *Ptr = getRandomPointerValue();
362 PointerType *Tp = cast<PointerType>(Ptr->getType());
363 Value *Val = getRandomValue(Tp->getElementType());
364 Type *ValTy = Val->getType();
365
366 // Do not store vectors of i1s because they are unsupported
367 // by the codegen.
368 if (ValTy->isVectorTy() && ValTy->getScalarSizeInBits() == 1)
369 return;
370
371 new StoreInst(Val, Ptr, BB->getTerminator());
372 }
373 };
374
375 struct BinModifier: public Modifier {
BinModifierllvm::__anond0a2ce370111::BinModifier376 BinModifier(BasicBlock *BB, PieceTable *PT, Random *R)
377 : Modifier(BB, PT, R) {}
378
Actllvm::__anond0a2ce370111::BinModifier379 void Act() override {
380 Value *Val0 = getRandomVal();
381 Value *Val1 = getRandomValue(Val0->getType());
382
383 // Don't handle pointer types.
384 if (Val0->getType()->isPointerTy() ||
385 Val1->getType()->isPointerTy())
386 return;
387
388 // Don't handle i1 types.
389 if (Val0->getType()->getScalarSizeInBits() == 1)
390 return;
391
392 bool isFloat = Val0->getType()->getScalarType()->isFloatingPointTy();
393 Instruction* Term = BB->getTerminator();
394 unsigned R = getRandom() % (isFloat ? 7 : 13);
395 Instruction::BinaryOps Op;
396
397 switch (R) {
398 default: llvm_unreachable("Invalid BinOp");
399 case 0:{Op = (isFloat?Instruction::FAdd : Instruction::Add); break; }
400 case 1:{Op = (isFloat?Instruction::FSub : Instruction::Sub); break; }
401 case 2:{Op = (isFloat?Instruction::FMul : Instruction::Mul); break; }
402 case 3:{Op = (isFloat?Instruction::FDiv : Instruction::SDiv); break; }
403 case 4:{Op = (isFloat?Instruction::FDiv : Instruction::UDiv); break; }
404 case 5:{Op = (isFloat?Instruction::FRem : Instruction::SRem); break; }
405 case 6:{Op = (isFloat?Instruction::FRem : Instruction::URem); break; }
406 case 7: {Op = Instruction::Shl; break; }
407 case 8: {Op = Instruction::LShr; break; }
408 case 9: {Op = Instruction::AShr; break; }
409 case 10:{Op = Instruction::And; break; }
410 case 11:{Op = Instruction::Or; break; }
411 case 12:{Op = Instruction::Xor; break; }
412 }
413
414 PT->push_back(BinaryOperator::Create(Op, Val0, Val1, "B", Term));
415 }
416 };
417
418 /// Generate constant values.
419 struct ConstModifier: public Modifier {
ConstModifierllvm::__anond0a2ce370111::ConstModifier420 ConstModifier(BasicBlock *BB, PieceTable *PT, Random *R)
421 : Modifier(BB, PT, R) {}
422
Actllvm::__anond0a2ce370111::ConstModifier423 void Act() override {
424 Type *Ty = pickType();
425
426 if (Ty->isVectorTy()) {
427 switch (getRandom() % 2) {
428 case 0: if (Ty->isIntOrIntVectorTy())
429 return PT->push_back(ConstantVector::getAllOnesValue(Ty));
430 break;
431 case 1: if (Ty->isIntOrIntVectorTy())
432 return PT->push_back(ConstantVector::getNullValue(Ty));
433 }
434 }
435
436 if (Ty->isFloatingPointTy()) {
437 // Generate 128 random bits, the size of the (currently)
438 // largest floating-point types.
439 uint64_t RandomBits[2];
440 for (unsigned i = 0; i < 2; ++i)
441 RandomBits[i] = Ran->Rand64();
442
443 APInt RandomInt(Ty->getPrimitiveSizeInBits(), makeArrayRef(RandomBits));
444 APFloat RandomFloat(Ty->getFltSemantics(), RandomInt);
445
446 if (getRandom() & 1)
447 return PT->push_back(ConstantFP::getNullValue(Ty));
448 return PT->push_back(ConstantFP::get(Ty->getContext(), RandomFloat));
449 }
450
451 if (Ty->isIntegerTy()) {
452 switch (getRandom() % 7) {
453 case 0:
454 return PT->push_back(ConstantInt::get(
455 Ty, APInt::getAllOnesValue(Ty->getPrimitiveSizeInBits())));
456 case 1:
457 return PT->push_back(ConstantInt::get(
458 Ty, APInt::getNullValue(Ty->getPrimitiveSizeInBits())));
459 case 2:
460 case 3:
461 case 4:
462 case 5:
463 case 6:
464 PT->push_back(ConstantInt::get(Ty, getRandom()));
465 }
466 }
467 }
468 };
469
470 struct AllocaModifier: public Modifier {
AllocaModifierllvm::__anond0a2ce370111::AllocaModifier471 AllocaModifier(BasicBlock *BB, PieceTable *PT, Random *R)
472 : Modifier(BB, PT, R) {}
473
Actllvm::__anond0a2ce370111::AllocaModifier474 void Act() override {
475 Type *Tp = pickType();
476 const DataLayout &DL = BB->getModule()->getDataLayout();
477 PT->push_back(new AllocaInst(Tp, DL.getAllocaAddrSpace(),
478 "A", BB->getFirstNonPHI()));
479 }
480 };
481
482 struct ExtractElementModifier: public Modifier {
ExtractElementModifierllvm::__anond0a2ce370111::ExtractElementModifier483 ExtractElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
484 : Modifier(BB, PT, R) {}
485
Actllvm::__anond0a2ce370111::ExtractElementModifier486 void Act() override {
487 Value *Val0 = getRandomVectorValue();
488 Value *V = ExtractElementInst::Create(
489 Val0,
490 ConstantInt::get(
491 Type::getInt32Ty(BB->getContext()),
492 getRandom() %
493 cast<FixedVectorType>(Val0->getType())->getNumElements()),
494 "E", BB->getTerminator());
495 return PT->push_back(V);
496 }
497 };
498
499 struct ShuffModifier: public Modifier {
ShuffModifierllvm::__anond0a2ce370111::ShuffModifier500 ShuffModifier(BasicBlock *BB, PieceTable *PT, Random *R)
501 : Modifier(BB, PT, R) {}
502
Actllvm::__anond0a2ce370111::ShuffModifier503 void Act() override {
504 Value *Val0 = getRandomVectorValue();
505 Value *Val1 = getRandomValue(Val0->getType());
506
507 unsigned Width = cast<FixedVectorType>(Val0->getType())->getNumElements();
508 std::vector<Constant*> Idxs;
509
510 Type *I32 = Type::getInt32Ty(BB->getContext());
511 for (unsigned i=0; i<Width; ++i) {
512 Constant *CI = ConstantInt::get(I32, getRandom() % (Width*2));
513 // Pick some undef values.
514 if (!(getRandom() % 5))
515 CI = UndefValue::get(I32);
516 Idxs.push_back(CI);
517 }
518
519 Constant *Mask = ConstantVector::get(Idxs);
520
521 Value *V = new ShuffleVectorInst(Val0, Val1, Mask, "Shuff",
522 BB->getTerminator());
523 PT->push_back(V);
524 }
525 };
526
527 struct InsertElementModifier: public Modifier {
InsertElementModifierllvm::__anond0a2ce370111::InsertElementModifier528 InsertElementModifier(BasicBlock *BB, PieceTable *PT, Random *R)
529 : Modifier(BB, PT, R) {}
530
Actllvm::__anond0a2ce370111::InsertElementModifier531 void Act() override {
532 Value *Val0 = getRandomVectorValue();
533 Value *Val1 = getRandomValue(Val0->getType()->getScalarType());
534
535 Value *V = InsertElementInst::Create(
536 Val0, Val1,
537 ConstantInt::get(
538 Type::getInt32Ty(BB->getContext()),
539 getRandom() %
540 cast<FixedVectorType>(Val0->getType())->getNumElements()),
541 "I", BB->getTerminator());
542 return PT->push_back(V);
543 }
544 };
545
546 struct CastModifier: public Modifier {
CastModifierllvm::__anond0a2ce370111::CastModifier547 CastModifier(BasicBlock *BB, PieceTable *PT, Random *R)
548 : Modifier(BB, PT, R) {}
549
Actllvm::__anond0a2ce370111::CastModifier550 void Act() override {
551 Value *V = getRandomVal();
552 Type *VTy = V->getType();
553 Type *DestTy = pickScalarType();
554
555 // Handle vector casts vectors.
556 if (VTy->isVectorTy()) {
557 auto *VecTy = cast<FixedVectorType>(VTy);
558 DestTy = pickVectorType(VecTy->getNumElements());
559 }
560
561 // no need to cast.
562 if (VTy == DestTy) return;
563
564 // Pointers:
565 if (VTy->isPointerTy()) {
566 if (!DestTy->isPointerTy())
567 DestTy = PointerType::get(DestTy, 0);
568 return PT->push_back(
569 new BitCastInst(V, DestTy, "PC", BB->getTerminator()));
570 }
571
572 unsigned VSize = VTy->getScalarType()->getPrimitiveSizeInBits();
573 unsigned DestSize = DestTy->getScalarType()->getPrimitiveSizeInBits();
574
575 // Generate lots of bitcasts.
576 if ((getRandom() & 1) && VSize == DestSize) {
577 return PT->push_back(
578 new BitCastInst(V, DestTy, "BC", BB->getTerminator()));
579 }
580
581 // Both types are integers:
582 if (VTy->isIntOrIntVectorTy() && DestTy->isIntOrIntVectorTy()) {
583 if (VSize > DestSize) {
584 return PT->push_back(
585 new TruncInst(V, DestTy, "Tr", BB->getTerminator()));
586 } else {
587 assert(VSize < DestSize && "Different int types with the same size?");
588 if (getRandom() & 1)
589 return PT->push_back(
590 new ZExtInst(V, DestTy, "ZE", BB->getTerminator()));
591 return PT->push_back(new SExtInst(V, DestTy, "Se", BB->getTerminator()));
592 }
593 }
594
595 // Fp to int.
596 if (VTy->isFPOrFPVectorTy() && DestTy->isIntOrIntVectorTy()) {
597 if (getRandom() & 1)
598 return PT->push_back(
599 new FPToSIInst(V, DestTy, "FC", BB->getTerminator()));
600 return PT->push_back(new FPToUIInst(V, DestTy, "FC", BB->getTerminator()));
601 }
602
603 // Int to fp.
604 if (VTy->isIntOrIntVectorTy() && DestTy->isFPOrFPVectorTy()) {
605 if (getRandom() & 1)
606 return PT->push_back(
607 new SIToFPInst(V, DestTy, "FC", BB->getTerminator()));
608 return PT->push_back(new UIToFPInst(V, DestTy, "FC", BB->getTerminator()));
609 }
610
611 // Both floats.
612 if (VTy->isFPOrFPVectorTy() && DestTy->isFPOrFPVectorTy()) {
613 if (VSize > DestSize) {
614 return PT->push_back(
615 new FPTruncInst(V, DestTy, "Tr", BB->getTerminator()));
616 } else if (VSize < DestSize) {
617 return PT->push_back(
618 new FPExtInst(V, DestTy, "ZE", BB->getTerminator()));
619 }
620 // If VSize == DestSize, then the two types must be fp128 and ppc_fp128,
621 // for which there is no defined conversion. So do nothing.
622 }
623 }
624 };
625
626 struct SelectModifier: public Modifier {
SelectModifierllvm::__anond0a2ce370111::SelectModifier627 SelectModifier(BasicBlock *BB, PieceTable *PT, Random *R)
628 : Modifier(BB, PT, R) {}
629
Actllvm::__anond0a2ce370111::SelectModifier630 void Act() override {
631 // Try a bunch of different select configuration until a valid one is found.
632 Value *Val0 = getRandomVal();
633 Value *Val1 = getRandomValue(Val0->getType());
634
635 Type *CondTy = Type::getInt1Ty(Context);
636
637 // If the value type is a vector, and we allow vector select, then in 50%
638 // of the cases generate a vector select.
639 if (isa<FixedVectorType>(Val0->getType()) && (getRandom() & 1)) {
640 unsigned NumElem =
641 cast<FixedVectorType>(Val0->getType())->getNumElements();
642 CondTy = FixedVectorType::get(CondTy, NumElem);
643 }
644
645 Value *Cond = getRandomValue(CondTy);
646 Value *V = SelectInst::Create(Cond, Val0, Val1, "Sl", BB->getTerminator());
647 return PT->push_back(V);
648 }
649 };
650
651 struct CmpModifier: public Modifier {
CmpModifierllvm::__anond0a2ce370111::CmpModifier652 CmpModifier(BasicBlock *BB, PieceTable *PT, Random *R)
653 : Modifier(BB, PT, R) {}
654
Actllvm::__anond0a2ce370111::CmpModifier655 void Act() override {
656 Value *Val0 = getRandomVal();
657 Value *Val1 = getRandomValue(Val0->getType());
658
659 if (Val0->getType()->isPointerTy()) return;
660 bool fp = Val0->getType()->getScalarType()->isFloatingPointTy();
661
662 int op;
663 if (fp) {
664 op = getRandom() %
665 (CmpInst::LAST_FCMP_PREDICATE - CmpInst::FIRST_FCMP_PREDICATE) +
666 CmpInst::FIRST_FCMP_PREDICATE;
667 } else {
668 op = getRandom() %
669 (CmpInst::LAST_ICMP_PREDICATE - CmpInst::FIRST_ICMP_PREDICATE) +
670 CmpInst::FIRST_ICMP_PREDICATE;
671 }
672
673 Value *V = CmpInst::Create(fp ? Instruction::FCmp : Instruction::ICmp,
674 (CmpInst::Predicate)op, Val0, Val1, "Cmp",
675 BB->getTerminator());
676 return PT->push_back(V);
677 }
678 };
679
680 } // end anonymous namespace
681
FillFunction(Function * F,Random & R)682 static void FillFunction(Function *F, Random &R) {
683 // Create a legal entry block.
684 BasicBlock *BB = BasicBlock::Create(F->getContext(), "BB", F);
685 ReturnInst::Create(F->getContext(), BB);
686
687 // Create the value table.
688 Modifier::PieceTable PT;
689
690 // Consider arguments as legal values.
691 for (auto &arg : F->args())
692 PT.push_back(&arg);
693
694 // List of modifiers which add new random instructions.
695 std::vector<std::unique_ptr<Modifier>> Modifiers;
696 Modifiers.emplace_back(new LoadModifier(BB, &PT, &R));
697 Modifiers.emplace_back(new StoreModifier(BB, &PT, &R));
698 auto SM = Modifiers.back().get();
699 Modifiers.emplace_back(new ExtractElementModifier(BB, &PT, &R));
700 Modifiers.emplace_back(new ShuffModifier(BB, &PT, &R));
701 Modifiers.emplace_back(new InsertElementModifier(BB, &PT, &R));
702 Modifiers.emplace_back(new BinModifier(BB, &PT, &R));
703 Modifiers.emplace_back(new CastModifier(BB, &PT, &R));
704 Modifiers.emplace_back(new SelectModifier(BB, &PT, &R));
705 Modifiers.emplace_back(new CmpModifier(BB, &PT, &R));
706
707 // Generate the random instructions
708 AllocaModifier{BB, &PT, &R}.ActN(5); // Throw in a few allocas
709 ConstModifier{BB, &PT, &R}.ActN(40); // Throw in a few constants
710
711 for (unsigned i = 0; i < SizeCL / Modifiers.size(); ++i)
712 for (auto &Mod : Modifiers)
713 Mod->Act();
714
715 SM->ActN(5); // Throw in a few stores.
716 }
717
IntroduceControlFlow(Function * F,Random & R)718 static void IntroduceControlFlow(Function *F, Random &R) {
719 std::vector<Instruction*> BoolInst;
720 for (auto &Instr : F->front()) {
721 if (Instr.getType() == IntegerType::getInt1Ty(F->getContext()))
722 BoolInst.push_back(&Instr);
723 }
724
725 llvm::shuffle(BoolInst.begin(), BoolInst.end(), R);
726
727 for (auto *Instr : BoolInst) {
728 BasicBlock *Curr = Instr->getParent();
729 BasicBlock::iterator Loc = Instr->getIterator();
730 BasicBlock *Next = Curr->splitBasicBlock(Loc, "CF");
731 Instr->moveBefore(Curr->getTerminator());
732 if (Curr != &F->getEntryBlock()) {
733 BranchInst::Create(Curr, Next, Instr, Curr->getTerminator());
734 Curr->getTerminator()->eraseFromParent();
735 }
736 }
737 }
738
739 } // end namespace llvm
740
main(int argc,char ** argv)741 int main(int argc, char **argv) {
742 using namespace llvm;
743
744 InitLLVM X(argc, argv);
745 cl::HideUnrelatedOptions({&StressCategory, &getColorCategory()});
746 cl::ParseCommandLineOptions(argc, argv, "llvm codegen stress-tester\n");
747
748 auto M = std::make_unique<Module>("/tmp/autogen.bc", Context);
749 Function *F = GenEmptyFunction(M.get());
750
751 // Pick an initial seed value
752 Random R(SeedCL);
753 // Generate lots of random instructions inside a single basic block.
754 FillFunction(F, R);
755 // Break the basic block into many loops.
756 IntroduceControlFlow(F, R);
757
758 // Figure out what stream we are supposed to write to...
759 std::unique_ptr<ToolOutputFile> Out;
760 // Default to standard output.
761 if (OutputFilename.empty())
762 OutputFilename = "-";
763
764 std::error_code EC;
765 Out.reset(new ToolOutputFile(OutputFilename, EC, sys::fs::OF_None));
766 if (EC) {
767 errs() << EC.message() << '\n';
768 return 1;
769 }
770
771 legacy::PassManager Passes;
772 Passes.add(createVerifierPass());
773 Passes.add(createPrintModulePass(Out->os()));
774 Passes.run(*M.get());
775 Out->keep();
776
777 return 0;
778 }
779