Index: llvm/lib/Analysis/InlineCost.cpp =================================================================== --- llvm/lib/Analysis/InlineCost.cpp +++ llvm/lib/Analysis/InlineCost.cpp @@ -2034,6 +2034,12 @@ " address space"); } + // FIXME: Currently, we can't mix strictfp and non-strictfp functions. + // FIXME: This overrides the AlwaysInline attribute! + if (Call.getCaller()->hasFnAttribute(Attribute::StrictFP) != + Callee->hasFnAttribute(Attribute::StrictFP)) + return llvm::InlineCost::getNever("conflicting strictfp attributes"); + // Calls to functions with always-inline attributes should be inlined // whenever possible. if (Call.hasFnAttr(Attribute::AlwaysInline)) { Index: llvm/test/Transforms/Inline/inline-strictfp.ll =================================================================== --- /dev/null +++ llvm/test/Transforms/Inline/inline-strictfp.ll @@ -0,0 +1,71 @@ +; RUN: opt < %s -inline -S | FileCheck %s + +; Test that strictfp and non-strictfp functions are not inlined. +; Also that that strictfp overrides alwaysinline. + +; Function Attrs: alwaysinline nounwind readnone strictfp uwtable +define double @alwaysInlineStrictFPFunction(double %a) #0 { +entry: + %mul = call double @llvm.experimental.constrained.fmul.f64( + double %a, double %a, + metadata !"round.dynamic", + metadata !"fpexcept.strict") #2 + ret double %mul +} + +; Function Attrs: alwaysinline nounwind readnone uwtable +define double @alwaysInlineVanillaFPFunction(double %a) #1 { +entry: + %mul = fmul double %a, %a + ret double %mul +} + +; Function Attrs: nounwind readnone strictfp uwtable +define double @simpleFunction(double %a) #2 { +entry: + %add = call double @llvm.experimental.constrained.fadd.f64( + double %a, double %a, + metadata !"round.dynamic", + metadata !"fpexcept.strict") #2 + ret double %add +} + +; Function Attrs: nounwind readnone uwtable +define double @VanillaFPFunction(double %a) #3 { +entry: + %0 = tail call double @alwaysInlineStrictFPFunction(double %a) + %1 = tail call double @simpleFunction(double %a) + %add = fadd double %0, %1 + ret double %add +} + +; CHECK-LABEL: @VanillaFPFunction +; CHECK: call double @alwaysInlineStrictFPFunction(double %a) +; CHECK: call double @simpleFunction(double %a) +; CHECK: ret + +; Function Attrs: nounwind readnone strictfp uwtable +define double @bar(double %a) #2 { +entry: + %0 = tail call double @VanillaFPFunction(double 5.0) + %1 = tail call double @simpleFunction(double 6.0) + %2 = tail call double @alwaysInlineStrictFPFunction(double %1) + %3 = tail call double @alwaysInlineVanillaFPFunction(double %2) + %add = fadd double %0, %3 + ret double %add +} + +; CHECK-LABEL: @bar +; CHECK: call double @VanillaFPFunction(double 5 +; CHECK-NOT: call double @simpleFunction(double 6 +; CHECK-NOT: call double @alwaysInlineStrictFPFunction(double +; CHECK: call double @alwaysInlineVanillaFPFunction(double +; CHECK: ret + +attributes #0 = { alwaysinline nounwind readnone strictfp uwtable } +attributes #1 = { alwaysinline nounwind readnone uwtable } +attributes #2 = { nounwind readnone strictfp uwtable } +attributes #3 = { nounwind readnone uwtable } + +declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata); +declare double @llvm.experimental.constrained.fmul.f64(double, double, metadata, metadata);