1 //===- OperationsTest.cpp - Tests for fuzzer operations -------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "llvm/FuzzMutate/Operations.h"
10 #include "llvm/AsmParser/Parser.h"
11 #include "llvm/FuzzMutate/OpDescriptor.h"
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Instructions.h"
14 #include "llvm/IR/Module.h"
15 #include "llvm/IR/Verifier.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
21 // Define some pretty printers to help with debugging failures.
23 void PrintTo(Type
*T
, ::std::ostream
*OS
) {
24 raw_os_ostream
ROS(*OS
);
28 void PrintTo(BasicBlock
*BB
, ::std::ostream
*OS
) {
29 raw_os_ostream
ROS(*OS
);
30 ROS
<< BB
<< " (" << BB
->getName() << ")";
33 void PrintTo(Value
*V
, ::std::ostream
*OS
) {
34 raw_os_ostream
ROS(*OS
);
39 void PrintTo(Constant
*C
, ::std::ostream
*OS
) { PrintTo(cast
<Value
>(C
), OS
); }
48 using testing::ElementsAre
;
51 using testing::PrintToString
;
52 using testing::SizeIs
;
56 std::unique_ptr
<Module
> parseAssembly(const char *Assembly
,
57 LLVMContext
&Context
) {
60 std::unique_ptr
<Module
> M
= parseAssemblyString(Assembly
, Error
, Context
);
63 raw_string_ostream
OS(ErrMsg
);
66 assert(M
&& !verifyModule(*M
, &errs()));
70 MATCHER_P(TypesMatch
, V
, "has type " + PrintToString(V
->getType())) {
71 return arg
->getType() == V
->getType();
74 MATCHER_P(HasType
, T
, "") { return arg
->getType() == T
; }
76 TEST(OperationsTest
, SourcePreds
) {
77 using namespace llvm::fuzzerop
;
81 Constant
*i1
= ConstantInt::getFalse(Ctx
);
82 Constant
*i8
= ConstantInt::get(Type::getInt8Ty(Ctx
), 3);
83 Constant
*i16
= ConstantInt::get(Type::getInt16Ty(Ctx
), 1 << 15);
84 Constant
*i32
= ConstantInt::get(Type::getInt32Ty(Ctx
), 0);
85 Constant
*i64
= ConstantInt::get(Type::getInt64Ty(Ctx
),
86 std::numeric_limits
<uint64_t>::max());
87 Constant
*f16
= ConstantFP::getInfinity(Type::getHalfTy(Ctx
));
88 Constant
*f32
= ConstantFP::get(Type::getFloatTy(Ctx
), 0.0);
89 Constant
*f64
= ConstantFP::get(Type::getDoubleTy(Ctx
), 123.45);
90 Constant
*s
= ConstantStruct::get(StructType::create(Ctx
, "OpaqueStruct"));
92 ConstantArray::get(ArrayType::get(i32
->getType(), 2), {i32
, i32
});
93 Constant
*v8i1
= ConstantVector::getSplat(ElementCount::getFixed(8), i1
);
94 Constant
*v8i8
= ConstantVector::getSplat(ElementCount::getFixed(8), i8
);
95 Constant
*v4f16
= ConstantVector::getSplat(ElementCount::getFixed(4), f16
);
97 ConstantPointerNull::get(PointerType::get(i32
->getType(), 0));
99 ConstantVector::getSplat(ElementCount::getFixed(8), p0i32
);
100 Constant
*vni32
= ConstantVector::getSplat(ElementCount::getScalable(8), i32
);
101 Constant
*vnf64
= ConstantVector::getSplat(ElementCount::getScalable(8), f64
);
103 ConstantVector::getSplat(ElementCount::getScalable(8), p0i32
);
105 auto OnlyI32
= onlyType(i32
->getType());
106 EXPECT_TRUE(OnlyI32
.matches({}, i32
));
107 EXPECT_FALSE(OnlyI32
.matches({}, i64
));
108 EXPECT_FALSE(OnlyI32
.matches({}, p0i32
));
109 EXPECT_FALSE(OnlyI32
.matches({}, a
));
111 EXPECT_THAT(OnlyI32
.generate({}, {}),
112 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32
))));
114 auto AnyType
= anyType();
115 EXPECT_TRUE(AnyType
.matches({}, i1
));
116 EXPECT_TRUE(AnyType
.matches({}, f64
));
117 EXPECT_TRUE(AnyType
.matches({}, s
));
118 EXPECT_TRUE(AnyType
.matches({}, v8i8
));
119 EXPECT_TRUE(AnyType
.matches({}, p0i32
));
122 AnyType
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
123 Each(AnyOf(TypesMatch(i32
), TypesMatch(f16
), TypesMatch(v8i8
))));
125 auto AnyInt
= anyIntType();
126 EXPECT_TRUE(AnyInt
.matches({}, i1
));
127 EXPECT_TRUE(AnyInt
.matches({}, i64
));
128 EXPECT_FALSE(AnyInt
.matches({}, f32
));
129 EXPECT_FALSE(AnyInt
.matches({}, v4f16
));
132 AnyInt
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
133 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32
))));
135 auto AnyIntOrVecInt
= anyIntOrVecIntType();
136 EXPECT_TRUE(AnyIntOrVecInt
.matches({}, i1
));
137 EXPECT_TRUE(AnyIntOrVecInt
.matches({}, i64
));
138 EXPECT_FALSE(AnyIntOrVecInt
.matches({}, f32
));
139 EXPECT_FALSE(AnyIntOrVecInt
.matches({}, v4f16
));
140 EXPECT_TRUE(AnyIntOrVecInt
.matches({}, v8i8
));
141 EXPECT_FALSE(AnyIntOrVecInt
.matches({}, v4f16
));
142 EXPECT_FALSE(AnyIntOrVecInt
.matches({}, v8p0i32
));
143 EXPECT_TRUE(AnyIntOrVecInt
.matches({}, vni32
));
144 EXPECT_FALSE(AnyIntOrVecInt
.matches({}, vnf64
));
145 EXPECT_FALSE(AnyIntOrVecInt
.matches({}, vnp0i32
));
147 EXPECT_THAT(AnyIntOrVecInt
.generate({}, {v8i8
->getType()}),
148 AllOf(Each(TypesMatch(v8i8
))));
150 auto BoolOrVecBool
= boolOrVecBoolType();
151 EXPECT_TRUE(BoolOrVecBool
.matches({}, i1
));
152 EXPECT_FALSE(BoolOrVecBool
.matches({}, i64
));
153 EXPECT_FALSE(BoolOrVecBool
.matches({}, f32
));
154 EXPECT_FALSE(BoolOrVecBool
.matches({}, v4f16
));
155 EXPECT_TRUE(BoolOrVecBool
.matches({}, v8i1
));
156 EXPECT_FALSE(BoolOrVecBool
.matches({}, v4f16
));
157 EXPECT_FALSE(BoolOrVecBool
.matches({}, v8p0i32
));
158 EXPECT_FALSE(BoolOrVecBool
.matches({}, vni32
));
159 EXPECT_FALSE(BoolOrVecBool
.matches({}, vnf64
));
160 EXPECT_FALSE(BoolOrVecBool
.matches({}, vnp0i32
));
162 EXPECT_THAT(BoolOrVecBool
.generate({}, {v8i8
->getType(), v8i1
->getType()}),
163 AllOf(Each(TypesMatch(v8i1
))));
165 auto AnyFP
= anyFloatType();
166 EXPECT_TRUE(AnyFP
.matches({}, f16
));
167 EXPECT_TRUE(AnyFP
.matches({}, f32
));
168 EXPECT_FALSE(AnyFP
.matches({}, i16
));
169 EXPECT_FALSE(AnyFP
.matches({}, p0i32
));
170 EXPECT_FALSE(AnyFP
.matches({}, v4f16
));
173 AnyFP
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
174 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16
))));
176 auto AnyFPOrVecFP
= anyFloatOrVecFloatType();
177 EXPECT_TRUE(AnyFPOrVecFP
.matches({}, f16
));
178 EXPECT_TRUE(AnyFPOrVecFP
.matches({}, f32
));
179 EXPECT_FALSE(AnyFPOrVecFP
.matches({}, i16
));
180 EXPECT_FALSE(AnyFPOrVecFP
.matches({}, p0i32
));
181 EXPECT_TRUE(AnyFPOrVecFP
.matches({}, v4f16
));
182 EXPECT_FALSE(AnyFPOrVecFP
.matches({}, v8p0i32
));
183 EXPECT_FALSE(AnyFPOrVecFP
.matches({}, vni32
));
184 EXPECT_TRUE(AnyFPOrVecFP
.matches({}, vnf64
));
185 EXPECT_FALSE(AnyFPOrVecFP
.matches({}, vnp0i32
));
187 EXPECT_THAT(AnyFPOrVecFP
.generate(
188 {}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
189 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16
))));
190 EXPECT_THAT(AnyFPOrVecFP
.generate({}, {v4f16
->getType()}),
191 AllOf(SizeIs(Ge(1u)), Each(TypesMatch(v4f16
))));
193 auto AnyPtr
= anyPtrType();
194 EXPECT_TRUE(AnyPtr
.matches({}, p0i32
));
195 EXPECT_FALSE(AnyPtr
.matches({}, i8
));
196 EXPECT_FALSE(AnyPtr
.matches({}, a
));
197 EXPECT_FALSE(AnyPtr
.matches({}, v8i8
));
198 EXPECT_FALSE(AnyPtr
.matches({}, v8p0i32
));
199 EXPECT_FALSE(AnyPtr
.matches({}, vni32
));
201 auto isPointer
= [](Value
*V
) { return V
->getType()->isPointerTy(); };
203 AnyPtr
.generate({}, {i32
->getType(), f16
->getType(), v8i8
->getType()}),
204 AllOf(SizeIs(Ge(3u)), Each(Truly(isPointer
))));
206 auto AnyVec
= anyVectorType();
207 EXPECT_TRUE(AnyVec
.matches({}, v8i8
));
208 EXPECT_TRUE(AnyVec
.matches({}, v4f16
));
209 EXPECT_FALSE(AnyVec
.matches({}, i8
));
210 EXPECT_FALSE(AnyVec
.matches({}, a
));
211 EXPECT_FALSE(AnyVec
.matches({}, s
));
212 EXPECT_TRUE(AnyVec
.matches({}, v8p0i32
));
213 EXPECT_TRUE(AnyVec
.matches({}, vni32
));
214 EXPECT_TRUE(AnyVec
.matches({}, vnf64
));
215 EXPECT_TRUE(AnyVec
.matches({}, vnp0i32
));
217 EXPECT_THAT(AnyVec
.generate({}, {v8i8
->getType()}), Each(TypesMatch(v8i8
)));
219 auto First
= matchFirstType();
220 EXPECT_TRUE(First
.matches({i8
}, i8
));
221 EXPECT_TRUE(First
.matches({s
, a
}, s
));
222 EXPECT_FALSE(First
.matches({f16
}, f32
));
223 EXPECT_FALSE(First
.matches({v4f16
, f64
}, f64
));
225 EXPECT_THAT(First
.generate({i8
}, {}), Each(TypesMatch(i8
)));
226 EXPECT_THAT(First
.generate({f16
}, {i8
->getType()}), Each(TypesMatch(f16
)));
227 EXPECT_THAT(First
.generate({v8i8
, i32
}, {}), Each(TypesMatch(v8i8
)));
229 auto FirstLength
= matchFirstLengthWAnyType();
230 EXPECT_TRUE(FirstLength
.matches({v8i8
}, v8i1
));
232 EXPECT_THAT(FirstLength
.generate({v8i1
}, {i8
->getType()}),
233 Each(TypesMatch(v8i8
)));
235 auto Second
= matchSecondType();
236 EXPECT_TRUE(Second
.matches({i32
, i8
}, i8
));
237 EXPECT_TRUE(Second
.matches({i8
, f16
}, f16
));
239 EXPECT_THAT(Second
.generate({v8i8
, i32
}, {}), Each(TypesMatch(i32
)));
240 EXPECT_THAT(Second
.generate({f32
, f16
}, {f16
->getType()}),
241 Each(TypesMatch(f16
)));
243 auto FirstScalar
= matchScalarOfFirstType();
244 EXPECT_TRUE(FirstScalar
.matches({v8i8
}, i8
));
245 EXPECT_TRUE(FirstScalar
.matches({i8
}, i8
));
246 EXPECT_TRUE(FirstScalar
.matches({v4f16
}, f16
));
248 EXPECT_THAT(FirstScalar
.generate({v8i8
}, {i8
->getType()}),
249 Each(TypesMatch(i8
)));
252 TEST(OperationsTest
, SplitBlock
) {
256 Function
*F
= Function::Create(FunctionType::get(Type::getVoidTy(Ctx
), {},
258 GlobalValue::ExternalLinkage
, "f", &M
);
259 auto SBOp
= fuzzerop::splitBlockDescriptor(1);
261 // Create a block with only a return and split it on the return.
262 auto *BB
= BasicBlock::Create(Ctx
, "BB", F
);
263 auto *RI
= ReturnInst::Create(Ctx
, BB
);
264 SBOp
.BuilderFunc({UndefValue::get(Type::getInt1Ty(Ctx
))}, RI
);
266 // We should end up with an unconditional branch from BB to BB1, and the
267 // return ends up in BB1.
268 auto *UncondBr
= cast
<BranchInst
>(BB
->getTerminator());
269 ASSERT_TRUE(UncondBr
->isUnconditional());
270 auto *BB1
= UncondBr
->getSuccessor(0);
271 ASSERT_THAT(RI
->getParent(), Eq(BB1
));
273 // Now add an instruction to BB1 and split on that.
274 auto *AI
= new AllocaInst(Type::getInt8Ty(Ctx
), 0, "a", RI
);
275 Value
*Cond
= ConstantInt::getFalse(Ctx
);
276 SBOp
.BuilderFunc({Cond
}, AI
);
278 // We should end up with a loop back on BB1 and the instruction we split on
280 auto *CondBr
= cast
<BranchInst
>(BB1
->getTerminator());
281 EXPECT_THAT(CondBr
->getCondition(), Eq(Cond
));
282 ASSERT_THAT(CondBr
->getNumSuccessors(), Eq(2u));
283 ASSERT_THAT(CondBr
->getSuccessor(0), Eq(BB1
));
284 auto *BB2
= CondBr
->getSuccessor(1);
285 EXPECT_THAT(AI
->getParent(), Eq(BB2
));
286 EXPECT_THAT(RI
->getParent(), Eq(BB2
));
288 EXPECT_FALSE(verifyModule(M
, &errs()));
291 TEST(OperationsTest
, SplitEHBlock
) {
292 // Check that we will not try to branch back to the landingpad block using
293 // regular branch instruction
296 const char *SourceCode
=
298 "declare i32 @personality_function()"
299 "define ptr @test() personality ptr @personality_function {\n"
301 " %val = invoke ptr @f()\n"
302 " to label %normal unwind label %exceptional\n"
306 " %landing_pad4 = landingpad token cleanup\n"
309 auto M
= parseAssembly(SourceCode
, Ctx
);
311 // Get the landingpad block
312 BasicBlock
&BB
= *std::next(M
->getFunction("test")->begin(), 2);
314 fuzzerop::OpDescriptor Descr
= fuzzerop::splitBlockDescriptor(1);
316 Descr
.BuilderFunc({ConstantInt::getTrue(Ctx
)}, &*BB
.getFirstInsertionPt());
317 ASSERT_TRUE(!verifyModule(*M
, &errs()));
320 TEST(OperationsTest
, SplitBlockWithPhis
) {
323 Type
*Int8Ty
= Type::getInt8Ty(Ctx
);
326 Function
*F
= Function::Create(FunctionType::get(Type::getVoidTy(Ctx
), {},
328 GlobalValue::ExternalLinkage
, "f", &M
);
329 auto SBOp
= fuzzerop::splitBlockDescriptor(1);
331 // Create 3 blocks with an if-then branch.
332 auto *BB1
= BasicBlock::Create(Ctx
, "BB1", F
);
333 auto *BB2
= BasicBlock::Create(Ctx
, "BB2", F
);
334 auto *BB3
= BasicBlock::Create(Ctx
, "BB3", F
);
335 BranchInst::Create(BB2
, BB3
, ConstantInt::getFalse(Ctx
), BB1
);
336 BranchInst::Create(BB3
, BB2
);
338 // Set up phi nodes selecting values for the incoming edges.
339 auto *PHI1
= PHINode::Create(Int8Ty
, /*NumReservedValues=*/2, "p1", BB3
);
340 PHI1
->addIncoming(ConstantInt::get(Int8Ty
, 0), BB1
);
341 PHI1
->addIncoming(ConstantInt::get(Int8Ty
, 1), BB2
);
342 auto *PHI2
= PHINode::Create(Int8Ty
, /*NumReservedValues=*/2, "p2", BB3
);
343 PHI2
->addIncoming(ConstantInt::get(Int8Ty
, 1), BB1
);
344 PHI2
->addIncoming(ConstantInt::get(Int8Ty
, 0), BB2
);
345 auto *RI
= ReturnInst::Create(Ctx
, BB3
);
347 // Now we split the block with PHI nodes, making sure they're all updated.
348 Value
*Cond
= ConstantInt::getFalse(Ctx
);
349 SBOp
.BuilderFunc({Cond
}, RI
);
351 // Make sure the PHIs are updated with a value for the third incoming edge.
352 EXPECT_THAT(PHI1
->getNumIncomingValues(), Eq(3u));
353 EXPECT_THAT(PHI2
->getNumIncomingValues(), Eq(3u));
354 EXPECT_FALSE(verifyModule(M
, &errs()));
357 TEST(OperationsTest
, GEP
) {
360 Type
*Int8PtrTy
= PointerType::getUnqual(Ctx
);
361 Type
*Int32Ty
= Type::getInt32Ty(Ctx
);
364 Function
*F
= Function::Create(FunctionType::get(Type::getVoidTy(Ctx
), {},
366 GlobalValue::ExternalLinkage
, "f", &M
);
367 auto *BB
= BasicBlock::Create(Ctx
, "BB", F
);
368 auto *RI
= ReturnInst::Create(Ctx
, BB
);
370 auto GEPOp
= fuzzerop::gepDescriptor(1);
371 EXPECT_TRUE(GEPOp
.SourcePreds
[0].matches({}, UndefValue::get(Int8PtrTy
)));
372 EXPECT_TRUE(GEPOp
.SourcePreds
[1].matches({UndefValue::get(Int8PtrTy
)},
373 ConstantInt::get(Int32Ty
, 0)));
375 GEPOp
.BuilderFunc({UndefValue::get(Int8PtrTy
), ConstantInt::get(Int32Ty
, 0)},
377 EXPECT_FALSE(verifyModule(M
, &errs()));
380 TEST(OperationsTest
, GEPPointerOperand
) {
381 // Check that we only pick sized pointers for the GEP instructions
384 const char *SourceCode
= "%opaque = type opaque\n"
385 "declare void @f()\n"
386 "define void @test(%opaque %o) {\n"
387 " %a = alloca i64, i32 10\n"
390 auto M
= parseAssembly(SourceCode
, Ctx
);
392 fuzzerop::OpDescriptor Descr
= fuzzerop::gepDescriptor(1);
394 // Get first basic block of the test function
395 Function
&F
= *M
->getFunction("test");
396 BasicBlock
&BB
= *F
.begin();
399 ASSERT_FALSE(Descr
.SourcePreds
[0].matches({}, &*F
.arg_begin()));
402 ASSERT_TRUE(Descr
.SourcePreds
[0].matches({}, &*BB
.begin()));
405 TEST(OperationsTest
, ExtractAndInsertValue
) {
408 Type
*Int8PtrTy
= PointerType::getUnqual(Ctx
);
409 Type
*Int32Ty
= Type::getInt32Ty(Ctx
);
410 Type
*Int64Ty
= Type::getInt64Ty(Ctx
);
412 Type
*StructTy
= StructType::create(Ctx
, {Int8PtrTy
, Int32Ty
});
413 Type
*OpaqueTy
= StructType::create(Ctx
, "OpaqueStruct");
414 Type
*ZeroSizedArrayTy
= ArrayType::get(Int64Ty
, 0);
415 Type
*ArrayTy
= ArrayType::get(Int64Ty
, 4);
416 Type
*VectorTy
= FixedVectorType::get(Int32Ty
, 2);
418 auto EVOp
= fuzzerop::extractValueDescriptor(1);
419 auto IVOp
= fuzzerop::insertValueDescriptor(1);
421 // Sanity check the source preds.
422 Constant
*SVal
= UndefValue::get(StructTy
);
423 Constant
*OVal
= UndefValue::get(OpaqueTy
);
424 Constant
*AVal
= UndefValue::get(ArrayTy
);
425 Constant
*ZAVal
= UndefValue::get(ZeroSizedArrayTy
);
426 Constant
*VVal
= UndefValue::get(VectorTy
);
428 EXPECT_TRUE(EVOp
.SourcePreds
[0].matches({}, SVal
));
429 EXPECT_FALSE(EVOp
.SourcePreds
[0].matches({}, OVal
));
430 EXPECT_TRUE(EVOp
.SourcePreds
[0].matches({}, AVal
));
431 EXPECT_FALSE(EVOp
.SourcePreds
[0].matches({}, VVal
));
432 EXPECT_TRUE(IVOp
.SourcePreds
[0].matches({}, SVal
));
433 EXPECT_FALSE(IVOp
.SourcePreds
[0].matches({}, OVal
));
434 EXPECT_TRUE(IVOp
.SourcePreds
[0].matches({}, AVal
));
435 EXPECT_FALSE(IVOp
.SourcePreds
[0].matches({}, VVal
));
437 // Don't consider zero sized arrays as viable sources
438 EXPECT_FALSE(EVOp
.SourcePreds
[0].matches({}, ZAVal
));
439 EXPECT_FALSE(IVOp
.SourcePreds
[0].matches({}, ZAVal
));
441 // Make sure we're range checking appropriately.
443 EVOp
.SourcePreds
[1].matches({SVal
}, ConstantInt::get(Int32Ty
, 0)));
445 EVOp
.SourcePreds
[1].matches({SVal
}, ConstantInt::get(Int32Ty
, 1)));
447 EVOp
.SourcePreds
[1].matches({SVal
}, ConstantInt::get(Int32Ty
, 2)));
449 EVOp
.SourcePreds
[1].matches({OVal
}, ConstantInt::get(Int32Ty
, 0)));
451 EVOp
.SourcePreds
[1].matches({OVal
}, ConstantInt::get(Int32Ty
, 65536)));
453 EVOp
.SourcePreds
[1].matches({AVal
}, ConstantInt::get(Int32Ty
, 0)));
455 EVOp
.SourcePreds
[1].matches({AVal
}, ConstantInt::get(Int32Ty
, 3)));
457 EVOp
.SourcePreds
[1].matches({AVal
}, ConstantInt::get(Int32Ty
, 4)));
460 EVOp
.SourcePreds
[1].generate({SVal
}, {}),
461 ElementsAre(ConstantInt::get(Int32Ty
, 0), ConstantInt::get(Int32Ty
, 1)));
463 // InsertValue should accept any type in the struct, but only in positions
464 // where it makes sense.
465 EXPECT_TRUE(IVOp
.SourcePreds
[1].matches({SVal
}, UndefValue::get(Int8PtrTy
)));
466 EXPECT_TRUE(IVOp
.SourcePreds
[1].matches({SVal
}, UndefValue::get(Int32Ty
)));
467 EXPECT_FALSE(IVOp
.SourcePreds
[1].matches({SVal
}, UndefValue::get(Int64Ty
)));
468 EXPECT_FALSE(IVOp
.SourcePreds
[2].matches({SVal
, UndefValue::get(Int32Ty
)},
469 ConstantInt::get(Int32Ty
, 0)));
470 EXPECT_TRUE(IVOp
.SourcePreds
[2].matches({SVal
, UndefValue::get(Int32Ty
)},
471 ConstantInt::get(Int32Ty
, 1)));
473 EXPECT_THAT(IVOp
.SourcePreds
[1].generate({SVal
}, {}),
474 Each(AnyOf(HasType(Int32Ty
), HasType(Int8PtrTy
))));
476 IVOp
.SourcePreds
[2].generate({SVal
, ConstantInt::get(Int32Ty
, 0)}, {}),
477 ElementsAre(ConstantInt::get(Int32Ty
, 1)));