xref: /llvm-project/llvm/unittests/FuzzMutate/OperationsTest.cpp (revision 97d691b4b3f5ba446d6827fc29fbe15e44a7adac)
1 //===- OperationsTest.cpp - Tests for fuzzer operations -------------------===//
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 #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"
19 #include <iostream>
20 
21 // Define some pretty printers to help with debugging failures.
22 namespace llvm {
23 void PrintTo(Type *T, ::std::ostream *OS) {
24   raw_os_ostream ROS(*OS);
25   T->print(ROS);
26 }
27 
28 void PrintTo(BasicBlock *BB, ::std::ostream *OS) {
29   raw_os_ostream ROS(*OS);
30   ROS << BB << " (" << BB->getName() << ")";
31 }
32 
33 void PrintTo(Value *V, ::std::ostream *OS) {
34   raw_os_ostream ROS(*OS);
35   ROS << V << " (";
36   V->print(ROS);
37   ROS << ")";
38 }
39 void PrintTo(Constant *C, ::std::ostream *OS) { PrintTo(cast<Value>(C), OS); }
40 
41 } // namespace llvm
42 
43 using namespace llvm;
44 
45 using testing::AllOf;
46 using testing::AnyOf;
47 using testing::Each;
48 using testing::ElementsAre;
49 using testing::Eq;
50 using testing::Ge;
51 using testing::PrintToString;
52 using testing::SizeIs;
53 using testing::Truly;
54 
55 namespace {
56 std::unique_ptr<Module> parseAssembly(const char *Assembly,
57                                       LLVMContext &Context) {
58 
59   SMDiagnostic Error;
60   std::unique_ptr<Module> M = parseAssemblyString(Assembly, Error, Context);
61 
62   std::string ErrMsg;
63   raw_string_ostream OS(ErrMsg);
64   Error.print("", OS);
65 
66   assert(M && !verifyModule(*M, &errs()));
67   return M;
68 }
69 
70 MATCHER_P(TypesMatch, V, "has type " + PrintToString(V->getType())) {
71   return arg->getType() == V->getType();
72 }
73 
74 MATCHER_P(HasType, T, "") { return arg->getType() == T; }
75 
76 TEST(OperationsTest, SourcePreds) {
77   using namespace llvm::fuzzerop;
78 
79   LLVMContext Ctx;
80 
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"));
91   Constant *a =
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);
96   Constant *p0i32 = ConstantPointerNull::get(PointerType::get(Ctx, 0));
97   Constant *v8p0i32 =
98       ConstantVector::getSplat(ElementCount::getFixed(8), p0i32);
99   Constant *vni32 = ConstantVector::getSplat(ElementCount::getScalable(8), i32);
100   Constant *vnf64 = ConstantVector::getSplat(ElementCount::getScalable(8), f64);
101   Constant *vnp0i32 =
102       ConstantVector::getSplat(ElementCount::getScalable(8), p0i32);
103 
104   auto OnlyI32 = onlyType(i32->getType());
105   EXPECT_TRUE(OnlyI32.matches({}, i32));
106   EXPECT_FALSE(OnlyI32.matches({}, i64));
107   EXPECT_FALSE(OnlyI32.matches({}, p0i32));
108   EXPECT_FALSE(OnlyI32.matches({}, a));
109 
110   EXPECT_THAT(OnlyI32.generate({}, {}),
111               AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
112 
113   auto AnyType = anyType();
114   EXPECT_TRUE(AnyType.matches({}, i1));
115   EXPECT_TRUE(AnyType.matches({}, f64));
116   EXPECT_TRUE(AnyType.matches({}, s));
117   EXPECT_TRUE(AnyType.matches({}, v8i8));
118   EXPECT_TRUE(AnyType.matches({}, p0i32));
119 
120   EXPECT_THAT(
121       AnyType.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
122       Each(AnyOf(TypesMatch(i32), TypesMatch(f16), TypesMatch(v8i8))));
123 
124   auto AnyInt = anyIntType();
125   EXPECT_TRUE(AnyInt.matches({}, i1));
126   EXPECT_TRUE(AnyInt.matches({}, i64));
127   EXPECT_FALSE(AnyInt.matches({}, f32));
128   EXPECT_FALSE(AnyInt.matches({}, v4f16));
129 
130   EXPECT_THAT(
131       AnyInt.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
132       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(i32))));
133 
134   auto AnyIntOrVecInt = anyIntOrVecIntType();
135   EXPECT_TRUE(AnyIntOrVecInt.matches({}, i1));
136   EXPECT_TRUE(AnyIntOrVecInt.matches({}, i64));
137   EXPECT_FALSE(AnyIntOrVecInt.matches({}, f32));
138   EXPECT_FALSE(AnyIntOrVecInt.matches({}, v4f16));
139   EXPECT_TRUE(AnyIntOrVecInt.matches({}, v8i8));
140   EXPECT_FALSE(AnyIntOrVecInt.matches({}, v4f16));
141   EXPECT_FALSE(AnyIntOrVecInt.matches({}, v8p0i32));
142   EXPECT_TRUE(AnyIntOrVecInt.matches({}, vni32));
143   EXPECT_FALSE(AnyIntOrVecInt.matches({}, vnf64));
144   EXPECT_FALSE(AnyIntOrVecInt.matches({}, vnp0i32));
145 
146   EXPECT_THAT(AnyIntOrVecInt.generate({}, {v8i8->getType()}),
147               AllOf(Each(TypesMatch(v8i8))));
148 
149   auto BoolOrVecBool = boolOrVecBoolType();
150   EXPECT_TRUE(BoolOrVecBool.matches({}, i1));
151   EXPECT_FALSE(BoolOrVecBool.matches({}, i64));
152   EXPECT_FALSE(BoolOrVecBool.matches({}, f32));
153   EXPECT_FALSE(BoolOrVecBool.matches({}, v4f16));
154   EXPECT_TRUE(BoolOrVecBool.matches({}, v8i1));
155   EXPECT_FALSE(BoolOrVecBool.matches({}, v4f16));
156   EXPECT_FALSE(BoolOrVecBool.matches({}, v8p0i32));
157   EXPECT_FALSE(BoolOrVecBool.matches({}, vni32));
158   EXPECT_FALSE(BoolOrVecBool.matches({}, vnf64));
159   EXPECT_FALSE(BoolOrVecBool.matches({}, vnp0i32));
160 
161   EXPECT_THAT(BoolOrVecBool.generate({}, {v8i8->getType(), v8i1->getType()}),
162               AllOf(Each(TypesMatch(v8i1))));
163 
164   auto AnyFP = anyFloatType();
165   EXPECT_TRUE(AnyFP.matches({}, f16));
166   EXPECT_TRUE(AnyFP.matches({}, f32));
167   EXPECT_FALSE(AnyFP.matches({}, i16));
168   EXPECT_FALSE(AnyFP.matches({}, p0i32));
169   EXPECT_FALSE(AnyFP.matches({}, v4f16));
170 
171   EXPECT_THAT(
172       AnyFP.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
173       AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
174 
175   auto AnyFPOrVecFP = anyFloatOrVecFloatType();
176   EXPECT_TRUE(AnyFPOrVecFP.matches({}, f16));
177   EXPECT_TRUE(AnyFPOrVecFP.matches({}, f32));
178   EXPECT_FALSE(AnyFPOrVecFP.matches({}, i16));
179   EXPECT_FALSE(AnyFPOrVecFP.matches({}, p0i32));
180   EXPECT_TRUE(AnyFPOrVecFP.matches({}, v4f16));
181   EXPECT_FALSE(AnyFPOrVecFP.matches({}, v8p0i32));
182   EXPECT_FALSE(AnyFPOrVecFP.matches({}, vni32));
183   EXPECT_TRUE(AnyFPOrVecFP.matches({}, vnf64));
184   EXPECT_FALSE(AnyFPOrVecFP.matches({}, vnp0i32));
185 
186   EXPECT_THAT(AnyFPOrVecFP.generate(
187                   {}, {i32->getType(), f16->getType(), v8i8->getType()}),
188               AllOf(SizeIs(Ge(1u)), Each(TypesMatch(f16))));
189   EXPECT_THAT(AnyFPOrVecFP.generate({}, {v4f16->getType()}),
190               AllOf(SizeIs(Ge(1u)), Each(TypesMatch(v4f16))));
191 
192   auto AnyPtr = anyPtrType();
193   EXPECT_TRUE(AnyPtr.matches({}, p0i32));
194   EXPECT_FALSE(AnyPtr.matches({}, i8));
195   EXPECT_FALSE(AnyPtr.matches({}, a));
196   EXPECT_FALSE(AnyPtr.matches({}, v8i8));
197   EXPECT_FALSE(AnyPtr.matches({}, v8p0i32));
198   EXPECT_FALSE(AnyPtr.matches({}, vni32));
199 
200   auto isPointer = [](Value *V) { return V->getType()->isPointerTy(); };
201   EXPECT_THAT(
202       AnyPtr.generate({}, {i32->getType(), f16->getType(), v8i8->getType()}),
203       AllOf(SizeIs(Ge(3u)), Each(Truly(isPointer))));
204 
205   auto AnyVec = anyVectorType();
206   EXPECT_TRUE(AnyVec.matches({}, v8i8));
207   EXPECT_TRUE(AnyVec.matches({}, v4f16));
208   EXPECT_FALSE(AnyVec.matches({}, i8));
209   EXPECT_FALSE(AnyVec.matches({}, a));
210   EXPECT_FALSE(AnyVec.matches({}, s));
211   EXPECT_TRUE(AnyVec.matches({}, v8p0i32));
212   EXPECT_TRUE(AnyVec.matches({}, vni32));
213   EXPECT_TRUE(AnyVec.matches({}, vnf64));
214   EXPECT_TRUE(AnyVec.matches({}, vnp0i32));
215 
216   EXPECT_THAT(AnyVec.generate({}, {v8i8->getType()}), Each(TypesMatch(v8i8)));
217 
218   auto First = matchFirstType();
219   EXPECT_TRUE(First.matches({i8}, i8));
220   EXPECT_TRUE(First.matches({s, a}, s));
221   EXPECT_FALSE(First.matches({f16}, f32));
222   EXPECT_FALSE(First.matches({v4f16, f64}, f64));
223 
224   EXPECT_THAT(First.generate({i8}, {}), Each(TypesMatch(i8)));
225   EXPECT_THAT(First.generate({f16}, {i8->getType()}), Each(TypesMatch(f16)));
226   EXPECT_THAT(First.generate({v8i8, i32}, {}), Each(TypesMatch(v8i8)));
227 
228   auto FirstLength = matchFirstLengthWAnyType();
229   EXPECT_TRUE(FirstLength.matches({v8i8}, v8i1));
230 
231   EXPECT_THAT(FirstLength.generate({v8i1}, {i8->getType()}),
232               Each(TypesMatch(v8i8)));
233 
234   auto Second = matchSecondType();
235   EXPECT_TRUE(Second.matches({i32, i8}, i8));
236   EXPECT_TRUE(Second.matches({i8, f16}, f16));
237 
238   EXPECT_THAT(Second.generate({v8i8, i32}, {}), Each(TypesMatch(i32)));
239   EXPECT_THAT(Second.generate({f32, f16}, {f16->getType()}),
240               Each(TypesMatch(f16)));
241 
242   auto FirstScalar = matchScalarOfFirstType();
243   EXPECT_TRUE(FirstScalar.matches({v8i8}, i8));
244   EXPECT_TRUE(FirstScalar.matches({i8}, i8));
245   EXPECT_TRUE(FirstScalar.matches({v4f16}, f16));
246 
247   EXPECT_THAT(FirstScalar.generate({v8i8}, {i8->getType()}),
248               Each(TypesMatch(i8)));
249 }
250 
251 TEST(OperationsTest, SplitBlock) {
252   LLVMContext Ctx;
253 
254   Module M("M", Ctx);
255   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
256                                                    /*isVarArg=*/false),
257                                  GlobalValue::ExternalLinkage, "f", &M);
258   auto SBOp = fuzzerop::splitBlockDescriptor(1);
259 
260   // Create a block with only a return and split it on the return.
261   auto *BB = BasicBlock::Create(Ctx, "BB", F);
262   auto *RI = ReturnInst::Create(Ctx, BB);
263   SBOp.BuilderFunc({PoisonValue::get(Type::getInt1Ty(Ctx))}, RI->getIterator());
264 
265   // We should end up with an unconditional branch from BB to BB1, and the
266   // return ends up in BB1.
267   auto *UncondBr = cast<BranchInst>(BB->getTerminator());
268   ASSERT_TRUE(UncondBr->isUnconditional());
269   auto *BB1 = UncondBr->getSuccessor(0);
270   ASSERT_THAT(RI->getParent(), Eq(BB1));
271 
272   // Now add an instruction to BB1 and split on that.
273   auto *AI = new AllocaInst(Type::getInt8Ty(Ctx), 0, "a", RI->getIterator());
274   Value *Cond = ConstantInt::getFalse(Ctx);
275   SBOp.BuilderFunc({Cond}, AI->getIterator());
276 
277   // We should end up with a loop back on BB1 and the instruction we split on
278   // moves to BB2.
279   auto *CondBr = cast<BranchInst>(BB1->getTerminator());
280   EXPECT_THAT(CondBr->getCondition(), Eq(Cond));
281   ASSERT_THAT(CondBr->getNumSuccessors(), Eq(2u));
282   ASSERT_THAT(CondBr->getSuccessor(0), Eq(BB1));
283   auto *BB2 = CondBr->getSuccessor(1);
284   EXPECT_THAT(AI->getParent(), Eq(BB2));
285   EXPECT_THAT(RI->getParent(), Eq(BB2));
286 
287   EXPECT_FALSE(verifyModule(M, &errs()));
288 }
289 
290 TEST(OperationsTest, SplitEHBlock) {
291   // Check that we will not try to branch back to the landingpad block using
292   // regular branch instruction
293 
294   LLVMContext Ctx;
295   const char *SourceCode =
296       "declare ptr @f()"
297       "declare i32 @personality_function()"
298       "define ptr @test() personality ptr @personality_function {\n"
299       "entry:\n"
300       "  %val = invoke ptr @f()\n"
301       "          to label %normal unwind label %exceptional\n"
302       "normal:\n"
303       "  ret ptr %val\n"
304       "exceptional:\n"
305       "  %landing_pad4 = landingpad token cleanup\n"
306       "  ret ptr undef\n"
307       "}";
308   auto M = parseAssembly(SourceCode, Ctx);
309 
310   // Get the landingpad block
311   BasicBlock &BB = *std::next(M->getFunction("test")->begin(), 2);
312 
313   fuzzerop::OpDescriptor Descr = fuzzerop::splitBlockDescriptor(1);
314 
315   Descr.BuilderFunc({ConstantInt::getTrue(Ctx)}, BB.getFirstInsertionPt());
316   ASSERT_TRUE(!verifyModule(*M, &errs()));
317 }
318 
319 TEST(OperationsTest, SplitBlockWithPhis) {
320   LLVMContext Ctx;
321 
322   Type *Int8Ty = Type::getInt8Ty(Ctx);
323 
324   Module M("M", Ctx);
325   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
326                                                    /*isVarArg=*/false),
327                                  GlobalValue::ExternalLinkage, "f", &M);
328   auto SBOp = fuzzerop::splitBlockDescriptor(1);
329 
330   // Create 3 blocks with an if-then branch.
331   auto *BB1 = BasicBlock::Create(Ctx, "BB1", F);
332   auto *BB2 = BasicBlock::Create(Ctx, "BB2", F);
333   auto *BB3 = BasicBlock::Create(Ctx, "BB3", F);
334   BranchInst::Create(BB2, BB3, ConstantInt::getFalse(Ctx), BB1);
335   BranchInst::Create(BB3, BB2);
336 
337   // Set up phi nodes selecting values for the incoming edges.
338   auto *PHI1 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p1", BB3);
339   PHI1->addIncoming(ConstantInt::get(Int8Ty, 0), BB1);
340   PHI1->addIncoming(ConstantInt::get(Int8Ty, 1), BB2);
341   auto *PHI2 = PHINode::Create(Int8Ty, /*NumReservedValues=*/2, "p2", BB3);
342   PHI2->addIncoming(ConstantInt::get(Int8Ty, 1), BB1);
343   PHI2->addIncoming(ConstantInt::get(Int8Ty, 0), BB2);
344   auto *RI = ReturnInst::Create(Ctx, BB3);
345 
346   // Now we split the block with PHI nodes, making sure they're all updated.
347   Value *Cond = ConstantInt::getFalse(Ctx);
348   SBOp.BuilderFunc({Cond}, RI->getIterator());
349 
350   // Make sure the PHIs are updated with a value for the third incoming edge.
351   EXPECT_THAT(PHI1->getNumIncomingValues(), Eq(3u));
352   EXPECT_THAT(PHI2->getNumIncomingValues(), Eq(3u));
353   EXPECT_FALSE(verifyModule(M, &errs()));
354 }
355 
356 TEST(OperationsTest, GEP) {
357   LLVMContext Ctx;
358 
359   Type *Int8PtrTy = PointerType::getUnqual(Ctx);
360   Type *Int32Ty = Type::getInt32Ty(Ctx);
361 
362   Module M("M", Ctx);
363   Function *F = Function::Create(FunctionType::get(Type::getVoidTy(Ctx), {},
364                                                    /*isVarArg=*/false),
365                                  GlobalValue::ExternalLinkage, "f", &M);
366   auto *BB = BasicBlock::Create(Ctx, "BB", F);
367   auto *RI = ReturnInst::Create(Ctx, BB);
368 
369   auto GEPOp = fuzzerop::gepDescriptor(1);
370   EXPECT_TRUE(GEPOp.SourcePreds[0].matches({}, PoisonValue::get(Int8PtrTy)));
371   EXPECT_TRUE(GEPOp.SourcePreds[1].matches({PoisonValue::get(Int8PtrTy)},
372                                            ConstantInt::get(Int32Ty, 0)));
373 
374   GEPOp.BuilderFunc({PoisonValue::get(Int8PtrTy), ConstantInt::get(Int32Ty, 0)},
375                     RI->getIterator());
376   EXPECT_FALSE(verifyModule(M, &errs()));
377 }
378 
379 TEST(OperationsTest, GEPPointerOperand) {
380   // Check that we only pick sized pointers for the GEP instructions
381 
382   LLVMContext Ctx;
383   const char *SourceCode = "%opaque = type opaque\n"
384                            "declare void @f()\n"
385                            "define void @test(%opaque %o) {\n"
386                            "  %a = alloca i64, i32 10\n"
387                            "  ret void\n"
388                            "}";
389   auto M = parseAssembly(SourceCode, Ctx);
390 
391   fuzzerop::OpDescriptor Descr = fuzzerop::gepDescriptor(1);
392 
393   // Get first basic block of the test function
394   Function &F = *M->getFunction("test");
395   BasicBlock &BB = *F.begin();
396 
397   // Don't match %o
398   ASSERT_FALSE(Descr.SourcePreds[0].matches({}, &*F.arg_begin()));
399 
400   // Match %a
401   ASSERT_TRUE(Descr.SourcePreds[0].matches({}, &*BB.begin()));
402 }
403 
404 TEST(OperationsTest, ExtractAndInsertValue) {
405   LLVMContext Ctx;
406 
407   Type *Int8PtrTy = PointerType::getUnqual(Ctx);
408   Type *Int32Ty = Type::getInt32Ty(Ctx);
409   Type *Int64Ty = Type::getInt64Ty(Ctx);
410 
411   Type *StructTy = StructType::create(Ctx, {Int8PtrTy, Int32Ty});
412   Type *OpaqueTy = StructType::create(Ctx, "OpaqueStruct");
413   Type *ZeroSizedArrayTy = ArrayType::get(Int64Ty, 0);
414   Type *ArrayTy = ArrayType::get(Int64Ty, 4);
415   Type *VectorTy = FixedVectorType::get(Int32Ty, 2);
416 
417   auto EVOp = fuzzerop::extractValueDescriptor(1);
418   auto IVOp = fuzzerop::insertValueDescriptor(1);
419 
420   // Sanity check the source preds.
421   Constant *SVal = PoisonValue::get(StructTy);
422   Constant *OVal = PoisonValue::get(OpaqueTy);
423   Constant *AVal = PoisonValue::get(ArrayTy);
424   Constant *ZAVal = PoisonValue::get(ZeroSizedArrayTy);
425   Constant *VVal = PoisonValue::get(VectorTy);
426 
427   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, SVal));
428   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, OVal));
429   EXPECT_TRUE(EVOp.SourcePreds[0].matches({}, AVal));
430   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, VVal));
431   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, SVal));
432   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, OVal));
433   EXPECT_TRUE(IVOp.SourcePreds[0].matches({}, AVal));
434   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, VVal));
435 
436   // Don't consider zero sized arrays as viable sources
437   EXPECT_FALSE(EVOp.SourcePreds[0].matches({}, ZAVal));
438   EXPECT_FALSE(IVOp.SourcePreds[0].matches({}, ZAVal));
439 
440   // Make sure we're range checking appropriately.
441   EXPECT_TRUE(
442       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 0)));
443   EXPECT_TRUE(
444       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 1)));
445   EXPECT_FALSE(
446       EVOp.SourcePreds[1].matches({SVal}, ConstantInt::get(Int32Ty, 2)));
447   EXPECT_FALSE(
448       EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 0)));
449   EXPECT_FALSE(
450       EVOp.SourcePreds[1].matches({OVal}, ConstantInt::get(Int32Ty, 65536)));
451   EXPECT_TRUE(
452       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 0)));
453   EXPECT_TRUE(
454       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 3)));
455   EXPECT_FALSE(
456       EVOp.SourcePreds[1].matches({AVal}, ConstantInt::get(Int32Ty, 4)));
457 
458   EXPECT_THAT(
459       EVOp.SourcePreds[1].generate({SVal}, {}),
460       ElementsAre(ConstantInt::get(Int32Ty, 0), ConstantInt::get(Int32Ty, 1)));
461 
462   // InsertValue should accept any type in the struct, but only in positions
463   // where it makes sense.
464   EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, PoisonValue::get(Int8PtrTy)));
465   EXPECT_TRUE(IVOp.SourcePreds[1].matches({SVal}, PoisonValue::get(Int32Ty)));
466   EXPECT_FALSE(IVOp.SourcePreds[1].matches({SVal}, PoisonValue::get(Int64Ty)));
467   EXPECT_FALSE(IVOp.SourcePreds[2].matches({SVal, PoisonValue::get(Int32Ty)},
468                                            ConstantInt::get(Int32Ty, 0)));
469   EXPECT_TRUE(IVOp.SourcePreds[2].matches({SVal, PoisonValue::get(Int32Ty)},
470                                           ConstantInt::get(Int32Ty, 1)));
471 
472   EXPECT_THAT(IVOp.SourcePreds[1].generate({SVal}, {}),
473               Each(AnyOf(HasType(Int32Ty), HasType(Int8PtrTy))));
474   EXPECT_THAT(
475       IVOp.SourcePreds[2].generate({SVal, ConstantInt::get(Int32Ty, 0)}, {}),
476       ElementsAre(ConstantInt::get(Int32Ty, 1)));
477 }
478 
479 } // namespace
480