1; RUN: opt -S -passes=dse < %s | FileCheck %s 2 3declare void @f() 4declare noalias ptr @malloc(i32) nounwind 5 6define void @test_0() { 7; CHECK-LABEL: @test_0( 8 %m = call ptr @malloc(i32 24) 9 tail call void @f() [ "unknown"(ptr %m) ] 10; CHECK: store i8 -19, ptr %m 11 store i8 -19, ptr %m 12 ret void 13} 14 15define ptr @test_1() { 16; CHECK-LABEL: @test_1( 17 %m = call ptr @malloc(i32 24) 18 tail call void @f() [ "unknown"(ptr %m) ] 19 store i8 -19, ptr %m 20 tail call void @f() 21 store i8 101, ptr %m 22 23; CHECK: tail call void @f() [ "unknown"(ptr %m) ] 24; CHECK: store i8 -19, ptr %m 25; CHECK: tail call void @f() 26; CHECK: store i8 101, ptr %m 27 28 ret ptr %m 29} 30 31define 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 ptr @malloc(i32 24) 37 tail call void @f() [ "deopt"(ptr %m) ] 38 store i8 -19, ptr %m 39 ret void 40 41; CHECK: tail call void @f() [ "deopt"(ptr %m) ] 42; CHECK-NEXT: ret void 43} 44 45define ptr @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 ptr @malloc(i32 24) 51 tail call void @f() [ "deopt"(ptr %m) ] 52 store i8 -19, ptr %m 53 tail call void @f() 54 store i8 101, ptr %m 55 ret ptr %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