Skip to content

Commit d18ab0e

Browse files
authored
[InstCombine] Fold fabs over selects (#86390)
This patch folds fabs over select if it is beneficial. I also tried other interger/fp intrinsics. Only handling fabs shows benefit to some real-world applications.
1 parent 8ff6434 commit d18ab0e

File tree

4 files changed

+87
-17
lines changed

4 files changed

+87
-17
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2501,10 +2501,16 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
25012501
if (match(II->getArgOperand(0),
25022502
m_Select(m_Value(Cond), m_Value(TVal), m_Value(FVal)))) {
25032503
// fabs (select Cond, TrueC, FalseC) --> select Cond, AbsT, AbsF
2504-
if (isa<Constant>(TVal) && isa<Constant>(FVal)) {
2504+
if (isa<Constant>(TVal) || isa<Constant>(FVal)) {
25052505
CallInst *AbsT = Builder.CreateCall(II->getCalledFunction(), {TVal});
25062506
CallInst *AbsF = Builder.CreateCall(II->getCalledFunction(), {FVal});
2507-
return SelectInst::Create(Cond, AbsT, AbsF);
2507+
SelectInst *SI = SelectInst::Create(Cond, AbsT, AbsF);
2508+
FastMathFlags FMF1 = II->getFastMathFlags();
2509+
FastMathFlags FMF2 =
2510+
cast<SelectInst>(II->getArgOperand(0))->getFastMathFlags();
2511+
FMF2.setNoSignedZeros(false);
2512+
SI->setFastMathFlags(FMF1 | FMF2);
2513+
return SI;
25082514
}
25092515
// fabs (select Cond, -FVal, FVal) --> fabs FVal
25102516
if (match(TVal, m_FNeg(m_Specific(FVal))))

llvm/test/Transforms/InstCombine/fabs.ll

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -179,9 +179,9 @@ define float @fabs_select_constant_neg0(i32 %c) {
179179
define float @fabs_select_var_constant_negative(i32 %c, float %x) {
180180
; CHECK-LABEL: @fabs_select_var_constant_negative(
181181
; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[C:%.*]], 0
182-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[CMP]], float [[X:%.*]], float -1.000000e+00
183-
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
184-
; CHECK-NEXT: ret float [[FABS]]
182+
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT:%.*]])
183+
; CHECK-NEXT: [[FABS1:%.*]] = select i1 [[CMP]], float [[FABS]], float 1.000000e+00
184+
; CHECK-NEXT: ret float [[FABS1]]
185185
;
186186
%cmp = icmp eq i32 %c, 0
187187
%select = select i1 %cmp, float %x, float -1.0

llvm/test/Transforms/InstCombine/intrinsic-select.ll

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,3 +280,67 @@ entry:
280280
%ret = icmp eq i64 %masked, 0
281281
ret i1 %ret
282282
}
283+
284+
define double @test_fabs_select1(double %a) {
285+
; CHECK-LABEL: @test_fabs_select1(
286+
; CHECK-NEXT: [[COND:%.*]] = fcmp uno double [[A:%.*]], 0.000000e+00
287+
; CHECK-NEXT: [[SEL1:%.*]] = select i1 [[COND]], double 0x7FF8000000000000, double [[A]]
288+
; CHECK-NEXT: ret double [[SEL1]]
289+
;
290+
%cond = fcmp uno double %a, 0.000000e+00
291+
%sel1 = select i1 %cond, double 0x7FF8000000000000, double %a
292+
%fabs = call double @llvm.fabs.f64(double %sel1)
293+
%sel2 = select i1 %cond, double %fabs, double %a
294+
ret double %sel2
295+
}
296+
297+
define <2 x double> @test_fabs_select1_vec(<2 x double> %a) {
298+
; CHECK-LABEL: @test_fabs_select1_vec(
299+
; CHECK-NEXT: [[COND:%.*]] = fcmp uno <2 x double> [[A:%.*]], zeroinitializer
300+
; CHECK-NEXT: [[SEL2:%.*]] = select <2 x i1> [[COND]], <2 x double> <double 0x7FF8000000000000, double 0x7FF8000000000000>, <2 x double> [[A]]
301+
; CHECK-NEXT: ret <2 x double> [[SEL2]]
302+
;
303+
%cond = fcmp uno <2 x double> %a, zeroinitializer
304+
%sel1 = select <2 x i1> %cond, <2 x double> splat(double 0x7FF8000000000000), <2 x double> %a
305+
%fabs = call <2 x double> @llvm.fabs.v2f64(<2 x double> %sel1)
306+
%sel2 = select <2 x i1> %cond, <2 x double> %fabs, <2 x double> %a
307+
ret <2 x double> %sel2
308+
}
309+
310+
define double @test_fabs_select2(double %a) {
311+
; CHECK-LABEL: @test_fabs_select2(
312+
; CHECK-NEXT: [[ABS1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
313+
; CHECK-NEXT: [[CMP:%.*]] = fcmp oeq double [[ABS1]], 0x7FF0000000000000
314+
; CHECK-NEXT: [[ABS2:%.*]] = select i1 [[CMP]], double 0.000000e+00, double [[ABS1]]
315+
; CHECK-NEXT: ret double [[ABS2]]
316+
;
317+
%abs1 = call double @llvm.fabs.f64(double %a)
318+
%cmp = fcmp oeq double %abs1, 0x7FF0000000000000
319+
%sel = select i1 %cmp, double -0.000000e+00, double %abs1
320+
%abs2 = call double @llvm.fabs.f64(double %sel)
321+
ret double %abs2
322+
}
323+
324+
; nsz flag should be dropped.
325+
326+
define double @test_fabs_select_fmf1(i1 %cond, double %a) {
327+
; CHECK-LABEL: @test_fabs_select_fmf1(
328+
; CHECK-NEXT: [[A:%.*]] = call double @llvm.fabs.f64(double [[A1:%.*]])
329+
; CHECK-NEXT: [[FABS:%.*]] = select nnan ninf i1 [[COND:%.*]], double 0.000000e+00, double [[A]]
330+
; CHECK-NEXT: ret double [[FABS]]
331+
;
332+
%sel1 = select nnan ninf nsz i1 %cond, double 0.0, double %a
333+
%fabs = call double @llvm.fabs.f64(double %sel1)
334+
ret double %fabs
335+
}
336+
337+
define double @test_fabs_select_fmf2(i1 %cond, double %a) {
338+
; CHECK-LABEL: @test_fabs_select_fmf2(
339+
; CHECK-NEXT: [[TMP1:%.*]] = call double @llvm.fabs.f64(double [[A:%.*]])
340+
; CHECK-NEXT: [[SEL1:%.*]] = select nnan ninf nsz i1 [[COND:%.*]], double 0.000000e+00, double [[TMP1]]
341+
; CHECK-NEXT: ret double [[SEL1]]
342+
;
343+
%sel1 = select i1 %cond, double 0.0, double %a
344+
%fabs = call nnan ninf nsz double @llvm.fabs.f64(double %sel1)
345+
ret double %fabs
346+
}

llvm/test/Transforms/InstCombine/simplify-demanded-fpclass.ll

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -387,8 +387,8 @@ define nofpclass(inf) float @ret_nofpclass_inf__fabs_select_pinf_rhs(i1 %cond, f
387387
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs(i1 %cond, float %x) {
388388
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__fabs_select_pinf_rhs
389389
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
390-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
391-
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
390+
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
391+
; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
392392
; CHECK-NEXT: ret float [[FABS]]
393393
;
394394
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -411,8 +411,8 @@ define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__fabs_
411411
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs(i1 %cond, float %x) {
412412
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nan__fabs_select_pinf_rhs
413413
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]]) {
414-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
415-
; CHECK-NEXT: [[FABS:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
414+
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
415+
; CHECK-NEXT: [[FABS:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
416416
; CHECK-NEXT: ret float [[FABS]]
417417
;
418418
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -665,8 +665,8 @@ define nofpclass(inf pnorm psub pzero) float @ret_nofpclass_no_positives_noinf__
665665
define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
666666
; CHECK-LABEL: define nofpclass(ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives__copysign_unknown_select_pinf_rhs
667667
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
668-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
669-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
668+
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
669+
; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
670670
; CHECK-NEXT: ret float [[COPYSIGN]]
671671
;
672672
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -678,8 +678,8 @@ define nofpclass(ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives__copys
678678
define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
679679
; CHECK-LABEL: define nofpclass(pinf pzero psub pnorm) float @ret_nofpclass_no_positives__copysign_unknown_select_pinf_rhs
680680
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
681-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
682-
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
681+
; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[X]])
682+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[TMP2]], float 0x7FF0000000000000
683683
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
684684
; CHECK-NEXT: ret float [[COPYSIGN]]
685685
;
@@ -692,8 +692,8 @@ define nofpclass(pinf pnorm psub pzero) float @ret_nofpclass_no_positives__copys
692692
define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
693693
; CHECK-LABEL: define nofpclass(nan ninf nzero nsub nnorm) float @ret_nofpclass_no_negatives_nonan__copysign_unknown_select_pinf_rhs
694694
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
695-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
696-
; CHECK-NEXT: [[COPYSIGN:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
695+
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[X]])
696+
; CHECK-NEXT: [[COPYSIGN:%.*]] = select i1 [[COND]], float [[TMP1]], float 0x7FF0000000000000
697697
; CHECK-NEXT: ret float [[COPYSIGN]]
698698
;
699699
%select = select i1 %cond, float %x, float 0x7FF0000000000000
@@ -705,8 +705,8 @@ define nofpclass(nan ninf nnorm nsub nzero) float @ret_nofpclass_no_negatives_no
705705
define nofpclass(nan pinf pnorm psub pzero) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs(i1 %cond, float %x, float %unknown.sign) {
706706
; CHECK-LABEL: define nofpclass(nan pinf pzero psub pnorm) float @ret_nofpclass_no_positives_nonan__copysign_unknown_select_pinf_rhs
707707
; CHECK-SAME: (i1 [[COND:%.*]], float [[X:%.*]], float [[UNKNOWN_SIGN:%.*]]) {
708-
; CHECK-NEXT: [[SELECT:%.*]] = select i1 [[COND]], float [[X]], float 0x7FF0000000000000
709-
; CHECK-NEXT: [[TMP1:%.*]] = call float @llvm.fabs.f32(float [[SELECT]])
708+
; CHECK-NEXT: [[TMP2:%.*]] = call float @llvm.fabs.f32(float [[X]])
709+
; CHECK-NEXT: [[TMP1:%.*]] = select i1 [[COND]], float [[TMP2]], float 0x7FF0000000000000
710710
; CHECK-NEXT: [[COPYSIGN:%.*]] = fneg float [[TMP1]]
711711
; CHECK-NEXT: ret float [[COPYSIGN]]
712712
;

0 commit comments

Comments
 (0)