diff --git a/llvm/lib/Analysis/InlineCost.cpp b/llvm/lib/Analysis/InlineCost.cpp --- a/llvm/lib/Analysis/InlineCost.cpp +++ b/llvm/lib/Analysis/InlineCost.cpp @@ -2034,6 +2034,13 @@ " address space"); } + // Currently, we can't mix strictfp and non-strictfp functions. This + // overrides the AlwaysInline attribute! + // This should be improved at some point. + 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)) { diff --git a/llvm/test/Transforms/Inline/inline-strictfp.ll b/llvm/test/Transforms/Inline/inline-strictfp.ll new file mode 100644 --- /dev/null +++ b/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);