Skip to content

Commit 567485a

Browse files
author
Chen Zheng
committed
[InstCombine] canonicalize abs pattern
Differential Revision: https://reviews.llvm.org/D48754 llvm-svn: 338092
1 parent be97297 commit 567485a

File tree

4 files changed

+171
-77
lines changed

4 files changed

+171
-77
lines changed

llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp

Lines changed: 50 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -794,8 +794,11 @@ canonicalizeMinMaxWithConstant(SelectInst &Sel, ICmpInst &Cmp,
794794
return &Sel;
795795
}
796796

797-
/// There are 4 select variants for each of ABS/NABS (different compare
798-
/// constants, compare predicates, select operands). Canonicalize to 1 pattern.
797+
/// There are many select variants for each of ABS/NABS.
798+
/// In matchSelectPattern(), there are different compare constants, compare
799+
/// predicates/operands and select operands.
800+
/// In isKnownNegation(), there are different formats of negated operands.
801+
/// Canonicalize all these variants to 1 pattern.
799802
/// This makes CSE more likely.
800803
static Instruction *canonicalizeAbsNabs(SelectInst &Sel, ICmpInst &Cmp,
801804
InstCombiner::BuilderTy &Builder) {
@@ -810,34 +813,61 @@ static Instruction *canonicalizeAbsNabs(SelectInst &Sel, ICmpInst &Cmp,
810813
if (SPF != SelectPatternFlavor::SPF_ABS &&
811814
SPF != SelectPatternFlavor::SPF_NABS)
812815
return nullptr;
813-
814-
// TODO: later canonicalization change will move this condition check.
815-
// Without this check, following assert will be hit.
816-
if (match(Cmp.getOperand(0), m_Sub(m_Value(), m_Value())))
817-
return nullptr;
816+
817+
Value *TVal = Sel.getTrueValue();
818+
Value *FVal = Sel.getFalseValue();
819+
assert(isKnownNegation(TVal, FVal) &&
820+
"Unexpected result from matchSelectPattern");
821+
822+
// The compare may use the negated abs()/nabs() operand, or it may use
823+
// negation in non-canonical form such as: sub A, B.
824+
bool CmpUsesNegatedOp = match(Cmp.getOperand(0), m_Neg(m_Specific(TVal))) ||
825+
match(Cmp.getOperand(0), m_Neg(m_Specific(FVal)));
826+
827+
bool CmpCanonicalized = !CmpUsesNegatedOp &&
828+
match(Cmp.getOperand(1), m_ZeroInt()) &&
829+
Cmp.getPredicate() == ICmpInst::ICMP_SLT;
830+
bool RHSCanonicalized = match(RHS, m_Neg(m_Specific(LHS)));
818831

819832
// Is this already canonical?
820-
if (match(Cmp.getOperand(1), m_ZeroInt()) &&
821-
Cmp.getPredicate() == ICmpInst::ICMP_SLT)
833+
if (CmpCanonicalized && RHSCanonicalized)
822834
return nullptr;
823835

824-
// Create the canonical compare.
825-
Cmp.setPredicate(ICmpInst::ICMP_SLT);
826-
Cmp.setOperand(1, ConstantInt::getNullValue(Cmp.getOperand(0)->getType()));
836+
// If RHS is used by other instructions except compare and select, don't
837+
// canonicalize it to not increase the instruction count.
838+
if (!(RHS->hasOneUse() || (RHS->hasNUses(2) && CmpUsesNegatedOp)))
839+
return nullptr;
840+
841+
// Create the canonical compare: icmp slt LHS 0.
842+
if (!CmpCanonicalized) {
843+
Cmp.setPredicate(ICmpInst::ICMP_SLT);
844+
Cmp.setOperand(1, ConstantInt::getNullValue(Cmp.getOperand(0)->getType()));
845+
if (CmpUsesNegatedOp)
846+
Cmp.setOperand(0, LHS);
847+
}
848+
849+
// Create the canonical RHS: RHS = sub (0, LHS).
850+
if (!RHSCanonicalized) {
851+
assert(RHS->hasOneUse() && "RHS use number is not right");
852+
RHS = Builder.CreateNeg(LHS);
853+
if (TVal == LHS) {
854+
Sel.setFalseValue(RHS);
855+
FVal = RHS;
856+
} else {
857+
Sel.setTrueValue(RHS);
858+
TVal = RHS;
859+
}
860+
}
827861

828862
// If the select operands do not change, we're done.
829-
Value *TVal = Sel.getTrueValue();
830-
Value *FVal = Sel.getFalseValue();
831863
if (SPF == SelectPatternFlavor::SPF_NABS) {
832-
if (TVal == LHS && match(FVal, m_Neg(m_Specific(TVal))))
864+
if (TVal == LHS)
833865
return &Sel;
834-
assert(FVal == LHS && match(TVal, m_Neg(m_Specific(FVal))) &&
835-
"Unexpected results from matchSelectPattern");
866+
assert(FVal == LHS && "Unexpected results from matchSelectPattern");
836867
} else {
837-
if (FVal == LHS && match(TVal, m_Neg(m_Specific(FVal))))
868+
if (FVal == LHS)
838869
return &Sel;
839-
assert(TVal == LHS && match(FVal, m_Neg(m_Specific(TVal))) &&
840-
"Unexpected results from matchSelectPattern");
870+
assert(TVal == LHS && "Unexpected results from matchSelectPattern");
841871
}
842872

843873
// We are swapping the select operands, so swap the metadata too.

llvm/test/Transforms/InstCombine/abs-1.ll

Lines changed: 80 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -134,9 +134,9 @@ define i32 @abs_canonical_5(i8 %x) {
134134
define i32 @abs_canonical_6(i32 %a, i32 %b) {
135135
; CHECK-LABEL: @abs_canonical_6(
136136
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
137-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
138-
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]]
139-
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]]
137+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
138+
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]]
139+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]]
140140
; CHECK-NEXT: ret i32 [[ABS]]
141141
;
142142
%tmp1 = sub i32 %a, %b
@@ -149,9 +149,9 @@ define i32 @abs_canonical_6(i32 %a, i32 %b) {
149149
define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
150150
; CHECK-LABEL: @abs_canonical_7(
151151
; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]]
152-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[TMP1]], <i8 -1, i8 -1>
153-
; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> [[B]], [[A]]
154-
; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]]
152+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer
153+
; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
154+
; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP2]], <2 x i8> [[TMP1]]
155155
; CHECK-NEXT: ret <2 x i8> [[ABS]]
156156
;
157157

