llvm.org GIT mirror llvm / 9a3e5b0
[EarlyCSE] recognize commuted and swapped variants of min/max as equivalent (PR35642) As shown in: https://bugs.llvm.org/show_bug.cgi?id=35642 ...we can have different forms of min/max, so we should recognize those here in EarlyCSE similar to how we already handle binops and compares that can commute. Differential Revision: https://reviews.llvm.org/D41136 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@320640 91177308-0d34-0410-b5e6-96231b3b80d8 Sanjay Patel 1 year, 9 months ago
2 changed file(s) with 54 addition(s) and 22 deletion(s). Raw diff Collapse all Expand all
2626 #include "llvm/Analysis/MemorySSAUpdater.h"
2727 #include "llvm/Analysis/TargetLibraryInfo.h"
2828 #include "llvm/Analysis/TargetTransformInfo.h"
29 #include "llvm/Analysis/ValueTracking.h"
2930 #include "llvm/IR/BasicBlock.h"
3031 #include "llvm/IR/Constants.h"
3132 #include "llvm/IR/DataLayout.h"
141142 return hash_combine(Inst->getOpcode(), Pred, LHS, RHS);
142143 }
143144
145 // Hash min/max (cmp + select) to allow for commuted operands, non-canonical
146 // compare predicate (eg, the compare for smin may use 'sgt' rather than
147 // 'slt'), and non-canonical operands in the compare.
148 Value *A, *B;
149 SelectPatternFlavor SPF = matchSelectPattern(Inst, A, B).Flavor;
150 // TODO: We should also detect abs and FP min/max.
151 if (SPF == SPF_SMIN || SPF == SPF_SMAX ||
152 SPF == SPF_UMIN || SPF == SPF_UMAX) {
153 if (A > B)
154 std::swap(A, B);
155 return hash_combine(Inst->getOpcode(), SPF, A, B);
156 }
157
144158 if (CastInst *CI = dyn_cast(Inst))
145159 return hash_combine(CI->getOpcode(), CI->getType(), CI->getOperand(0));
146160
197211 return LHSCmp->getOperand(0) == RHSCmp->getOperand(1) &&
198212 LHSCmp->getOperand(1) == RHSCmp->getOperand(0) &&
199213 LHSCmp->getSwappedPredicate() == RHSCmp->getPredicate();
214 }
215
216 // Min/max can occur with commuted operands, non-canonical predicates, and/or
217 // non-canonical operands.
218 Value *LHSA, *LHSB;
219 SelectPatternFlavor LSPF = matchSelectPattern(LHSI, LHSA, LHSB).Flavor;
220 // TODO: We should also detect abs and FP min/max.
221 if (LSPF == SPF_SMIN || LSPF == SPF_SMAX ||
222 LSPF == SPF_UMIN || LSPF == SPF_UMAX) {
223 Value *RHSA, *RHSB;
224 SelectPatternFlavor RSPF = matchSelectPattern(RHSI, RHSA, RHSB).Flavor;
225 return (LSPF == RSPF && ((LHSA == RHSA && LHSB == RHSB) ||
226 (LHSA == RHSB && LHSB == RHSA)));
200227 }
201228
202229 return false;
7777 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, %b
7878 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 %b, %a
7979 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
80 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %b, i8 %a
81 ; CHECK-NEXT: [[R:%.*]] = mul i8 [[M1]], [[M2]]
80 ; CHECK-NEXT: [[R:%.*]] = mul i8 [[M1]], [[M1]]
8281 ; CHECK-NEXT: ret i8 [[R]]
8382 ;
8483 %cmp1 = icmp slt i8 %a, %b
9695 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 %a, %b
9796 ; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i8 %a, %b
9897 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a
99 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %a, i8 %b
100 ; CHECK-NEXT: [[R:%.*]] = icmp eq i8 [[M2]], [[M1]]
101 ; CHECK-NEXT: ret i1 [[R]]
98 ; CHECK-NEXT: ret i1 true
10299 ;
103100 %cmp1 = icmp sgt i8 %a, %b
104101 %cmp2 = icmp slt i8 %a, %b
113110 ; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i8 %a, %b
114111 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 %b, %a
115112 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
116 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %b, i8 %a
117 ; CHECK-NEXT: [[R:%.*]] = urem i8 [[M2]], [[M1]]
118 ; CHECK-NEXT: ret i8 [[R]]
113 ; CHECK-NEXT: ret i8 0
119114 ;
120115 %cmp1 = icmp sgt i8 %a, %b
121116 %cmp2 = icmp sgt i8 %b, %a
130125 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, %b
131126 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 %a, %b
132127 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a
133 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %a, i8 %b
134 ; CHECK-NEXT: [[R:%.*]] = sdiv i8 [[M1]], [[M2]]
135 ; CHECK-NEXT: ret i8 [[R]]
128 ; CHECK-NEXT: ret i8 1
136129 ;
137130 %cmp1 = icmp slt i8 %a, %b
138131 %cmp2 = icmp sgt i8 %a, %b
147140 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 %a, %b
148141 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult i8 %b, %a
149142 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
150 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %b, i8 %a
151 ; CHECK-NEXT: [[R:%.*]] = sub i8 [[M2]], [[M1]]
152 ; CHECK-NEXT: ret i8 [[R]]
143 ; CHECK-NEXT: ret i8 0
153144 ;
154145 %cmp1 = icmp ult i8 %a, %b
155146 %cmp2 = icmp ult i8 %b, %a
166157 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt <2 x i8> %a, %b
167158 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ult <2 x i8> %a, %b
168159 ; CHECK-NEXT: [[M1:%.*]] = select <2 x i1> [[CMP1]], <2 x i8> %b, <2 x i8> %a
169 ; CHECK-NEXT: [[M2:%.*]] = select <2 x i1> [[CMP2]], <2 x i8> %a, <2 x i8> %b
170 ; CHECK-NEXT: [[R:%.*]] = sub <2 x i8> [[M2]], [[M1]]
171 ; CHECK-NEXT: ret <2 x i8> [[R]]
160 ; CHECK-NEXT: ret <2 x i8> zeroinitializer
172161 ;
173162 %cmp1 = icmp ugt <2 x i8> %a, %b
174163 %cmp2 = icmp ult <2 x i8> %a, %b
183172 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ugt i8 %a, %b
184173 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 %b, %a
185174 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %a, i8 %b
186 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %b, i8 %a
187 ; CHECK-NEXT: [[R:%.*]] = udiv i8 [[M1]], [[M2]]
188 ; CHECK-NEXT: ret i8 [[R]]
175 ; CHECK-NEXT: ret i8 1
189176 ;
190177 %cmp1 = icmp ugt i8 %a, %b
191178 %cmp2 = icmp ugt i8 %b, %a
200187 ; CHECK-NEXT: [[CMP1:%.*]] = icmp ult i8 %a, %b
201188 ; CHECK-NEXT: [[CMP2:%.*]] = icmp ugt i8 %a, %b
202189 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 %b, i8 %a
203 ; CHECK-NEXT: [[M2:%.*]] = select i1 [[CMP2]], i8 %a, i8 %b
204 ; CHECK-NEXT: [[R:%.*]] = add i8 [[M2]], [[M1]]
190 ; CHECK-NEXT: [[R:%.*]] = add i8 [[M1]], [[M1]]
205191 ; CHECK-NEXT: ret i8 [[R]]
206192 ;
207193 %cmp1 = icmp ult i8 %a, %b
212198 ret i8 %r
213199 }
214200
201 ; Min/max may exist with non-canonical operands. Value tracking can match those.
202
203 define i8 @smax_nsw(i8 %a, i8 %b) {
204 ; CHECK-LABEL: @smax_nsw(
205 ; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 %a, %b
206 ; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i8 %a, %b
207 ; CHECK-NEXT: [[CMP2:%.*]] = icmp sgt i8 [[SUB]], 0
208 ; CHECK-NEXT: [[M1:%.*]] = select i1 [[CMP1]], i8 0, i8 [[SUB]]
209 ; CHECK-NEXT: ret i8 0
210 ;
211 %sub = sub nsw i8 %a, %b
212 %cmp1 = icmp slt i8 %a, %b
213 %cmp2 = icmp sgt i8 %sub, 0
214 %m1 = select i1 %cmp1, i8 0, i8 %sub
215 %m2 = select i1 %cmp2, i8 %sub, i8 0
216 %r = sub i8 %m2, %m1
217 ret i8 %r
218 }
219