summaryrefslogtreecommitdiffstats
path: root/llvm/test
diff options
context:
space:
mode:
authorSanjoy Das <sanjoy@playingwithpointers.com>2015-11-26 01:16:05 +0000
committerSanjoy Das <sanjoy@playingwithpointers.com>2015-11-26 01:16:05 +0000
commitbcd150362aff56aafdecb5545b36a50c00c63cd5 (patch)
tree2a33305e568d5cbc9fe1735a13e543ba22965837 /llvm/test
parent5cad22519d7e70b7fd78db348e56314360b625ee (diff)
downloadbcm5719-llvm-bcd150362aff56aafdecb5545b36a50c00c63cd5.tar.gz
bcm5719-llvm-bcd150362aff56aafdecb5545b36a50c00c63cd5.zip
[OperandBundles] Treat "deopt" operand bundles specially
Teach LLVM optimize to more precisely in the presence of "deopt" operand bundles. "deopt" operand bundles imply that the call they're attached to is at least `readonly` (i.e. they don't imply clobber semantics), and they don't capture their bundle operands. llvm-svn: 254118
Diffstat (limited to 'llvm/test')
-rw-r--r--llvm/test/Feature/OperandBundles/adce.ll8
-rw-r--r--llvm/test/Feature/OperandBundles/basic-aa-argmemonly.ll23
-rw-r--r--llvm/test/Feature/OperandBundles/dse.ll33
-rw-r--r--llvm/test/Feature/OperandBundles/early-cse.ll22
-rw-r--r--llvm/test/Feature/OperandBundles/function-attrs.ll9
5 files changed, 93 insertions, 2 deletions
diff --git a/llvm/test/Feature/OperandBundles/adce.ll b/llvm/test/Feature/OperandBundles/adce.ll
index 33bb87e5fc1..a729ba71068 100644
--- a/llvm/test/Feature/OperandBundles/adce.ll
+++ b/llvm/test/Feature/OperandBundles/adce.ll
@@ -39,3 +39,11 @@ define void @test3() {
call void @readnone_function() readnone [ "tag"() ]
ret void
}
+
+define void @test4() {
+; CHECK-LABEL: @test4(
+ entry:
+; CHECK-NOT: @readonly_function()
+ call void @readonly_function() [ "deopt"() ]
+ ret void
+}
diff --git a/llvm/test/Feature/OperandBundles/basic-aa-argmemonly.ll b/llvm/test/Feature/OperandBundles/basic-aa-argmemonly.ll
index 1f3b378868e..aa944588606 100644
--- a/llvm/test/Feature/OperandBundles/basic-aa-argmemonly.ll
+++ b/llvm/test/Feature/OperandBundles/basic-aa-argmemonly.ll
@@ -26,3 +26,26 @@ define i32 @test1(i32* %P, i32* noalias %P2) {
ret i32 %diff
; CHECK: ret i32 0
}
+
+define i32 @test2(i32* %P, i32* noalias %P2) {
+; Note: in this test we //can// GVN %v1 and %v2 into one value in theory. Calls
+; with deopt operand bundles are not argmemonly because they *read* the entire
+; heap, but they don't write to any location in the heap if the callee does not
+; deoptimize the caller. This fact, combined with the fact that
+; @argmemonly_function is, well, an argmemonly function, can be used to conclude
+; that %P is not written to at the callsite. However LLVM currently cannot
+; describe the "does not write to non-args, and reads the entire heap" effect on
+; a callsite.
+
+; CHECK-LABEL: @test2(
+ %v1 = load i32, i32* %P
+; CHECK: %v1 = load i32, i32* %P
+ call void @argmemonly_function(i32* %P2) [ "deopt"() ]
+; CHECK: call void @argmemonly_function(
+ %v2 = load i32, i32* %P
+; CHECK: %v2 = load i32, i32* %P
+ %diff = sub i32 %v1, %v2
+; CHECK: %diff = sub i32 %v1, %v2
+ ret i32 %diff
+; CHECK: ret i32 %diff
+}
diff --git a/llvm/test/Feature/OperandBundles/dse.ll b/llvm/test/Feature/OperandBundles/dse.ll
index cc5647a2fa0..9ddf7f02e38 100644
--- a/llvm/test/Feature/OperandBundles/dse.ll
+++ b/llvm/test/Feature/OperandBundles/dse.ll
@@ -27,3 +27,36 @@ define i8* @test_1() {
ret i8* %m
}
+
+define void @test_2() {
+; Since the deopt operand bundle does not escape %m (see caveat below), it is
+; legal to elide the final store that location.
+
+; CHECK-LABEL: @test_2(
+ %m = call i8* @malloc(i32 24)
+ tail call void @f() [ "deopt"(i8* %m) ]
+ store i8 -19, i8* %m
+ ret void
+
+; CHECK: tail call void @f() [ "deopt"(i8* %m) ]
+; CHECK-NEXT ret void
+}
+
+define i8* @test_3() {
+; Since the deopt operand bundle does not escape %m (see caveat below), @f
+; cannot observe the stores to %m
+
+; CHECK-LABEL: @test_3(
+ %m = call i8* @malloc(i32 24)
+ tail call void @f() [ "deopt"(i8* %m) ]
+ store i8 -19, i8* %m
+ tail call void @f()
+ store i8 101, i8* %m
+ ret i8* %m
+}
+
+
+; Caveat: technically, %m can only escape if the calling function is deoptimized
+; at the call site (i.e. the call returns to the "deopt" continuation). Since
+; the calling function body will be invalidated in that case, the calling
+; function can be optimized under the assumption that %m does not escape.
diff --git a/llvm/test/Feature/OperandBundles/early-cse.ll b/llvm/test/Feature/OperandBundles/early-cse.ll
index 076ce3baeab..fc201479d8c 100644
--- a/llvm/test/Feature/OperandBundles/early-cse.ll
+++ b/llvm/test/Feature/OperandBundles/early-cse.ll
@@ -2,8 +2,8 @@
; 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.
+; they're carrying unknown 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
@@ -69,3 +69,21 @@ define void @test5(i32* %x) {
; CHECK: store i32 200, i32* %x
ret void
}
+
+define void @test6(i32* %x) {
+; The "deopt" operand bundle does not make the call to
+; @readonly_function read-write; and so the nounwind readonly call can
+; be deleted.
+
+; CHECK-LABEL: @test6(
+ entry:
+
+; CHECK-NEXT: entry:
+; CHECK-NEXT: store i32 200, i32* %x
+; CHECK-NEXT: ret void
+
+ store i32 100, i32* %x
+ call void @readonly_function() [ "deopt"() ]
+ store i32 200, i32* %x
+ ret void
+}
diff --git a/llvm/test/Feature/OperandBundles/function-attrs.ll b/llvm/test/Feature/OperandBundles/function-attrs.ll
index 3d429b3e9d9..808f396fed8 100644
--- a/llvm/test/Feature/OperandBundles/function-attrs.ll
+++ b/llvm/test/Feature/OperandBundles/function-attrs.ll
@@ -22,3 +22,12 @@ define void @test_1(i32* %x) {
call void @f_readnone() [ "foo"(i32* %x) ]
ret void
}
+
+define void @test_2(i32* %x) {
+; The "deopt" operand bundle does not capture or write to %x.
+
+; CHECK-LABEL: define void @test_2(i32* nocapture readonly %x)
+ entry:
+ call void @f_readonly() [ "deopt"(i32* %x) ]
+ ret void
+}
OpenPOWER on IntegriCloud