diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1767,22 +1767,15 @@ /// /// \param CI Constrained intrinsic call. /// \param St Exception flags raised during constant evaluation. -static bool mayFoldConstrained(ConstrainedFPIntrinsic *CI, +static bool mayFoldConstrained(const ConstrainedFPIntrinsic *CI, APFloat::opStatus St) { Optional ORM = CI->getRoundingMode(); Optional EB = CI->getExceptionBehavior(); // If the operation does not change exception status flags, it is safe // to fold. - if (St == APFloat::opStatus::opOK) { - // When FP exceptions are not ignored, intrinsic call will not be - // eliminated, because it is considered as having side effect. But we - // know that its evaluation does not raise exceptions, so side effect - // is absent. To allow removing the call, mark it as not accessing memory. - if (EB && *EB != fp::ExceptionBehavior::ebIgnore) - CI->addFnAttr(Attribute::ReadNone); + if (St == APFloat::opStatus::opOK) return true; - } // If evaluation raised FP exception, the result can depend on rounding // mode. If the latter is unknown, folding is not possible. @@ -2349,8 +2342,7 @@ St = Res.mod(Op2V); break; } - if (mayFoldConstrained(const_cast(ConstrIntr), - St)) + if (mayFoldConstrained(ConstrIntr, St)) return ConstantFP::get(Ty->getContext(), Res); return nullptr; } @@ -2778,8 +2770,7 @@ St = Res.fusedMultiplyAdd(C2, C3, RM); break; } - if (mayFoldConstrained( - const_cast(ConstrIntr), St)) + if (mayFoldConstrained(ConstrIntr, St)) return ConstantFP::get(Ty->getContext(), Res); return nullptr; } diff --git a/llvm/lib/Transforms/Scalar/InstSimplifyPass.cpp b/llvm/lib/Transforms/Scalar/InstSimplifyPass.cpp --- a/llvm/lib/Transforms/Scalar/InstSimplifyPass.cpp +++ b/llvm/lib/Transforms/Scalar/InstSimplifyPass.cpp @@ -30,6 +30,23 @@ STATISTIC(NumSimplified, "Number of redundant instructions removed"); +static bool isReplacedInstructionDead(Instruction *I) { + if (!I->use_empty()) + return false; + if (wouldInstructionBeTriviallyDead(I)) + return true; + // Constrained intrinsics usually are marked as having side effect to indicate + // possible effect on floating point environment. If however such instruction + // is replaced, it is assumed that the environment is actually is not changed, + // the change is ignored, or the replacement has the same effect. In this case + // remove the side effect and consider the instruction as dead. + if (auto *CI = dyn_cast(I)) { + CI->addFnAttr(Attribute::ReadNone); + return true; + } + return false; +} + static bool runImpl(Function &F, const SimplifyQuery &SQ, OptimizationRemarkEmitter *ORE) { SmallPtrSet S1, S2, *ToSimplify = &S1, *Next = &S2; @@ -51,7 +68,7 @@ continue; // Don't waste time simplifying dead/unused instructions. - if (isInstructionTriviallyDead(&I)) { + if (isReplacedInstructionDead(&I)) { DeadInstsInBB.push_back(&I); Changed = true; } else if (!I.use_empty()) { @@ -62,8 +79,8 @@ I.replaceAllUsesWith(V); ++NumSimplified; Changed = true; - // A call can get simplified, but it may not be trivially dead. - if (isInstructionTriviallyDead(&I)) + // A call can get simplified, but it may not be dead. + if (isReplacedInstructionDead(&I)) DeadInstsInBB.push_back(&I); } } diff --git a/llvm/test/Transforms/InstSimplify/constfold-constrained.ll b/llvm/test/Transforms/InstSimplify/constfold-constrained.ll --- a/llvm/test/Transforms/InstSimplify/constfold-constrained.ll +++ b/llvm/test/Transforms/InstSimplify/constfold-constrained.ll @@ -17,7 +17,6 @@ define double @floor_02() #0 { ; CHECK-LABEL: @floor_02( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.floor.f64(double -1.010000e+01, metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]] ; CHECK-NEXT: ret double -1.100000e+01 ; entry: @@ -40,7 +39,6 @@ define double @ceil_02() #0 { ; CHECK-LABEL: @ceil_02( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.ceil.f64(double -1.010000e+01, metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double -1.000000e+01 ; entry: @@ -63,7 +61,6 @@ define double @trunc_02() #0 { ; CHECK-LABEL: @trunc_02( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double -1.010000e+01, metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double -1.000000e+01 ; entry: @@ -86,7 +83,6 @@ define double @round_02() #0 { ; CHECK-LABEL: @round_02( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.round.f64(double -1.050000e+01, metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double -1.100000e+01 ; entry: @@ -120,7 +116,6 @@ define double @nearbyint_03() #0 { ; CHECK-LABEL: @nearbyint_03( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.towardzero", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double 1.000000e+01 ; entry: @@ -132,7 +127,6 @@ define double @nearbyint_04() #0 { ; CHECK-LABEL: @nearbyint_04( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double 1.000000e+01 ; entry: @@ -144,7 +138,7 @@ define double @nearbyint_05() #0 { ; CHECK-LABEL: @nearbyint_05( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] +; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.nearbyint.f64(double 1.050000e+01, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0:[0-9]+]] ; CHECK-NEXT: ret double [[RESULT]] ; entry: @@ -179,7 +173,6 @@ define double @nonfinite_03() #0 { ; CHECK-LABEL: @nonfinite_03( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF8000000000000, metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double 0x7FF8000000000000 ; entry: @@ -191,7 +184,6 @@ define double @nonfinite_04() #0 { ; CHECK-LABEL: @nonfinite_04( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.trunc.f64(double 0x7FF0000000000000, metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double 0x7FF0000000000000 ; entry: @@ -203,7 +195,6 @@ define double @rint_01() #0 { ; CHECK-LABEL: @rint_01( ; CHECK-NEXT: entry: -; CHECK-NEXT: [[RESULT:%.*]] = call double @llvm.experimental.constrained.rint.f64(double 1.000000e+01, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret double 1.000000e+01 ; entry: diff --git a/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll b/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll --- a/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll +++ b/llvm/test/Transforms/InstSimplify/fp-undef-poison-strictfp.ll @@ -44,7 +44,6 @@ define float @fadd_poison_op0_strict(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op0_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -112,7 +111,6 @@ define float @fadd_poison_op1_strict(float %x) #0 { ; CHECK-LABEL: @fadd_poison_op1_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fadd.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fadd.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -184,7 +182,6 @@ define float @fsub_poison_op0_strict(float %x) { ; CHECK-LABEL: @fsub_poison_op0_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -252,7 +249,6 @@ define float @fsub_poison_op1_strict(float %x) { ; CHECK-LABEL: @fsub_poison_op1_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fsub.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fsub.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -324,7 +320,6 @@ define float @fmul_poison_op0_strict(float %x) { ; CHECK-LABEL: @fmul_poison_op0_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -392,7 +387,6 @@ define float @fmul_poison_op1_strict(float %x) { ; CHECK-LABEL: @fmul_poison_op1_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fmul.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fmul.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -464,7 +458,6 @@ define float @fdiv_poison_op0_strict(float %x) { ; CHECK-LABEL: @fdiv_poison_op0_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -532,7 +525,6 @@ define float @fdiv_poison_op1_strict(float %x) { ; CHECK-LABEL: @fdiv_poison_op1_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fdiv.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fdiv.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -604,7 +596,6 @@ define float @frem_poison_op0_strict(float %x) { ; CHECK-LABEL: @frem_poison_op0_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float poison, float [[X:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float poison, float %x, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -672,7 +663,6 @@ define float @frem_poison_op1_strict(float %x) { ; CHECK-LABEL: @frem_poison_op1_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.frem.f32(float [[X:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.frem.f32(float %x, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -744,7 +734,6 @@ define float @fma_poison_op0_strict(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op0_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float poison, float [[X:%.*]], float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float poison, float %x, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -812,7 +801,6 @@ define float @fma_poison_op1_strict(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op1_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float poison, float [[Y:%.*]], metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float poison, float %y, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 @@ -880,7 +868,6 @@ define float @fma_poison_op2_strict(float %x, float %y) { ; CHECK-LABEL: @fma_poison_op2_strict( -; CHECK-NEXT: [[R:%.*]] = call float @llvm.experimental.constrained.fma.f32(float [[X:%.*]], float [[Y:%.*]], float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #[[ATTR0]] ; CHECK-NEXT: ret float poison ; %r = call float @llvm.experimental.constrained.fma.f32(float %x, float %y, float poison, metadata !"round.dynamic", metadata !"fpexcept.strict") #0 diff --git a/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll b/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll --- a/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll +++ b/llvm/test/Transforms/InstSimplify/strictfp-fadd.ll @@ -135,8 +135,7 @@ define float @fadd_nnan_x_n0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fadd_nnan_x_n0_ebstrict( -; CHECK-NEXT: [[RET:%.*]] = call nnan float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float -0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[A]] +; CHECK-NEXT: ret float [[A:%.*]] ; %ret = call nnan float @llvm.experimental.constrained.fadd.f32(float %a, float -0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %ret @@ -144,8 +143,7 @@ define <2 x float> @fadd_vec_nnan_x_n0_ebstrict(<2 x float> %a) #0 { ; CHECK-LABEL: @fadd_vec_nnan_x_n0_ebstrict( -; CHECK-NEXT: [[RET:%.*]] = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> , metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[A]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %ret = call nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float>, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret <2 x float> %ret @@ -297,8 +295,7 @@ define float @fold_fadd_nsz_nnan_x_0_ebstrict(float %a) #0 { ; CHECK-LABEL: @fold_fadd_nsz_nnan_x_0_ebstrict( -; CHECK-NEXT: [[ADD:%.*]] = call nnan nsz float @llvm.experimental.constrained.fadd.f32(float [[A:%.*]], float 0.000000e+00, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret float [[A]] +; CHECK-NEXT: ret float [[A:%.*]] ; %add = call nsz nnan float @llvm.experimental.constrained.fadd.f32(float %a, float 0.0, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret float %add @@ -306,8 +303,7 @@ define <2 x float> @fold_fadd_vec_nsz_nnan_x_0_ebstrict(<2 x float> %a) #0 { ; CHECK-LABEL: @fold_fadd_vec_nsz_nnan_x_0_ebstrict( -; CHECK-NEXT: [[ADD:%.*]] = call nnan nsz <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> [[A:%.*]], <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.strict") #[[ATTR0]] -; CHECK-NEXT: ret <2 x float> [[A]] +; CHECK-NEXT: ret <2 x float> [[A:%.*]] ; %add = call nsz nnan <2 x float> @llvm.experimental.constrained.fadd.v2f32(<2 x float> %a, <2 x float> zeroinitializer, metadata !"round.tonearest", metadata !"fpexcept.strict") #0 ret <2 x float> %add