1 ; RUN: opt -S -dse < %s | FileCheck %s 2 3 declare void @f() 4 declare noalias i8* @malloc(i32) nounwind 5 6 define void @test_0() { 7 ; CHECK-LABEL: @test_0( 8 %m = call i8* @malloc(i32 24) 9 tail call void @f() [ "unknown"(i8* %m) ] 10 ; CHECK: store i8 -19, i8* %m 11 store i8 -19, i8* %m 12 ret void 13 } 14 15 define i8* @test_1() { 16 ; CHECK-LABEL: @test_1( 17 %m = call i8* @malloc(i32 24) 18 tail call void @f() [ "unknown"(i8* %m) ] 19 store i8 -19, i8* %m 20 tail call void @f() 21 store i8 101, i8* %m 22 23 ; CHECK: tail call void @f() [ "unknown"(i8* %m) ] 24 ; CHECK: store i8 -19, i8* %m 25 ; CHECK: tail call void @f() 26 ; CHECK: store i8 101, i8* %m 27 28 ret i8* %m 29 } 30 31 define void @test_2() { 32 ; Since the deopt operand bundle does not escape %m (see caveat below), it is 33 ; legal to elide the final store that location. 34 35 ; CHECK-LABEL: @test_2( 36 %m = call i8* @malloc(i32 24) 37 tail call void @f() [ "deopt"(i8* %m) ] 38 store i8 -19, i8* %m 39 ret void 40 41 ; CHECK: tail call void @f() [ "deopt"(i8* %m) ] 42 ; CHECK-NEXT ret void 43 } 44 45 define i8* @test_3() { 46 ; Since the deopt operand bundle does not escape %m (see caveat below), @f 47 ; cannot observe the stores to %m 48 49 ; CHECK-LABEL: @test_3( 50 %m = call i8* @malloc(i32 24) 51 tail call void @f() [ "deopt"(i8* %m) ] 52 store i8 -19, i8* %m 53 tail call void @f() 54 store i8 101, i8* %m 55 ret i8* %m 56 } 57 58 59 ; Caveat: technically, %m can only escape if the calling function is deoptimized 60 ; at the call site (i.e. the call returns to the "deopt" continuation). Since 61 ; the calling function body will be invalidated in that case, the calling 62 ; function can be optimized under the assumption that %m does not escape. 63