summaryrefslogtreecommitdiffstats
path: root/llvm/test/Feature
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/test/Feature')
-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