Index: lib/Target/ARM/ARMAsmPrinter.cpp =================================================================== --- lib/Target/ARM/ARMAsmPrinter.cpp +++ lib/Target/ARM/ARMAsmPrinter.cpp @@ -633,17 +633,17 @@ return ARMBuildAttrs::v4; } -// Returns true if all functions have the same function attribute value -static bool haveAllFunctionsAttribute(const Module &M, StringRef Attr, - StringRef Value) { - for (auto &F : M) - if (F.getFnAttribute(Attr).getValueAsString() != Value) - return false; - - return true; +// Returns true if all functions have the same function attribute value. +// It also returns true when there are no functions, or when +// the particular function attribute is not set to a value. +static bool checkFunctionsAttributeConsistency(const Module &M, StringRef Attr, + StringRef Value) { + return !any_of(M, [&](const Function &F) { + return F.hasFnAttribute(Attr) && + F.getFnAttribute(Attr).getValueAsString() != Value; + }); } - void ARMAsmPrinter::emitAttributes() { MCTargetStreamer &TS = *OutStreamer->getTargetStreamer(); ARMTargetStreamer &ATS = static_cast(TS); @@ -781,13 +781,15 @@ } // Set FP Denormals. - if (haveAllFunctionsAttribute(*MMI->getModule(), "denormal-fp-math", - "preserve-sign") || + if (checkFunctionsAttributeConsistency(*MMI->getModule(), + "denormal-fp-math", + "preserve-sign") || TM.Options.FPDenormalMode == FPDenormal::PreserveSign) ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::PreserveFPSign); - else if (haveAllFunctionsAttribute(*MMI->getModule(), "denormal-fp-math", - "positive-zero") || + else if (checkFunctionsAttributeConsistency(*MMI->getModule(), + "denormal-fp-math", + "positive-zero") || TM.Options.FPDenormalMode == FPDenormal::PositiveZero) ATS.emitAttribute(ARMBuildAttrs::ABI_FP_denormal, ARMBuildAttrs::PositiveZero); @@ -821,7 +823,8 @@ } // Set FP exceptions and rounding - if (haveAllFunctionsAttribute(*MMI->getModule(), "no-trapping-math", "true") || + if (checkFunctionsAttributeConsistency(*MMI->getModule(), + "no-trapping-math", "true") || TM.Options.NoTrappingFPMath) ATS.emitAttribute(ARMBuildAttrs::ABI_FP_exceptions, ARMBuildAttrs::Not_Allowed); Index: test/CodeGen/ARM/build-attributes-fn-attr0.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr0.ll @@ -0,0 +1,11 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed +; as function attributes, which map on to build attributes ABI_FP_exceptions +; ABI_FP_denormal. In the backend we therefore have a check to see if all +; functions have consistent function attributes values. This check also returns +; true when the compilation unit does not have any functions (i.e. the +; attributes are consistent), which is what we check with this regression test. + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 2 +; CHECK: .eabi_attribute 21, 0 Index: test/CodeGen/ARM/build-attributes-fn-attr1.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr1.ll @@ -0,0 +1,18 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed as +; function attributes, which map on to build attributes ABI_FP_exceptions ABI_FP_denormal. +; In the backend we have a check to see if all functions have consistent function +; attributes values. This checks the "default" behaviour when these FP function +; attributes are not set at all. + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 2 +; CHECK: .eabi_attribute 21, 0 + + +define i32 @foo_no_fn_attr() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +attributes #0 = { minsize norecurse nounwind optsize readnone } Index: test/CodeGen/ARM/build-attributes-fn-attr2.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr2.ll @@ -0,0 +1,18 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed +; as function attributes, which map on to build attributes ABI_FP_exceptions +; ABI_FP_denormal. In the backend we therefore have a check to see if all +; functions have consistent function attributes values. +; Here we just test correct output for specific values of no trapping math +; and denormals. + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 1 +; CHECK: .eabi_attribute 21, 1 + +define i32 @foo() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +attributes #0 = { minsize norecurse nounwind optsize readnone "no-trapping-math"="false" "denormal-fp-math"="ieee"} Index: test/CodeGen/ARM/build-attributes-fn-attr3.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr3.ll @@ -0,0 +1,17 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed +; as function attributes, which map on to build attributes ABI_FP_exceptions +; ABI_FP_denormal. In the backend we therefore have a check to see if all +; functions have consistent function attributes values. +; Here we check: no-trapping-math=true + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 1 +; CHECK: .eabi_attribute 21, 0 + +define i32 @foo() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +attributes #0 = { minsize norecurse nounwind optsize readnone "no-trapping-math"="true"} Index: test/CodeGen/ARM/build-attributes-fn-attr4.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr4.ll @@ -0,0 +1,22 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed +; as function attributes, which map on to build attributes ABI_FP_exceptions +; ABI_FP_denormal. In the backend we therefore have a check to see if all +; functions have consistent function attributes values. +; Here we check: denormal-fp-math=positive-zero + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 0 +; CHECK: .eabi_attribute 21, 0 + +define i32 @foo1() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +define i32 @foo2() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +attributes #0 = { minsize norecurse nounwind optsize readnone "denormal-fp-math"="positive-zero"} Index: test/CodeGen/ARM/build-attributes-fn-attr5.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr5.ll @@ -0,0 +1,22 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed +; as function attributes, which map on to build attributes ABI_FP_exceptions +; ABI_FP_denormal. In the backend we therefore have a check to see if all +; functions have consistent function attributes values. +; Here we check: denormal-fp-math=preserve-sign + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 2 +; CHECK: .eabi_attribute 21, 0 + +define i32 @foo1() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +define i32 @foo2() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +attributes #0 = { minsize norecurse nounwind optsize readnone "denormal-fp-math"="preserve-sign"} Index: test/CodeGen/ARM/build-attributes-fn-attr6.ll =================================================================== --- /dev/null +++ test/CodeGen/ARM/build-attributes-fn-attr6.ll @@ -0,0 +1,23 @@ +; Check FP options -fno-trapping-math and -fdenormal-fp-math. They are passed +; as function attributes, which map on to build attributes ABI_FP_exceptions +; ABI_FP_denormal. In the backend we therefore have a check to see if all +; functions have consistent function attributes values. Here we check two +; functions have inconsistent values, and that a default is returned. + +; RUN: llc < %s -mtriple=armv7-linux-gnueabi -mcpu=cortex-a15 | FileCheck %s --check-prefix=CHECK + +; CHECK: .eabi_attribute 20, 0 +; CHECK: .eabi_attribute 21, 0 + +define i32 @foo1() local_unnamed_addr #0 { +entry: + ret i32 42 +} + +define i32 @foo2() local_unnamed_addr #1 { +entry: + ret i32 42 +} + +attributes #0 = { minsize norecurse nounwind optsize readnone "denormal-fp-math"="preserve-sign"} +attributes #0 = { minsize norecurse nounwind optsize readnone "denormal-fp-math"="positive-zero"}