1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -passes=globalopt -S %s | FileCheck %s 3 4%struct.global.20ptr = type { ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr, ptr } 5 6@global.20ptr = internal unnamed_addr global %struct.global.20ptr zeroinitializer 7 8declare i32 @fn0() 9 10declare i32 @fn1() 11 12declare i32 @fn2() 13 14declare i32 @fn3() 15 16declare void @llvm.memcpy.p0i8.p0i8.i64(ptr, ptr, i64, i1) local_unnamed_addr 17 18define void @stores_single_use_gep_constexpr() { 19; CHECK-LABEL: @stores_single_use_gep_constexpr( 20; CHECK-NEXT: entry: 21; CHECK-NEXT: ret void 22; 23entry: 24 store ptr @fn0, ptr @global.20ptr, align 8 25 store ptr @fn1, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 1), align 8 26 store ptr @fn2, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 2), align 8 27 store ptr @fn3, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 3), align 8 28 store ptr @fn0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 4), align 8 29 store ptr @fn1, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 5), align 8 30 store ptr @fn2, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 6), align 8 31 store ptr @fn3, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 7), align 8 32 store ptr @fn0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 8), align 8 33 ret void 34} 35 36define void @stores_multi_use_gep_constexpr() { 37; CHECK-LABEL: @stores_multi_use_gep_constexpr( 38; CHECK-NEXT: entry: 39; CHECK-NEXT: ret void 40; 41entry: 42 store i32 0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 16), align 8 43 store i32 0, ptr getelementptr inbounds (%struct.global.20ptr, ptr @global.20ptr, i64 0, i32 16), align 8 44 ret void 45} 46 47define void @stores_ptrtoint_constexpr() { 48; CHECK-LABEL: @stores_ptrtoint_constexpr( 49; CHECK-NEXT: entry: 50; CHECK-NEXT: ret void 51; 52entry: 53 store i32 0, ptr inttoptr (i64 ptrtoint (ptr @global.20ptr to i64) to ptr), align 8 54 ret void 55} 56 57@gv = internal unnamed_addr global [3 x ptr] zeroinitializer, align 16 58@gv2 = internal unnamed_addr global i32 0, align 4 59 60;; This is a negative test which includes a load from @gv. No stores 61;; or memintrinsics with destination @gv should be removed. 62define i32 @load_from_gv_no_remove() local_unnamed_addr { 63; CHECK-LABEL: @load_from_gv_no_remove( 64; CHECK-NEXT: entry: 65; CHECK-NEXT: [[E:%.*]] = alloca i32, align 4 66; CHECK-NEXT: store ptr [[E]], ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16 67; CHECK-NEXT: [[LOAD_B:%.*]] = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16 68; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr @gv, ptr @gv2, i64 8, i1 false) 69; CHECK-NEXT: ret i32 0 70; 71entry: 72 %e = alloca i32, align 4 73 store ptr %e, ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16 74 %load.b = load ptr, ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 2), align 16 75 call void @llvm.memcpy.p0i8.p0i8.i64(ptr getelementptr inbounds ([3 x ptr], ptr @gv, i64 0, i64 0), ptr @gv2, i64 8, i1 false) 76 ret i32 0 77} 78 79@a = internal unnamed_addr global i32 0, align 4 80@b = internal unnamed_addr global [3 x ptr] zeroinitializer, align 16 81 82;; This test is extracted from the issue reported in #64680, with an 83;; additional memcpy and a memset. Ensure all stores and memintrinsics with 84;; destination @b are removed as @b is dead. 85define i32 @load_gv_from_op_remove_store(ptr %p) local_unnamed_addr { 86; CHECK-LABEL: @load_gv_from_op_remove_store( 87; CHECK-NEXT: entry: 88; CHECK-NEXT: [[E:%.*]] = alloca i32, align 4 89; CHECK-NEXT: [[DOTPR:%.*]] = load i32, ptr @a, align 4 90; CHECK-NEXT: [[CMP1:%.*]] = icmp slt i32 [[DOTPR]], 3 91; CHECK-NEXT: br i1 [[CMP1]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]] 92; CHECK: for.body: 93; CHECK-NEXT: store i32 8, ptr [[E]], align 4 94; CHECK-NEXT: call void @fn1() 95; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[E]], align 4 96; CHECK-NEXT: [[TOBOOL_NOT:%.*]] = icmp eq i32 [[TMP0]], 0 97; CHECK-NEXT: br i1 [[TOBOOL_NOT]], label [[IF_THEN:%.*]], label [[IF_END:%.*]] 98; CHECK: if.then: 99; CHECK-NEXT: call void @fn0() 100; CHECK-NEXT: br label [[IF_END]] 101; CHECK: if.end: 102; CHECK-NEXT: store ptr [[E]], ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 2), align 16 103; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr @a, align 4 104; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[TMP1]], 1 105; CHECK-NEXT: store i32 [[INC]], ptr @a, align 4 106; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[TMP1]], 2 107; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END]] 108; CHECK: for.end: 109; CHECK-NEXT: call void @llvm.memcpy.p0.p0.i64(ptr @b, ptr [[P:%.*]], i64 8, i1 false) 110; CHECK-NEXT: ret i32 0 111; 112entry: 113 %e = alloca i32, align 4 114 %.pr = load i32, ptr @a, align 4 115 %cmp1 = icmp slt i32 %.pr, 3 116 br i1 %cmp1, label %for.body, label %for.end 117 118for.body: ; preds = %entry, %if.end 119 store i32 8, ptr %e, align 4 120 call void @fn1() 121 %0 = load i32, ptr %e, align 4 122 %tobool.not = icmp eq i32 %0, 0 123 br i1 %tobool.not, label %if.then, label %if.end 124 125if.then: ; preds = %for.body 126 call void @fn0() 127 br label %if.end 128 129if.end: ; preds = %if.then, %for.body 130 store ptr %e, ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 2), align 16 131 %1 = load i32, ptr @a, align 4 132 %inc = add nsw i32 %1, 1 133 store i32 %inc, ptr @a, align 4 134 %cmp = icmp slt i32 %1, 2 135 call void @llvm.memset.p0i8.i64(ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 0), i8 0, i64 8, i1 false) 136 br i1 %cmp, label %for.body, label %for.end 137 138for.end: ; preds = %if.end, %entry 139 call void @llvm.memcpy.p0i8.p0i8.i64(ptr getelementptr inbounds ([3 x ptr], ptr @b, i64 0, i64 0), ptr %p, i64 8, i1 false) 140 ret i32 0 141} 142