[llvm] [LLVM] Simplify cabs libcall if real or imaginary part of input is zero (PR #97976)

Hendrik Hübner via llvm-commits llvm-commits at lists.llvm.org
Sun Jul 7 17:00:00 PDT 2024


https://github.com/HendrikHuebner updated https://github.com/llvm/llvm-project/pull/97976

>From d74e828ce58ef9114e1bb53076fad4026ea8d7cd Mon Sep 17 00:00:00 2001
From: hhuebner <ge84pip at mytum.de>
Date: Mon, 8 Jul 2024 01:33:49 +0200
Subject: [PATCH 1/2] Simplify cabs libcall if real or imaginary part is zero

---
 .../lib/Transforms/Utils/SimplifyLibCalls.cpp | 36 ++++++++++---
 .../Transforms/InstCombine/cabs-discrete.ll   | 54 +++++++++++++++++++
 2 files changed, 83 insertions(+), 7 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index 2e68a9c01898c..f44d59e54851f 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -27,6 +27,7 @@
 #include "llvm/IR/Intrinsics.h"
 #include "llvm/IR/Module.h"
 #include "llvm/IR/PatternMatch.h"
+#include "llvm/Support/Casting.h"
 #include "llvm/Support/CommandLine.h"
 #include "llvm/Support/KnownBits.h"
 #include "llvm/Support/MathExtras.h"
@@ -1880,25 +1881,46 @@ static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilderBase &B,
 
 // cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z)))
 Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilderBase &B) {
-  if (!CI->isFast())
-    return nullptr;
-
-  // Propagate fast-math flags from the existing call to new instructions.
-  IRBuilderBase::FastMathFlagGuard Guard(B);
-  B.setFastMathFlags(CI->getFastMathFlags());
-
   Value *Real, *Imag;
+
   if (CI->arg_size() == 1) {
     Value *Op = CI->getArgOperand(0);
     assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!");
     Real = B.CreateExtractValue(Op, 0, "real");
     Imag = B.CreateExtractValue(Op, 1, "imag");
+
   } else {
     assert(CI->arg_size() == 2 && "Unexpected signature for cabs!");
     Real = CI->getArgOperand(0);
     Imag = CI->getArgOperand(1);
   }
 
+  // if real or imaginary part is zero, simplify to abs(cimag(z))
+  // or abs(creal(z))
+  if (ConstantFP *ConstReal = dyn_cast<ConstantFP>(Real)) {
+    if (ConstReal->isZeroValue()) {
+      IRBuilderBase::FastMathFlagGuard Guard(B);
+      B.setFastMathFlags(CI->getFastMathFlags());
+      
+      return copyFlags(
+          *CI, B.CreateUnaryIntrinsic(Intrinsic::fabs, Imag, nullptr, "cabs"));
+    }
+  } else if (ConstantFP *ConstReal = dyn_cast<ConstantFP>(Imag)) {
+    if (ConstReal->isZeroValue()) {
+      IRBuilderBase::FastMathFlagGuard Guard(B);
+      B.setFastMathFlags(CI->getFastMathFlags());
+      return copyFlags(
+          *CI, B.CreateUnaryIntrinsic(Intrinsic::fabs, Real, nullptr, "cabs"));
+    }
+  }
+
+  if (!CI->isFast())
+    return nullptr;
+
+  // Propagate fast-math flags from the existing call to new instructions.
+  IRBuilderBase::FastMathFlagGuard Guard(B);
+  B.setFastMathFlags(CI->getFastMathFlags());
+
   Value *RealReal = B.CreateFMul(Real, Real);
   Value *ImagImag = B.CreateFMul(Imag, Imag);
 
diff --git a/llvm/test/Transforms/InstCombine/cabs-discrete.ll b/llvm/test/Transforms/InstCombine/cabs-discrete.ll
index 38aaf45e65fa4..7acd5edf61c40 100644
--- a/llvm/test/Transforms/InstCombine/cabs-discrete.ll
+++ b/llvm/test/Transforms/InstCombine/cabs-discrete.ll
@@ -40,6 +40,24 @@ define double @fast_cabs(double %real, double %imag) {
   ret double %call
 }
 
+define double @fast_cabs_zero_real(double %imag) {
+; CHECK-LABEL: @fast_cabs_zero_real(
+; CHECK-NEXT:    [[CABS:%.*]] = tail call double @llvm.fabs.f64(double [[IMAG:%.*]])
+; CHECK-NEXT:    ret double [[CABS]]
+;
+  %call = tail call double @cabs(double 0.0, double %imag)
+  ret double %call
+}
+
+define double @fast_cabs_zero_real(double %real) {
+; CHECK-LABEL: @fast_cabs_zero_real(
+; CHECK-NEXT:    [[CABS:%.*]] = tail call double @llvm.fabs.f64(double [[REAL:%.*]])
+; CHECK-NEXT:    ret double [[CABS]]
+;
+  %call = tail call double @cabs(double %real, 0.0)
+  ret double %call
+}
+
 define float @fast_cabsf(float %real, float %imag) {
 ; CHECK-LABEL: @fast_cabsf(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast float [[REAL:%.*]], [[REAL]]
@@ -52,6 +70,24 @@ define float @fast_cabsf(float %real, float %imag) {
   ret float %call
 }
 
+define float @fast_cabsf_zero_real(float %imag) {
+; CHECK-LABEL: @fast_cabsf_zero_real(
+; CHECK-NEXT:    [[CABS:%.*]] = tail call float @llvm.fabs.f32(float [[IMAG:%.*]])
+; CHECK-NEXT:    ret float [[CABS]]
+;
+  %call = tail call float @cabsf(float 0.0, float %imag)
+  ret float %call
+}
+
+define float @fast_cabsf_zero_real(float %real) {
+; CHECK-LABEL: @fast_cabsf_zero_real(
+; CHECK-NEXT:    [[CABS:%.*]] = tail call float @llvm.fabs.f64(float [[REAL:%.*]])
+; CHECK-NEXT:    ret float [[CABS]]
+;
+  %call = tail call float @cabsf(float %real, 0.0)
+  ret float %call
+}
+
 define fp128 @fast_cabsl(fp128 %real, fp128 %imag) {
 ; CHECK-LABEL: @fast_cabsl(
 ; CHECK-NEXT:    [[TMP1:%.*]] = fmul fast fp128 [[REAL:%.*]], [[REAL]]
@@ -64,6 +100,24 @@ define fp128 @fast_cabsl(fp128 %real, fp128 %imag) {
   ret fp128 %call
 }
 
+define fp128 @fast_cabsl_zero_real(fp128 %imag) {
+; CHECK-LABEL: @fast_cabsl_zero_real(
+; CHECK-NEXT:    [[CABS:%.*]] = tail call fp128 @llvm.fabsl.f128(fp128 [[IMAG:%.*]])
+; CHECK-NEXT:    ret fp128 [[CABS]]
+;
+  %call = tail call fp128 @cabsl(double 0.0, fp128 %imag)
+  ret fp128 %call
+}
+
+define fp128 @fast_cabsl_zero_real(fp128 %real) {
+; CHECK-LABEL: @fast_cabsl_zero_real(
+; CHECK-NEXT:    [[CABS:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[REAL:%.*]])
+; CHECK-NEXT:    ret fp128 [[CABS]]
+;
+  %call = tail call fp128 @cabsl(fp128 %real, 0.0)
+  ret fp128 %call
+}
+
 declare double @cabs(double %real, double %imag)
 declare float @cabsf(float %real, float %imag)
 declare fp128 @cabsl(fp128 %real, fp128 %imag)

>From e90e07e87df58122c9dcd974933a3da26cb3cf94 Mon Sep 17 00:00:00 2001
From: hhuebner <ge84pip at mytum.de>
Date: Mon, 8 Jul 2024 01:51:21 +0200
Subject: [PATCH 2/2] Add more tests

---
 llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp |  1 -
 .../Transforms/InstCombine/cabs-discrete.ll    | 18 +++++++++---------
 2 files changed, 9 insertions(+), 10 deletions(-)

diff --git a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
index f44d59e54851f..a14599da50f95 100644
--- a/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -1901,7 +1901,6 @@ Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilderBase &B) {
     if (ConstReal->isZeroValue()) {
       IRBuilderBase::FastMathFlagGuard Guard(B);
       B.setFastMathFlags(CI->getFastMathFlags());
-      
       return copyFlags(
           *CI, B.CreateUnaryIntrinsic(Intrinsic::fabs, Imag, nullptr, "cabs"));
     }
diff --git a/llvm/test/Transforms/InstCombine/cabs-discrete.ll b/llvm/test/Transforms/InstCombine/cabs-discrete.ll
index 7acd5edf61c40..68b962d90e2bd 100644
--- a/llvm/test/Transforms/InstCombine/cabs-discrete.ll
+++ b/llvm/test/Transforms/InstCombine/cabs-discrete.ll
@@ -49,12 +49,12 @@ define double @fast_cabs_zero_real(double %imag) {
   ret double %call
 }
 
-define double @fast_cabs_zero_real(double %real) {
-; CHECK-LABEL: @fast_cabs_zero_real(
+define double @fast_cabs_zero_imag(double %real) {
+; CHECK-LABEL: @fast_cabs_zero_imag(
 ; CHECK-NEXT:    [[CABS:%.*]] = tail call double @llvm.fabs.f64(double [[REAL:%.*]])
 ; CHECK-NEXT:    ret double [[CABS]]
 ;
-  %call = tail call double @cabs(double %real, 0.0)
+  %call = tail call double @cabs(double %real, double 0.0)
   ret double %call
 }
 
@@ -79,12 +79,12 @@ define float @fast_cabsf_zero_real(float %imag) {
   ret float %call
 }
 
-define float @fast_cabsf_zero_real(float %real) {
-; CHECK-LABEL: @fast_cabsf_zero_real(
+define float @fast_cabsf_zero_imag(float %real) {
+; CHECK-LABEL: @fast_cabsf_zero_imag(
 ; CHECK-NEXT:    [[CABS:%.*]] = tail call float @llvm.fabs.f64(float [[REAL:%.*]])
 ; CHECK-NEXT:    ret float [[CABS]]
 ;
-  %call = tail call float @cabsf(float %real, 0.0)
+  %call = tail call float @cabsf(float %real, float 0.0)
   ret float %call
 }
 
@@ -109,12 +109,12 @@ define fp128 @fast_cabsl_zero_real(fp128 %imag) {
   ret fp128 %call
 }
 
-define fp128 @fast_cabsl_zero_real(fp128 %real) {
-; CHECK-LABEL: @fast_cabsl_zero_real(
+define fp128 @fast_cabsl_zero_imag(fp128 %real) {
+; CHECK-LABEL: @fast_cabsl_zero_imag(
 ; CHECK-NEXT:    [[CABS:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[REAL:%.*]])
 ; CHECK-NEXT:    ret fp128 [[CABS]]
 ;
-  %call = tail call fp128 @cabsl(fp128 %real, 0.0)
+  %call = tail call fp128 @cabsl(fp128 %real, fp128 0.0)
   ret fp128 %call
 }
 



More information about the llvm-commits mailing list