-
Notifications
You must be signed in to change notification settings - Fork 15.3k
[InstCombine] Fold select pattern with sub and negation to abs intrinsic #156246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
|
@llvm/pr-subscribers-llvm-transforms Author: AZero13 (AZero13) Changes%sub = sub nsw T %x, %y
%cmp = icmp sgt T %x, %y ; or sge
%neg = sub T 0, %sub
%abs = select i1 %cmp, T %sub, T %negbecomes:| %sub = sub nsw T %x, %y
%abs = call T @<!-- -->llvm.abs.T(T %sub, i1 false)0940842e61b4 Full diff: https://github.com/llvm/llvm-project/pull/156246.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index eb4332fbc0959..d75e34f90d469 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -1153,6 +1153,15 @@ static Value *foldAbsDiff(ICmpInst *Cmp, Value *TVal, Value *FVal,
return Builder.CreateBinaryIntrinsic(Intrinsic::abs, TI, Builder.getTrue());
}
+ // Match: (A > B) ? (A - B) : (0 - (A - B)) --> abs(A - B)
+ // Recognize the pattern where we have sub, icmp, neg(sub), select
+ if (Pred == CmpInst::ICMP_SGT &&
+ match(TI, m_Sub(m_Specific(A), m_Specific(B))) &&
+ match(FI, m_Neg(m_Specific(TI))) &&
+ TI->hasNoSignedWrap()) {
+ return Builder.CreateBinaryIntrinsic(Intrinsic::abs, TI, Builder.getFalse());
+ }
+
return nullptr;
}
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index d32f0e4690502..b58038bbec7ad 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -847,3 +847,74 @@ cond.end:
%r = phi i32 [ %0, %cond.true ], [ 0, %entry ]
ret i32 %r
}
+
+define i32 @abs_diff(i32 %x, i32 %y) {
+; CHECK-LABEL: @abs_diff(
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %sub = sub nsw i32 %x, %y
+ %cmp = icmp sgt i32 %x, %y
+ %sub1 = sub i32 0, %sub
+ %cond = select i1 %cmp, i32 %sub, i32 %sub1
+ ret i32 %cond
+}
+
+define i32 @abs_diff_neg_no_nsw_neg(i32 %x, i32 %y) {
+; CHECK-LABEL: @abs_diff_neg_no_nsw_neg(
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SUB1:%.*]] = sub i32 0, [[SUB]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[SUB1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %sub = sub i32 %x, %y
+ %cmp = icmp sgt i32 %x, %y
+ %sub1 = sub i32 0, %sub
+ %cond = select i1 %cmp, i32 %sub, i32 %sub1
+ ret i32 %cond
+}
+
+define i32 @abs_diff_neg(i32 %x, i32 %y) {
+; CHECK-LABEL: @abs_diff_neg(
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SUB1:%.*]] = sub i32 0, [[SUB]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[SUB1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %sub = sub nsw i32 %y, %x
+ %cmp = icmp sgt i32 %x, %y
+ %sub1 = sub i32 0, %sub
+ %cond = select i1 %cmp, i32 %sub, i32 %sub1
+ ret i32 %cond
+}
+
+define i32 @abs_diff_neg_no_nsw(i32 %x, i32 %y) {
+; CHECK-LABEL: @abs_diff_neg_no_nsw(
+; CHECK-NEXT: [[SUB:%.*]] = sub i32 [[Y:%.*]], [[X:%.*]]
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[X]], [[Y]]
+; CHECK-NEXT: [[SUB1:%.*]] = sub i32 0, [[SUB]]
+; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[SUB]], i32 [[SUB1]]
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %sub = sub i32 %y, %x
+ %cmp = icmp sgt i32 %x, %y
+ %sub1 = sub i32 0, %sub
+ %cond = select i1 %cmp, i32 %sub, i32 %sub1
+ ret i32 %cond
+}
+
+define i32 @abs_diff_ge(i32 %x, i32 %y) {
+; CHECK-LABEL: @abs_diff_ge(
+; CHECK-NEXT: [[SUB:%.*]] = sub nsw i32 [[X:%.*]], [[Y:%.*]]
+; CHECK-NEXT: [[COND:%.*]] = call i32 @llvm.abs.i32(i32 [[SUB]], i1 false)
+; CHECK-NEXT: ret i32 [[COND]]
+;
+ %sub = sub nsw i32 %x, %y
+ %cmp = icmp sge i32 %x, %y
+ %sub1 = sub i32 0, %sub
+ %cond = select i1 %cmp, i32 %sub, i32 %sub1
+ ret i32 %cond
+}
|
|
✅ With the latest revision this PR passed the C/C++ code formatter. |
|
@zyw-bot mfuzz |
|
Missing fold for another variant: https://alive2.llvm.org/ce/z/gRTmZk |
This patch adds a new fold in InstCombine to recognize and optimize a common absolute value pattern. ```llvm %sub = sub nsw T %x, %y %cmp = icmp sgt T %x, %y ; or sge %neg = sub T 0, %sub %abs = select i1 %cmp, T %sub, T %neg ``` becomes:| ```llvm %sub = sub nsw T %x, %y %abs = call T @llvm.abs.T(T %sub, i1 false) ```
|
@dtcxzyw done! |
dtcxzyw
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LG w/ some nits. Please avoid force-pushing your branch, unless you need to rebase on top of other commits... The two-commit history is not enforced.
|
Done @dtcxzyw |
|
@dtcxzyw Could you please merge? |
becomes:
Alive2: https://alive2.llvm.org/ce/z/ApdJX8
https://alive2.llvm.org/ce/z/gRTmZk