Skip to content

Commit 971c49f

Browse files
authored
[InstCombine] Ensure Safe Handling of Flags in foldFNegIntoConstant (#94148)
Fix #93769 alive2: https://alive2.llvm.org/ce/z/MHShQY
1 parent d517f15 commit 971c49f

File tree

3 files changed

+173
-5
lines changed

3 files changed

+173
-5
lines changed

llvm/lib/Transforms/InstCombine/InstCombineAddSub.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2857,8 +2857,14 @@ static Instruction *foldFNegIntoConstant(Instruction &I, const DataLayout &DL) {
28572857
// Fold negation into constant operand.
28582858
// -(X * C) --> X * (-C)
28592859
if (match(FNegOp, m_FMul(m_Value(X), m_Constant(C))))
2860-
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))
2861-
return BinaryOperator::CreateFMulFMF(X, NegC, &I);
2860+
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL)) {
2861+
FastMathFlags FNegF = I.getFastMathFlags();
2862+
FastMathFlags OpF = FNegOp->getFastMathFlags();
2863+
FastMathFlags FMF = FastMathFlags::unionValue(FNegF, OpF) |
2864+
FastMathFlags::intersectRewrite(FNegF, OpF);
2865+
FMF.setNoInfs(FNegF.noInfs() && OpF.noInfs());
2866+
return BinaryOperator::CreateFMulFMF(X, NegC, FMF);
2867+
}
28622868
// -(X / C) --> X / (-C)
28632869
if (match(FNegOp, m_FDiv(m_Value(X), m_Constant(C))))
28642870
if (Constant *NegC = ConstantFoldUnaryOpOperand(Instruction::FNeg, C, DL))

llvm/test/Transforms/InstCombine/fneg.ll

