llvm.org GIT mirror llvm / 26e097c
Teach jump threading to "look through" a select when the branch direction of a terminator depends on it. When it sees a promising select it now tries to figure out whether the condition of the select is known in any of the predecessors and if so it maps the operands appropriately. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@121859 91177308-0d34-0410-b5e6-96231b3b80d8 Frits van Bommel 8 years ago
2 changed file(s) with 157 addition(s) and 0 deletion(s). Raw diff Collapse all Expand all
537537 }
538538 }
539539
540 if (SelectInst *SI = dyn_cast(I)) {
541 // Handle select instructions where at least one operand is a known constant
542 // and we can figure out the condition value for any predecessor block.
543 Constant *TrueVal = getKnownConstant(SI->getTrueValue(), Preference);
544 Constant *FalseVal = getKnownConstant(SI->getFalseValue(), Preference);
545 PredValueInfoTy Conds;
546 if ((TrueVal || FalseVal) &&
547 ComputeValueKnownInPredecessors(SI->getCondition(), BB, Conds,
548 WantInteger)) {
549 for (unsigned i = 0, e = Conds.size(); i != e; ++i) {
550 Constant *Cond = Conds[i].first;
551
552 // Figure out what value to use for the condition.
553 bool KnownCond;
554 if (ConstantInt *CI = dyn_cast(Cond)) {
555 // A known boolean.
556 KnownCond = CI->isOne();
557 } else {
558 assert(isa(Cond) && "Unexpected condition value");
559 // Either operand will do, so be sure to pick the one that's a known
560 // constant.
561 // FIXME: Do this more cleverly if both values are known constants?
562 KnownCond = (TrueVal != 0);
563 }
564
565 // See if the select has a known constant value for this predecessor.
566 if (Constant *Val = KnownCond ? TrueVal : FalseVal)
567 Result.push_back(std::make_pair(Val, Conds[i].second));
568 }
569
570 return !Result.empty();
571 }
572 }
573
540574 // If all else fails, see if LVI can figure out a constant value for us.
541575 Constant *CI = LVI->getConstant(V, BB);
542576 if (Constant *KC = getKnownConstant(CI, Preference)) {
0 ; RUN: opt -S -jump-threading < %s | FileCheck %s
1
2 declare void @foo()
3 declare void @bar()
4 declare void @baz()
5 declare void @quux()
6
7
8 ; Jump threading of branch with select as condition.
9 ; Mostly theoretical since instruction combining simplifies all selects of
10 ; booleans where at least one operand is true/false/undef.
11
12 ; CHECK: @test_br
13 ; CHECK-NEXT: entry:
14 ; CHECK-NEXT: br i1 %cond, label %L1,
15 define void @test_br(i1 %cond, i1 %value) nounwind {
16 entry:
17 br i1 %cond, label %L0, label %L3
18 L0:
19 %expr = select i1 %cond, i1 true, i1 %value
20 br i1 %expr, label %L1, label %L2
21
22 L1:
23 call void @foo()
24 ret void
25 L2:
26 call void @bar()
27 ret void
28 L3:
29 call void @baz()
30 br label %L0
31 }
32
33
34 ; Jump threading of switch with select as condition.
35
36 ; CHECK: @test_switch
37 ; CHECK-NEXT: entry:
38 ; CHECK-NEXT: br i1 %cond, label %L1,
39 define void @test_switch(i1 %cond, i8 %value) nounwind {
40 entry:
41 br i1 %cond, label %L0, label %L4
42 L0:
43 %expr = select i1 %cond, i8 1, i8 %value
44 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
45
46 L1:
47 call void @foo()
48 ret void
49 L2:
50 call void @bar()
51 ret void
52 L3:
53 call void @baz()
54 ret void
55 L4:
56 call void @quux()
57 br label %L0
58 }
59
60 ; Make sure the blocks in the indirectbr test aren't trivially removable as
61 ; successors by taking their addresses.
62 @anchor = constant [3 x i8*] [
63 i8* blockaddress(@test_indirectbr, %L1),
64 i8* blockaddress(@test_indirectbr, %L2),
65 i8* blockaddress(@test_indirectbr, %L3)
66 ]
67
68
69 ; Jump threading of indirectbr with select as address.
70
71 ; CHECK: @test_indirectbr
72 ; CHECK-NEXT: entry:
73 ; CHECK-NEXT: br i1 %cond, label %L1, label %L3
74 define void @test_indirectbr(i1 %cond, i8* %address) nounwind {
75 entry:
76 br i1 %cond, label %L0, label %L3
77 L0:
78 %indirect.goto.dest = select i1 %cond, i8* blockaddress(@test_indirectbr, %L1), i8* %address
79 indirectbr i8* %indirect.goto.dest, [label %L1, label %L2, label %L3]
80
81 L1:
82 call void @foo()
83 ret void
84 L2:
85 call void @bar()
86 ret void
87 L3:
88 call void @baz()
89 ret void
90 }
91
92
93 ; A more complicated case: the condition is a select based on a comparison.
94
95 ; CHECK: @test_switch_cmp
96 ; CHECK-NEXT: entry:
97 ; CHECK-NEXT: br i1 %cond, label %L0, label %[[THREADED:[A-Za-z.0-9]+]]
98 ; CHECK: [[THREADED]]:
99 ; CHECK-NEXT: call void @quux
100 ; CHECK-NEXT: br label %L1
101 define void @test_switch_cmp(i1 %cond, i32 %val, i8 %value) nounwind {
102 entry:
103 br i1 %cond, label %L0, label %L4
104 L0:
105 %val.phi = phi i32 [%val, %entry], [-1, %L4]
106 %cmp = icmp slt i32 %val.phi, 0
107 %expr = select i1 %cmp, i8 1, i8 %value
108 switch i8 %expr, label %L3 [i8 1, label %L1 i8 2, label %L2]
109
110 L1:
111 call void @foo()
112 ret void
113 L2:
114 call void @bar()
115 ret void
116 L3:
117 call void @baz()
118 ret void
119 L4:
120 call void @quux()
121 br label %L0
122 }