1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 2 2; RUN: opt -passes='loop-mssa(licm)' -S < %s | FileCheck %s --check-prefixes=CHECK,NOT_CONSTRAINED 3; RUN: opt -passes='loop-mssa(licm)' -licm-max-num-int-reassociations=1 -S < %s | FileCheck %s --check-prefixes=CHECK,CONSTRAINED 4 5; 6; A simple loop: 7; 8; int j; 9; 10; for (j = 0; j <= i; j++) 11; cells[j] = d1 * cells[j + 1] * delta; 12; 13; ...should be transformed by the LICM pass into this: 14; 15; int j; 16; const uint64_t d1d = d1 * delta; 17; 18; for (j = 0; j <= i; j++) 19; cells[j] = d1d * cells[j + 1]; 20; 21 22define void @innermost_loop_1d_shouldhoist(i32 %i, i64 %d1, i64 %delta, ptr %cells) { 23; CHECK-LABEL: define void @innermost_loop_1d_shouldhoist 24; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 25; CHECK-NEXT: entry: 26; CHECK-NEXT: [[MUL_1:%.*]] = mul nuw nsw i64 [[DELTA]], [[D1]] 27; CHECK-NEXT: br label [[FOR_COND:%.*]] 28; CHECK: for.cond: 29; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 30; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 31; CHECK-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 32; CHECK: for.body: 33; CHECK-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 34; CHECK-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 35; CHECK-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 36; CHECK-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 37; CHECK-NEXT: [[MUL_2:%.*]] = mul i64 [[MUL_1]], [[CELL_1]] 38; CHECK-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 39; CHECK-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] 40; CHECK-NEXT: store i64 [[MUL_2]], ptr [[ARRAYIDX_J]], align 8 41; CHECK-NEXT: br label [[FOR_COND]] 42; CHECK: for.end: 43; CHECK-NEXT: ret void 44; 45entry: 46 br label %for.cond 47 48for.cond: 49 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 50 %cmp.not = icmp sgt i32 %j, %i 51 br i1 %cmp.not, label %for.end, label %for.body 52 53for.body: 54 %add.j.1 = add nuw nsw i32 %j, 1 55 %idxprom.j.1 = zext i32 %add.j.1 to i64 56 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 57 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 58 %mul.1 = mul nsw nuw i64 %delta, %d1 59 %mul.2 = mul i64 %mul.1, %cell.1 60 %idxprom.j = zext i32 %j to i64 61 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j 62 store i64 %mul.2, ptr %arrayidx.j, align 8 63 br label %for.cond 64 65for.end: 66 ret void 67} 68 69; 70; The following loop will be modified by the 'Reassociate expressions' pass, 71; 72; int j; 73; const uint64_t d1d = d1 * delta; 74; const uint64_t d2d = d2 * delta; 75; 76; for (j = 0; j <= i; j++) 77; cells[j] = d1d * cells[j + 1] + d2d * cells[j]; 78; 79; ...into this: 80; 81; int j; 82; 83; for (j = 0; j <= i; j++) 84; cells[j] = (d1 * cells[j + 1] + d2 * cells[j]) * delta; 85; 86; We expect the LICM pass to undo this transformation. 87; 88 89define void @innermost_loop_2d(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { 90; NOT_CONSTRAINED-LABEL: define void @innermost_loop_2d 91; NOT_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 92; NOT_CONSTRAINED-NEXT: entry: 93; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D1]], [[DELTA]] 94; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D2]], [[DELTA]] 95; NOT_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 96; NOT_CONSTRAINED: for.cond: 97; NOT_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 98; NOT_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 99; NOT_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 100; NOT_CONSTRAINED: for.body: 101; NOT_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 102; NOT_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 103; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 104; NOT_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 105; NOT_CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL]] 106; NOT_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 107; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] 108; NOT_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 109; NOT_CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL1]] 110; NOT_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] 111; NOT_CONSTRAINED-NEXT: store i64 [[REASS_ADD]], ptr [[ARRAYIDX_J]], align 8 112; NOT_CONSTRAINED-NEXT: br label [[FOR_COND]] 113; NOT_CONSTRAINED: for.end: 114; NOT_CONSTRAINED-NEXT: ret void 115; 116; CONSTRAINED-LABEL: define void @innermost_loop_2d 117; CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 118; CONSTRAINED-NEXT: entry: 119; CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 120; CONSTRAINED: for.cond: 121; CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 122; CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 123; CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 124; CONSTRAINED: for.body: 125; CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 126; CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 127; CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 128; CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 129; CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] 130; CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 131; CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] 132; CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 133; CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul nuw nsw i64 [[CELL_2]], [[D2]] 134; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add nuw nsw i64 [[MUL_2]], [[MUL_1]] 135; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul i64 [[REASS_ADD]], [[DELTA]] 136; CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 137; CONSTRAINED-NEXT: br label [[FOR_COND]] 138; CONSTRAINED: for.end: 139; CONSTRAINED-NEXT: ret void 140; 141entry: 142 br label %for.cond 143 144for.cond: 145 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 146 %cmp.not = icmp sgt i32 %j, %i 147 br i1 %cmp.not, label %for.end, label %for.body 148 149for.body: 150 %add.j.1 = add nuw nsw i32 %j, 1 151 %idxprom.j.1 = zext i32 %add.j.1 to i64 152 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 153 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 154 %mul.1 = mul i64 %cell.1, %d1 155 %idxprom.j = zext i32 %j to i64 156 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j 157 %cell.2 = load i64, ptr %arrayidx.j, align 8 158 %mul.2 = mul nsw nuw i64 %cell.2, %d2 159 %reass.add = add nsw nuw i64 %mul.2, %mul.1 160 %reass.mul = mul i64 %reass.add, %delta 161 store i64 %reass.mul, ptr %arrayidx.j, align 8 162 br label %for.cond 163 164for.end: 165 ret void 166} 167 168; 169; The following loop will be modified by the 'Reassociate expressions' pass, 170; 171; int j; 172; const uint64_t d1d = d1 * delta; 173; const uint64_t d2d = d2 * delta; 174; const uint64_t d3d = d3 * delta; 175; 176; for (j = 0; j <= i; j++) 177; cells[j] = d1d * cells[j + 1] + d2d * cells[j] + d3d * cells[j + 2]; 178; 179; ...into this: 180; 181; int j; 182; 183; for (j = 0; j <= i; j++) 184; cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + d3 * cells[j + 2]) * delta; 185; 186; We expect the LICM pass to undo this transformation. 187; 188 189 190define void @innermost_loop_3d(i32 %i, i64 %d1, i64 %d2, i64 %d3, i64 %delta, ptr %cells) { 191; NOT_CONSTRAINED-LABEL: define void @innermost_loop_3d 192; NOT_CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 193; NOT_CONSTRAINED-NEXT: entry: 194; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i64 [[D3]], [[DELTA]] 195; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL1:%.*]] = mul i64 [[D1]], [[DELTA]] 196; NOT_CONSTRAINED-NEXT: [[FACTOR_OP_MUL2:%.*]] = mul i64 [[D2]], [[DELTA]] 197; NOT_CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 198; NOT_CONSTRAINED: for.cond: 199; NOT_CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 200; NOT_CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 201; NOT_CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 202; NOT_CONSTRAINED: for.body: 203; NOT_CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 204; NOT_CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 205; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 206; NOT_CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 207; NOT_CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[FACTOR_OP_MUL1]] 208; NOT_CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 209; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] 210; NOT_CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 211; NOT_CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[FACTOR_OP_MUL2]] 212; NOT_CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 213; NOT_CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 214; NOT_CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 215; NOT_CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 216; NOT_CONSTRAINED-NEXT: [[MUL_3:%.*]] = mul i64 [[CELL_3]], [[FACTOR_OP_MUL]] 217; NOT_CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add i64 [[MUL_2]], [[MUL_1]] 218; NOT_CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add i64 [[REASS_ADD]], [[MUL_3]] 219; NOT_CONSTRAINED-NEXT: store i64 [[REASS_ADD1]], ptr [[ARRAYIDX_J_2]], align 8 220; NOT_CONSTRAINED-NEXT: br label [[FOR_COND]] 221; NOT_CONSTRAINED: for.end: 222; NOT_CONSTRAINED-NEXT: ret void 223; 224; CONSTRAINED-LABEL: define void @innermost_loop_3d 225; CONSTRAINED-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[D3:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 226; CONSTRAINED-NEXT: entry: 227; CONSTRAINED-NEXT: br label [[FOR_COND:%.*]] 228; CONSTRAINED: for.cond: 229; CONSTRAINED-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 230; CONSTRAINED-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 231; CONSTRAINED-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 232; CONSTRAINED: for.body: 233; CONSTRAINED-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 234; CONSTRAINED-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 235; CONSTRAINED-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 236; CONSTRAINED-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 237; CONSTRAINED-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] 238; CONSTRAINED-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 239; CONSTRAINED-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] 240; CONSTRAINED-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 241; CONSTRAINED-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_2]], [[D2]] 242; CONSTRAINED-NEXT: [[ADD_J_2:%.*]] = add nuw nsw i32 [[J]], 2 243; CONSTRAINED-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_2]] to i64 244; CONSTRAINED-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 245; CONSTRAINED-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 246; CONSTRAINED-NEXT: [[MUL_3:%.*]] = mul nuw nsw i64 [[CELL_3]], [[D3]] 247; CONSTRAINED-NEXT: [[REASS_ADD:%.*]] = add nuw nsw i64 [[MUL_2]], [[MUL_1]] 248; CONSTRAINED-NEXT: [[REASS_ADD1:%.*]] = add nuw nsw i64 [[REASS_ADD]], [[MUL_3]] 249; CONSTRAINED-NEXT: [[REASS_MUL:%.*]] = mul nuw nsw i64 [[REASS_ADD1]], [[DELTA]] 250; CONSTRAINED-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J_2]], align 8 251; CONSTRAINED-NEXT: br label [[FOR_COND]] 252; CONSTRAINED: for.end: 253; CONSTRAINED-NEXT: ret void 254; 255entry: 256 br label %for.cond 257 258for.cond: 259 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 260 %cmp.not = icmp sgt i32 %j, %i 261 br i1 %cmp.not, label %for.end, label %for.body 262 263for.body: 264 %add.j.1 = add nuw nsw i32 %j, 1 265 %idxprom.j.1 = zext i32 %add.j.1 to i64 266 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 267 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 268 %mul.1 = mul i64 %cell.1, %d1 269 %idxprom.j = zext i32 %j to i64 270 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j 271 %cell.2 = load i64, ptr %arrayidx.j, align 8 272 %mul.2 = mul i64 %cell.2, %d2 273 %add.j.2 = add nuw nsw i32 %j, 2 274 %idxprom.j.2 = zext i32 %add.j.2 to i64 275 %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 276 %cell.3 = load i64, ptr %arrayidx.j.2, align 8 277 %mul.3 = mul nsw nuw i64 %cell.3, %d3 278 %reass.add = add nsw nuw i64 %mul.2, %mul.1 279 %reass.add1 = add nsw nuw i64 %reass.add, %mul.3 280 %reass.mul = mul nsw nuw i64 %reass.add1, %delta 281 store i64 %reass.mul, ptr %arrayidx.j.2, align 8 282 br label %for.cond 283 284for.end: 285 ret void 286} 287 288; 289; The following loop will not be modified by the LICM pass: 290; 291; int j; 292; 293; for (j = 0; j <= i; j++) 294; cells[j] = (d1 * cells[j + 1] + d2 * cells[j] + 295; cells[j] * cells[j + 1]) * delta; 296; 297; This case differs as one of the multiplications involves no invariants. 298; 299 300define void @innermost_loop_3d_reassociated_different(i32 %i, i64 %d1, i64 %d2, i64 %delta, ptr %cells) { 301; CHECK-LABEL: define void @innermost_loop_3d_reassociated_different 302; CHECK-SAME: (i32 [[I:%.*]], i64 [[D1:%.*]], i64 [[D2:%.*]], i64 [[DELTA:%.*]], ptr [[CELLS:%.*]]) { 303; CHECK-NEXT: entry: 304; CHECK-NEXT: br label [[FOR_COND:%.*]] 305; CHECK: for.cond: 306; CHECK-NEXT: [[J:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[ADD_J_1:%.*]], [[FOR_BODY:%.*]] ] 307; CHECK-NEXT: [[CMP_NOT:%.*]] = icmp sgt i32 [[J]], [[I]] 308; CHECK-NEXT: br i1 [[CMP_NOT]], label [[FOR_END:%.*]], label [[FOR_BODY]] 309; CHECK: for.body: 310; CHECK-NEXT: [[ADD_J_1]] = add nuw nsw i32 [[J]], 1 311; CHECK-NEXT: [[IDXPROM_J_1:%.*]] = zext i32 [[ADD_J_1]] to i64 312; CHECK-NEXT: [[ARRAYIDX_J_1:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_1]] 313; CHECK-NEXT: [[CELL_1:%.*]] = load i64, ptr [[ARRAYIDX_J_1]], align 8 314; CHECK-NEXT: [[IDXPROM_J_2:%.*]] = zext i32 [[ADD_J_1]] to i64 315; CHECK-NEXT: [[ARRAYIDX_J_2:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J_2]] 316; CHECK-NEXT: [[CELL_2:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 317; CHECK-NEXT: [[CELL_3:%.*]] = load i64, ptr [[ARRAYIDX_J_2]], align 8 318; CHECK-NEXT: [[IDXPROM_J:%.*]] = zext i32 [[J]] to i64 319; CHECK-NEXT: [[ARRAYIDX_J:%.*]] = getelementptr inbounds i64, ptr [[CELLS]], i64 [[IDXPROM_J]] 320; CHECK-NEXT: [[CELL_4:%.*]] = load i64, ptr [[ARRAYIDX_J]], align 8 321; CHECK-NEXT: [[MUL_1:%.*]] = mul i64 [[CELL_1]], [[D1]] 322; CHECK-NEXT: [[MUL_2:%.*]] = mul i64 [[CELL_4]], [[D2]] 323; CHECK-NEXT: [[EXTRA_MUL:%.*]] = mul i64 [[CELL_3]], [[CELL_2]] 324; CHECK-NEXT: [[REASS_ADD:%.*]] = add i64 [[EXTRA_MUL]], [[MUL_1]] 325; CHECK-NEXT: [[EXTRA_ADD:%.*]] = add i64 [[REASS_ADD]], [[MUL_2]] 326; CHECK-NEXT: [[REASS_MUL:%.*]] = mul i64 [[EXTRA_ADD]], [[DELTA]] 327; CHECK-NEXT: store i64 [[REASS_MUL]], ptr [[ARRAYIDX_J]], align 8 328; CHECK-NEXT: br label [[FOR_COND]] 329; CHECK: for.end: 330; CHECK-NEXT: ret void 331; 332entry: 333 br label %for.cond 334 335for.cond: 336 %j = phi i32 [ 0, %entry ], [ %add.j.1, %for.body ] 337 %cmp.not = icmp sgt i32 %j, %i 338 br i1 %cmp.not, label %for.end, label %for.body 339 340for.body: 341 %add.j.1 = add nuw nsw i32 %j, 1 342 %idxprom.j.1 = zext i32 %add.j.1 to i64 343 %arrayidx.j.1 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.1 344 %cell.1 = load i64, ptr %arrayidx.j.1, align 8 345 %idxprom.j.2 = zext i32 %add.j.1 to i64 346 %arrayidx.j.2 = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j.2 347 %cell.2 = load i64, ptr %arrayidx.j.2, align 8 348 %idxprom.j.3 = zext i32 %add.j.1 to i64 349 %cell.3 = load i64, ptr %arrayidx.j.2, align 8 350 %idxprom.j = zext i32 %j to i64 351 %arrayidx.j = getelementptr inbounds i64, ptr %cells, i64 %idxprom.j 352 %cell.4 = load i64, ptr %arrayidx.j, align 8 353 %mul.1 = mul i64 %cell.1, %d1 354 %mul.2 = mul i64 %cell.4, %d2 355 %extra.mul = mul i64 %cell.3, %cell.2 356 %reass.add = add i64 %extra.mul, %mul.1 357 %extra.add = add i64 %reass.add, %mul.2 358 %reass.mul = mul i64 %extra.add, %delta 359 store i64 %reass.mul, ptr %arrayidx.j, align 8 360 br label %for.cond 361 362for.end: 363 ret void 364} 365 366; Make sure we drop poison flags on the mul in the loop. 367define i32 @pr85457(i32 %x, i32 %y) { 368; CHECK-LABEL: define i32 @pr85457 369; CHECK-SAME: (i32 [[X:%.*]], i32 [[Y:%.*]]) { 370; CHECK-NEXT: entry: 371; CHECK-NEXT: [[FACTOR_OP_MUL:%.*]] = mul i32 [[X]], [[Y]] 372; CHECK-NEXT: br label [[LOOP:%.*]] 373; CHECK: loop: 374; CHECK-NEXT: [[IV:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ [[IV_NEXT:%.*]], [[LOOP]] ] 375; CHECK-NEXT: [[IV_NEXT]] = add nuw nsw i32 [[IV]], 1 376; CHECK-NEXT: [[MUL0:%.*]] = mul i32 [[FACTOR_OP_MUL]], [[IV]] 377; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[MUL0]], 1 378; CHECK-NEXT: br i1 [[CMP]], label [[EXIT:%.*]], label [[LOOP]] 379; CHECK: exit: 380; CHECK-NEXT: ret i32 0 381; 382entry: 383 br label %loop 384 385loop: 386 %iv = phi i32 [ 1, %entry ], [ %iv.next, %loop ] 387 %iv.next = add nuw nsw i32 %iv, 1 388 %mul0 = mul nuw nsw i32 %x, %iv 389 %mul1 = mul nuw i32 %mul0, %y 390 %cmp = icmp slt i32 %mul1, 1 391 br i1 %cmp, label %exit, label %loop 392 393exit: 394 ret i32 0 395} 396