Skip to content

Commit e2f56de

Browse files
committed
InstCombine: Fold fabs (copysign x, y) -> fabs x
1 parent 84a8a57 commit e2f56de

File tree

3 files changed

+43
-37
lines changed

3 files changed

+43
-37
lines changed

llvm/include/llvm/IR/PatternMatch.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2206,6 +2206,12 @@ inline typename m_Intrinsic_Ty<Opnd0>::Ty m_Sqrt(const Opnd0 &Op0) {
22062206
return m_Intrinsic<Intrinsic::sqrt>(Op0);
22072207
}
22082208

2209+
template <typename Opnd0, typename Opnd1>
2210+
inline typename m_Intrinsic_Ty<Opnd0, Opnd1>::Ty m_CopySign(const Opnd0 &Op0,
2211+
const Opnd1 &Op1) {
2212+
return m_Intrinsic<Intrinsic::copysign>(Op0, Op1);
2213+
}
2214+
22092215
template <typename Opnd0>
22102216
inline typename m_Intrinsic_Ty<Opnd0>::Ty m_VecReverse(const Opnd0 &Op0) {
22112217
return m_Intrinsic<Intrinsic::experimental_vector_reverse>(Op0);

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,6 +2008,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
20082008
return replaceOperand(*II, 0, TVal);
20092009
}
20102010

2011+
Value *Magnitude, *Sign;
2012+
if (match(II->getArgOperand(0),
2013+
m_CopySign(m_Value(Magnitude), m_Value(Sign)))) {
2014+
// fabs (copysign x, y) -> (fabs x)
2015+
CallInst *AbsSign =
2016+
Builder.CreateCall(II->getCalledFunction(), {Magnitude});
2017+
AbsSign->copyFastMathFlags(II);
2018+
return replaceInstUsesWith(*II, AbsSign);
2019+
}
2020+
20112021
[[fallthrough]];
20122022
}
20132023
case Intrinsic::ceil:

llvm/test/Transforms/InstCombine/copysign-fneg-fabs.ll