@@ -165,8 +165,8 @@ define <2 x i8> @abs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
165165
define i32 @abs_canonical_8(i32 %a) {
166166
; CHECK-LABEL: @abs_canonical_8(
167167
; CHECK-NEXT: [[TMP:%.*]] = sub i32 0, [[A:%.*]]
168-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP]], 0
169-
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]]
168+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0
169+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP]], i32 [[A]]
170170
; CHECK-NEXT: ret i32 [[ABS]]
171171
;
172172
%tmp = sub i32 0, %a
@@ -175,6 +175,38 @@ define i32 @abs_canonical_8(i32 %a) {
175175
ret i32 %abs
176176
}
177177

178+
define i32 @abs_canonical_9(i32 %a, i32 %b) {
179+
; CHECK-LABEL: @abs_canonical_9(
180+
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
181+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
182+
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]]
183+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]]
184+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[ABS]], [[TMP2]]
185+
; CHECK-NEXT: ret i32 [[ADD]]
186+
;
187+
%tmp1 = sub i32 %a, %b
188+
%cmp = icmp sgt i32 %tmp1, -1
189+
%tmp2 = sub i32 %b, %a
190+
%abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
191+
%add = add i32 %abs, %tmp2 ; increase use count for %tmp2.
192+
ret i32 %add
193+
}
194+
195+
define i32 @abs_canonical_10(i32 %a, i32 %b) {
196+
; CHECK-LABEL: @abs_canonical_10(
197+
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
198+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
199+
; CHECK-NEXT: [[NEGTMP:%.*]] = sub i32 0, [[TMP1]]
200+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[NEGTMP]], i32 [[TMP1]]
201+
; CHECK-NEXT: ret i32 [[ABS]]
202+
;
203+
%tmp2 = sub i32 %b, %a
204+
%tmp1 = sub i32 %a, %b
205+
%cmp = icmp sgt i32 %tmp1, -1
206+
%abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
207+
ret i32 %abs
208+
}
209+
178210
; We have a canonical form of nabs to make CSE easier.
179211

