Skip to content

Commit 16f22c0

Browse files
authored
Fold fma x, -1.0, y into fsub x, y (#100106)
Alive2 proof (Please run alive-tv locally with larger `smt-to`): https://alive2.llvm.org/ce/z/YvUVg-
1 parent eb9bf18 commit 16f22c0

File tree

2 files changed

+74
-6
lines changed

2 files changed

+74
-6
lines changed

llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -2480,6 +2480,7 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
24802480
// fma fneg(x), fneg(y), z -> fma x, y, z
24812481
Value *Src0 = II->getArgOperand(0);
24822482
Value *Src1 = II->getArgOperand(1);
2483+
Value *Src2 = II->getArgOperand(2);
24832484
Value *X, *Y;
24842485
if (match(Src0, m_FNeg(m_Value(X))) && match(Src1, m_FNeg(m_Value(Y)))) {
24852486
replaceOperand(*II, 0, X);
@@ -2497,22 +2498,24 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
24972498

24982499
// Try to simplify the underlying FMul. We can only apply simplifications
24992500
// that do not require rounding.
2500-
if (Value *V = simplifyFMAFMul(II->getArgOperand(0), II->getArgOperand(1),
2501-
II->getFastMathFlags(),
2501+
if (Value *V = simplifyFMAFMul(Src0, Src1, II->getFastMathFlags(),
25022502
SQ.getWithInstruction(II))) {
2503-
auto *FAdd = BinaryOperator::CreateFAdd(V, II->getArgOperand(2));
2503+
auto *FAdd = BinaryOperator::CreateFAdd(V, Src2);
25042504
FAdd->copyFastMathFlags(II);
25052505
return FAdd;
25062506
}
25072507

25082508
// fma x, y, 0 -> fmul x, y
25092509
// This is always valid for -0.0, but requires nsz for +0.0 as
25102510
// -0.0 + 0.0 = 0.0, which would not be the same as the fmul on its own.
2511-
if (match(II->getArgOperand(2), m_NegZeroFP()) ||
2512-
(match(II->getArgOperand(2), m_PosZeroFP()) &&
2513-
II->getFastMathFlags().noSignedZeros()))
2511+
if (match(Src2, m_NegZeroFP()) ||
2512+
(match(Src2, m_PosZeroFP()) && II->getFastMathFlags().noSignedZeros()))
25142513
return BinaryOperator::CreateFMulFMF(Src0, Src1, II);
25152514

2515+
// fma x, -1.0, y -> fsub y, x
2516+
if (match(Src1, m_SpecificFP(-1.0)))
2517+
return BinaryOperator::CreateFSubFMF(Src2, Src0, II);
2518+
25162519
break;
25172520
}
25182521
case Intrinsic::copysign: {

llvm/test/Transforms/InstCombine/fma.ll

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -856,3 +856,68 @@ define <2 x float> @fma_unary_shuffle_ops_uses(<2 x float> %x, <2 x float> %y, <
856856
%r = call <2 x float> @llvm.fma.v2f32(<2 x float> %a, <2 x float> %b, <2 x float> %c)
857857
ret <2 x float> %r
858858
}
859+
860+
define half @fma_negone(half %x, half %y) {
861+
; CHECK-LABEL: @fma_negone(
862+
; CHECK-NEXT: [[SUB:%.*]] = fsub half [[Y:%.*]], [[X:%.*]]
863+
; CHECK-NEXT: ret half [[SUB]]
864+
;
865+
%sub = call half @llvm.fma.f16(half %x, half -1.0, half %y)
866+
ret half %sub
867+
}
868+
869+
define half @fmuladd_negone(half %x, half %y) {
870+
; CHECK-LABEL: @fmuladd_negone(
871+
; CHECK-NEXT: [[SUB:%.*]] = fsub half [[Y:%.*]], [[X:%.*]]
872+
; CHECK-NEXT: ret half [[SUB]]
873+
;
874+
%sub = call half @llvm.fmuladd.f16(half %x, half -1.0, half %y)
875+
ret half %sub
876+
}
877+
878+
define half @fma_negone_fmf(half %x, half %y) {
879+
; CHECK-LABEL: @fma_negone_fmf(
880+
; CHECK-NEXT: [[SUB:%.*]] = fsub nnan ninf nsz half [[Y:%.*]], [[X:%.*]]
881+
; CHECK-NEXT: ret half [[SUB]]
882+
;
883+
%sub = call nnan ninf nsz half @llvm.fma.f16(half %x, half -1.0, half %y)
884+
ret half %sub
885+
}
886+
887+
define half @fmuladd_negone_fmf(half %x, half %y) {
888+
; CHECK-LABEL: @fmuladd_negone_fmf(
889+
; CHECK-NEXT: [[SUB:%.*]] = fsub nnan ninf nsz half [[Y:%.*]], [[X:%.*]]
890+
; CHECK-NEXT: ret half [[SUB]]
891+
;
892+
%sub = call nnan ninf nsz half @llvm.fmuladd.f16(half %x, half -1.0, half %y)
893+
ret half %sub
894+
}
895+
896+
define <2 x half> @fma_negone_vec(<2 x half> %x, <2 x half> %y) {
897+
; CHECK-LABEL: @fma_negone_vec(
898+
; CHECK-NEXT: [[SUB:%.*]] = fsub <2 x half> [[Y:%.*]], [[X:%.*]]
899+
; CHECK-NEXT: ret <2 x half> [[SUB]]
900+
;
901+
%sub = call <2 x half> @llvm.fma.v2f16(<2 x half> %x, <2 x half> splat(half -1.0), <2 x half> %y)
902+
ret <2 x half> %sub
903+
}
904+
905+
define <2 x half> @fma_negone_vec_partial_undef(<2 x half> %x, <2 x half> %y) {
906+
; CHECK-LABEL: @fma_negone_vec_partial_undef(
907+
; CHECK-NEXT: [[SUB:%.*]] = call <2 x half> @llvm.fma.v2f16(<2 x half> [[X:%.*]], <2 x half> <half undef, half 0xHBC00>, <2 x half> [[Y:%.*]])
908+
; CHECK-NEXT: ret <2 x half> [[SUB]]
909+
;
910+
%sub = call <2 x half> @llvm.fma.v2f16(<2 x half> %x, <2 x half> <half undef, half -1.0>, <2 x half> %y)
911+
ret <2 x half> %sub
912+
}
913+
914+
; negative tests
915+
916+
define half @fma_non_negone(half %x, half %y) {
917+
; CHECK-LABEL: @fma_non_negone(
918+
; CHECK-NEXT: [[SUB:%.*]] = call half @llvm.fma.f16(half [[X:%.*]], half 0xHBE00, half [[Y:%.*]])
919+
; CHECK-NEXT: ret half [[SUB]]
920+
;
921+
%sub = call half @llvm.fma.f16(half %x, half -1.5, half %y)
922+
ret half %sub
923+
}

0 commit comments

Comments
 (0)