Skip to content

Commit e980990

Browse files
[SimplifyLibCalls] Simplify cabs libcall if real or imaginary part of input is zero (#97976)
cabs(a + i0) -> abs(a) cabs(0 +ib) -> abs(b) Closes #97336
1 parent 67f4968 commit e980990

File tree

2 files changed

+117
-7
lines changed

2 files changed

+117
-7
lines changed

llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "llvm/IR/Intrinsics.h"
2828
#include "llvm/IR/Module.h"
2929
#include "llvm/IR/PatternMatch.h"
30+
#include "llvm/Support/Casting.h"
3031
#include "llvm/Support/CommandLine.h"
3132
#include "llvm/Support/KnownBits.h"
3233
#include "llvm/Support/MathExtras.h"
@@ -1958,25 +1959,53 @@ static Value *optimizeBinaryDoubleFP(CallInst *CI, IRBuilderBase &B,
19581959

19591960
// cabs(z) -> sqrt((creal(z)*creal(z)) + (cimag(z)*cimag(z)))
19601961
Value *LibCallSimplifier::optimizeCAbs(CallInst *CI, IRBuilderBase &B) {
1961-
if (!CI->isFast())
1962-
return nullptr;
1963-
1964-
// Propagate fast-math flags from the existing call to new instructions.
1965-
IRBuilderBase::FastMathFlagGuard Guard(B);
1966-
B.setFastMathFlags(CI->getFastMathFlags());
1967-
19681962
Value *Real, *Imag;
1963+
19691964
if (CI->arg_size() == 1) {
1965+
1966+
if (!CI->isFast())
1967+
return nullptr;
1968+
19701969
Value *Op = CI->getArgOperand(0);
19711970
assert(Op->getType()->isArrayTy() && "Unexpected signature for cabs!");
1971+
19721972
Real = B.CreateExtractValue(Op, 0, "real");
19731973
Imag = B.CreateExtractValue(Op, 1, "imag");
1974+
19741975
} else {
19751976
assert(CI->arg_size() == 2 && "Unexpected signature for cabs!");
1977+
19761978
Real = CI->getArgOperand(0);
19771979
Imag = CI->getArgOperand(1);
1980+
1981+
// if real or imaginary part is zero, simplify to abs(cimag(z))
1982+
// or abs(creal(z))
1983+
Value *AbsOp = nullptr;
1984+
if (ConstantFP *ConstReal = dyn_cast<ConstantFP>(Real)) {
1985+
if (ConstReal->isZero())
1986+
AbsOp = Imag;
1987+
1988+
} else if (ConstantFP *ConstImag = dyn_cast<ConstantFP>(Imag)) {
1989+
if (ConstImag->isZero())
1990+
AbsOp = Real;
1991+
}
1992+
1993+
if (AbsOp) {
1994+
IRBuilderBase::FastMathFlagGuard Guard(B);
1995+
B.setFastMathFlags(CI->getFastMathFlags());
1996+
1997+
return copyFlags(
1998+
*CI, B.CreateUnaryIntrinsic(Intrinsic::fabs, AbsOp, nullptr, "cabs"));
1999+
}
2000+
2001+
if (!CI->isFast())
2002+
return nullptr;
19782003
}
19792004

2005+
// Propagate fast-math flags from the existing call to new instructions.
2006+
IRBuilderBase::FastMathFlagGuard Guard(B);
2007+
B.setFastMathFlags(CI->getFastMathFlags());
2008+
19802009
Value *RealReal = B.CreateFMul(Real, Real);
19812010
Value *ImagImag = B.CreateFMul(Imag, Imag);
19822011

llvm/test/Transforms/InstCombine/cabs-discrete.ll

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,33 @@ define double @fast_cabs(double %real, double %imag) {
4040
ret double %call
4141
}
4242

43+
define double @cabs_zero_real(double %imag) {
44+
; CHECK-LABEL: @cabs_zero_real(
45+
; CHECK-NEXT: [[CABS:%.*]] = tail call double @llvm.fabs.f64(double [[IMAG:%.*]])
46+
; CHECK-NEXT: ret double [[CABS]]
47+
;
48+
%call = tail call double @cabs(double 0.0, double %imag)
49+
ret double %call
50+
}
51+
52+
define double @fast_cabs_neg_zero_real(double %imag) {
53+
; CHECK-LABEL: @fast_cabs_neg_zero_real(
54+
; CHECK-NEXT: [[CABS:%.*]] = tail call fast double @llvm.fabs.f64(double [[IMAG:%.*]])
55+
; CHECK-NEXT: ret double [[CABS]]
56+
;
57+
%call = tail call fast double @cabs(double -0.0, double %imag)
58+
ret double %call
59+
}
60+
61+
define double @cabs_zero_imag(double %real) {
62+
; CHECK-LABEL: @cabs_zero_imag(
63+
; CHECK-NEXT: [[CABS:%.*]] = tail call double @llvm.fabs.f64(double [[REAL:%.*]])
64+
; CHECK-NEXT: ret double [[CABS]]
65+
;
66+
%call = tail call double @cabs(double %real, double 0.0)
67+
ret double %call
68+
}
69+
4370
define float @fast_cabsf(float %real, float %imag) {
4471
; CHECK-LABEL: @fast_cabsf(
4572
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast float [[REAL:%.*]], [[REAL]]
@@ -52,6 +79,33 @@ define float @fast_cabsf(float %real, float %imag) {
5279
ret float %call
5380
}
5481

82+
define float @cabsf_zero_real(float %imag) {
83+
; CHECK-LABEL: @cabsf_zero_real(
84+
; CHECK-NEXT: [[CABS:%.*]] = tail call float @llvm.fabs.f32(float [[IMAG:%.*]])
85+
; CHECK-NEXT: ret float [[CABS]]
86+
;
87+
%call = tail call float @cabsf(float 0.0, float %imag)
88+
ret float %call
89+
}
90+
91+
define float @fast_cabsf_neg_zero_real(float %imag) {
92+
; CHECK-LABEL: @fast_cabsf_neg_zero_real(
93+
; CHECK-NEXT: [[CABS:%.*]] = tail call fast float @llvm.fabs.f32(float [[IMAG:%.*]])
94+
; CHECK-NEXT: ret float [[CABS]]
95+
;
96+
%call = tail call fast float @cabsf(float -0.0, float %imag)
97+
ret float %call
98+
}
99+
100+
define float @cabsf_zero_imag(float %real) {
101+
; CHECK-LABEL: @cabsf_zero_imag(
102+
; CHECK-NEXT: [[CABS:%.*]] = tail call float @llvm.fabs.f32(float [[REAL:%.*]])
103+
; CHECK-NEXT: ret float [[CABS]]
104+
;
105+
%call = tail call float @cabsf(float %real, float 0.0)
106+
ret float %call
107+
}
108+
55109
define fp128 @fast_cabsl(fp128 %real, fp128 %imag) {
56110
; CHECK-LABEL: @fast_cabsl(
57111
; CHECK-NEXT: [[TMP1:%.*]] = fmul fast fp128 [[REAL:%.*]], [[REAL]]
@@ -64,6 +118,33 @@ define fp128 @fast_cabsl(fp128 %real, fp128 %imag) {
64118
ret fp128 %call
65119
}
66120

121+
define fp128 @cabsl_zero_real(fp128 %imag) {
122+
; CHECK-LABEL: @cabsl_zero_real(
123+
; CHECK-NEXT: [[CABS:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[IMAG:%.*]])
124+
; CHECK-NEXT: ret fp128 [[CABS]]
125+
;
126+
%call = tail call fp128 @cabsl(fp128 0xL00000000000000000000000000000000, fp128 %imag)
127+
ret fp128 %call
128+
}
129+
130+
define fp128 @cabsl_zero_imag(fp128 %real) {
131+
; CHECK-LABEL: @cabsl_zero_imag(
132+
; CHECK-NEXT: [[CABS:%.*]] = tail call fp128 @llvm.fabs.f128(fp128 [[REAL:%.*]])
133+
; CHECK-NEXT: ret fp128 [[CABS]]
134+
;
135+
%call = tail call fp128 @cabsl(fp128 %real, fp128 0xL00000000000000000000000000000000)
136+
ret fp128 %call
137+
}
138+
139+
define fp128 @fast_cabsl_neg_zero_imag(fp128 %real) {
140+
; CHECK-LABEL: @fast_cabsl_neg_zero_imag(
141+
; CHECK-NEXT: [[CABS:%.*]] = tail call fast fp128 @llvm.fabs.f128(fp128 [[REAL:%.*]])
142+
; CHECK-NEXT: ret fp128 [[CABS]]
143+
;
144+
%call = tail call fast fp128 @cabsl(fp128 %real, fp128 0xL00000000000000008000000000000000)
145+
ret fp128 %call
146+
}
147+
67148
declare double @cabs(double %real, double %imag)
68149
declare float @cabsf(float %real, float %imag)
69150
declare fp128 @cabsl(fp128 %real, fp128 %imag)

0 commit comments

Comments
 (0)