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