[PATCH] D39766: [InstCombine] Teach visitICmpInst to not break integer absolute value idioms
Craig Topper via Phabricator via llvm-commits
llvm-commits at lists.llvm.org
Tue Nov 7 16:27:15 PST 2017
craig.topper updated this revision to Diff 122018.
craig.topper added a comment.
Add full context
https://reviews.llvm.org/D39766
Files:
lib/Transforms/InstCombine/InstCombineCompares.cpp
test/Transforms/InstCombine/icmp.ll
Index: test/Transforms/InstCombine/icmp.ll
===================================================================
--- test/Transforms/InstCombine/icmp.ll
+++ test/Transforms/InstCombine/icmp.ll
@@ -3270,3 +3270,19 @@
%c = icmp sgt i8 %b2, %a2
ret i1 %c
}
+
+; Make sure InstCombine doesn't try too hard to simplify the icmp and break the abs idiom
+define i32 @abs_preserve(i32 %x) {
+; CHECK-LABEL: @abs_preserve(
+; CHECK-NEXT: [[A:%.*]] = shl nsw i32 [[X:%.*]], 1
+; CHECK-NEXT: [[C:%.*]] = icmp sgt i32 [[A]], -1
+; CHECK-NEXT: [[NEGA:%.*]] = sub i32 0, [[A]]
+; CHECK-NEXT: [[ABS:%.*]] = select i1 [[C]], i32 [[A]], i32 [[NEGA]]
+; CHECK-NEXT: ret i32 [[ABS]]
+;
+ %a = mul nsw i32 %x, 2
+ %c = icmp sge i32 %a, 0
+ %nega = sub i32 0, %a
+ %abs = select i1 %c, i32 %a, i32 %nega
+ ret i32 %abs
+}
Index: lib/Transforms/InstCombine/InstCombineCompares.cpp
===================================================================
--- lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -4462,11 +4462,28 @@
// operands has at least one user besides the compare (the select),
// which would often largely negate the benefit of folding anyway.
if (I.hasOneUse())
- if (SelectInst *SI = dyn_cast<SelectInst>(*I.user_begin()))
- if ((SI->getOperand(1) == Op0 && SI->getOperand(2) == Op1) ||
- (SI->getOperand(2) == Op0 && SI->getOperand(1) == Op1))
+ if (SelectInst *SI = dyn_cast<SelectInst>(*I.user_begin())) {
+ Value *TrueVal = SI->getTrueValue();
+ Value *FalseVal = SI->getFalseValue();
+ if ((TrueVal == Op0 && FalseVal == Op1) ||
+ (FalseVal == Op0 && TrueVal == Op1))
return nullptr;
+ // Prevent disturbing an absolute value operation as well.
+ const APInt *C;
+ if (match(Op1, m_APInt(C))) {
+ if ((Op0 == TrueVal && match(FalseVal, m_Neg(m_Specific(Op0)))) ||
+ (Op0 == FalseVal && match(TrueVal, m_Neg(m_Specific(Op0))))) {
+ ICmpInst::Predicate Pred = I.getPredicate();
+ if ((Pred == ICmpInst::ICMP_SGT &&
+ (C->isNullValue() || C->isAllOnesValue())) ||
+ (Pred == ICmpInst::ICMP_SLT &&
+ (C->isNullValue() || C->isOneValue())))
+ return nullptr;
+ }
+ }
+ }
+
// Do this after checking for min/max to prevent infinite looping.
if (Instruction *Res = foldICmpWithZero(I))
return Res;
-------------- next part --------------
A non-text attachment was scrubbed...
Name: D39766.122018.patch
Type: text/x-patch
Size: 2468 bytes
Desc: not available
URL: <http://lists.llvm.org/pipermail/llvm-commits/attachments/20171108/6437e0c6/attachment.bin>
More information about the llvm-commits
mailing list