1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -S -passes=memcpyopt < %s -verify-memoryssa | FileCheck %s 3declare void @may_throw(ptr nocapture %x) 4 5define void @test1(ptr nocapture noalias dereferenceable(4) %x) { 6; CHECK-LABEL: @test1( 7; CHECK-NEXT: entry: 8; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 9; CHECK-NEXT: call void @may_throw(ptr nonnull [[T]]) 10; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[T]], align 4 11; CHECK-NEXT: store i32 [[LOAD]], ptr [[X:%.*]], align 4 12; CHECK-NEXT: ret void 13; 14entry: 15 %t = alloca i32, align 4 16 call void @may_throw(ptr nonnull %t) 17 %load = load i32, ptr %t, align 4 18 store i32 %load, ptr %x, align 4 19 ret void 20} 21 22declare void @always_throws() 23 24define void @test2(ptr nocapture noalias dereferenceable(4) %x) { 25; CHECK-LABEL: @test2( 26; CHECK-NEXT: entry: 27; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 28; CHECK-NEXT: call void @may_throw(ptr nonnull [[T]]) #[[ATTR0:[0-9]+]] 29; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[T]], align 4 30; CHECK-NEXT: call void @always_throws() 31; CHECK-NEXT: store i32 [[LOAD]], ptr [[X:%.*]], align 4 32; CHECK-NEXT: ret void 33; 34entry: 35 %t = alloca i32, align 4 36 call void @may_throw(ptr nonnull %t) nounwind 37 %load = load i32, ptr %t, align 4 38 call void @always_throws() 39 store i32 %load, ptr %x, align 4 40 ret void 41} 42 43; byval argument is not visible on unwind. 44define void @test_byval(ptr nocapture noalias dereferenceable(4) byval(i32) %x) { 45; CHECK-LABEL: @test_byval( 46; CHECK-NEXT: entry: 47; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 48; CHECK-NEXT: call void @may_throw(ptr nonnull [[X:%.*]]) 49; CHECK-NEXT: ret void 50; 51entry: 52 %t = alloca i32, align 4 53 call void @may_throw(ptr nonnull %t) 54 %load = load i32, ptr %t, align 4 55 store i32 %load, ptr %x, align 4 56 ret void 57} 58 59define void @test_dead_on_unwind(ptr nocapture noalias writable dead_on_unwind dereferenceable(4) %x) { 60; CHECK-LABEL: @test_dead_on_unwind( 61; CHECK-NEXT: entry: 62; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 63; CHECK-NEXT: call void @may_throw(ptr nonnull [[X:%.*]]) 64; CHECK-NEXT: ret void 65; 66entry: 67 %t = alloca i32, align 4 68 call void @may_throw(ptr nonnull %t) 69 %load = load i32, ptr %t, align 4 70 store i32 %load, ptr %x, align 4 71 ret void 72} 73 74; Same as previous test, but dereferenceability information is provided by sret. 75define void @test_dead_on_unwind_sret(ptr nocapture noalias writable dead_on_unwind sret(i32) %x) { 76; CHECK-LABEL: @test_dead_on_unwind_sret( 77; CHECK-NEXT: entry: 78; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 79; CHECK-NEXT: call void @may_throw(ptr nonnull [[X:%.*]]) 80; CHECK-NEXT: ret void 81; 82entry: 83 %t = alloca i32, align 4 84 call void @may_throw(ptr nonnull %t) 85 %load = load i32, ptr %t, align 4 86 store i32 %load, ptr %x, align 4 87 ret void 88} 89 90define void @test_dead_on_unwind_missing_writable(ptr nocapture noalias dead_on_unwind dereferenceable(4) %x) { 91; CHECK-LABEL: @test_dead_on_unwind_missing_writable( 92; CHECK-NEXT: entry: 93; CHECK-NEXT: [[T:%.*]] = alloca i32, align 4 94; CHECK-NEXT: call void @may_throw(ptr nonnull [[T]]) 95; CHECK-NEXT: [[LOAD:%.*]] = load i32, ptr [[T]], align 4 96; CHECK-NEXT: store i32 [[LOAD]], ptr [[X:%.*]], align 4 97; CHECK-NEXT: ret void 98; 99entry: 100 %t = alloca i32, align 4 101 call void @may_throw(ptr nonnull %t) 102 %load = load i32, ptr %t, align 4 103 store i32 %load, ptr %x, align 4 104 ret void 105} 106