[Inliner] Merge the attributes of the caller and callee functions

This patch turns off the fast-math optimization attribute on the caller
if the callee's fast-math attribute is not turned on.

For example,

- before inlining
 caller: "less-precise-fpmad"="true"
 callee: "less-precise-fpmad"="false"

- after inlining
 caller: "less-precise-fpmad"="false"

Alternatively, it's possible to block inlining if the caller's and
callee's attributes don't match. If this approach is preferable to the
one in this patch, we can discuss post-commit.

rdar://problem/19836465

Differential Revision: http://reviews.llvm.org/D7802

llvm-svn: 257575
This commit is contained in:
Akira Hatanaka 2016-01-13 06:02:45 +00:00
parent e9a1c31ebf
commit b45b1ea86f
2 changed files with 89 additions and 0 deletions

View File

@ -189,4 +189,9 @@ class MergeRule<string F> {
string MergeFunc = F;
}
def : MergeRule<"setAND<LessPreciseFPMADAttr>">;
def : MergeRule<"setAND<NoInfsFPMathAttr>">;
def : MergeRule<"setAND<NoNansFPMathAttr>">;
def : MergeRule<"setAND<UnsafeFPMathAttr>">;
def : MergeRule<"setOR<NoImplicitFloatAttr>">;
def : MergeRule<"adjustCallerSSPLevel">;

View File

@ -160,3 +160,87 @@ define i32 @test_target_features1(i32 %i) "target-features"="+sse4.2" {
; CHECK-NEXT: @test_target_features_callee1
; CHECK-NEXT: ret i32
}
define i32 @less-precise-fpmad_callee0(i32 %i) "less-precise-fpmad"="false" {
ret i32 %i
; CHECK: @less-precise-fpmad_callee0(i32 %i) [[FPMAD_FALSE:#[0-9]+]] {
; CHECK-NEXT: ret i32
}
define i32 @less-precise-fpmad_callee1(i32 %i) "less-precise-fpmad"="true" {
ret i32 %i
; CHECK: @less-precise-fpmad_callee1(i32 %i) [[FPMAD_TRUE:#[0-9]+]] {
; CHECK-NEXT: ret i32
}
define i32 @test_less-precise-fpmad0(i32 %i) "less-precise-fpmad"="false" {
%1 = call i32 @less-precise-fpmad_callee0(i32 %i)
ret i32 %1
; CHECK: @test_less-precise-fpmad0(i32 %i) [[FPMAD_FALSE]] {
; CHECK-NEXT: ret i32
}
define i32 @test_less-precise-fpmad1(i32 %i) "less-precise-fpmad"="false" {
%1 = call i32 @less-precise-fpmad_callee1(i32 %i)
ret i32 %1
; CHECK: @test_less-precise-fpmad1(i32 %i) [[FPMAD_FALSE]] {
; CHECK-NEXT: ret i32
}
define i32 @test_less-precise-fpmad2(i32 %i) "less-precise-fpmad"="true" {
%1 = call i32 @less-precise-fpmad_callee0(i32 %i)
ret i32 %1
; CHECK: @test_less-precise-fpmad2(i32 %i) [[FPMAD_FALSE]] {
; CHECK-NEXT: ret i32
}
define i32 @test_less-precise-fpmad3(i32 %i) "less-precise-fpmad"="true" {
%1 = call i32 @less-precise-fpmad_callee1(i32 %i)
ret i32 %1
; CHECK: @test_less-precise-fpmad3(i32 %i) [[FPMAD_TRUE]] {
; CHECK-NEXT: ret i32
}
define i32 @no-implicit-float_callee0(i32 %i) {
ret i32 %i
; CHECK: @no-implicit-float_callee0(i32 %i) {
; CHECK-NEXT: ret i32
}
define i32 @no-implicit-float_callee1(i32 %i) noimplicitfloat {
ret i32 %i
; CHECK: @no-implicit-float_callee1(i32 %i) [[NOIMPLICITFLOAT:#[0-9]+]] {
; CHECK-NEXT: ret i32
}
define i32 @test_no-implicit-float0(i32 %i) {
%1 = call i32 @no-implicit-float_callee0(i32 %i)
ret i32 %1
; CHECK: @test_no-implicit-float0(i32 %i) {
; CHECK-NEXT: ret i32
}
define i32 @test_no-implicit-float1(i32 %i) {
%1 = call i32 @no-implicit-float_callee1(i32 %i)
ret i32 %1
; CHECK: @test_no-implicit-float1(i32 %i) [[NOIMPLICITFLOAT]] {
; CHECK-NEXT: ret i32
}
define i32 @test_no-implicit-float2(i32 %i) noimplicitfloat {
%1 = call i32 @no-implicit-float_callee0(i32 %i)
ret i32 %1
; CHECK: @test_no-implicit-float2(i32 %i) [[NOIMPLICITFLOAT]] {
; CHECK-NEXT: ret i32
}
define i32 @test_no-implicit-float3(i32 %i) noimplicitfloat {
%1 = call i32 @no-implicit-float_callee1(i32 %i)
ret i32 %1
; CHECK: @test_no-implicit-float3(i32 %i) [[NOIMPLICITFLOAT]] {
; CHECK-NEXT: ret i32
}
; CHECK: attributes [[FPMAD_FALSE]] = { "less-precise-fpmad"="false" }
; CHECK: attributes [[FPMAD_TRUE]] = { "less-precise-fpmad"="true" }
; CHECK: attributes [[NOIMPLICITFLOAT]] = { noimplicitfloat }