Lines changed: 27 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -79,9 +79,8 @@ define half @fneg_copysign(half %x, half %y) {
7979

8080
define half @fneg_fabs_copysign(half %x, half %y) {
8181
; CHECK-LABEL: @fneg_fabs_copysign(
82-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
83-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call half @llvm.fabs.f16(half [[COPYSIGN]])
84-
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg half [[FABS_COPYSIGN]]
82+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
83+
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg half [[TMP1]]
8584
; CHECK-NEXT: ret half [[FNEG_FABS_COPYSIGN]]
8685
;
8786
%copysign = call half @llvm.copysign.f16(half %x, half %y)
@@ -93,9 +92,8 @@ define half @fneg_fabs_copysign(half %x, half %y) {
9392
; https://alive2.llvm.org/ce/z/Ft-7ea
9493
define half @fabs_copysign(half %x, half %y) {
9594
; CHECK-LABEL: @fabs_copysign(
96-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
97-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call half @llvm.fabs.f16(half [[COPYSIGN]])
98-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
95+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
96+
; CHECK-NEXT: ret half [[TMP1]]
9997
;
10098
%copysign = call half @llvm.copysign.f16(half %x, half %y)
10199
%fabs.copysign = call half @llvm.fabs.f16(half %copysign)
@@ -115,9 +113,8 @@ define <2 x half> @fneg_copysign_vector(<2 x half> %x, <2 x half> %y) {
115113

116114
define <2 x half> @fneg_fabs_copysign_vector(<2 x half> %x, <2 x half> %y) {
117115
; CHECK-LABEL: @fneg_fabs_copysign_vector(
118-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[X:%.*]], <2 x half> [[Y:%.*]])
119-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[COPYSIGN]])
120-
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg <2 x half> [[FABS_COPYSIGN]]
116+
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
117+
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg <2 x half> [[TMP1]]
121118
; CHECK-NEXT: ret <2 x half> [[FNEG_FABS_COPYSIGN]]
122119
;
123120
%copysign = call <2 x half> @llvm.copysign.v2f16(<2 x half> %x, <2 x half> %y)
@@ -128,9 +125,8 @@ define <2 x half> @fneg_fabs_copysign_vector(<2 x half> %x, <2 x half> %y) {
128125

129126
define <2 x half> @fabs_copysign_vector(<2 x half> %x, <2 x half> %y) {
130127
; CHECK-LABEL: @fabs_copysign_vector(
131-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call <2 x half> @llvm.copysign.v2f16(<2 x half> [[X:%.*]], <2 x half> [[Y:%.*]])
132-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[COPYSIGN]])
133-
; CHECK-NEXT: ret <2 x half> [[FABS_COPYSIGN]]
128+
; CHECK-NEXT: [[TMP1:%.*]] = call <2 x half> @llvm.fabs.v2f16(<2 x half> [[X:%.*]])
129+
; CHECK-NEXT: ret <2 x half> [[TMP1]]
134130
;
135131
%copysign = call <2 x half> @llvm.copysign.v2f16(<2 x half> %x, <2 x half> %y)
136132
%fabs.copysign = call <2 x half> @llvm.fabs.v2f16(<2 x half> %copysign)
@@ -150,9 +146,8 @@ define half @fneg_copysign_flags(half %x, half %y) {
150146

151147
define half @fneg_fabs_copysign_flags(half %x, half %y) {
152148
; CHECK-LABEL: @fneg_fabs_copysign_flags(
153-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan ninf nsz half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
154-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call nnan ninf afn half @llvm.fabs.f16(half [[COPYSIGN]])
155-
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg reassoc ninf half [[FABS_COPYSIGN]]
149+
; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf afn half @llvm.fabs.f16(half [[X:%.*]])
150+
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg reassoc ninf half [[TMP1]]
156151
; CHECK-NEXT: ret half [[FNEG_FABS_COPYSIGN]]
157152
;
158153
%copysign = call nnan nsz ninf half @llvm.copysign.f16(half %x, half %y)
@@ -175,9 +170,8 @@ define half @fneg_nsz_copysign(half %x, half %y) {
175170

176171
define half @fneg_fabs_copysign_flags_none_fabs(half %x, half %y) {
177172
; CHECK-LABEL: @fneg_fabs_copysign_flags_none_fabs(
178-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan ninf nsz half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
179-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call half @llvm.fabs.f16(half [[COPYSIGN]])
180-
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg fast half [[FABS_COPYSIGN]]
173+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
174+
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg fast half [[TMP1]]
181175
; CHECK-NEXT: ret half [[FNEG_FABS_COPYSIGN]]
182176
;
183177
%copysign = call nnan nsz ninf half @llvm.copysign.f16(half %x, half %y)
@@ -188,9 +182,8 @@ define half @fneg_fabs_copysign_flags_none_fabs(half %x, half %y) {
188182

189183
define half @fabs_copysign_flags(half %x, half %y) {
190184
; CHECK-LABEL: @fabs_copysign_flags(
191-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
192-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call nnan nsz half @llvm.fabs.f16(half [[COPYSIGN]])
193-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
185+
; CHECK-NEXT: [[TMP1:%.*]] = call nnan nsz half @llvm.fabs.f16(half [[X:%.*]])
186+
; CHECK-NEXT: ret half [[TMP1]]
194187
;
195188
%copysign = call nnan half @llvm.copysign.f16(half %x, half %y)
196189
%fabs.copysign = call nsz nnan half @llvm.fabs.f16(half %copysign)
@@ -199,9 +192,8 @@ define half @fabs_copysign_flags(half %x, half %y) {
199192

200193
define half @fabs_copysign_all_flags(half %x, half %y) {
201194
; CHECK-LABEL: @fabs_copysign_all_flags(
202-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call fast half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
203-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call fast half @llvm.fabs.f16(half [[COPYSIGN]])
204-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
195+
; CHECK-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[X:%.*]])
196+
; CHECK-NEXT: ret half [[TMP1]]
205197
;
206198
%copysign = call fast half @llvm.copysign.f16(half %x, half %y)
207199
%fabs.copysign = call fast half @llvm.fabs.f16(half %copysign)
@@ -212,8 +204,8 @@ define half @fabs_copysign_no_flags_copysign_user(half %x, half %y, ptr %ptr) {
212204
; CHECK-LABEL: @fabs_copysign_no_flags_copysign_user(
213205
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
214206
; CHECK-NEXT: store half [[COPYSIGN]], ptr [[PTR:%.*]], align 2
215-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call fast half @llvm.fabs.f16(half [[COPYSIGN]])
216-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
207+
; CHECK-NEXT: [[TMP1:%.*]] = call fast half @llvm.fabs.f16(half [[X]])
208+
; CHECK-NEXT: ret half [[TMP1]]
217209
;
218210
%copysign = call half @llvm.copysign.f16(half %x, half %y)
219211
store half %copysign, ptr %ptr
@@ -223,9 +215,8 @@ define half @fabs_copysign_no_flags_copysign_user(half %x, half %y, ptr %ptr) {
223215

224216
define half @fneg_fabs_copysign_drop_flags(half %x, half %y) {
225217
; CHECK-LABEL: @fneg_fabs_copysign_drop_flags(
226-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call nnan half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
227-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call ninf half @llvm.fabs.f16(half [[COPYSIGN]])
228-
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg nsz half [[FABS_COPYSIGN]]
218+
; CHECK-NEXT: [[TMP1:%.*]] = call ninf half @llvm.fabs.f16(half [[X:%.*]])
219+
; CHECK-NEXT: [[FNEG_FABS_COPYSIGN:%.*]] = fneg nsz half [[TMP1]]
229220
; CHECK-NEXT: ret half [[FNEG_FABS_COPYSIGN]]
230221
;
231222
%copysign = call nnan half @llvm.copysign.f16(half %x, half %y)
@@ -251,8 +242,8 @@ define half @fabs_copysign_multi_use(half %x, half %y, ptr %ptr) {
251242
; CHECK-LABEL: @fabs_copysign_multi_use(
252243
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
253244
; CHECK-NEXT: store half [[COPYSIGN]], ptr [[PTR:%.*]], align 2
254-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call half @llvm.fabs.f16(half [[COPYSIGN]])
255-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
245+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X]])
246+
; CHECK-NEXT: ret half [[TMP1]]
256247
;
257248
%copysign = call half @llvm.copysign.f16(half %x, half %y)
258249
store half %copysign, ptr %ptr
@@ -264,8 +255,8 @@ define half @fabs_flags_copysign_multi_use(half %x, half %y, ptr %ptr) {
264255
; CHECK-LABEL: @fabs_flags_copysign_multi_use(
265256
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
266257
; CHECK-NEXT: store half [[COPYSIGN]], ptr [[PTR:%.*]], align 2
267-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call nnan ninf half @llvm.fabs.f16(half [[COPYSIGN]])
268-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
258+
; CHECK-NEXT: [[TMP1:%.*]] = call nnan ninf half @llvm.fabs.f16(half [[X]])
259+
; CHECK-NEXT: ret half [[TMP1]]
269260
;
270261
%copysign = call half @llvm.copysign.f16(half %x, half %y)
271262
store half %copysign, ptr %ptr
@@ -275,10 +266,9 @@ define half @fabs_flags_copysign_multi_use(half %x, half %y, ptr %ptr) {
275266

276267
define half @fneg_fabs_copysign_multi_use_fabs(half %x, half %y, ptr %ptr) {
277268
; CHECK-LABEL: @fneg_fabs_copysign_multi_use_fabs(
278-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call half @llvm.copysign.f16(half [[X:%.*]], half [[Y:%.*]])
279-
; CHECK-NEXT: [[FABS_COPYSIGN:%.*]] = call half @llvm.fabs.f16(half [[COPYSIGN]])
280-
; CHECK-NEXT: store half [[FABS_COPYSIGN]], ptr [[PTR:%.*]], align 2
281-
; CHECK-NEXT: ret half [[FABS_COPYSIGN]]
269+
; CHECK-NEXT: [[TMP1:%.*]] = call half @llvm.fabs.f16(half [[X:%.*]])
270+
; CHECK-NEXT: store half [[TMP1]], ptr [[PTR:%.*]], align 2
271+
; CHECK-NEXT: ret half [[TMP1]]
282272
;
283273
%copysign = call half @llvm.copysign.f16(half %x, half %y)
284274
%fabs.copysign = call half @llvm.fabs.f16(half %copysign)

0 commit comments

Comments
 (0)