Lines changed: 164 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ define float @fmul_fneg(float %x) {
4242

4343
define float @fmul_fsub_fmf(float %x) {
4444
; CHECK-LABEL: @fmul_fsub_fmf(
45-
; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
45+
; CHECK-NEXT: [[R:%.*]] = fmul nsz float [[X:%.*]], -4.200000e+01
4646
; CHECK-NEXT: ret float [[R]]
4747
;
4848
%m = fmul float %x, 42.0
@@ -52,7 +52,7 @@ define float @fmul_fsub_fmf(float %x) {
5252

5353
define float @fmul_fneg_fmf(float %x) {
5454
; CHECK-LABEL: @fmul_fneg_fmf(
55-
; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -4.200000e+01
55+
; CHECK-NEXT: [[R:%.*]] = fmul nsz float [[X:%.*]], -4.200000e+01
5656
; CHECK-NEXT: ret float [[R]]
5757
;
5858
%m = fmul float %x, 42.0
@@ -1142,4 +1142,166 @@ define <vscale x 2 x double> @test_fneg_select_svec_3(<vscale x 2 x i1> %cond, <
11421142
ret <vscale x 2 x double> %2
11431143
}
11441144

1145+
define float @test_fneg_ninf_mul_with_anyzero(float %a) {
1146+
; CHECK-LABEL: @test_fneg_ninf_mul_with_anyzero(
1147+
; CHECK-NEXT: [[F:%.*]] = fmul float [[A:%.*]], -0.000000e+00
1148+
; CHECK-NEXT: ret float [[F]]
1149+
;
1150+
%mul = fmul float %a, 0.0
1151+
%f = fneg ninf float %mul
1152+
ret float %f
1153+
}
1154+
1155+
define float @test_fsub_ninf_mul_with_anyzero(float %a) {
1156+
; CHECK-LABEL: @test_fsub_ninf_mul_with_anyzero(
1157+
; CHECK-NEXT: [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
1158+
; CHECK-NEXT: ret float [[F2]]
1159+
;
1160+
%f1 = fmul nsz float %a, 0.000000
1161+
%f2 = fsub ninf float -0.000000, %f1
1162+
ret float %f2
1163+
}
1164+
1165+
define float @test_fneg_nnan_mul_with_anyzero(float %a) {
1166+
; CHECK-LABEL: @test_fneg_nnan_mul_with_anyzero(
1167+
; CHECK-NEXT: [[TMP1:%.*]] = fneg nnan float [[A:%.*]]
1168+
; CHECK-NEXT: [[F2:%.*]] = call nnan float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])
1169+
; CHECK-NEXT: ret float [[F2]]
1170+
;
1171+
%f1 = fmul ninf float %a, 0.000000
1172+
%f2 = fneg nnan float %f1
1173+
ret float %f2
1174+
}
1175+
1176+
define float @test_fneg_nsz_mul_with_anyzero(float %a) {
1177+
; CHECK-LABEL: @test_fneg_nsz_mul_with_anyzero(
1178+
; CHECK-NEXT: [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
1179+
; CHECK-NEXT: ret float [[F2]]
1180+
;
1181+
%f1 = fmul ninf float %a, 0.000000
1182+
%f2 = fneg nsz float %f1
1183+
ret float %f2
1184+
}
1185+
1186+
define float @test_fneg_ninf_mul_nnan_with_const(float %a) {
1187+
; CHECK-LABEL: @test_fneg_ninf_mul_nnan_with_const(
1188+
; CHECK-NEXT: [[TMP1:%.*]] = fneg float [[A:%.*]]
1189+
; CHECK-NEXT: [[F2:%.*]] = call float @llvm.copysign.f32(float 0.000000e+00, float [[TMP1]])
1190+
; CHECK-NEXT: ret float [[F2]]
1191+
;
1192+
%f1 = fmul nnan float %a, 0.000000
1193+
%f2 = fneg ninf float %f1
1194+
ret float %f2
1195+
}
1196+
1197+
define float @test_fneg_ninf_mul_nsz_with_const(float %a) {
1198+
; CHECK-LABEL: @test_fneg_ninf_mul_nsz_with_const(
1199+
; CHECK-NEXT: [[F2:%.*]] = fmul nsz float [[A:%.*]], -0.000000e+00
1200+
; CHECK-NEXT: ret float [[F2]]
1201+
;
1202+
%f1 = fmul nsz float %a, 0.000000
1203+
%f2 = fneg ninf float %f1
1204+
ret float %f2
1205+
}
1206+
1207+
define <2 x float> @test_fneg_mul_combine_nnan_ninf_with_vec_const(<2 x float> %a) {
1208+
; CHECK-LABEL: @test_fneg_mul_combine_nnan_ninf_with_vec_const(
1209+
; CHECK-NEXT: [[F2:%.*]] = fmul nnan <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1210+
; CHECK-NEXT: ret <2 x float> [[F2]]
1211+
;
1212+
%f1 = fmul nnan <2 x float> %a, <float 0.000000, float -0.000000>
1213+
%f2 = fneg ninf <2 x float> %f1
1214+
ret <2 x float> %f2
1215+
}
1216+
1217+
define <2 x float> @test_fneg_mul_combine_nsz_ninf_with_vec_const(<2 x float> %a) {
1218+
; CHECK-LABEL: @test_fneg_mul_combine_nsz_ninf_with_vec_const(
1219+
; CHECK-NEXT: [[F2:%.*]] = fmul nsz <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1220+
; CHECK-NEXT: ret <2 x float> [[F2]]
1221+
;
1222+
%f1 = fmul nsz <2 x float> %a, <float 0.000000, float -0.000000>
1223+
%f2 = fneg ninf <2 x float> %f1
1224+
ret <2 x float> %f2
1225+
}
1226+
1227+
define <2 x float> @test_fneg_ninf_nnan_mul_with_vec_const(<2 x float> %a) {
1228+
; CHECK-LABEL: @test_fneg_ninf_nnan_mul_with_vec_const(
1229+
; CHECK-NEXT: [[F2:%.*]] = fmul nnan <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1230+
; CHECK-NEXT: ret <2 x float> [[F2]]
1231+
;
1232+
%f1 = fmul <2 x float> %a, <float 0.000000, float -0.000000>
1233+
%f2 = fneg nnan ninf <2 x float> %f1
1234+
ret <2 x float> %f2
1235+
}
1236+
1237+
define <2 x float> @test_fneg_mul_combine_nnan_ninf_with_vec_const2(<2 x float> %a) {
1238+
; CHECK-LABEL: @test_fneg_mul_combine_nnan_ninf_with_vec_const2(
1239+
; CHECK-NEXT: [[F2:%.*]] = fmul nnan ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1240+
; CHECK-NEXT: ret <2 x float> [[F2]]
1241+
;
1242+
%f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>
1243+
%f2 = fneg nnan ninf <2 x float> %f1
1244+
ret <2 x float> %f2
1245+
}
1246+
1247+
define <2 x float> @test_fneg_mul_combine_reassoc_ninf_with_vec_const1(<2 x float> %a) {
1248+
; CHECK-LABEL: @test_fneg_mul_combine_reassoc_ninf_with_vec_const1(
1249+
; CHECK-NEXT: [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1250+
; CHECK-NEXT: ret <2 x float> [[F2]]
1251+
;
1252+
%f1 = fmul reassoc <2 x float> %a, <float 0.000000, float -0.000000>
1253+
%f2 = fneg ninf <2 x float> %f1
1254+
ret <2 x float> %f2
1255+
}
1256+
1257+
define <2 x float> @test_fneg_mul_combine_reassoc_ninf_with_vec_const2(<2 x float> %a) {
1258+
; CHECK-LABEL: @test_fneg_mul_combine_reassoc_ninf_with_vec_const2(
1259+
; CHECK-NEXT: [[F2:%.*]] = fmul ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1260+
; CHECK-NEXT: ret <2 x float> [[F2]]
1261+
;
1262+
%f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>
1263+
%f2 = fneg reassoc ninf <2 x float> %f1
1264+
ret <2 x float> %f2
1265+
}
1266+
1267+
define <2 x float> @test_fneg_mul_combine_reassoc_ninf_with_vec_const3(<2 x float> %a) {
1268+
; CHECK-LABEL: @test_fneg_mul_combine_reassoc_ninf_with_vec_const3(
1269+
; CHECK-NEXT: [[F2:%.*]] = fmul reassoc <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1270+
; CHECK-NEXT: ret <2 x float> [[F2]]
1271+
;
1272+
%f1 = fmul reassoc <2 x float> %a, <float 0.000000, float -0.000000>
1273+
%f2 = fneg reassoc ninf <2 x float> %f1
1274+
ret <2 x float> %f2
1275+
}
1276+
1277+
define <2 x float> @test_fneg_mul_combine_contract_ninf_with_vec_const1(<2 x float> %a) {
1278+
; CHECK-LABEL: @test_fneg_mul_combine_contract_ninf_with_vec_const1(
1279+
; CHECK-NEXT: [[F2:%.*]] = fmul <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1280+
; CHECK-NEXT: ret <2 x float> [[F2]]
1281+
;
1282+
%f1 = fmul contract <2 x float> %a, <float 0.000000, float -0.000000>
1283+
%f2 = fneg ninf <2 x float> %f1
1284+
ret <2 x float> %f2
1285+
}
1286+
1287+
define <2 x float> @test_fneg_mul_combine_contract_ninf_with_vec_const2(<2 x float> %a) {
1288+
; CHECK-LABEL: @test_fneg_mul_combine_contract_ninf_with_vec_const2(
1289+
; CHECK-NEXT: [[F2:%.*]] = fmul ninf <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1290+
; CHECK-NEXT: ret <2 x float> [[F2]]
1291+
;
1292+
%f1 = fmul ninf <2 x float> %a, <float 0.000000, float -0.000000>
1293+
%f2 = fneg contract ninf <2 x float> %f1
1294+
ret <2 x float> %f2
1295+
}
1296+
1297+
define <2 x float> @test_fneg_mul_combine_contract_ninf_with_vec_const3(<2 x float> %a) {
1298+
; CHECK-LABEL: @test_fneg_mul_combine_contract_ninf_with_vec_const3(
1299+
; CHECK-NEXT: [[F2:%.*]] = fmul contract <2 x float> [[A:%.*]], <float -0.000000e+00, float 0.000000e+00>
1300+
; CHECK-NEXT: ret <2 x float> [[F2]]
1301+
;
1302+
%f1 = fmul contract <2 x float> %a, <float 0.000000, float -0.000000>
1303+
%f2 = fneg contract ninf <2 x float> %f1
1304+
ret <2 x float> %f2
1305+
}
1306+
11451307
!0 = !{}

llvm/test/Transforms/InstCombine/fsub.ll

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ define float @sub_sub_nsz(float %x, float %y, float %z) {
9898

9999
define float @sub_add_neg_x(float %x, float %y) {
100100
; CHECK-LABEL: @sub_add_neg_x(
101-
; CHECK-NEXT: [[R:%.*]] = fmul reassoc nsz float [[X:%.*]], -5.000000e+00
101+
; CHECK-NEXT: [[R:%.*]] = fmul nsz float [[X:%.*]], -5.000000e+00
102102
; CHECK-NEXT: ret float [[R]]
103103
;
104104
%mul = fmul float %x, 5.000000e+00

0 commit comments

Comments
 (0)