llvm.org GIT mirror llvm / a33c572
[IndVarSimplify] Add AShr exact flags using induction variables ranges. This adds exact flags to AShr/LShr flags where we can statically prove it is valid using the range of induction variables. This allows further optimisations to remove extra loads. Differential Revision: https://reviews.llvm.org/D34207 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@307157 91177308-0d34-0410-b5e6-96231b3b80d8 David Green 2 years ago
2 changed file(s) with 118 addition(s) and 2 deletion(s). Raw diff Collapse all Expand all
2424 #include "llvm/IR/IRBuilder.h"
2525 #include "llvm/IR/Instructions.h"
2626 #include "llvm/IR/IntrinsicInst.h"
27 #include "llvm/IR/PatternMatch.h"
2728 #include "llvm/Support/Debug.h"
2829 #include "llvm/Support/raw_ostream.h"
2930
7980 bool IsSigned);
8081 bool eliminateSDiv(BinaryOperator *SDiv);
8182 bool strengthenOverflowingOperation(BinaryOperator *OBO, Value *IVOperand);
83 bool strengthenRightShift(BinaryOperator *BO, Value *IVOperand);
8284 };
8385 }
8486
582584 return Changed;
583585 }
584586
587 /// Annotate the Shr in (X << IVOperand) >> C as exact using the
588 /// information from the IV's range. Returns true if anything changed, false
589 /// otherwise.
590 bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO,
591 Value *IVOperand) {
592 using namespace llvm::PatternMatch;
593
594 if (BO->getOpcode() == Instruction::Shl) {
595 bool Changed = false;
596 ConstantRange IVRange = SE->getUnsignedRange(SE->getSCEV(IVOperand));
597 for (auto *U : BO->users()) {
598 const APInt *C;
599 if (match(U,
600 m_AShr(m_Shl(m_Value(), m_Specific(IVOperand)), m_APInt(C))) ||
601 match(U,
602 m_LShr(m_Shl(m_Value(), m_Specific(IVOperand)), m_APInt(C)))) {
603 BinaryOperator *Shr = cast(U);
604 if (!Shr->isExact() && IVRange.getUnsignedMin().uge(*C)) {
605 Shr->setIsExact(true);
606 Changed = true;
607 }
608 }
609 }
610 return Changed;
611 }
612
613 return false;
614 }
615
585616 /// Add all uses of Def to the current IV's worklist.
586617 static void pushIVUsers(
587618 Instruction *Def,
674705 }
675706
676707 if (BinaryOperator *BO = dyn_cast(UseOper.first)) {
677 if (isa(BO) &&
678 strengthenOverflowingOperation(BO, IVOperand)) {
708 if ((isa(BO) &&
709 strengthenOverflowingOperation(BO, IVOperand)) ||
710 (isa(BO) && strengthenRightShift(BO, IVOperand))) {
679711 // re-queue uses of the now modified binary operator and fall
680712 // through to the checks that remain.
681713 pushIVUsers(IVOperand, Simplified, SimpleIVUsers);
103103 ret i32 42
104104 }
105105
106 define hidden void @test.shl.exact.equal() {
107 ; CHECK-LABEL: @test.shl.exact.equal
108 entry:
109 br label %for.body
110
111 for.body:
112 ; CHECK-LABEL: for.body
113 %k.021 = phi i32 [ 1, %entry ], [ %inc, %for.body ]
114 %shl = shl i32 1, %k.021
115 %shr1 = ashr i32 %shl, 1
116 ; CHECK: %shr1 = ashr exact i32 %shl, 1
117 %shr2 = lshr i32 %shl, 1
118 ; CHECK: %shr2 = lshr exact i32 %shl, 1
119 %inc = add nuw nsw i32 %k.021, 1
120 %exitcond = icmp eq i32 %inc, 9
121 br i1 %exitcond, label %for.end, label %for.body
122
123 for.end:
124 ret void
125 }
126
127 define hidden void @test.shl.exact.greater() {
128 ; CHECK-LABEL: @test.shl.exact.greater
129 entry:
130 br label %for.body
131
132 for.body:
133 ; CHECK-LABEL: for.body
134 %k.021 = phi i32 [ 3, %entry ], [ %inc, %for.body ]
135 %shl = shl i32 1, %k.021
136 %shr1 = ashr i32 %shl, 2
137 ; CHECK: %shr1 = ashr exact i32 %shl, 2
138 %shr2 = lshr i32 %shl, 2
139 ; CHECK: %shr2 = lshr exact i32 %shl, 2
140 %inc = add nuw nsw i32 %k.021, 1
141 %exitcond = icmp eq i32 %inc, 9
142 br i1 %exitcond, label %for.end, label %for.body
143
144 for.end:
145 ret void
146 }
147
148 define hidden void @test.shl.exact.unbound(i32 %arg) {
149 ; CHECK-LABEL: @test.shl.exact.unbound
150 entry:
151 br label %for.body
152
153 for.body:
154 ; CHECK-LABEL: for.body
155 %k.021 = phi i32 [ 2, %entry ], [ %inc, %for.body ]
156 %shl = shl i32 1, %k.021
157 %shr1 = ashr i32 %shl, 2
158 ; CHECK: %shr1 = ashr exact i32 %shl, 2
159 %shr2 = lshr i32 %shl, 2
160 ; CHECK: %shr2 = lshr exact i32 %shl, 2
161 %inc = add nuw nsw i32 %k.021, 1
162 %exitcond = icmp eq i32 %inc, %arg
163 br i1 %exitcond, label %for.end, label %for.body
164
165 for.end:
166 ret void
167 }
168
169 define hidden void @test.shl.nonexact() {
170 ; CHECK-LABEL: @test.shl.nonexact
171 entry:
172 br label %for.body
173
174 for.body:
175 ; CHECK-LABEL: for.body
176 %k.021 = phi i32 [ 2, %entry ], [ %inc, %for.body ]
177 %shl = shl i32 1, %k.021
178 %shr1 = ashr i32 %shl, 3
179 ; CHECK: %shr1 = ashr i32 %shl, 3
180 %shr2 = lshr i32 %shl, 3
181 ; CHECK: %shr2 = lshr i32 %shl, 3
182 %inc = add nuw nsw i32 %k.021, 1
183 %exitcond = icmp eq i32 %inc, 9
184 br i1 %exitcond, label %for.end, label %for.body
185
186 for.end:
187 ret void
188 }
189
106190 !0 = !{i32 0, i32 2}
107191 !1 = !{i32 0, i32 42}