Skip to content
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

[InstCombine] Fold abs(a * abs(b)) --> abs(a * b) #78110

Merged
merged 2 commits into from
Feb 19, 2024

Conversation

elhewaty
Copy link
Contributor

@elhewaty elhewaty commented Jan 14, 2024

@llvmbot
Copy link
Collaborator

llvmbot commented Jan 14, 2024

@llvm/pr-subscribers-llvm-transforms

Author: None (elhewaty)

Changes

Full diff: https://github.com/llvm/llvm-project/pull/78110.diff

2 Files Affected:

  • (modified) llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp (+8)
  • (modified) llvm/test/Transforms/InstCombine/abs-intrinsic.ll (+49)
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 64fbd5543a9e203..978a7c1e256cef6 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -1601,6 +1601,14 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
       return CastInst::Create(Instruction::ZExt, NarrowAbs, II->getType());
     }
 
+    // abs(a * abs(b)) --> abs(a * b)
+    Value *A, *B;
+    if (match(IIOperand,
+              m_c_Mul(m_Value(A), m_Intrinsic<Intrinsic::abs>(m_Value(B))))) {
+      Value *New = Builder.CreateMul(A, B);
+      return replaceOperand(*II, 0, New);
+    }
+
     // Match a complicated way to check if a number is odd/even:
     // abs (srem X, 2) --> and X, 1
     const APInt *C;
diff --git a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
index 7fe34d923764857..8f31cb58dc8f14b 100644
--- a/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
+++ b/llvm/test/Transforms/InstCombine/abs-intrinsic.ll
@@ -5,8 +5,57 @@ declare i8 @llvm.abs.i8(i8, i1)
 declare i32 @llvm.abs.i32(i32, i1)
 declare <4 x i32> @llvm.abs.v4i32(<4 x i32>, i1)
 declare <3 x i82> @llvm.abs.v3i82(<3 x i82>, i1)
+declare <2 x i8> @llvm.abs.v2i8(<2 x i8>, i1)
 declare void @llvm.assume(i1)
 
+define i8 @test_abs_abs_a_mul_b_i8(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_abs_abs_a_mul_b_i8(
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i8 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[ABS2:%.*]] = call i8 @llvm.abs.i8(i8 [[TMP1]], i1 true)
+; CHECK-NEXT:    ret i8 [[ABS2]]
+;
+  %abs1 = call i8 @llvm.abs.i8(i8 %a, i1 true)
+  %mul = mul i8 %abs1, %b
+  %abs2 = call i8 @llvm.abs.i8(i8 %mul, i1 true)
+  ret i8 %abs2
+}
+
+define i8 @test_abs_a_mul_abs_b_i8(i8 %a, i8 %b) {
+; CHECK-LABEL: @test_abs_a_mul_abs_b_i8(
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i8 [[A:%.*]], [[B:%.*]]
+; CHECK-NEXT:    [[ABS2:%.*]] = call i8 @llvm.abs.i8(i8 [[TMP1]], i1 true)
+; CHECK-NEXT:    ret i8 [[ABS2]]
+;
+  %abs1 = call i8 @llvm.abs.i8(i8 %b, i1 true)
+  %mul = mul i8 %abs1, %a
+  %abs2 = call i8 @llvm.abs.i8(i8 %mul, i1 true)
+  ret i8 %abs2
+}
+
+define i32 @test_abs_abs_a_mul_b_i16(i32 %a, i32 %b) {
+; CHECK-LABEL: @test_abs_abs_a_mul_b_i16(
+; CHECK-NEXT:    [[TMP1:%.*]] = mul i32 [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[ABS2:%.*]] = call i32 @llvm.abs.i32(i32 [[TMP1]], i1 true)
+; CHECK-NEXT:    ret i32 [[ABS2]]
+;
+  %abs1 = call i32 @llvm.abs.i32(i32 %a, i1 true)
+  %mul = mul i32 %abs1, %b
+  %abs2 = call i32 @llvm.abs.i32(i32 %mul, i1 true)
+  ret i32 %abs2
+}
+
+define <2 x i8> @test_abs_abs_a_mul_b_vector_i8(<2 x i8> %a, <2 x i8> %b) {
+; CHECK-LABEL: @test_abs_abs_a_mul_b_vector_i8(
+; CHECK-NEXT:    [[TMP1:%.*]] = mul <2 x i8> [[B:%.*]], [[A:%.*]]
+; CHECK-NEXT:    [[ABS2:%.*]] = call <2 x i8> @llvm.abs.v2i8(<2 x i8> [[TMP1]], i1 true)
+; CHECK-NEXT:    ret <2 x i8> [[ABS2]]
+;
+  %abs = call <2 x i8> @llvm.abs.v2i8(<2 x i8> %a, i1 true)
+  %mul = mul <2 x i8> %abs, %b
+  %abs2 = call <2 x i8> @llvm.abs.v2i8(<2 x i8> %mul, i1 true)
+  ret <2 x i8> %abs2
+}
+
 ; abs preserves trailing zeros so the second and is unneeded
 define i32 @abs_trailing_zeros(i32 %x) {
 ; CHECK-LABEL: @abs_trailing_zeros(

@elhewaty
Copy link
Contributor Author

cc @dtcxzyw @goldsteinn

dtcxzyw added a commit to dtcxzyw/llvm-opt-benchmark that referenced this pull request Jan 17, 2024
@elhewaty
Copy link
Contributor Author

@nikic Can you please review this again?
and what is wrong with the build?

@elhewaty
Copy link
Contributor Author

@dtcxzyw, please share your thoughts.

@elhewaty
Copy link
Contributor Author

elhewaty commented Feb 6, 2024

@nikic @goldsteinn ping

@elhewaty
Copy link
Contributor Author

@dtcxzyw ping

@elhewaty elhewaty force-pushed the instcombine-fold-abs branch 2 times, most recently from 802fa00 to 5397dc6 Compare February 17, 2024 18:24
Copy link
Contributor

@nikic nikic left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp Outdated Show resolved Hide resolved
llvm/test/Transforms/InstCombine/abs-intrinsic.ll Outdated Show resolved Hide resolved
@elhewaty elhewaty requested a review from nikic February 17, 2024 20:33
@nikic nikic merged commit 69d4890 into llvm:main Feb 19, 2024
4 checks passed
@elhewaty elhewaty deleted the instcombine-fold-abs branch February 25, 2024 23:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

abs(b * abs(a)) --> abs(a * b)
5 participants