1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -basic-aa -loop-interchange -verify-dom-info -verify-loop-info -verify-scev -verify-loop-lcssa -S | FileCheck %s 3 4target triple = "powerpc64le-unknown-linux-gnu" 5@b = common dso_local local_unnamed_addr global [200 x [200 x i32]] zeroinitializer, align 4 6@a = common dso_local local_unnamed_addr global i32 0, align 4 7 8;; int a, c, d, e; 9;; int b[200][200]; 10;; void fn1() { 11;; for (c = 0; c < 100; c++) { 12;; for (d = 5, e = 5; d > 0, e > 0; d--, e--) 13;; a |= b[d][c + 9]; 14;; } 15;; } 16; 17; There are multiple inner loop indvars and only one 18; of them is used in the loop exit condition at the 19; inner loop latch. 20; 21define void @test1() { 22; CHECK-LABEL: @test1( 23; CHECK-NEXT: entry: 24; CHECK-NEXT: [[A:%.*]] = load i32, i32* @a, align 4 25; CHECK-NEXT: br label [[FOR_BODY3_PREHEADER:%.*]] 26; CHECK: for.body.preheader: 27; CHECK-NEXT: br label [[FOR_BODY:%.*]] 28; CHECK: for.body: 29; CHECK-NEXT: [[INDVARS_OUTER:%.*]] = phi i64 [ [[INDVARS_OUTER_NEXT:%.*]], [[FOR_INC7:%.*]] ], [ 0, [[FOR_BODY_PREHEADER:%.*]] ] 30; CHECK-NEXT: [[OR_REDUCTION_INNER:%.*]] = phi i32 [ [[OR:%.*]], [[FOR_INC7]] ], [ [[OR_REDUCTION_OUTER:%.*]], [[FOR_BODY_PREHEADER]] ] 31; CHECK-NEXT: [[INDEX:%.*]] = add nsw i64 [[INDVARS_OUTER]], 9 32; CHECK-NEXT: br label [[FOR_BODY3_SPLIT1:%.*]] 33; CHECK: for.body3.preheader: 34; CHECK-NEXT: br label [[FOR_BODY3:%.*]] 35; CHECK: for.body3: 36; CHECK-NEXT: [[INDVAR0:%.*]] = phi i64 [ [[TMP0:%.*]], [[FOR_BODY3_SPLIT:%.*]] ], [ 5, [[FOR_BODY3_PREHEADER]] ] 37; CHECK-NEXT: [[INDVAR1:%.*]] = phi i32 [ [[TMP1:%.*]], [[FOR_BODY3_SPLIT]] ], [ 5, [[FOR_BODY3_PREHEADER]] ] 38; CHECK-NEXT: [[OR_REDUCTION_OUTER]] = phi i32 [ [[OR_LCSSA:%.*]], [[FOR_BODY3_SPLIT]] ], [ [[A]], [[FOR_BODY3_PREHEADER]] ] 39; CHECK-NEXT: br label [[FOR_BODY_PREHEADER]] 40; CHECK: for.body3.split1: 41; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [200 x [200 x i32]], [200 x [200 x i32]]* @b, i64 0, i64 [[INDVAR0]], i64 [[INDEX]] 42; CHECK-NEXT: [[LOAD_VAL:%.*]] = load i32, i32* [[ARRAYIDX5]], align 4 43; CHECK-NEXT: [[OR]] = or i32 [[OR_REDUCTION_INNER]], [[LOAD_VAL]] 44; CHECK-NEXT: [[INDVAR0_NEXT:%.*]] = add nsw i64 [[INDVAR0]], -1 45; CHECK-NEXT: [[INDVAR1_NEXT:%.*]] = add nsw i32 [[INDVAR1]], -1 46; CHECK-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[INDVAR1_NEXT]], 0 47; CHECK-NEXT: br label [[FOR_INC7]] 48; CHECK: for.body3.split: 49; CHECK-NEXT: [[OR_LCSSA]] = phi i32 [ [[OR]], [[FOR_INC7]] ] 50; CHECK-NEXT: [[TMP0]] = add nsw i64 [[INDVAR0]], -1 51; CHECK-NEXT: [[TMP1]] = add nsw i32 [[INDVAR1]], -1 52; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], 0 53; CHECK-NEXT: br i1 [[TMP2]], label [[FOR_COND_FOR_END8_CRIT_EDGE:%.*]], label [[FOR_BODY3]] 54; CHECK: for.inc7: 55; CHECK-NEXT: [[INDVARS_OUTER_NEXT]] = add nsw i64 [[INDVARS_OUTER]], 1 56; CHECK-NEXT: [[INDVARS_OUTER_NEXT_TRUNC:%.*]] = trunc i64 [[INDVARS_OUTER_NEXT]] to i32 57; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[INDVARS_OUTER_NEXT_TRUNC]], 100 58; CHECK-NEXT: br i1 [[TOBOOL]], label [[FOR_BODY3_SPLIT]], label [[FOR_BODY]] 59; CHECK: for.cond.for.end8_crit_edge: 60; CHECK-NEXT: [[OR_LCSSA_LCSSA:%.*]] = phi i32 [ [[OR_LCSSA]], [[FOR_BODY3_SPLIT]] ] 61; CHECK-NEXT: store i32 [[OR_LCSSA_LCSSA]], i32* @a, align 4 62; CHECK-NEXT: br label [[FOR_END8:%.*]] 63; CHECK: for.end8: 64; CHECK-NEXT: ret void 65; 66 67entry: 68 %a = load i32, i32* @a 69 br label %for.body 70 71for.body: ; preds = %for.body.lr.ph, %for.inc7 72 %indvars.outer = phi i64 [ 0, %entry ], [ %indvars.outer.next, %for.inc7 ] 73 %or.reduction.outer = phi i32 [ %a, %entry ], [ %or.lcssa, %for.inc7 ] 74 %index = add nsw i64 %indvars.outer, 9 75 br label %for.body3 76 77for.body3: ; preds = %for.body, %for.body3 78 %or.reduction.inner = phi i32 [ %or.reduction.outer, %for.body ], [ %or, %for.body3 ] 79 %indvar0 = phi i64 [ 5, %for.body ], [ %indvar0.next, %for.body3 ] 80 %indvar1 = phi i32 [ 5, %for.body ], [ %indvar1.next, %for.body3 ] 81 %arrayidx5 = getelementptr inbounds [200 x [200 x i32]], [200 x [200 x i32]]* @b, i64 0, i64 %indvar0, i64 %index 82 %load.val = load i32, i32* %arrayidx5, align 4 83 %or = or i32 %or.reduction.inner, %load.val 84 %indvar0.next = add nsw i64 %indvar0, -1 85 %indvar1.next = add nsw i32 %indvar1, -1 86 %tobool2 = icmp eq i32 %indvar1.next, 0 87 br i1 %tobool2, label %for.inc7, label %for.body3 88 89for.inc7: ; preds = %for.body3 90 %or.lcssa = phi i32 [ %or, %for.body3 ] 91 %indvars.outer.next = add nsw i64 %indvars.outer, 1 92 %indvars.outer.next.trunc = trunc i64 %indvars.outer.next to i32 93 %tobool = icmp eq i32 %indvars.outer.next.trunc, 100 94 br i1 %tobool, label %for.cond.for.end8_crit_edge, label %for.body 95 96for.cond.for.end8_crit_edge: ; preds = %for.inc7 97 %or.lcssa.lcssa = phi i32 [ %or.lcssa, %for.inc7 ] 98 store i32 %or.lcssa.lcssa, i32* @a 99 br label %for.end8 100 101for.end8: ; preds = %for.cond.for.end8_crit_edge, %entry 102 ret void 103} 104 105;; int a, c, d, e; 106;; int b[200][200]; 107;; void fn1() { 108;; for (c = 0 ; c < 100; c++) { 109;; for (d = 5, e = 6; d + e > 0; d--, e = e - 2) 110;; a |= b[d][c + 9]; 111;; } 112;; } 113; 114; All inner loop indvars are used in the inner latch. 115; 116define void @test2() { 117; CHECK-LABEL: @test2( 118; CHECK-NEXT: entry: 119; CHECK-NEXT: [[A:%.*]] = load i32, i32* @a, align 4 120; CHECK-NEXT: br label [[FOR_BODY3_PREHEADER:%.*]] 121; CHECK: for.body.preheader: 122; CHECK-NEXT: br label [[FOR_BODY:%.*]] 123; CHECK: for.body: 124; CHECK-NEXT: [[INDVARS_OUTER:%.*]] = phi i64 [ [[INDVARS_OUTER_NEXT:%.*]], [[FOR_INC7:%.*]] ], [ 0, [[FOR_BODY_PREHEADER:%.*]] ] 125; CHECK-NEXT: [[OR_REDUCTION_INNER:%.*]] = phi i32 [ [[OR:%.*]], [[FOR_INC7]] ], [ [[OR_REDUCTION_OUTER:%.*]], [[FOR_BODY_PREHEADER]] ] 126; CHECK-NEXT: [[INDEX:%.*]] = add nsw i64 [[INDVARS_OUTER]], 9 127; CHECK-NEXT: br label [[FOR_BODY3_SPLIT1:%.*]] 128; CHECK: for.body3.preheader: 129; CHECK-NEXT: br label [[FOR_BODY3:%.*]] 130; CHECK: for.body3: 131; CHECK-NEXT: [[INDVAR0:%.*]] = phi i64 [ [[TMP2:%.*]], [[FOR_BODY3_SPLIT:%.*]] ], [ 5, [[FOR_BODY3_PREHEADER]] ] 132; CHECK-NEXT: [[INDVAR1:%.*]] = phi i32 [ [[TMP0:%.*]], [[FOR_BODY3_SPLIT]] ], [ 6, [[FOR_BODY3_PREHEADER]] ] 133; CHECK-NEXT: [[OR_REDUCTION_OUTER]] = phi i32 [ [[OR_LCSSA:%.*]], [[FOR_BODY3_SPLIT]] ], [ [[A]], [[FOR_BODY3_PREHEADER]] ] 134; CHECK-NEXT: br label [[FOR_BODY_PREHEADER]] 135; CHECK: for.body3.split1: 136; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [200 x [200 x i32]], [200 x [200 x i32]]* @b, i64 0, i64 [[INDVAR0]], i64 [[INDEX]] 137; CHECK-NEXT: [[LOAD_VAL:%.*]] = load i32, i32* [[ARRAYIDX5]], align 4 138; CHECK-NEXT: [[OR]] = or i32 [[OR_REDUCTION_INNER]], [[LOAD_VAL]] 139; CHECK-NEXT: [[INDVAR0_NEXT:%.*]] = add nsw i64 [[INDVAR0]], -1 140; CHECK-NEXT: [[INDVAR1_NEXT:%.*]] = add nsw i32 [[INDVAR1]], -2 141; CHECK-NEXT: [[INDVAR1_NEXT_EXT:%.*]] = sext i32 [[INDVAR1_NEXT]] to i64 142; CHECK-NEXT: [[INDVARS_ADD:%.*]] = add nsw i64 [[INDVAR0_NEXT]], [[INDVAR1_NEXT_EXT]] 143; CHECK-NEXT: [[TOBOOL2:%.*]] = icmp eq i64 [[INDVARS_ADD]], 0 144; CHECK-NEXT: br label [[FOR_INC7]] 145; CHECK: for.body3.split: 146; CHECK-NEXT: [[OR_LCSSA]] = phi i32 [ [[OR]], [[FOR_INC7]] ] 147; CHECK-NEXT: [[TMP0]] = add nsw i32 [[INDVAR1]], -2 148; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[TMP0]] to i64 149; CHECK-NEXT: [[TMP2]] = add nsw i64 [[INDVAR0]], -1 150; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[TMP2]], [[TMP1]] 151; CHECK-NEXT: [[TMP4:%.*]] = icmp eq i64 [[TMP3]], 0 152; CHECK-NEXT: br i1 [[TMP4]], label [[FOR_COND_FOR_END8_CRIT_EDGE:%.*]], label [[FOR_BODY3]] 153; CHECK: for.inc7: 154; CHECK-NEXT: [[INDVARS_OUTER_NEXT]] = add nsw i64 [[INDVARS_OUTER]], 1 155; CHECK-NEXT: [[INDVARS_OUTER_NEXT_TRUNC:%.*]] = trunc i64 [[INDVARS_OUTER_NEXT]] to i32 156; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[INDVARS_OUTER_NEXT_TRUNC]], 100 157; CHECK-NEXT: br i1 [[TOBOOL]], label [[FOR_BODY3_SPLIT]], label [[FOR_BODY]] 158; CHECK: for.cond.for.end8_crit_edge: 159; CHECK-NEXT: [[OR_LCSSA_LCSSA:%.*]] = phi i32 [ [[OR_LCSSA]], [[FOR_BODY3_SPLIT]] ] 160; CHECK-NEXT: store i32 [[OR_LCSSA_LCSSA]], i32* @a, align 4 161; CHECK-NEXT: br label [[FOR_END8:%.*]] 162; CHECK: for.end8: 163; CHECK-NEXT: ret void 164; 165entry: 166 %a = load i32, i32* @a 167 br label %for.body 168 169for.body: ; preds = %for.body.lr.ph, %for.inc7 170 %indvars.outer = phi i64 [ 0, %entry ], [ %indvars.outer.next, %for.inc7 ] 171 %or.reduction.outer = phi i32 [ %a, %entry ], [ %or.lcssa, %for.inc7 ] 172 %index = add nsw i64 %indvars.outer, 9 173 br label %for.body3 174 175for.body3: ; preds = %for.body, %for.body3 176 %or.reduction.inner = phi i32 [ %or.reduction.outer, %for.body ], [ %or, %for.body3 ] 177 %indvar0 = phi i64 [ 5, %for.body ], [ %indvar0.next, %for.body3 ] 178 %indvar1 = phi i32 [ 6, %for.body ], [ %indvar1.next, %for.body3 ] 179 %arrayidx5 = getelementptr inbounds [200 x [200 x i32]], [200 x [200 x i32]]* @b, i64 0, i64 %indvar0, i64 %index 180 %load.val = load i32, i32* %arrayidx5, align 4 181 %or = or i32 %or.reduction.inner, %load.val 182 %indvar0.next = add nsw i64 %indvar0, -1 183 %indvar1.next = add nsw i32 %indvar1, -2 184 %indvar1.next.ext = sext i32 %indvar1.next to i64 185 %indvars.add = add nsw i64 %indvar0.next, %indvar1.next.ext 186 %tobool2 = icmp eq i64 %indvars.add, 0 187 br i1 %tobool2, label %for.inc7, label %for.body3 188 189for.inc7: ; preds = %for.body3 190 %or.lcssa = phi i32 [ %or, %for.body3 ] 191 %indvars.outer.next = add nsw i64 %indvars.outer, 1 192 %indvars.outer.next.trunc = trunc i64 %indvars.outer.next to i32 193 %tobool = icmp eq i32 %indvars.outer.next.trunc, 100 194 br i1 %tobool, label %for.cond.for.end8_crit_edge, label %for.body 195 196for.cond.for.end8_crit_edge: ; preds = %for.inc7 197 %or.lcssa.lcssa = phi i32 [ %or.lcssa, %for.inc7 ] 198 store i32 %or.lcssa.lcssa, i32* @a 199 br label %for.end8 200 201for.end8: ; preds = %for.cond.for.end8_crit_edge, %entry 202 ret void 203} 204 205;; int a, c, d, e; 206;; int b[200][200]; 207;; void fn1() { 208;; for (c = 0 ; c < 100; c++) { 209;; d = 5; 210;; e = 49; 211;; for (; d != e; d++, e--) 212;; a |= b[d][c + 9]; 213;; } 214;; } 215; 216; Two inner loop indvars are involved in the inner loop exit 217; condition as LHS and RHS. 218define void @test3() { 219; CHECK-LABEL: @test3( 220; CHECK-NEXT: entry: 221; CHECK-NEXT: [[A:%.*]] = load i32, i32* @a, align 4 222; CHECK-NEXT: br label [[FOR_BODY3_PREHEADER:%.*]] 223; CHECK: for.body.preheader: 224; CHECK-NEXT: br label [[FOR_BODY:%.*]] 225; CHECK: for.body: 226; CHECK-NEXT: [[INDVARS_OUTER:%.*]] = phi i64 [ [[INDVARS_OUTER_NEXT:%.*]], [[FOR_INC7:%.*]] ], [ 0, [[FOR_BODY_PREHEADER:%.*]] ] 227; CHECK-NEXT: [[OR_REDUCTION_INNER:%.*]] = phi i32 [ [[OR:%.*]], [[FOR_INC7]] ], [ [[OR_REDUCTION_OUTER:%.*]], [[FOR_BODY_PREHEADER]] ] 228; CHECK-NEXT: [[INDEX:%.*]] = add nsw i64 [[INDVARS_OUTER]], 9 229; CHECK-NEXT: br label [[FOR_BODY3_SPLIT1:%.*]] 230; CHECK: for.body3.preheader: 231; CHECK-NEXT: br label [[FOR_BODY3:%.*]] 232; CHECK: for.body3: 233; CHECK-NEXT: [[INDVAR0:%.*]] = phi i32 [ [[TMP1:%.*]], [[FOR_BODY3_SPLIT:%.*]] ], [ 5, [[FOR_BODY3_PREHEADER]] ] 234; CHECK-NEXT: [[INDVAR1:%.*]] = phi i32 [ [[TMP0:%.*]], [[FOR_BODY3_SPLIT]] ], [ 49, [[FOR_BODY3_PREHEADER]] ] 235; CHECK-NEXT: [[OR_REDUCTION_OUTER]] = phi i32 [ [[OR_LCSSA:%.*]], [[FOR_BODY3_SPLIT]] ], [ [[A]], [[FOR_BODY3_PREHEADER]] ] 236; CHECK-NEXT: br label [[FOR_BODY_PREHEADER]] 237; CHECK: for.body3.split1: 238; CHECK-NEXT: [[ARRAYIDX5:%.*]] = getelementptr inbounds [200 x [200 x i32]], [200 x [200 x i32]]* @b, i64 0, i32 [[INDVAR0]], i64 [[INDEX]] 239; CHECK-NEXT: [[LOAD_VAL:%.*]] = load i32, i32* [[ARRAYIDX5]], align 4 240; CHECK-NEXT: [[OR]] = or i32 [[OR_REDUCTION_INNER]], [[LOAD_VAL]] 241; CHECK-NEXT: [[INDVAR0_NEXT:%.*]] = add nsw i32 [[INDVAR0]], 1 242; CHECK-NEXT: [[INDVAR1_NEXT:%.*]] = add nsw i32 [[INDVAR1]], -1 243; CHECK-NEXT: [[TOBOOL2:%.*]] = icmp eq i32 [[INDVAR0_NEXT]], [[INDVAR1_NEXT]] 244; CHECK-NEXT: br label [[FOR_INC7]] 245; CHECK: for.body3.split: 246; CHECK-NEXT: [[OR_LCSSA]] = phi i32 [ [[OR]], [[FOR_INC7]] ] 247; CHECK-NEXT: [[TMP0]] = add nsw i32 [[INDVAR1]], -1 248; CHECK-NEXT: [[TMP1]] = add nsw i32 [[INDVAR0]], 1 249; CHECK-NEXT: [[TMP2:%.*]] = icmp eq i32 [[TMP1]], [[TMP0]] 250; CHECK-NEXT: br i1 [[TMP2]], label [[FOR_COND_FOR_END8_CRIT_EDGE:%.*]], label [[FOR_BODY3]] 251; CHECK: for.inc7: 252; CHECK-NEXT: [[INDVARS_OUTER_NEXT]] = add nsw i64 [[INDVARS_OUTER]], 1 253; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i64 [[INDVARS_OUTER_NEXT]], 100 254; CHECK-NEXT: br i1 [[TOBOOL]], label [[FOR_BODY3_SPLIT]], label [[FOR_BODY]] 255; CHECK: for.cond.for.end8_crit_edge: 256; CHECK-NEXT: [[OR_LCSSA_LCSSA:%.*]] = phi i32 [ [[OR_LCSSA]], [[FOR_BODY3_SPLIT]] ] 257; CHECK-NEXT: store i32 [[OR_LCSSA_LCSSA]], i32* @a, align 4 258; CHECK-NEXT: br label [[FOR_END8:%.*]] 259; CHECK: for.end8: 260; CHECK-NEXT: ret void 261; 262 263entry: 264 %a = load i32, i32* @a 265 br label %for.body 266 267for.body: ; preds = %for.body.lr.ph, %for.inc7 268 %indvars.outer = phi i64 [ 0, %entry ], [ %indvars.outer.next, %for.inc7 ] 269 %or.reduction.outer = phi i32 [ %a, %entry ], [ %or.lcssa, %for.inc7 ] 270 %index = add nsw i64 %indvars.outer, 9 271 br label %for.body3 272 273for.body3: ; preds = %for.body, %for.body3 274 %or.reduction.inner = phi i32 [ %or.reduction.outer, %for.body ], [ %or, %for.body3 ] 275 %indvar0 = phi i32 [ 5, %for.body ], [ %indvar0.next, %for.body3 ] 276 %indvar1 = phi i32 [ 49, %for.body ], [ %indvar1.next, %for.body3 ] 277 %arrayidx5 = getelementptr inbounds [200 x [200 x i32]], [200 x [200 x i32]]* @b, i64 0, i32 %indvar0, i64 %index 278 %load.val = load i32, i32* %arrayidx5, align 4 279 %or = or i32 %or.reduction.inner, %load.val 280 %indvar0.next = add nsw i32 %indvar0, 1 281 %indvar1.next = add nsw i32 %indvar1, -1 282 %tobool2 = icmp eq i32 %indvar0.next, %indvar1.next 283 br i1 %tobool2, label %for.inc7, label %for.body3 284 285for.inc7: ; preds = %for.body3 286 %or.lcssa = phi i32 [ %or, %for.body3 ] 287 %indvars.outer.next = add nsw i64 %indvars.outer, 1 288 %tobool = icmp eq i64 %indvars.outer.next, 100 289 br i1 %tobool, label %for.cond.for.end8_crit_edge, label %for.body 290 291for.cond.for.end8_crit_edge: ; preds = %for.inc7 292 %or.lcssa.lcssa = phi i32 [ %or.lcssa, %for.inc7 ] 293 store i32 %or.lcssa.lcssa, i32* @a 294 br label %for.end8 295 296for.end8: ; preds = %for.cond.for.end8_crit_edge, %entry 297 ret void 298} 299