-
Notifications
You must be signed in to change notification settings - Fork 14.3k
[InstCombine] Simplify compare abs(X) and X. #76385
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: None (Z572) Changesfix #72653 Full diff: https://github.com/llvm/llvm-project/pull/76385.diff 2 Files Affected:
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
index 289976718e52f3..19ddffe75ff9b6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp
@@ -7109,6 +7109,47 @@ Instruction *InstCombinerImpl::visitICmpInst(ICmpInst &I) {
}
}
+ {
+ Value *X;
+ Constant *C;
+ if (match(Op0, m_OneUse(m_Intrinsic<Intrinsic::abs>(m_Value(X),
+ m_Constant(C)))) &&
+ match(Op1, m_Specific(X))) {
+ auto *NullValue = Constant::getNullValue(X->getType());
+ auto *MinVal = ConstantInt::get(
+ X->getType(),
+ APInt::getSignedMinValue(X->getType()->getScalarSizeInBits()));
+ bool IsIntMinPosion = C->isZeroValue();
+ switch (Pred) {
+ case CmpInst::ICMP_ULE:
+ case CmpInst::ICMP_SGE:
+ return replaceInstUsesWith(I, ConstantInt::getTrue(I.getType()));
+ case CmpInst::ICMP_UGT:
+ case CmpInst::ICMP_SLT:
+ return replaceInstUsesWith(I, ConstantInt::getFalse(I.getType()));
+ case CmpInst::ICMP_UGE:
+ case CmpInst::ICMP_SLE:
+ case CmpInst::ICMP_EQ: {
+ auto *SGE = Builder.CreateICmpSGE(X, NullValue);
+ return replaceInstUsesWith(
+ I, IsIntMinPosion
+ ? Builder.CreateOr(SGE, Builder.CreateICmpEQ(X, MinVal))
+ : SGE);
+ }
+ case CmpInst::ICMP_ULT:
+ case CmpInst::ICMP_NE:
+ case CmpInst::ICMP_SGT: {
+ auto *SLT = Builder.CreateICmpSLT(X, NullValue);
+ return replaceInstUsesWith(
+ I, IsIntMinPosion
+ ? Builder.CreateAnd(SLT, Builder.CreateICmpNE(X, MinVal))
+ : SLT);
+ }
+ default:
+ break;
+ }
+ }
+ }
if (Instruction *Res = foldICmpEquality(I))
return Res;
diff --git a/llvm/test/Transforms/InstCombine/icmp-abs.ll b/llvm/test/Transforms/InstCombine/icmp-abs.ll
new file mode 100644
index 00000000000000..382dab800dd942
--- /dev/null
+++ b/llvm/test/Transforms/InstCombine/icmp-abs.ll
@@ -0,0 +1,212 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -passes=instcombine -S | FileCheck %s
+
+target datalayout = "e-p:64:64:64-p1:16:16:16-p2:32:32:32-p3:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
+
+declare i4 @llvm.abs.i4(i4, i1)
+declare void @use_i4(i4)
+
+define i1 @icmp_sge_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_sge_abs(
+; CHECK-NEXT: ret i1 true
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp sge i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_sge_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_sge_abs_false(
+; CHECK-NEXT: ret i1 true
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp sge i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_eq_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_eq_abs(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i4 [[ARG:%.*]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp eq i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_eq_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_eq_abs_false(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i4 [[ARG:%.*]], -7
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp eq i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ne_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_ne_abs(
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i4 [[ARG:%.*]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp ne i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ne_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_ne_abs_false(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i4 [[ARG:%.*]], -8
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp ne i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_sle_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_sle_abs(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i4 [[ARG:%.*]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp sle i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_sle_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_sle_abs_false(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i4 [[ARG:%.*]], -7
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp sle i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_slt_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_slt_abs(
+; CHECK-NEXT: ret i1 false
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp slt i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_slt_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_slt_abs_false(
+; CHECK-NEXT: ret i1 false
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp slt i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_sgt_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_sgt_abs(
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i4 [[ARG:%.*]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp sgt i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_sgt_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_sgt_abs_false(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i4 [[ARG:%.*]], -8
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp sgt i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ugt_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_ugt_abs(
+; CHECK-NEXT: ret i1 false
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp ugt i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ugt_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_ugt_abs_false(
+; CHECK-NEXT: ret i1 false
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp ugt i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_uge_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_uge_abs(
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i4 [[ARG:%.*]], -1
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp uge i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_uge_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_uge_abs_false(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ult i4 [[ARG:%.*]], -7
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp uge i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ule_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_ule_abs(
+; CHECK-NEXT: ret i1 true
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp ule i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ule_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_ule_abs_false(
+; CHECK-NEXT: ret i1 true
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp ule i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ult_abs(i4 %arg) {
+; CHECK-LABEL: @icmp_ult_abs(
+; CHECK-NEXT: [[CMP:%.*]] = icmp slt i4 [[ARG:%.*]], 0
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 true)
+ %cmp = icmp ult i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_ult_abs_false(i4 %arg) {
+; CHECK-LABEL: @icmp_ult_abs_false(
+; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i4 [[ARG:%.*]], -8
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp ult i4 %abs, %arg
+ ret i1 %cmp
+}
+
+define i1 @icmp_sgt_abs_use(i4 %arg) {
+; CHECK-LABEL: @icmp_sgt_abs_use(
+; CHECK-NEXT: [[ABS:%.*]] = call i4 @llvm.abs.i4(i4 [[ARG:%.*]], i1 false)
+; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i4 [[ABS]], [[ARG]]
+; CHECK-NEXT: call void @use_i4(i4 [[ABS]])
+; CHECK-NEXT: ret i1 [[CMP]]
+;
+ %abs = call i4 @llvm.abs.i4(i4 %arg, i1 false)
+ %cmp = icmp sgt i4 %abs, %arg
+ call void @use_i4(i4 %abs)
+ ret i1 %cmp
+}
|
See also #73189. |
Please rebase over 9d5b096 and move the fold into foldICmpCommutative(). |
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.
LGTM. Please wait for additional approval from other reviewers.
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.
LGTM. Please wait for additional approval from other reviewers.
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.
LGTM
fix #72653
proof: https://alive2.llvm.org/ce/z/LZzZaj