1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2 3; RUN: opt -passes=dse -S %s | FileCheck %s 4 5target datalayout = "e-m:e-i64:64-n32:64-v256:256:256-v512:512:512" 6 7declare void @use(i32) 8 9; Test cases with a loop carried dependence in %loop.2, where both %l.0 and 10; %l.1 read the value stored by the previous iteration. Hence, the store in 11; %loop.2 is not dead at the end of the function. 12define void @test.1() { 13; CHECK-LABEL: @test.1( 14; CHECK-NEXT: entry: 15; CHECK-NEXT: [[A:%.*]] = alloca [100 x i32], align 4 16; CHECK-NEXT: br label [[LOOP_1:%.*]] 17; CHECK: loop.1: 18; CHECK-NEXT: [[IV_1:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP_1]] ] 19; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[IV_1]] 20; CHECK-NEXT: store i32 0, ptr [[ARRAYIDX1]], align 4 21; CHECK-NEXT: [[IV_1_NEXT]] = add nsw i64 [[IV_1]], 1 22; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV_1_NEXT]], 100 23; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[LOOP_2_PH:%.*]] 24; CHECK: loop.2.ph: 25; CHECK-NEXT: br label [[LOOP_2:%.*]] 26; CHECK: loop.2: 27; CHECK-NEXT: [[IV_2:%.*]] = phi i64 [ [[IV_2_NEXT:%.*]], [[LOOP_2]] ], [ 0, [[LOOP_2_PH]] ] 28; CHECK-NEXT: [[PTR_IV_2:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[IV_2]] 29; CHECK-NEXT: [[L_0:%.*]] = load i32, ptr [[PTR_IV_2]], align 4 30; CHECK-NEXT: call void @use(i32 [[L_0]]) 31; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[IV_2]], 1 32; CHECK-NEXT: [[PTR_IV_2_ADD_1:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[ADD]] 33; CHECK-NEXT: store i32 10, ptr [[PTR_IV_2_ADD_1]], align 4 34; CHECK-NEXT: [[L_1:%.*]] = load i32, ptr [[PTR_IV_2]], align 4 35; CHECK-NEXT: call void @use(i32 [[L_1]]) 36; CHECK-NEXT: [[IV_2_NEXT]] = add nsw i64 [[IV_2]], 1 37; CHECK-NEXT: [[C_2:%.*]] = icmp slt i64 [[IV_2_NEXT]], 100 38; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[EXIT:%.*]] 39; CHECK: exit: 40; CHECK-NEXT: ret void 41; 42entry: 43 %A = alloca [100 x i32], align 4 44 br label %loop.1 45 46loop.1: 47 %iv.1 = phi i64 [ 1, %entry ], [ %iv.1.next, %loop.1 ] 48 %arrayidx1 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %iv.1 49 store i32 0, ptr %arrayidx1, align 4 50 %iv.1.next = add nsw i64 %iv.1, 1 51 %c.1 = icmp slt i64 %iv.1.next, 100 52 br i1 %c.1, label %loop.1, label %loop.2.ph 53 54loop.2.ph: 55 br label %loop.2 56 57loop.2: 58 %iv.2 = phi i64 [ %iv.2.next, %loop.2 ], [ 0, %loop.2.ph ] 59 %ptr.iv.2 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %iv.2 60 %l.0 = load i32, ptr %ptr.iv.2, align 4 61 call void @use(i32 %l.0) 62 %add = add nsw i64 %iv.2, 1 63 %ptr.iv.2.add.1 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %add 64 store i32 10, ptr %ptr.iv.2.add.1, align 4 65 %l.1 = load i32, ptr %ptr.iv.2, align 4 66 call void @use(i32 %l.1) 67 %iv.2.next = add nsw i64 %iv.2, 1 68 %c.2 = icmp slt i64 %iv.2.next, 100 69 br i1 %c.2, label %loop.2, label %exit 70 71exit: 72 ret void 73} 74 75; Test cases with a loop carried dependence in %loop.2, where both %l.0 and 76; %l.1 read the value stored by the previous iteration. Hence, the store in 77; %loop.2 is not dead at the end of the function or after the call to lifetime.end(). 78define void @test.2() { 79; CHECK-LABEL: @test.2( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: [[A:%.*]] = alloca [100 x i32], align 4 82; CHECK-NEXT: br label [[LOOP_1:%.*]] 83; CHECK: loop.1: 84; CHECK-NEXT: [[IV_1:%.*]] = phi i64 [ 1, [[ENTRY:%.*]] ], [ [[IV_1_NEXT:%.*]], [[LOOP_1]] ] 85; CHECK-NEXT: [[ARRAYIDX1:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[IV_1]] 86; CHECK-NEXT: store i32 0, ptr [[ARRAYIDX1]], align 4 87; CHECK-NEXT: [[IV_1_NEXT]] = add nsw i64 [[IV_1]], 1 88; CHECK-NEXT: [[C_1:%.*]] = icmp slt i64 [[IV_1_NEXT]], 100 89; CHECK-NEXT: br i1 [[C_1]], label [[LOOP_1]], label [[LOOP_2_PH:%.*]] 90; CHECK: loop.2.ph: 91; CHECK-NEXT: br label [[LOOP_2:%.*]] 92; CHECK: loop.2: 93; CHECK-NEXT: [[IV_2:%.*]] = phi i64 [ [[IV_2_NEXT:%.*]], [[LOOP_2]] ], [ 0, [[LOOP_2_PH]] ] 94; CHECK-NEXT: [[PTR_IV_2:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[IV_2]] 95; CHECK-NEXT: [[L_0:%.*]] = load i32, ptr [[PTR_IV_2]], align 4 96; CHECK-NEXT: call void @use(i32 [[L_0]]) 97; CHECK-NEXT: [[ADD:%.*]] = add nsw i64 [[IV_2]], 1 98; CHECK-NEXT: [[PTR_IV_2_ADD_1:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[ADD]] 99; CHECK-NEXT: store i32 10, ptr [[PTR_IV_2_ADD_1]], align 4 100; CHECK-NEXT: [[L_1:%.*]] = load i32, ptr [[PTR_IV_2]], align 4 101; CHECK-NEXT: call void @use(i32 [[L_1]]) 102; CHECK-NEXT: [[IV_2_NEXT]] = add nsw i64 [[IV_2]], 1 103; CHECK-NEXT: [[C_2:%.*]] = icmp slt i64 [[IV_2_NEXT]], 100 104; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_2]], label [[EXIT:%.*]] 105; CHECK: exit: 106; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 400, ptr nonnull [[A]]) 107; CHECK-NEXT: ret void 108; 109entry: 110 %A = alloca [100 x i32], align 4 111 br label %loop.1 112 113loop.1: 114 %iv.1 = phi i64 [ 1, %entry ], [ %iv.1.next, %loop.1 ] 115 %arrayidx1 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %iv.1 116 store i32 0, ptr %arrayidx1, align 4 117 %iv.1.next = add nsw i64 %iv.1, 1 118 %c.1 = icmp slt i64 %iv.1.next, 100 119 br i1 %c.1, label %loop.1, label %loop.2.ph 120 121loop.2.ph: 122 br label %loop.2 123 124loop.2: 125 %iv.2 = phi i64 [ %iv.2.next, %loop.2 ], [ 0, %loop.2.ph ] 126 %ptr.iv.2 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %iv.2 127 %l.0 = load i32, ptr %ptr.iv.2, align 4 128 call void @use(i32 %l.0) 129 %add = add nsw i64 %iv.2, 1 130 %ptr.iv.2.add.1 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %add 131 store i32 10, ptr %ptr.iv.2.add.1, align 4 132 %l.1 = load i32, ptr %ptr.iv.2, align 4 133 call void @use(i32 %l.1) 134 %iv.2.next = add nsw i64 %iv.2, 1 135 %c.2 = icmp slt i64 %iv.2.next, 100 136 br i1 %c.2, label %loop.2, label %exit 137 138exit: 139 call void @llvm.lifetime.end.p0(i64 400, ptr nonnull %A) #5 140 ret void 141} 142 143declare void @llvm.lifetime.end.p0(i64 immarg, ptr nocapture) 144 145; Make sure `store i32 10, ptr %ptr.2` in %cond.store is not removed. The 146; stored value may be read by `%use = load i32, ptr %ptr.1` in a future 147; iteration. 148define void@test.3() { 149; CHECK-LABEL: @test.3( 150; CHECK-NEXT: entry: 151; CHECK-NEXT: [[NODESTACK:%.*]] = alloca [12 x i32], align 4 152; CHECK-NEXT: [[C_1:%.*]] = call i1 @cond(i32 1) 153; CHECK-NEXT: br i1 [[C_1]], label [[CLEANUP:%.*]], label [[LOOP_HEADER:%.*]] 154; CHECK: loop.header: 155; CHECK-NEXT: [[DEPTH_1:%.*]] = phi i32 [ [[DEPTH_1_BE:%.*]], [[LOOP_LATCH:%.*]] ], [ 3, [[ENTRY:%.*]] ] 156; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEPTH_1]], 0 157; CHECK-NEXT: br i1 [[CMP]], label [[COND_READ:%.*]], label [[COND_STORE:%.*]] 158; CHECK: cond.read: 159; CHECK-NEXT: [[SUB:%.*]] = add nsw i32 [[DEPTH_1]], -3 160; CHECK-NEXT: [[PTR_1:%.*]] = getelementptr inbounds [12 x i32], ptr [[NODESTACK]], i32 0, i32 [[SUB]] 161; CHECK-NEXT: [[USE:%.*]] = load i32, ptr [[PTR_1]], align 4 162; CHECK-NEXT: [[C_2:%.*]] = call i1 @cond(i32 [[USE]]) 163; CHECK-NEXT: br i1 [[C_2]], label [[LOOP_LATCH]], label [[COND_STORE]] 164; CHECK: cond.store: 165; CHECK-NEXT: [[PTR_2:%.*]] = getelementptr inbounds [12 x i32], ptr [[NODESTACK]], i32 0, i32 [[DEPTH_1]] 166; CHECK-NEXT: store i32 10, ptr [[PTR_2]], align 4 167; CHECK-NEXT: [[INC:%.*]] = add nsw i32 [[DEPTH_1]], 1 168; CHECK-NEXT: [[C_3:%.*]] = call i1 @cond(i32 20) 169; CHECK-NEXT: br i1 [[C_3]], label [[CLEANUP]], label [[LOOP_LATCH]] 170; CHECK: loop.latch: 171; CHECK-NEXT: [[DEPTH_1_BE]] = phi i32 [ [[SUB]], [[COND_READ]] ], [ [[INC]], [[COND_STORE]] ] 172; CHECK-NEXT: br label [[LOOP_HEADER]] 173; CHECK: cleanup: 174; CHECK-NEXT: call void @llvm.lifetime.end.p0(i64 48, ptr nonnull [[NODESTACK]]) 175; CHECK-NEXT: ret void 176; 177entry: 178 %nodeStack = alloca [12 x i32], align 4 179 %c.1 = call i1 @cond(i32 1) 180 br i1 %c.1, label %cleanup, label %loop.header 181 182loop.header: ; preds = %entry, %while.cond.backedge 183 %depth.1 = phi i32 [ %depth.1.be, %loop.latch ], [ 3, %entry ] 184 %cmp = icmp sgt i32 %depth.1, 0 185 br i1 %cmp, label %cond.read, label %cond.store 186 187cond.read: ; preds = %while.cond 188 %sub = add nsw i32 %depth.1, -3 189 %ptr.1 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %sub 190 %use = load i32, ptr %ptr.1, align 4 191 %c.2 = call i1 @cond(i32 %use) 192 br i1 %c.2, label %loop.latch, label %cond.store 193 194cond.store: 195 %ptr.2 = getelementptr inbounds [12 x i32], ptr %nodeStack, i32 0, i32 %depth.1 196 store i32 10, ptr %ptr.2, align 4 197 %inc = add nsw i32 %depth.1, 1 198 %c.3 = call i1 @cond(i32 20) 199 br i1 %c.3, label %cleanup, label %loop.latch 200 201loop.latch: 202 %depth.1.be = phi i32 [ %sub, %cond.read ], [ %inc, %cond.store ] 203 br label %loop.header 204 205cleanup: ; preds = %while.body, %while.end, %entry 206 call void @llvm.lifetime.end.p0(i64 48, ptr nonnull %nodeStack) #3 207 ret void 208} 209 210define void @store_to_invariant_loc() { 211; CHECK-LABEL: @store_to_invariant_loc( 212; CHECK-NEXT: entry: 213; CHECK-NEXT: [[A:%.*]] = alloca [100 x i32], align 4 214; CHECK-NEXT: [[PTR_20:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 20 215; CHECK-NEXT: br label [[LOOP:%.*]] 216; CHECK: loop: 217; CHECK-NEXT: [[IV:%.*]] = phi i64 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 218; CHECK-NEXT: [[PTR_IV:%.*]] = getelementptr inbounds [100 x i32], ptr [[A]], i64 0, i64 [[IV]] 219; CHECK-NEXT: [[L_0:%.*]] = load i32, ptr [[PTR_IV]], align 4 220; CHECK-NEXT: call void @use(i32 [[L_0]]) 221; CHECK-NEXT: store i32 10, ptr [[PTR_20]], align 4 222; CHECK-NEXT: [[IV_NEXT]] = add nsw i64 [[IV]], 1 223; CHECK-NEXT: [[C:%.*]] = icmp slt i64 [[IV_NEXT]], 100 224; CHECK-NEXT: br i1 [[C]], label [[LOOP]], label [[EXIT:%.*]] 225; CHECK: exit: 226; CHECK-NEXT: ret void 227; 228entry: 229 %A = alloca [100 x i32], align 4 230 %ptr.20 = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 20 231 br label %loop 232 233loop: 234 %iv = phi i64 [ %iv.next, %loop ], [ 0, %entry ] 235 %ptr.iv = getelementptr inbounds [100 x i32], ptr %A, i64 0, i64 %iv 236 %l.0 = load i32, ptr %ptr.iv, align 4 237 call void @use(i32 %l.0) 238 store i32 10, ptr %ptr.20, align 4 239 %iv.next = add nsw i64 %iv, 1 240 %c = icmp slt i64 %iv.next, 100 241 br i1 %c, label %loop , label %exit 242 243exit: 244 ret void 245} 246 247declare i1 @cond(i32) 248