180212
define i8 @nabs_canonical_1(i8 %x) {
@@ -266,9 +298,9 @@ define i32 @nabs_canonical_5(i8 %x) {
266298
define i32 @nabs_canonical_6(i32 %a, i32 %b) {
267299
; CHECK-LABEL: @nabs_canonical_6(
268300
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
269-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
270-
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]]
271-
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]]
301+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
302+
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 0, [[TMP1]]
303+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[TMP2]]
272304
; CHECK-NEXT: ret i32 [[ABS]]
273305
;
274306
%tmp1 = sub i32 %a, %b
@@ -281,9 +313,9 @@ define i32 @nabs_canonical_6(i32 %a, i32 %b) {
281313
define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
282314
; CHECK-LABEL: @nabs_canonical_7(
283315
; CHECK-NEXT: [[TMP1:%.*]] = sub <2 x i8> [[A:%.*]], [[B:%.*]]
284-
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt <2 x i8> [[TMP1]], <i8 -1, i8 -1>
285-
; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> [[B]], [[A]]
286-
; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP2]], <2 x i8> [[TMP1]]
316+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt <2 x i8> [[TMP1]], zeroinitializer
317+
; CHECK-NEXT: [[TMP2:%.*]] = sub <2 x i8> zeroinitializer, [[TMP1]]
318+
; CHECK-NEXT: [[ABS:%.*]] = select <2 x i1> [[CMP]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]]
287319
; CHECK-NEXT: ret <2 x i8> [[ABS]]
288320
;
289321
%tmp1 = sub <2 x i8> %a, %b
@@ -296,8 +328,8 @@ define <2 x i8> @nabs_canonical_7(<2 x i8> %a, <2 x i8 > %b) {
296328
define i32 @nabs_canonical_8(i32 %a) {
297329
; CHECK-LABEL: @nabs_canonical_8(
298330
; CHECK-NEXT: [[TMP:%.*]] = sub i32 0, [[A:%.*]]
299-
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP]], 0
300-
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP]], i32 [[A]]
331+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[A]], 0
332+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[A]], i32 [[TMP]]
301333
; CHECK-NEXT: ret i32 [[ABS]]
302334
;
303335
%tmp = sub i32 0, %a
@@ -306,6 +338,38 @@ define i32 @nabs_canonical_8(i32 %a) {
306338
ret i32 %abs
307339
}
308340

341+
define i32 @nabs_canonical_9(i32 %a, i32 %b) {
342+
; CHECK-LABEL: @nabs_canonical_9(
343+
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
344+
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[TMP1]], -1
345+
; CHECK-NEXT: [[TMP2:%.*]] = sub i32 [[B]], [[A]]
346+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP2]], i32 [[TMP1]]
347+
; CHECK-NEXT: [[ADD:%.*]] = add i32 [[TMP2]], [[ABS]]
348+
; CHECK-NEXT: ret i32 [[ADD]]
349+
;
350+
%tmp1 = sub i32 %a, %b
351+
%cmp = icmp sgt i32 %tmp1, -1
352+
%tmp2 = sub i32 %b, %a
353+
%abs = select i1 %cmp, i32 %tmp2, i32 %tmp1
354+
%add = add i32 %tmp2, %abs ; increase use count for %tmp2
355+
ret i32 %add
356+
}
357+
358+
define i32 @nabs_canonical_10(i32 %a, i32 %b) {
359+
; CHECK-LABEL: @nabs_canonical_10(
360+
; CHECK-NEXT: [[TMP1:%.*]] = sub i32 [[A:%.*]], [[B:%.*]]
361+
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 0
362+
; CHECK-NEXT: [[NEGTMP:%.*]] = sub i32 0, [[TMP1]]
363+
; CHECK-NEXT: [[ABS:%.*]] = select i1 [[CMP]], i32 [[TMP1]], i32 [[NEGTMP]]
364+
; CHECK-NEXT: ret i32 [[ABS]]
365+
;
366+
%tmp2 = sub i32 %b, %a
367+
%tmp1 = sub i32 %a, %b
368+
%cmp = icmp slt i32 %tmp1, 1
369+
%abs = select i1 %cmp, i32 %tmp1, i32 %tmp2
370+
ret i32 %abs
371+
}
372+
309373
; The following 5 tests use a shift+add+xor to implement abs():
310374
; B = ashr i8 A, 7 -- smear the sign bit.
311375
; xor (add A, B), B -- add -1 and flip bits if negative

0 commit comments

Comments
 (0)