LLVM  8.0.1
RandomIRBuilder.cpp
Go to the documentation of this file.
1 //===-- RandomIRBuilder.cpp -----------------------------------------------===//
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 
11 #include "llvm/ADT/STLExtras.h"
12 #include "llvm/FuzzMutate/Random.h"
13 #include "llvm/IR/BasicBlock.h"
14 #include "llvm/IR/Constants.h"
15 #include "llvm/IR/Function.h"
16 #include "llvm/IR/Instructions.h"
17 #include "llvm/IR/IntrinsicInst.h"
18 
19 using namespace llvm;
20 using namespace fuzzerop;
21 
24  return findOrCreateSource(BB, Insts, {}, anyType());
25 }
26 
29  ArrayRef<Value *> Srcs,
30  SourcePred Pred) {
31  auto MatchesPred = [&Srcs, &Pred](Instruction *Inst) {
32  return Pred.matches(Srcs, Inst);
33  };
34  auto RS = makeSampler(Rand, make_filter_range(Insts, MatchesPred));
35  // Also consider choosing no source, meaning we want a new one.
36  RS.sample(nullptr, /*Weight=*/1);
37  if (Instruction *Src = RS.getSelection())
38  return Src;
39  return newSource(BB, Insts, Srcs, Pred);
40 }
41 
43  ArrayRef<Value *> Srcs, SourcePred Pred) {
44  // Generate some constants to choose from.
45  auto RS = makeSampler<Value *>(Rand);
46  RS.sample(Pred.generate(Srcs, KnownTypes));
47 
48  // If we can find a pointer to load from, use it half the time.
49  Value *Ptr = findPointer(BB, Insts, Srcs, Pred);
50  if (Ptr) {
51  // Create load from the chosen pointer
52  auto IP = BB.getFirstInsertionPt();
53  if (auto *I = dyn_cast<Instruction>(Ptr)) {
54  IP = ++I->getIterator();
55  assert(IP != BB.end() && "guaranteed by the findPointer");
56  }
57  auto *NewLoad = new LoadInst(Ptr, "L", &*IP);
58 
59  // Only sample this load if it really matches the descriptor
60  if (Pred.matches(Srcs, NewLoad))
61  RS.sample(NewLoad, RS.totalWeight());
62  else
63  NewLoad->eraseFromParent();
64  }
65 
66  assert(!RS.isEmpty() && "Failed to generate sources");
67  return RS.getSelection();
68 }
69 
70 static bool isCompatibleReplacement(const Instruction *I, const Use &Operand,
71  const Value *Replacement) {
72  if (Operand->getType() != Replacement->getType())
73  return false;
74  switch (I->getOpcode()) {
75  case Instruction::GetElementPtr:
76  case Instruction::ExtractElement:
77  case Instruction::ExtractValue:
78  // TODO: We could potentially validate these, but for now just leave indices
79  // alone.
80  if (Operand.getOperandNo() >= 1)
81  return false;
82  break;
83  case Instruction::InsertValue:
84  case Instruction::InsertElement:
85  case Instruction::ShuffleVector:
86  if (Operand.getOperandNo() >= 2)
87  return false;
88  break;
89  default:
90  break;
91  }
92  return true;
93 }
94 
96  ArrayRef<Instruction *> Insts, Value *V) {
97  auto RS = makeSampler<Use *>(Rand);
98  for (auto &I : Insts) {
99  if (isa<IntrinsicInst>(I))
100  // TODO: Replacing operands of intrinsics would be interesting, but
101  // there's no easy way to verify that a given replacement is valid given
102  // that intrinsics can impose arbitrary constraints.
103  continue;
104  for (Use &U : I->operands())
105  if (isCompatibleReplacement(I, U, V))
106  RS.sample(&U, 1);
107  }
108  // Also consider choosing no sink, meaning we want a new one.
109  RS.sample(nullptr, /*Weight=*/1);
110 
111  if (Use *Sink = RS.getSelection()) {
112  User *U = Sink->getUser();
113  unsigned OpNo = Sink->getOperandNo();
114  U->setOperand(OpNo, V);
115  return;
116  }
117  newSink(BB, Insts, V);
118 }
119 
121  Value *V) {
122  Value *Ptr = findPointer(BB, Insts, {V}, matchFirstType());
123  if (!Ptr) {
124  if (uniform(Rand, 0, 1))
125  Ptr = new AllocaInst(V->getType(), 0, "A", &*BB.getFirstInsertionPt());
126  else
127  Ptr = UndefValue::get(PointerType::get(V->getType(), 0));
128  }
129 
130  new StoreInst(V, Ptr, Insts.back());
131 }
132 
135  ArrayRef<Value *> Srcs, SourcePred Pred) {
136  auto IsMatchingPtr = [&Srcs, &Pred](Instruction *Inst) {
137  // Invoke instructions sometimes produce valid pointers but currently
138  // we can't insert loads or stores from them
139  if (Inst->isTerminator())
140  return false;
141 
142  if (auto PtrTy = dyn_cast<PointerType>(Inst->getType())) {
143  // We can never generate loads from non first class or non sized types
144  if (!PtrTy->getElementType()->isSized() ||
145  !PtrTy->getElementType()->isFirstClassType())
146  return false;
147 
148  // TODO: Check if this is horribly expensive.
149  return Pred.matches(Srcs, UndefValue::get(PtrTy->getElementType()));
150  }
151  return false;
152  };
153  if (auto RS = makeSampler(Rand, make_filter_range(Insts, IsMatchingPtr)))
154  return RS.getSelection();
155  return nullptr;
156 }
const T & back() const
back - Get the last element.
Definition: ArrayRef.h:158
This class represents lattice values for constants.
Definition: AllocatorList.h:24
Value * findPointer(BasicBlock &BB, ArrayRef< Instruction *> Insts, ArrayRef< Value *> Srcs, fuzzerop::SourcePred Pred)
static PointerType * get(Type *ElementType, unsigned AddressSpace)
This constructs a pointer to an object of the specified type in a numbered address space...
Definition: Type.cpp:630
An instruction for reading from memory.
Definition: Instructions.h:168
A Use represents the edge between a Value definition and its users.
Definition: Use.h:56
T uniform(GenT &Gen, T Min, T Max)
Return a uniformly distributed random value between Min and Max.
Definition: Random.h:22
static SourcePred matchFirstType()
Match values that have the same type as the first source.
Definition: OpDescriptor.h:195
Value * newSource(BasicBlock &BB, ArrayRef< Instruction *> Insts, ArrayRef< Value *> Srcs, fuzzerop::SourcePred Pred)
Create some Value suitable as a source for some operation.
Type * getType() const
All values are typed, get the type of this value.
Definition: Value.h:245
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:33
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
Definition: Instruction.h:126
static SourcePred anyType()
Definition: OpDescriptor.h:106
An instruction for storing to memory.
Definition: Instructions.h:321
unsigned getOperandNo() const
Return the operand # of this use in its User.
Definition: Use.cpp:48
static bool isCompatibleReplacement(const Instruction *I, const Use &Operand, const Value *Replacement)
Value * findOrCreateSource(BasicBlock &BB, ArrayRef< Instruction *> Insts)
Find a "source" for some operation, which will be used in one of the operation&#39;s operands.
const_iterator getFirstInsertionPt() const
Returns an iterator to the first instruction in this block that is suitable for inserting a non-PHI i...
Definition: BasicBlock.cpp:217
LLVM Basic Block Representation.
Definition: BasicBlock.h:58
This file contains the declarations for the subclasses of Constant, which represent the different fla...
ReservoirSampler< ElT, GenT > makeSampler(GenT &RandGen, RangeT &&Items)
Definition: Random.h:76
bool matches(ArrayRef< Value *> Cur, const Value *New)
Returns true if New is compatible for the argument after Cur.
Definition: OpDescriptor.h:78
static UndefValue * get(Type *T)
Static factory methods - Return an &#39;undef&#39; object of the specified type.
Definition: Constants.cpp:1415
void connectToSink(BasicBlock &BB, ArrayRef< Instruction *> Insts, Value *V)
Find a viable user for V in Insts, which should all be contained in BB.
std::vector< Constant * > generate(ArrayRef< Value *> Cur, ArrayRef< Type *> BaseTypes)
Generates a list of potential values for the argument after Cur.
Definition: OpDescriptor.h:83
iterator end()
Definition: BasicBlock.h:271
A matcher/generator for finding suitable values for the next source in an operation&#39;s partially compl...
Definition: OpDescriptor.h:44
void setOperand(unsigned i, Value *Val)
Definition: User.h:175
void newSink(BasicBlock &BB, ArrayRef< Instruction *> Insts, Value *V)
Create a user for V in BB.
#define I(x, y, z)
Definition: MD5.cpp:58
iterator_range< filter_iterator< detail::IterOfRange< RangeT >, PredicateT > > make_filter_range(RangeT &&Range, PredicateT Pred)
Convenience function that takes a range of elements and a predicate, and return a new filter_iterator...
Definition: STLExtras.h:428
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:73
an instruction to allocate memory on the stack
Definition: Instructions.h:60