Index: llvm/lib/IR/Verifier.cpp =================================================================== --- llvm/lib/IR/Verifier.cpp +++ llvm/lib/IR/Verifier.cpp @@ -279,6 +279,10 @@ /// already. bool SawFrameEscape; + /// Whether or not we've seen constrained floating-point intrinsics + /// in a function. + bool HasConstrainedFP; + /// Whether the current function has a DISubprogram attached to it. bool HasDebugInfo = false; @@ -2215,6 +2219,8 @@ // visitFunction - Verify that a function is ok. // void Verifier::visitFunction(const Function &F) { + HasConstrainedFP = false; + visitGlobalValue(F); // Check function arguments. @@ -2403,6 +2409,13 @@ Assert(false, "Invalid user of intrinsic instruction!", U); } + // Verify that the function has the correct attributes if a constrained + // floating-point value was seen. + if (HasConstrainedFP) + Assert (F.hasFnAttribute(Attribute::StrictFP), + "Constrained floating point requires function attribute strictfp!", + &F); + auto *N = F.getSubprogram(); HasDebugInfo = (N != nullptr); if (!HasDebugInfo) @@ -2956,6 +2969,15 @@ // Verify call attributes. verifyFunctionAttrs(FTy, Attrs, &Call, IsIntrinsic); + // Verify strictfp attributes match. + Function *ContainingF = Call.getFunction(); + AttributeSet CallAttrs = Attrs.getFnAttributes(); + Assert (ContainingF->hasFnAttribute(Attribute::StrictFP) == + CallAttrs.hasAttribute(Attribute::StrictFP), + "Functions and their contained calls must match " + "in use of attribute strictfp!", + ContainingF, &Call); + // Conservatively check the inalloca argument. // We have a bug if we can find that there is an underlying alloca without // inalloca. @@ -5008,6 +5030,10 @@ void Verifier::visitConstrainedFPIntrinsic(ConstrainedFPIntrinsic &FPI) { unsigned NumOperands; bool HasRoundingMD; + HasConstrainedFP = true; + AttributeSet CallAttrs = FPI.getAttributes().getFnAttributes(); + Assert (CallAttrs.hasAttribute(Attribute::StrictFP), + "Constrained FP intrinsics require strictfp attribute.", &FPI); switch (FPI.getIntrinsicID()) { #define INSTRUCTION(NAME, NARG, ROUND_MODE, INTRINSIC) \ case Intrinsic::INTRINSIC: \ Index: llvm/test/Verifier/fp-intrinsics.ll =================================================================== --- llvm/test/Verifier/fp-intrinsics.ll +++ llvm/test/Verifier/fp-intrinsics.ll @@ -3,9 +3,13 @@ ; RUN: sed -e s/.T3:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK3 %s ; RUN: sed -e s/.T4:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK4 %s ; RUN: sed -e s/.T5:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK5 %s +; RUN: sed -e s/.T6:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK6 %s +; RUN: sed -e s/.T7:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK7 %s +; RUN: sed -e s/.T8:// %s | not opt -verify -disable-output 2>&1 | FileCheck --check-prefix=CHECK8 %s ; Common declarations used for all runs. declare double @llvm.experimental.constrained.fadd.f64(double, double, metadata, metadata) +declare float @llvm.experimental.constrained.fadd.f32(float, float, metadata, metadata) declare double @llvm.experimental.constrained.sqrt.f64(double, metadata, metadata) ; Test that the verifier accepts legal code, and that the correct attributes are @@ -77,4 +81,35 @@ ;T5: ret double %fadd ;T5: } +; Test for mismatched function and function call attributes +; CHECK6: Functions and their contained calls must match in use of attribute strictfp! +;T6: define double @f6(double %a) #0 { +;T6: entry: +;T6: %fadd = call double @llvm.experimental.constrained.sqrt.f64( +;T6: double %a, +;T6: metadata !"round.dynamic", +;T6: metadata !"fpexcept.strict") +;T6: ret double %fadd +;T6: } + +; Test for mismatched function and function call attributes +; CHECK7: Functions and their contained calls must match in use of attribute strictfp! +;T7: declare double @llvm.sqrt.f64(double) +;T7: define double @f7(double %a) #0 { +;T7: entry: +;T7: %sqrt = call double @llvm.sqrt.f64(double %a) +;T7: ret double %sqrt +;T7: } + +; Test for mismatched function and function call attributes +; CHECK8: Functions and their contained calls must match in use of attribute strictfp! +;T8: define double @f8(double %a) { +;T8: entry: +;T8: %fadd = call double @llvm.experimental.constrained.sqrt.f64( +;T8: double %a, +;T8: metadata !"round.dynamic", +;T8: metadata !"fpexcept.strict") #0 +;T8: ret double %fadd +;T8: } + attributes #0 = { strictfp }