diff options
Diffstat (limited to 'llvm/test')
-rw-r--r-- | llvm/test/Feature/OperandBundles/adce.ll | 8 | ||||
-rw-r--r-- | llvm/test/Feature/OperandBundles/basic-aa-argmemonly.ll | 23 | ||||
-rw-r--r-- | llvm/test/Feature/OperandBundles/dse.ll | 33 | ||||
-rw-r--r-- | llvm/test/Feature/OperandBundles/early-cse.ll | 22 | ||||
-rw-r--r-- | llvm/test/Feature/OperandBundles/function-attrs.ll | 9 |
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 +} |