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