llvm.org GIT mirror llvm / 5cadc32
[EarlyCSE] Propagate conditions of AND and OR instructions This patches teaches EarlyCSE to figure out that if `and i1 %x, %y` is true then both `%x` and `%y` are true in the taken branch, and if `or i1 %x, %y` is false then both `%x` and `%y` are false in non-taken branch. Fix for PR37635. Differential Revision: https://reviews.llvm.org/D47574 Reviewed By: reames git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@334707 91177308-0d34-0410-b5e6-96231b3b80d8 Max Kazantsev 1 year, 3 months ago
2 changed file(s) with 189 addition(s) and 16 deletion(s). Raw diff Collapse all Expand all
718718 auto *TorF = (BI->getSuccessor(0) == BB)
719719 ? ConstantInt::getTrue(BB->getContext())
720720 : ConstantInt::getFalse(BB->getContext());
721 AvailableValues.insert(CondInst, TorF);
722 LLVM_DEBUG(dbgs() << "EarlyCSE CVP: Add conditional value for '"
723 << CondInst->getName() << "' as " << *TorF << " in "
724 << BB->getName() << "\n");
725 if (!DebugCounter::shouldExecute(CSECounter)) {
726 LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
727 } else {
728 // Replace all dominated uses with the known value.
729 if (unsigned Count = replaceDominatedUsesWith(CondInst, TorF, DT,
730 BasicBlockEdge(Pred, BB))) {
731
732 NumCSECVP += Count;
733 return true;
734 }
735 }
736 return false;
721 auto IsAnd = [](Instruction *I) {
722 if (BinaryOperator *BOp = dyn_cast(I))
723 return BOp->getOpcode() == Instruction::And;
724 return false;
725 };
726 auto IsOr = [](Instruction *I) {
727 if (BinaryOperator *BOp = dyn_cast(I))
728 return BOp->getOpcode() == Instruction::Or;
729 return false;
730 };
731 // If the condition is AND operation, we can propagate its operands into the
732 // true branch. If it is OR operation, we can propagate them into the false
733 // branch.
734 auto CanPropagateOperands = (BI->getSuccessor(0) == BB) ? IsAnd : IsOr;
735
736 bool MadeChanges = false;
737 SmallVector WorkList;
738 SmallPtrSet Visited;
739 WorkList.push_back(CondInst);
740 while (!WorkList.empty()) {
741 Instruction *Curr = WorkList.pop_back_val();
742
743 AvailableValues.insert(Curr, TorF);
744 LLVM_DEBUG(dbgs() << "EarlyCSE CVP: Add conditional value for '"
745 << Curr->getName() << "' as " << *TorF << " in "
746 << BB->getName() << "\n");
747 if (!DebugCounter::shouldExecute(CSECounter)) {
748 LLVM_DEBUG(dbgs() << "Skipping due to debug counter\n");
749 } else {
750 // Replace all dominated uses with the known value.
751 if (unsigned Count = replaceDominatedUsesWith(Curr, TorF, DT,
752 BasicBlockEdge(Pred, BB))) {
753 NumCSECVP += Count;
754 MadeChanges = true;
755 }
756 }
757
758 if (CanPropagateOperands(Curr))
759 for (auto &Op : cast(Curr)->operands())
760 if (Instruction *OPI = dyn_cast(Op))
761 if (SimpleValue::canHandle(OPI) && Visited.insert(OPI).second)
762 WorkList.push_back(OPI);
763 }
764
765 return MadeChanges;
737766 }
738767
739768 bool EarlyCSE::processNode(DomTreeNode *Node) {
0 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
1 ; RUN: opt -early-cse -S < %s | FileCheck %s
2 ; RUN: opt -basicaa -early-cse-memssa -S < %s | FileCheck %s
3
4 define i32 @test_01(i32 %a, i32 %b) {
5 ; CHECK-LABEL: @test_01(
6 ; CHECK-NEXT: entry:
7 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
8 ; CHECK-NEXT: br i1 [[COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
9 ; CHECK: if.true:
10 ; CHECK-NEXT: ret i32 [[A]]
11 ; CHECK: if.false:
12 ; CHECK-NEXT: ret i32 [[B]]
13 ;
14 entry:
15 %cond = icmp slt i32 %a, %b
16 br i1 %cond, label %if.true, label %if.false
17
18 if.true:
19 %cond2 = icmp slt i32 %a, %b
20 %x = select i1 %cond2, i32 %a, i32 %b
21 ret i32 %x
22
23 if.false:
24 %cond3 = icmp slt i32 %a, %b
25 %y = select i1 %cond3, i32 %a, i32 %b
26 ret i32 %y
27 }
28
29 define i32 @test_02(i32 %a, i32 %b, i1 %c) {
30 ; CHECK-LABEL: @test_02(
31 ; CHECK-NEXT: entry:
32 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
33 ; CHECK-NEXT: [[AND_COND:%.*]] = and i1 [[COND]], [[C:%.*]]
34 ; CHECK-NEXT: br i1 [[AND_COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
35 ; CHECK: if.true:
36 ; CHECK-NEXT: ret i32 [[A]]
37 ; CHECK: if.false:
38 ; CHECK-NEXT: [[Y:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
39 ; CHECK-NEXT: ret i32 [[Y]]
40 ;
41 entry:
42 %cond = icmp slt i32 %a, %b
43 %and.cond = and i1 %cond, %c
44 br i1 %and.cond, label %if.true, label %if.false
45
46 if.true:
47 %cond2 = icmp slt i32 %a, %b
48 %x = select i1 %cond2, i32 %a, i32 %b
49 ret i32 %x
50
51 if.false:
52 %cond3 = icmp slt i32 %a, %b
53 %y = select i1 %cond3, i32 %a, i32 %b
54 ret i32 %y
55 }
56
57 define i32 @test_03(i32 %a, i32 %b, i1 %c) {
58 ; CHECK-LABEL: @test_03(
59 ; CHECK-NEXT: entry:
60 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
61 ; CHECK-NEXT: [[OR_COND:%.*]] = or i1 [[COND]], [[C:%.*]]
62 ; CHECK-NEXT: br i1 [[OR_COND]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
63 ; CHECK: if.true:
64 ; CHECK-NEXT: [[X:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
65 ; CHECK-NEXT: ret i32 [[X]]
66 ; CHECK: if.false:
67 ; CHECK-NEXT: ret i32 [[B]]
68 ;
69 entry:
70 %cond = icmp slt i32 %a, %b
71 %or.cond = or i1 %cond, %c
72 br i1 %or.cond, label %if.true, label %if.false
73
74 if.true:
75 %cond2 = icmp slt i32 %a, %b
76 %x = select i1 %cond2, i32 %a, i32 %b
77 ret i32 %x
78
79 if.false:
80 %cond3 = icmp slt i32 %a, %b
81 %y = select i1 %cond3, i32 %a, i32 %b
82 ret i32 %y
83 }
84
85 define i32 @test_04(i32 %a, i32 %b, i1 %c1, i1 %c2) {
86 ; CHECK-LABEL: @test_04(
87 ; CHECK-NEXT: entry:
88 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
89 ; CHECK-NEXT: [[AND_COND1:%.*]] = and i1 [[COND]], [[C1:%.*]]
90 ; CHECK-NEXT: [[AND_COND2:%.*]] = and i1 [[AND_COND1]], [[C2:%.*]]
91 ; CHECK-NEXT: br i1 [[AND_COND2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
92 ; CHECK: if.true:
93 ; CHECK-NEXT: ret i32 [[A]]
94 ; CHECK: if.false:
95 ; CHECK-NEXT: [[Y:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
96 ; CHECK-NEXT: ret i32 [[Y]]
97 ;
98 entry:
99 %cond = icmp slt i32 %a, %b
100 %and.cond1 = and i1 %cond, %c1
101 %and.cond2 = and i1 %and.cond1, %c2
102 br i1 %and.cond2, label %if.true, label %if.false
103
104 if.true:
105 %cond2 = icmp slt i32 %a, %b
106 %x = select i1 %cond2, i32 %a, i32 %b
107 ret i32 %x
108
109 if.false:
110 %cond3 = icmp slt i32 %a, %b
111 %y = select i1 %cond3, i32 %a, i32 %b
112 ret i32 %y
113 }
114
115 define i32 @test_05(i32 %a, i32 %b, i1 %c1, i1 %c2) {
116 ; CHECK-LABEL: @test_05(
117 ; CHECK-NEXT: entry:
118 ; CHECK-NEXT: [[COND:%.*]] = icmp slt i32 [[A:%.*]], [[B:%.*]]
119 ; CHECK-NEXT: [[OR_COND1:%.*]] = or i1 [[COND]], [[C1:%.*]]
120 ; CHECK-NEXT: [[OR_COND2:%.*]] = or i1 [[OR_COND1]], [[C2:%.*]]
121 ; CHECK-NEXT: br i1 [[OR_COND2]], label [[IF_TRUE:%.*]], label [[IF_FALSE:%.*]]
122 ; CHECK: if.true:
123 ; CHECK-NEXT: [[X:%.*]] = select i1 [[COND]], i32 [[A]], i32 [[B]]
124 ; CHECK-NEXT: ret i32 [[X]]
125 ; CHECK: if.false:
126 ; CHECK-NEXT: ret i32 [[B]]
127 ;
128 entry:
129 %cond = icmp slt i32 %a, %b
130 %or.cond1 = or i1 %cond, %c1
131 %or.cond2 = or i1 %or.cond1, %c2
132 br i1 %or.cond2, label %if.true, label %if.false
133
134 if.true:
135 %cond2 = icmp slt i32 %a, %b
136 %x = select i1 %cond2, i32 %a, i32 %b
137 ret i32 %x
138
139 if.false:
140 %cond3 = icmp slt i32 %a, %b
141 %y = select i1 %cond3, i32 %a, i32 %b
142 ret i32 %y
143 }