1 //===- SparsePropagation.cpp - Unit tests for the generic solver ----------===//
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/Analysis/SparsePropagation.h"
10 #include "llvm/ADT/PointerIntPair.h"
11 #include "llvm/IR/IRBuilder.h"
12 #include "gtest/gtest.h"
13 using namespace llvm;
14 
15 namespace {
16 /// To enable interprocedural analysis, we assign LLVM values to the following
17 /// groups. The register group represents SSA registers, the return group
18 /// represents the return values of functions, and the memory group represents
19 /// in-memory values. An LLVM Value can technically be in more than one group.
20 /// It's necessary to distinguish these groups so we can, for example, track a
21 /// global variable separately from the value stored at its location.
22 enum class IPOGrouping { Register, Return, Memory };
23 
24 /// Our LatticeKeys are PointerIntPairs composed of LLVM values and groupings.
25 /// The PointerIntPair header provides a DenseMapInfo specialization, so using
26 /// these as LatticeKeys is fine.
27 using TestLatticeKey = PointerIntPair<Value *, 2, IPOGrouping>;
28 } // namespace
29 
30 namespace llvm {
31 /// A specialization of LatticeKeyInfo for TestLatticeKeys. The generic solver
32 /// must translate between LatticeKeys and LLVM Values when adding Values to
33 /// its work list and inspecting the state of control-flow related values.
34 template <> struct LatticeKeyInfo<TestLatticeKey> {
getValueFromLatticeKeyllvm::LatticeKeyInfo35   static inline Value *getValueFromLatticeKey(TestLatticeKey Key) {
36     return Key.getPointer();
37   }
getLatticeKeyFromValuellvm::LatticeKeyInfo38   static inline TestLatticeKey getLatticeKeyFromValue(Value *V) {
39     return TestLatticeKey(V, IPOGrouping::Register);
40   }
41 };
42 } // namespace llvm
43 
44 namespace {
45 /// This class defines a simple test lattice value that could be used for
46 /// solving problems similar to constant propagation. The value is maintained
47 /// as a PointerIntPair.
48 class TestLatticeVal {
49 public:
50   /// The states of the lattices value. Only the ConstantVal state is
51   /// interesting; the rest are special states used by the generic solver. The
52   /// UntrackedVal state differs from the other three in that the generic
53   /// solver uses it to avoid doing unnecessary work. In particular, when a
54   /// value moves to the UntrackedVal state, it's users are not notified.
55   enum TestLatticeStateTy {
56     UndefinedVal,
57     ConstantVal,
58     OverdefinedVal,
59     UntrackedVal
60   };
61 
TestLatticeVal()62   TestLatticeVal() : LatticeVal(nullptr, UndefinedVal) {}
TestLatticeVal(Constant * C,TestLatticeStateTy State)63   TestLatticeVal(Constant *C, TestLatticeStateTy State)
64       : LatticeVal(C, State) {}
65 
66   /// Return true if this lattice value is in the Constant state. This is used
67   /// for checking the solver results.
isConstant() const68   bool isConstant() const { return LatticeVal.getInt() == ConstantVal; }
69 
70   /// Return true if this lattice value is in the Overdefined state. This is
71   /// used for checking the solver results.
isOverdefined() const72   bool isOverdefined() const { return LatticeVal.getInt() == OverdefinedVal; }
73 
operator ==(const TestLatticeVal & RHS) const74   bool operator==(const TestLatticeVal &RHS) const {
75     return LatticeVal == RHS.LatticeVal;
76   }
77 
operator !=(const TestLatticeVal & RHS) const78   bool operator!=(const TestLatticeVal &RHS) const {
79     return LatticeVal != RHS.LatticeVal;
80   }
81 
82 private:
83   /// A simple lattice value type for problems similar to constant propagation.
84   /// It holds the constant value and the lattice state.
85   PointerIntPair<const Constant *, 2, TestLatticeStateTy> LatticeVal;
86 };
87 
88 /// This class defines a simple test lattice function that could be used for
89 /// solving problems similar to constant propagation. The test lattice differs
90 /// from a "real" lattice in a few ways. First, it initializes all return
91 /// values, values stored in global variables, and arguments in the undefined
92 /// state. This means that there are no limitations on what we can track
93 /// interprocedurally. For simplicity, all global values in the tests will be
94 /// given internal linkage, since this is not something this lattice function
95 /// tracks. Second, it only handles the few instructions necessary for the
96 /// tests.
97 class TestLatticeFunc
98     : public AbstractLatticeFunction<TestLatticeKey, TestLatticeVal> {
99 public:
100   /// Construct a new test lattice function with special values for the
101   /// Undefined, Overdefined, and Untracked states.
TestLatticeFunc()102   TestLatticeFunc()
103       : AbstractLatticeFunction(
104             TestLatticeVal(nullptr, TestLatticeVal::UndefinedVal),
105             TestLatticeVal(nullptr, TestLatticeVal::OverdefinedVal),
106             TestLatticeVal(nullptr, TestLatticeVal::UntrackedVal)) {}
107 
108   /// Compute and return a TestLatticeVal for the given TestLatticeKey. For the
109   /// test analysis, a LatticeKey will begin in the undefined state, unless it
110   /// represents an LLVM Constant in the register grouping.
ComputeLatticeVal(TestLatticeKey Key)111   TestLatticeVal ComputeLatticeVal(TestLatticeKey Key) override {
112     if (Key.getInt() == IPOGrouping::Register)
113       if (auto *C = dyn_cast<Constant>(Key.getPointer()))
114         return TestLatticeVal(C, TestLatticeVal::ConstantVal);
115     return getUndefVal();
116   }
117 
118   /// Merge the two given lattice values. This merge should be equivalent to
119   /// what is done for constant propagation. That is, the resulting lattice
120   /// value is constant only if the two given lattice values are constant and
121   /// hold the same value.
MergeValues(TestLatticeVal X,TestLatticeVal Y)122   TestLatticeVal MergeValues(TestLatticeVal X, TestLatticeVal Y) override {
123     if (X == getUntrackedVal() || Y == getUntrackedVal())
124       return getUntrackedVal();
125     if (X == getOverdefinedVal() || Y == getOverdefinedVal())
126       return getOverdefinedVal();
127     if (X == getUndefVal() && Y == getUndefVal())
128       return getUndefVal();
129     if (X == getUndefVal())
130       return Y;
131     if (Y == getUndefVal())
132       return X;
133     if (X == Y)
134       return X;
135     return getOverdefinedVal();
136   }
137 
138   /// Compute the lattice values that change as a result of executing the given
139   /// instruction. We only handle the few instructions needed for the tests.
ComputeInstructionState(Instruction & I,DenseMap<TestLatticeKey,TestLatticeVal> & ChangedValues,SparseSolver<TestLatticeKey,TestLatticeVal> & SS)140   void ComputeInstructionState(
141       Instruction &I, DenseMap<TestLatticeKey, TestLatticeVal> &ChangedValues,
142       SparseSolver<TestLatticeKey, TestLatticeVal> &SS) override {
143     switch (I.getOpcode()) {
144     case Instruction::Call:
145       return visitCallBase(cast<CallBase>(I), ChangedValues, SS);
146     case Instruction::Ret:
147       return visitReturn(*cast<ReturnInst>(&I), ChangedValues, SS);
148     case Instruction::Store:
149       return visitStore(*cast<StoreInst>(&I), ChangedValues, SS);
150     default:
151       return visitInst(I, ChangedValues, SS);
152     }
153   }
154 
155 private:
156   /// Handle call sites. The state of a called function's argument is the merge
157   /// of the current formal argument state with the call site's corresponding
158   /// actual argument state. The call site state is the merge of the call site
159   /// state with the returned value state of the called function.
visitCallBase(CallBase & I,DenseMap<TestLatticeKey,TestLatticeVal> & ChangedValues,SparseSolver<TestLatticeKey,TestLatticeVal> & SS)160   void visitCallBase(CallBase &I,
161                      DenseMap<TestLatticeKey, TestLatticeVal> &ChangedValues,
162                      SparseSolver<TestLatticeKey, TestLatticeVal> &SS) {
163     Function *F = I.getCalledFunction();
164     auto RegI = TestLatticeKey(&I, IPOGrouping::Register);
165     if (!F) {
166       ChangedValues[RegI] = getOverdefinedVal();
167       return;
168     }
169     SS.MarkBlockExecutable(&F->front());
170     for (Argument &A : F->args()) {
171       auto RegFormal = TestLatticeKey(&A, IPOGrouping::Register);
172       auto RegActual =
173           TestLatticeKey(I.getArgOperand(A.getArgNo()), IPOGrouping::Register);
174       ChangedValues[RegFormal] =
175           MergeValues(SS.getValueState(RegFormal), SS.getValueState(RegActual));
176     }
177     auto RetF = TestLatticeKey(F, IPOGrouping::Return);
178     ChangedValues[RegI] =
179         MergeValues(SS.getValueState(RegI), SS.getValueState(RetF));
180   }
181 
182   /// Handle return instructions. The function's return state is the merge of
183   /// the returned value state and the function's current return state.
visitReturn(ReturnInst & I,DenseMap<TestLatticeKey,TestLatticeVal> & ChangedValues,SparseSolver<TestLatticeKey,TestLatticeVal> & SS)184   void visitReturn(ReturnInst &I,
185                    DenseMap<TestLatticeKey, TestLatticeVal> &ChangedValues,
186                    SparseSolver<TestLatticeKey, TestLatticeVal> &SS) {
187     Function *F = I.getParent()->getParent();
188     if (F->getReturnType()->isVoidTy())
189       return;
190     auto RegR = TestLatticeKey(I.getReturnValue(), IPOGrouping::Register);
191     auto RetF = TestLatticeKey(F, IPOGrouping::Return);
192     ChangedValues[RetF] =
193         MergeValues(SS.getValueState(RegR), SS.getValueState(RetF));
194   }
195 
196   /// Handle store instructions. If the pointer operand of the store is a
197   /// global variable, we attempt to track the value. The global variable state
198   /// is the merge of the stored value state with the current global variable
199   /// state.
visitStore(StoreInst & I,DenseMap<TestLatticeKey,TestLatticeVal> & ChangedValues,SparseSolver<TestLatticeKey,TestLatticeVal> & SS)200   void visitStore(StoreInst &I,
201                   DenseMap<TestLatticeKey, TestLatticeVal> &ChangedValues,
202                   SparseSolver<TestLatticeKey, TestLatticeVal> &SS) {
203     auto *GV = dyn_cast<GlobalVariable>(I.getPointerOperand());
204     if (!GV)
205       return;
206     auto RegVal = TestLatticeKey(I.getValueOperand(), IPOGrouping::Register);
207     auto MemPtr = TestLatticeKey(GV, IPOGrouping::Memory);
208     ChangedValues[MemPtr] =
209         MergeValues(SS.getValueState(RegVal), SS.getValueState(MemPtr));
210   }
211 
212   /// Handle all other instructions. All other instructions are marked
213   /// overdefined.
visitInst(Instruction & I,DenseMap<TestLatticeKey,TestLatticeVal> & ChangedValues,SparseSolver<TestLatticeKey,TestLatticeVal> & SS)214   void visitInst(Instruction &I,
215                  DenseMap<TestLatticeKey, TestLatticeVal> &ChangedValues,
216                  SparseSolver<TestLatticeKey, TestLatticeVal> &SS) {
217     auto RegI = TestLatticeKey(&I, IPOGrouping::Register);
218     ChangedValues[RegI] = getOverdefinedVal();
219   }
220 };
221 
222 /// This class defines the common data used for all of the tests. The tests
223 /// should add code to the module and then run the solver.
224 class SparsePropagationTest : public testing::Test {
225 protected:
226   LLVMContext Context;
227   Module M;
228   IRBuilder<> Builder;
229   TestLatticeFunc Lattice;
230   SparseSolver<TestLatticeKey, TestLatticeVal> Solver;
231 
232 public:
SparsePropagationTest()233   SparsePropagationTest()
234       : M("", Context), Builder(Context), Solver(&Lattice) {}
235 };
236 } // namespace
237 
238 /// Test that we mark discovered functions executable.
239 ///
240 /// define internal void @f() {
241 ///   call void @g()
242 ///   ret void
243 /// }
244 ///
245 /// define internal void @g() {
246 ///   call void @f()
247 ///   ret void
248 /// }
249 ///
250 /// For this test, we initially mark "f" executable, and the solver discovers
251 /// "g" because of the call in "f". The mutually recursive call in "g" also
252 /// tests that we don't add a block to the basic block work list if it is
253 /// already executable. Doing so would put the solver into an infinite loop.
TEST_F(SparsePropagationTest,MarkBlockExecutable)254 TEST_F(SparsePropagationTest, MarkBlockExecutable) {
255   Function *F = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
256                                  GlobalValue::InternalLinkage, "f", &M);
257   Function *G = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
258                                  GlobalValue::InternalLinkage, "g", &M);
259   BasicBlock *FEntry = BasicBlock::Create(Context, "", F);
260   BasicBlock *GEntry = BasicBlock::Create(Context, "", G);
261   Builder.SetInsertPoint(FEntry);
262   Builder.CreateCall(G);
263   Builder.CreateRetVoid();
264   Builder.SetInsertPoint(GEntry);
265   Builder.CreateCall(F);
266   Builder.CreateRetVoid();
267 
268   Solver.MarkBlockExecutable(FEntry);
269   Solver.Solve();
270 
271   EXPECT_TRUE(Solver.isBlockExecutable(GEntry));
272 }
273 
274 /// Test that we propagate information through global variables.
275 ///
276 /// @gv = internal global i64
277 ///
278 /// define internal void @f() {
279 ///   store i64 1, i64* @gv
280 ///   ret void
281 /// }
282 ///
283 /// define internal void @g() {
284 ///   store i64 1, i64* @gv
285 ///   ret void
286 /// }
287 ///
288 /// For this test, we initially mark both "f" and "g" executable, and the
289 /// solver computes the lattice state of the global variable as constant.
TEST_F(SparsePropagationTest,GlobalVariableConstant)290 TEST_F(SparsePropagationTest, GlobalVariableConstant) {
291   Function *F = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
292                                  GlobalValue::InternalLinkage, "f", &M);
293   Function *G = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
294                                  GlobalValue::InternalLinkage, "g", &M);
295   GlobalVariable *GV =
296       new GlobalVariable(M, Builder.getInt64Ty(), false,
297                          GlobalValue::InternalLinkage, nullptr, "gv");
298   BasicBlock *FEntry = BasicBlock::Create(Context, "", F);
299   BasicBlock *GEntry = BasicBlock::Create(Context, "", G);
300   Builder.SetInsertPoint(FEntry);
301   Builder.CreateStore(Builder.getInt64(1), GV);
302   Builder.CreateRetVoid();
303   Builder.SetInsertPoint(GEntry);
304   Builder.CreateStore(Builder.getInt64(1), GV);
305   Builder.CreateRetVoid();
306 
307   Solver.MarkBlockExecutable(FEntry);
308   Solver.MarkBlockExecutable(GEntry);
309   Solver.Solve();
310 
311   auto MemGV = TestLatticeKey(GV, IPOGrouping::Memory);
312   EXPECT_TRUE(Solver.getExistingValueState(MemGV).isConstant());
313 }
314 
315 /// Test that we propagate information through global variables.
316 ///
317 /// @gv = internal global i64
318 ///
319 /// define internal void @f() {
320 ///   store i64 0, i64* @gv
321 ///   ret void
322 /// }
323 ///
324 /// define internal void @g() {
325 ///   store i64 1, i64* @gv
326 ///   ret void
327 /// }
328 ///
329 /// For this test, we initially mark both "f" and "g" executable, and the
330 /// solver computes the lattice state of the global variable as overdefined.
TEST_F(SparsePropagationTest,GlobalVariableOverDefined)331 TEST_F(SparsePropagationTest, GlobalVariableOverDefined) {
332   Function *F = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
333                                  GlobalValue::InternalLinkage, "f", &M);
334   Function *G = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
335                                  GlobalValue::InternalLinkage, "g", &M);
336   GlobalVariable *GV =
337       new GlobalVariable(M, Builder.getInt64Ty(), false,
338                          GlobalValue::InternalLinkage, nullptr, "gv");
339   BasicBlock *FEntry = BasicBlock::Create(Context, "", F);
340   BasicBlock *GEntry = BasicBlock::Create(Context, "", G);
341   Builder.SetInsertPoint(FEntry);
342   Builder.CreateStore(Builder.getInt64(0), GV);
343   Builder.CreateRetVoid();
344   Builder.SetInsertPoint(GEntry);
345   Builder.CreateStore(Builder.getInt64(1), GV);
346   Builder.CreateRetVoid();
347 
348   Solver.MarkBlockExecutable(FEntry);
349   Solver.MarkBlockExecutable(GEntry);
350   Solver.Solve();
351 
352   auto MemGV = TestLatticeKey(GV, IPOGrouping::Memory);
353   EXPECT_TRUE(Solver.getExistingValueState(MemGV).isOverdefined());
354 }
355 
356 /// Test that we propagate information through function returns.
357 ///
358 /// define internal i64 @f(i1* %cond) {
359 /// if:
360 ///   %0 = load i1, i1* %cond
361 ///   br i1 %0, label %then, label %else
362 ///
363 /// then:
364 ///   ret i64 1
365 ///
366 /// else:
367 ///   ret i64 1
368 /// }
369 ///
370 /// For this test, we initially mark "f" executable, and the solver computes
371 /// the return value of the function as constant.
TEST_F(SparsePropagationTest,FunctionDefined)372 TEST_F(SparsePropagationTest, FunctionDefined) {
373   Function *F =
374       Function::Create(FunctionType::get(Builder.getInt64Ty(),
375                                          {Type::getInt1PtrTy(Context)}, false),
376                        GlobalValue::InternalLinkage, "f", &M);
377   BasicBlock *If = BasicBlock::Create(Context, "if", F);
378   BasicBlock *Then = BasicBlock::Create(Context, "then", F);
379   BasicBlock *Else = BasicBlock::Create(Context, "else", F);
380   F->arg_begin()->setName("cond");
381   Builder.SetInsertPoint(If);
382   LoadInst *Cond = Builder.CreateLoad(Type::getInt1Ty(Context), F->arg_begin());
383   Builder.CreateCondBr(Cond, Then, Else);
384   Builder.SetInsertPoint(Then);
385   Builder.CreateRet(Builder.getInt64(1));
386   Builder.SetInsertPoint(Else);
387   Builder.CreateRet(Builder.getInt64(1));
388 
389   Solver.MarkBlockExecutable(If);
390   Solver.Solve();
391 
392   auto RetF = TestLatticeKey(F, IPOGrouping::Return);
393   EXPECT_TRUE(Solver.getExistingValueState(RetF).isConstant());
394 }
395 
396 /// Test that we propagate information through function returns.
397 ///
398 /// define internal i64 @f(i1* %cond) {
399 /// if:
400 ///   %0 = load i1, i1* %cond
401 ///   br i1 %0, label %then, label %else
402 ///
403 /// then:
404 ///   ret i64 0
405 ///
406 /// else:
407 ///   ret i64 1
408 /// }
409 ///
410 /// For this test, we initially mark "f" executable, and the solver computes
411 /// the return value of the function as overdefined.
TEST_F(SparsePropagationTest,FunctionOverDefined)412 TEST_F(SparsePropagationTest, FunctionOverDefined) {
413   Function *F =
414       Function::Create(FunctionType::get(Builder.getInt64Ty(),
415                                          {Type::getInt1PtrTy(Context)}, false),
416                        GlobalValue::InternalLinkage, "f", &M);
417   BasicBlock *If = BasicBlock::Create(Context, "if", F);
418   BasicBlock *Then = BasicBlock::Create(Context, "then", F);
419   BasicBlock *Else = BasicBlock::Create(Context, "else", F);
420   F->arg_begin()->setName("cond");
421   Builder.SetInsertPoint(If);
422   LoadInst *Cond = Builder.CreateLoad(Type::getInt1Ty(Context), F->arg_begin());
423   Builder.CreateCondBr(Cond, Then, Else);
424   Builder.SetInsertPoint(Then);
425   Builder.CreateRet(Builder.getInt64(0));
426   Builder.SetInsertPoint(Else);
427   Builder.CreateRet(Builder.getInt64(1));
428 
429   Solver.MarkBlockExecutable(If);
430   Solver.Solve();
431 
432   auto RetF = TestLatticeKey(F, IPOGrouping::Return);
433   EXPECT_TRUE(Solver.getExistingValueState(RetF).isOverdefined());
434 }
435 
436 /// Test that we propagate information through arguments.
437 ///
438 /// define internal void @f() {
439 ///   call void @g(i64 0, i64 1)
440 ///   call void @g(i64 1, i64 1)
441 ///   ret void
442 /// }
443 ///
444 /// define internal void @g(i64 %a, i64 %b) {
445 ///   ret void
446 /// }
447 ///
448 /// For this test, we initially mark "f" executable, and the solver discovers
449 /// "g" because of the calls in "f". The solver computes the state of argument
450 /// "a" as overdefined and the state of "b" as constant.
451 ///
452 /// In addition, this test demonstrates that ComputeInstructionState can alter
453 /// the state of multiple lattice values, in addition to the one associated
454 /// with the instruction definition. Each call instruction in this test updates
455 /// the state of arguments "a" and "b".
TEST_F(SparsePropagationTest,ComputeInstructionState)456 TEST_F(SparsePropagationTest, ComputeInstructionState) {
457   Function *F = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
458                                  GlobalValue::InternalLinkage, "f", &M);
459   Function *G = Function::Create(
460       FunctionType::get(Builder.getVoidTy(),
461                         {Builder.getInt64Ty(), Builder.getInt64Ty()}, false),
462       GlobalValue::InternalLinkage, "g", &M);
463   Argument *A = G->arg_begin();
464   Argument *B = std::next(G->arg_begin());
465   A->setName("a");
466   B->setName("b");
467   BasicBlock *FEntry = BasicBlock::Create(Context, "", F);
468   BasicBlock *GEntry = BasicBlock::Create(Context, "", G);
469   Builder.SetInsertPoint(FEntry);
470   Builder.CreateCall(G, {Builder.getInt64(0), Builder.getInt64(1)});
471   Builder.CreateCall(G, {Builder.getInt64(1), Builder.getInt64(1)});
472   Builder.CreateRetVoid();
473   Builder.SetInsertPoint(GEntry);
474   Builder.CreateRetVoid();
475 
476   Solver.MarkBlockExecutable(FEntry);
477   Solver.Solve();
478 
479   auto RegA = TestLatticeKey(A, IPOGrouping::Register);
480   auto RegB = TestLatticeKey(B, IPOGrouping::Register);
481   EXPECT_TRUE(Solver.getExistingValueState(RegA).isOverdefined());
482   EXPECT_TRUE(Solver.getExistingValueState(RegB).isConstant());
483 }
484 
485 /// Test that we can handle exceptional terminator instructions.
486 ///
487 /// declare internal void @p()
488 ///
489 /// declare internal void @g()
490 ///
491 /// define internal void @f() personality i8* bitcast (void ()* @p to i8*) {
492 /// entry:
493 ///   invoke void @g()
494 ///           to label %exit unwind label %catch.pad
495 ///
496 /// catch.pad:
497 ///   %0 = catchswitch within none [label %catch.body] unwind to caller
498 ///
499 /// catch.body:
500 ///   %1 = catchpad within %0 []
501 ///   catchret from %1 to label %exit
502 ///
503 /// exit:
504 ///   ret void
505 /// }
506 ///
507 /// For this test, we initially mark the entry block executable. The solver
508 /// then discovers the rest of the blocks in the function are executable.
TEST_F(SparsePropagationTest,ExceptionalTerminatorInsts)509 TEST_F(SparsePropagationTest, ExceptionalTerminatorInsts) {
510   Function *P = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
511                                  GlobalValue::InternalLinkage, "p", &M);
512   Function *G = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
513                                  GlobalValue::InternalLinkage, "g", &M);
514   Function *F = Function::Create(FunctionType::get(Builder.getVoidTy(), false),
515                                  GlobalValue::InternalLinkage, "f", &M);
516   Constant *C =
517       ConstantExpr::getCast(Instruction::BitCast, P, Builder.getInt8PtrTy());
518   F->setPersonalityFn(C);
519   BasicBlock *Entry = BasicBlock::Create(Context, "entry", F);
520   BasicBlock *Pad = BasicBlock::Create(Context, "catch.pad", F);
521   BasicBlock *Body = BasicBlock::Create(Context, "catch.body", F);
522   BasicBlock *Exit = BasicBlock::Create(Context, "exit", F);
523   Builder.SetInsertPoint(Entry);
524   Builder.CreateInvoke(G, Exit, Pad);
525   Builder.SetInsertPoint(Pad);
526   CatchSwitchInst *CatchSwitch =
527       Builder.CreateCatchSwitch(ConstantTokenNone::get(Context), nullptr, 1);
528   CatchSwitch->addHandler(Body);
529   Builder.SetInsertPoint(Body);
530   CatchPadInst *CatchPad = Builder.CreateCatchPad(CatchSwitch, {});
531   Builder.CreateCatchRet(CatchPad, Exit);
532   Builder.SetInsertPoint(Exit);
533   Builder.CreateRetVoid();
534 
535   Solver.MarkBlockExecutable(Entry);
536   Solver.Solve();
537 
538   EXPECT_TRUE(Solver.isBlockExecutable(Pad));
539   EXPECT_TRUE(Solver.isBlockExecutable(Body));
540   EXPECT_TRUE(Solver.isBlockExecutable(Exit));
541 }
542