summaryrefslogtreecommitdiff
path: root/test/Feature
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-10-22 03:12:22 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-10-22 03:12:22 +0000
commitf1c277c27096a55a1ab2220294a69457d0951bf7 (patch)
treef168ecaf4784145aaba61d90db449704c511736f /test/Feature
parent55a57a7674acbd7265598b11119d84af737de6d2 (diff)
[OperandBundles] Make function attributes conservatively correct
Summary: This makes attribute accessors on `CallInst` and `InvokeInst` do the (conservatively) right thing. This essentially involves, in some cases, *not* falling back querying the attributes on the called `llvm::Function` when operand bundles are present. Attributes locally present on the `CallInst` or `InvokeInst` will still override operand bundle semantics. The LangRef has been amended to reflect this. Note: this change does not do anything prevent `-function-attrs` from inferring `CallSite` local attributes after inspecting the called function -- that will be done as a separate change. I've used `-adce` and `-early-cse` to test these changes. There is nothing special about these passes (and they did not require any changes) except that they seemed be the easiest way to write the tests. This change does not add deal with `argmemonly`. That's a later change because alias analysis requires a related fix before `argmemonly` can be tested. Reviewers: reames, chandlerc Subscribers: llvm-commits Differential Revision: http://reviews.llvm.org/D13961 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@250973 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'test/Feature')
-rw-r--r--test/Feature/OperandBundles/adce.ll41
-rw-r--r--test/Feature/OperandBundles/early-cse.ll71
2 files changed, 112 insertions, 0 deletions
diff --git a/test/Feature/OperandBundles/adce.ll b/test/Feature/OperandBundles/adce.ll
new file mode 100644
index 00000000000..33bb87e5fc1
--- /dev/null
+++ b/test/Feature/OperandBundles/adce.ll
@@ -0,0 +1,41 @@
+; RUN: opt -S -adce < %s | FileCheck %s
+
+; While it is normally okay to DCE out calls to @readonly_function and
+; @readnone_function, we cannot do that if they're carrying operand
+; bundles since the presence of unknown operand bundles implies
+; arbitrary memory effects.
+
+declare void @readonly_function() readonly nounwind
+declare void @readnone_function() readnone nounwind
+
+define void @test0() {
+; CHECK-LABEL: @test0(
+ entry:
+ call void @readonly_function() [ "tag"() ]
+; CHECK: call void @readonly_function
+ ret void
+}
+
+define void @test1() {
+; CHECK-LABEL: @test1(
+ entry:
+ call void @readnone_function() [ "tag"() ]
+; CHECK: call void @readnone_function
+ ret void
+}
+
+define void @test2() {
+; CHECK-LABEL: @test2(
+ entry:
+; CHECK-NOT: @readonly_function(
+ call void @readonly_function() readonly [ "tag"() ]
+ ret void
+}
+
+define void @test3() {
+; CHECK-LABEL: @test3(
+ entry:
+; CHECK-NOT: @readnone_function(
+ call void @readnone_function() readnone [ "tag"() ]
+ ret void
+}
diff --git a/test/Feature/OperandBundles/early-cse.ll b/test/Feature/OperandBundles/early-cse.ll
new file mode 100644
index 00000000000..076ce3baeab
--- /dev/null
+++ b/test/Feature/OperandBundles/early-cse.ll
@@ -0,0 +1,71 @@
+; RUN: opt -S -early-cse < %s | FileCheck %s
+
+; While it is normally okay to do memory optimizations over calls to
+; @readonly_function and @readnone_function, we cannot do that if
+; they're carrying operand bundles since the presence of unknown
+; operand bundles implies arbitrary memory effects.
+
+declare void @readonly_function() readonly nounwind
+declare void @readnone_function() readnone nounwind
+
+define i32 @test0(i32* %x) {
+; CHECK-LABEL: @test0(
+ entry:
+ store i32 100, i32* %x
+; CHECK: store i32 100, i32* %x
+ call void @readonly_function() [ "tag"() ]
+; CHECK: call void @readonly_function()
+
+ %v = load i32, i32* %x
+; CHECK: %v = load i32, i32* %x
+; CHECK: ret i32 %v
+ ret i32 %v
+}
+
+define i32 @test1(i32* %x) {
+; CHECK: @test1(
+ entry:
+ store i32 100, i32* %x
+; CHECK: store i32 100, i32* %x
+ call void @readonly_function() readonly [ "tag"() ]
+; CHECK-NOT: call void @readonly_function
+ %v = load i32, i32* %x
+ ret i32 %v
+; CHECK: ret i32 100
+}
+
+define i32 @test3(i32* %x) {
+; CHECK-LABEL: @test3(
+ entry:
+ store i32 100, i32* %x
+; CHECK: store i32 100, i32* %x
+ call void @readonly_function()
+; CHECK-NOT: call void @readonly_function
+ %v = load i32, i32* %x
+ ret i32 %v
+; CHECK: ret i32 100
+}
+
+define void @test4(i32* %x) {
+; CHECK-LABEL: @test4(
+ entry:
+ store i32 100, i32* %x
+; CHECK: store i32 100, i32* %x
+ call void @readnone_function() [ "tag"() ]
+; CHECK: call void @readnone_function
+ store i32 200, i32* %x
+; CHECK: store i32 200, i32* %x
+ ret void
+}
+
+define void @test5(i32* %x) {
+; CHECK-LABEL: @test5(
+ entry:
+ store i32 100, i32* %x
+; CHECK-NOT: store i32 100, i32* %x
+; CHECK-NOT: call void @readnone_function
+ call void @readnone_function() readnone [ "tag"() ]
+ store i32 200, i32* %x
+; CHECK: store i32 200, i32* %x
+ ret void
+}