1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -S -loop-simplify -loop-flatten -loop-flatten-widen-iv=true -verify-loop-info -verify-dom-info -verify-scev -verify | FileCheck %s --check-prefix=CHECK 3; RUN: opt < %s -S -loop-simplify -loop-flatten -loop-flatten-widen-iv=false -verify-loop-info -verify-dom-info -verify-scev -verify | FileCheck %s --check-prefix=DONTWIDEN 4 5target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128" 6 7; DONTWIDEN-NOT: %flatten.tripcount 8; DONTWIDEN-NOT: %flatten.trunciv 9 10; Function Attrs: nounwind 11define void @foo(i32* %A, i32 %N, i32 %M) { 12; CHECK-LABEL: @foo( 13; CHECK-NEXT: entry: 14; CHECK-NEXT: [[CMP17:%.*]] = icmp sgt i32 [[N:%.*]], 0 15; CHECK-NEXT: br i1 [[CMP17]], label [[FOR_COND1_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]] 16; CHECK: for.cond1.preheader.lr.ph: 17; CHECK-NEXT: [[CMP215:%.*]] = icmp sgt i32 [[M:%.*]], 0 18; CHECK-NEXT: br i1 [[CMP215]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND_CLEANUP]] 19; CHECK: for.cond1.preheader.us.preheader: 20; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[M]] to i64 21; CHECK-NEXT: [[TMP1:%.*]] = sext i32 [[N]] to i64 22; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]] 23; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]] 24; CHECK: for.cond1.preheader.us: 25; CHECK-NEXT: [[INDVAR1:%.*]] = phi i64 [ [[INDVAR_NEXT2:%.*]], [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ] 26; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVAR1]] to i32 27; CHECK-NEXT: [[MUL_US:%.*]] = mul nsw i32 [[TMP2]], [[M]] 28; CHECK-NEXT: [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR1]] to i32 29; CHECK-NEXT: br label [[FOR_BODY4_US:%.*]] 30; CHECK: for.body4.us: 31; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US]] ] 32; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i32 33; CHECK-NEXT: [[ADD_US:%.*]] = add nsw i32 [[TMP3]], [[MUL_US]] 34; CHECK-NEXT: [[IDXPROM_US:%.*]] = sext i32 [[FLATTEN_TRUNCIV]] to i64 35; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[IDXPROM_US]] 36; CHECK-NEXT: tail call void @f(i32* [[ARRAYIDX_US]]) 37; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 38; CHECK-NEXT: [[CMP2_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]] 39; CHECK-NEXT: br label [[FOR_COND1_FOR_COND_CLEANUP3_CRIT_EDGE_US]] 40; CHECK: for.cond1.for.cond.cleanup3_crit_edge.us: 41; CHECK-NEXT: [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1 42; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]] 43; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 44; CHECK: for.cond.cleanup.loopexit: 45; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 46; CHECK: for.cond.cleanup: 47; CHECK-NEXT: ret void 48; 49entry: 50 %cmp17 = icmp sgt i32 %N, 0 51 br i1 %cmp17, label %for.cond1.preheader.lr.ph, label %for.cond.cleanup 52 53for.cond1.preheader.lr.ph: 54 %cmp215 = icmp sgt i32 %M, 0 55 br i1 %cmp215, label %for.cond1.preheader.us.preheader, label %for.cond.cleanup 56 57for.cond1.preheader.us.preheader: 58 br label %for.cond1.preheader.us 59 60for.cond1.preheader.us: 61 %i.018.us = phi i32 [ %inc6.us, %for.cond1.for.cond.cleanup3_crit_edge.us ], [ 0, %for.cond1.preheader.us.preheader ] 62 %mul.us = mul nsw i32 %i.018.us, %M 63 br label %for.body4.us 64 65for.body4.us: 66 %j.016.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body4.us ] 67 %add.us = add nsw i32 %j.016.us, %mul.us 68 %idxprom.us = sext i32 %add.us to i64 69 %arrayidx.us = getelementptr inbounds i32, i32* %A, i64 %idxprom.us 70 tail call void @f(i32* %arrayidx.us) #2 71 %inc.us = add nuw nsw i32 %j.016.us, 1 72 %cmp2.us = icmp slt i32 %inc.us, %M 73 br i1 %cmp2.us, label %for.body4.us, label %for.cond1.for.cond.cleanup3_crit_edge.us 74 75for.cond1.for.cond.cleanup3_crit_edge.us: 76 %inc6.us = add nuw nsw i32 %i.018.us, 1 77 %cmp.us = icmp slt i32 %inc6.us, %N 78 br i1 %cmp.us, label %for.cond1.preheader.us, label %for.cond.cleanup 79 80for.cond.cleanup: 81 ret void 82} 83 84define void @zext(i32 %N, i16* nocapture %A, i16 %val) { 85; CHECK-LABEL: @zext( 86; CHECK-NEXT: entry: 87; CHECK-NEXT: [[CMP20_NOT:%.*]] = icmp eq i32 [[N:%.*]], 0 88; CHECK-NEXT: br i1 [[CMP20_NOT]], label [[FOR_END9:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]] 89; CHECK: for.cond1.preheader.us.preheader: 90; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[N]] to i64 91; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[N]] to i64 92; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]] 93; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]] 94; CHECK: for.cond1.preheader.us: 95; CHECK-NEXT: [[INDVAR1:%.*]] = phi i64 [ [[INDVAR_NEXT2:%.*]], [[FOR_COND1_FOR_INC7_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ] 96; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVAR1]] to i32 97; CHECK-NEXT: [[MUL_US:%.*]] = mul i32 [[TMP2]], [[N]] 98; CHECK-NEXT: [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR1]] to i32 99; CHECK-NEXT: br label [[FOR_BODY3_US:%.*]] 100; CHECK: for.body3.us: 101; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US]] ] 102; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i32 103; CHECK-NEXT: [[ADD_US:%.*]] = add i32 [[TMP3]], [[MUL_US]] 104; CHECK-NEXT: [[IDXPROM_US:%.*]] = zext i32 [[FLATTEN_TRUNCIV]] to i64 105; CHECK-NEXT: [[ARRAYIDX_US:%.*]] = getelementptr inbounds i16, i16* [[A:%.*]], i64 [[IDXPROM_US]] 106; CHECK-NEXT: [[TMP4:%.*]] = load i16, i16* [[ARRAYIDX_US]], align 2 107; CHECK-NEXT: [[ADD5_US:%.*]] = add i16 [[TMP4]], [[VAL:%.*]] 108; CHECK-NEXT: store i16 [[ADD5_US]], i16* [[ARRAYIDX_US]], align 2 109; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 110; CHECK-NEXT: [[CMP2_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] 111; CHECK-NEXT: br label [[FOR_COND1_FOR_INC7_CRIT_EDGE_US]] 112; CHECK: for.cond1.for.inc7_crit_edge.us: 113; CHECK-NEXT: [[INDVAR_NEXT2]] = add i64 [[INDVAR1]], 1 114; CHECK-NEXT: [[CMP_US:%.*]] = icmp ult i64 [[INDVAR_NEXT2]], [[FLATTEN_TRIPCOUNT]] 115; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END9_LOOPEXIT:%.*]] 116; CHECK: for.end9.loopexit: 117; CHECK-NEXT: br label [[FOR_END9]] 118; CHECK: for.end9: 119; CHECK-NEXT: ret void 120; 121entry: 122 %cmp20.not = icmp eq i32 %N, 0 123 br i1 %cmp20.not, label %for.end9, label %for.cond1.preheader.us.preheader 124 125for.cond1.preheader.us.preheader: 126 br label %for.cond1.preheader.us 127 128for.cond1.preheader.us: 129 %i.021.us = phi i32 [ %inc8.us, %for.cond1.for.inc7_crit_edge.us ], [ 0, %for.cond1.preheader.us.preheader ] 130 %mul.us = mul i32 %i.021.us, %N 131 br label %for.body3.us 132 133for.body3.us: 134 %j.019.us = phi i32 [ 0, %for.cond1.preheader.us ], [ %inc.us, %for.body3.us ] 135 %add.us = add i32 %j.019.us, %mul.us 136 %idxprom.us = zext i32 %add.us to i64 137 %arrayidx.us = getelementptr inbounds i16, i16* %A, i64 %idxprom.us 138 %0 = load i16, i16* %arrayidx.us, align 2 139 %add5.us = add i16 %0, %val 140 store i16 %add5.us, i16* %arrayidx.us, align 2 141 %inc.us = add nuw i32 %j.019.us, 1 142 %cmp2.us = icmp ult i32 %inc.us, %N 143 br i1 %cmp2.us, label %for.body3.us, label %for.cond1.for.inc7_crit_edge.us 144 145for.cond1.for.inc7_crit_edge.us: 146 %inc8.us = add i32 %i.021.us, 1 147 %cmp.us = icmp ult i32 %inc8.us, %N 148 br i1 %cmp.us, label %for.cond1.preheader.us, label %for.end9.loopexit 149 150for.end9.loopexit: 151 br label %for.end9 152 153for.end9: 154 ret void 155} 156 157; This IR corresponds to this input: 158; 159; void test(char n, char m) { 160; for(char i = 0; i < n; i++) 161; for(char j = 0; j < m; j++) { 162; char x = i*m+j; 163; use_32(x); 164; } 165; } 166; 167define void @test(i8 %n, i8 %m) { 168; CHECK-LABEL: @test( 169; CHECK-NEXT: entry: 170; CHECK-NEXT: [[CMP25_NOT:%.*]] = icmp eq i8 [[N:%.*]], 0 171; CHECK-NEXT: br i1 [[CMP25_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]] 172; CHECK: for.cond3.preheader.lr.ph: 173; CHECK-NEXT: [[CMP623_NOT:%.*]] = icmp eq i8 [[M:%.*]], 0 174; CHECK-NEXT: br i1 [[CMP623_NOT]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]] 175; CHECK: for.cond3.preheader.preheader: 176; CHECK-NEXT: br label [[FOR_COND3_PREHEADER:%.*]] 177; CHECK: for.cond3.preheader.us.preheader: 178; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[M]] to i64 179; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[N]] to i64 180; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]] 181; CHECK-NEXT: br label [[FOR_COND3_PREHEADER_US:%.*]] 182; CHECK: for.cond3.preheader.us: 183; CHECK-NEXT: [[INDVAR2:%.*]] = phi i64 [ [[INDVAR_NEXT3:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ] 184; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVAR2]] to i8 185; CHECK-NEXT: [[MUL_US:%.*]] = mul i8 [[TMP2]], [[M]] 186; CHECK-NEXT: [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR2]] to i8 187; CHECK-NEXT: br label [[FOR_BODY9_US:%.*]] 188; CHECK: for.body9.us: 189; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND3_PREHEADER_US]] ] 190; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i8 191; CHECK-NEXT: [[ADD_US:%.*]] = add i8 [[TMP3]], [[MUL_US]] 192; CHECK-NEXT: [[CONV14_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i32 193; CHECK-NEXT: [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 194; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 195; CHECK-NEXT: [[CMP6_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] 196; CHECK-NEXT: br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] 197; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us: 198; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1 199; CHECK-NEXT: [[CMP_US:%.*]] = icmp ult i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]] 200; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]] 201; CHECK: for.cond3.preheader: 202; CHECK-NEXT: [[I_026:%.*]] = phi i8 [ [[INC16:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ] 203; CHECK-NEXT: [[INC16]] = add i8 [[I_026]], 1 204; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[INC16]], [[N]] 205; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 206; CHECK: for.cond.cleanup.loopexit: 207; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 208; CHECK: for.cond.cleanup.loopexit1: 209; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 210; CHECK: for.cond.cleanup: 211; CHECK-NEXT: ret void 212; 213entry: 214 %cmp25.not = icmp eq i8 %n, 0 215 br i1 %cmp25.not, label %for.cond.cleanup, label %for.cond3.preheader.lr.ph 216 217for.cond3.preheader.lr.ph: 218 %cmp623.not = icmp eq i8 %m, 0 219 br i1 %cmp623.not, label %for.cond3.preheader.preheader, label %for.cond3.preheader.us.preheader 220 221for.cond3.preheader.preheader: 222 br label %for.cond3.preheader 223 224for.cond3.preheader.us.preheader: 225 br label %for.cond3.preheader.us 226 227for.cond3.preheader.us: 228 %i.026.us = phi i8 [ %inc16.us, %for.cond3.for.cond.cleanup8_crit_edge.us ], [ 0, %for.cond3.preheader.us.preheader ] 229 %mul.us = mul i8 %i.026.us, %m 230 br label %for.body9.us 231 232for.body9.us: 233 %j.024.us = phi i8 [ 0, %for.cond3.preheader.us ], [ %inc.us, %for.body9.us ] 234 %add.us = add i8 %j.024.us, %mul.us 235 %conv14.us = zext i8 %add.us to i32 236 %call.us = tail call i32 @use_32(i32 %conv14.us) #2 237 %inc.us = add nuw i8 %j.024.us, 1 238 %cmp6.us = icmp ult i8 %inc.us, %m 239 br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us 240 241for.cond3.for.cond.cleanup8_crit_edge.us: 242 %inc16.us = add i8 %i.026.us, 1 243 %cmp.us = icmp ult i8 %inc16.us, %n 244 br i1 %cmp.us, label %for.cond3.preheader.us, label %for.cond.cleanup 245 246for.cond3.preheader: 247 %i.026 = phi i8 [ %inc16, %for.cond3.preheader ], [ 0, %for.cond3.preheader.preheader ] 248 %inc16 = add i8 %i.026, 1 249 %cmp = icmp ult i8 %inc16, %n 250 br i1 %cmp, label %for.cond3.preheader, label %for.cond.cleanup 251 252for.cond.cleanup: 253 ret void 254} 255 256; This IR corresponds to this input: 257; 258; void test3(char n, char m) { 259; for(char i = 0; i < n; i++) 260; for(char j = 0; j < m; j++) { 261; char x = i*m+j; 262; use_32(x); 263; use_16(x); 264; use_32(x); 265; use_16(x); 266; use_64(x); 267; } 268; } 269; 270define void @test3(i8 %n, i8 %m) { 271; CHECK-LABEL: @test3( 272; CHECK-NEXT: entry: 273; CHECK-NEXT: [[CMP37_NOT:%.*]] = icmp eq i8 [[N:%.*]], 0 274; CHECK-NEXT: br i1 [[CMP37_NOT]], label [[FOR_COND_CLEANUP:%.*]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]] 275; CHECK: for.cond3.preheader.lr.ph: 276; CHECK-NEXT: [[CMP635_NOT:%.*]] = icmp eq i8 [[M:%.*]], 0 277; CHECK-NEXT: br i1 [[CMP635_NOT]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]] 278; CHECK: for.cond3.preheader.preheader: 279; CHECK-NEXT: br label [[FOR_COND3_PREHEADER:%.*]] 280; CHECK: for.cond3.preheader.us.preheader: 281; CHECK-NEXT: [[TMP0:%.*]] = zext i8 [[M]] to i64 282; CHECK-NEXT: [[TMP1:%.*]] = zext i8 [[N]] to i64 283; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]] 284; CHECK-NEXT: br label [[FOR_COND3_PREHEADER_US:%.*]] 285; CHECK: for.cond3.preheader.us: 286; CHECK-NEXT: [[INDVAR2:%.*]] = phi i64 [ [[INDVAR_NEXT3:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ] 287; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVAR2]] to i8 288; CHECK-NEXT: [[MUL_US:%.*]] = mul i8 [[TMP2]], [[M]] 289; CHECK-NEXT: [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR2]] to i8 290; CHECK-NEXT: br label [[FOR_BODY9_US:%.*]] 291; CHECK: for.body9.us: 292; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND3_PREHEADER_US]] ] 293; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i8 294; CHECK-NEXT: [[ADD_US:%.*]] = add i8 [[TMP3]], [[MUL_US]] 295; CHECK-NEXT: [[CONV14_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i32 296; CHECK-NEXT: [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 297; CHECK-NEXT: [[CONV15_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i16 298; CHECK-NEXT: [[CALL16_US:%.*]] = tail call i32 @use_16(i16 [[CONV15_US]]) 299; CHECK-NEXT: [[CALL18_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 300; CHECK-NEXT: [[CALL20_US:%.*]] = tail call i32 @use_16(i16 [[CONV15_US]]) 301; CHECK-NEXT: [[CONV21_US:%.*]] = zext i8 [[FLATTEN_TRUNCIV]] to i64 302; CHECK-NEXT: [[CALL22_US:%.*]] = tail call i32 @use_64(i64 [[CONV21_US]]) 303; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 304; CHECK-NEXT: [[CMP6_US:%.*]] = icmp ult i64 [[INDVAR_NEXT]], [[TMP0]] 305; CHECK-NEXT: br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] 306; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us: 307; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1 308; CHECK-NEXT: [[CMP_US:%.*]] = icmp ult i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]] 309; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]] 310; CHECK: for.cond3.preheader: 311; CHECK-NEXT: [[I_038:%.*]] = phi i8 [ [[INC24:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ] 312; CHECK-NEXT: [[INC24]] = add i8 [[I_038]], 1 313; CHECK-NEXT: [[CMP:%.*]] = icmp ult i8 [[INC24]], [[N]] 314; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 315; CHECK: for.cond.cleanup.loopexit: 316; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 317; CHECK: for.cond.cleanup.loopexit1: 318; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 319; CHECK: for.cond.cleanup: 320; CHECK-NEXT: ret void 321; 322entry: 323 %cmp37.not = icmp eq i8 %n, 0 324 br i1 %cmp37.not, label %for.cond.cleanup, label %for.cond3.preheader.lr.ph 325 326for.cond3.preheader.lr.ph: 327 %cmp635.not = icmp eq i8 %m, 0 328 br i1 %cmp635.not, label %for.cond3.preheader.preheader, label %for.cond3.preheader.us.preheader 329 330for.cond3.preheader.preheader: 331 br label %for.cond3.preheader 332 333for.cond3.preheader.us.preheader: 334 br label %for.cond3.preheader.us 335 336for.cond3.preheader.us: 337 %i.038.us = phi i8 [ %inc24.us, %for.cond3.for.cond.cleanup8_crit_edge.us ], [ 0, %for.cond3.preheader.us.preheader ] 338 %mul.us = mul i8 %i.038.us, %m 339 br label %for.body9.us 340 341for.body9.us: 342 %j.036.us = phi i8 [ 0, %for.cond3.preheader.us ], [ %inc.us, %for.body9.us ] 343 %add.us = add i8 %j.036.us, %mul.us 344 %conv14.us = zext i8 %add.us to i32 345 %call.us = tail call i32 @use_32(i32 %conv14.us) 346 %conv15.us = zext i8 %add.us to i16 347 %call16.us = tail call i32 @use_16(i16 %conv15.us) 348 %call18.us = tail call i32 @use_32(i32 %conv14.us) 349 %call20.us = tail call i32 @use_16(i16 %conv15.us) 350 %conv21.us = zext i8 %add.us to i64 351 %call22.us = tail call i32 @use_64(i64 %conv21.us) 352 %inc.us = add nuw i8 %j.036.us, 1 353 %cmp6.us = icmp ult i8 %inc.us, %m 354 br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us 355 356for.cond3.for.cond.cleanup8_crit_edge.us: 357 %inc24.us = add i8 %i.038.us, 1 358 %cmp.us = icmp ult i8 %inc24.us, %n 359 br i1 %cmp.us, label %for.cond3.preheader.us, label %for.cond.cleanup 360 361for.cond3.preheader: 362 %i.038 = phi i8 [ %inc24, %for.cond3.preheader ], [ 0, %for.cond3.preheader.preheader ] 363 %inc24 = add i8 %i.038, 1 364 %cmp = icmp ult i8 %inc24, %n 365 br i1 %cmp, label %for.cond3.preheader, label %for.cond.cleanup 366 367for.cond.cleanup: 368 ret void 369} 370 371; This IR corresponds to this input: 372; 373; void test4(short n, short m) { 374; for(short i = 0; i < n; i++) 375; for(short j = 0; j < m; j++) { 376; short x = i*m+j; 377; use_32(x); 378; use_16(x); 379; use_32(x); 380; use_16(x); 381; use_64(x); 382; } 383; } 384; 385define void @test4(i16 %n, i16 %m) { 386; CHECK-LABEL: @test4( 387; CHECK-NEXT: entry: 388; CHECK-NEXT: [[CMP38:%.*]] = icmp sgt i16 [[N:%.*]], 0 389; CHECK-NEXT: br i1 [[CMP38]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]] 390; CHECK: for.cond3.preheader.lr.ph: 391; CHECK-NEXT: [[CMP636:%.*]] = icmp sgt i16 [[M:%.*]], 0 392; CHECK-NEXT: br i1 [[CMP636]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]] 393; CHECK: for.cond3.preheader.preheader: 394; CHECK-NEXT: br label [[FOR_COND3_PREHEADER:%.*]] 395; CHECK: for.cond3.preheader.us.preheader: 396; CHECK-NEXT: [[TMP0:%.*]] = sext i16 [[M]] to i64 397; CHECK-NEXT: [[TMP1:%.*]] = sext i16 [[N]] to i64 398; CHECK-NEXT: [[FLATTEN_TRIPCOUNT:%.*]] = mul i64 [[TMP0]], [[TMP1]] 399; CHECK-NEXT: br label [[FOR_COND3_PREHEADER_US:%.*]] 400; CHECK: for.cond3.preheader.us: 401; CHECK-NEXT: [[INDVAR2:%.*]] = phi i64 [ [[INDVAR_NEXT3:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ] 402; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVAR2]] to i16 403; CHECK-NEXT: [[MUL_US:%.*]] = mul i16 [[TMP2]], [[M]] 404; CHECK-NEXT: [[FLATTEN_TRUNCIV:%.*]] = trunc i64 [[INDVAR2]] to i16 405; CHECK-NEXT: br label [[FOR_BODY9_US:%.*]] 406; CHECK: for.body9.us: 407; CHECK-NEXT: [[INDVAR:%.*]] = phi i64 [ 0, [[FOR_COND3_PREHEADER_US]] ] 408; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[INDVAR]] to i16 409; CHECK-NEXT: [[ADD_US:%.*]] = add i16 [[TMP3]], [[MUL_US]] 410; CHECK-NEXT: [[CONV14_US:%.*]] = sext i16 [[FLATTEN_TRUNCIV]] to i32 411; CHECK-NEXT: [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 412; CHECK-NEXT: [[CALL15_US:%.*]] = tail call i32 @use_16(i16 [[FLATTEN_TRUNCIV]]) 413; CHECK-NEXT: [[CALL17_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 414; CHECK-NEXT: [[CALL18_US:%.*]] = tail call i32 @use_16(i16 [[FLATTEN_TRUNCIV]]) 415; CHECK-NEXT: [[CONV19_US:%.*]] = sext i16 [[FLATTEN_TRUNCIV]] to i64 416; CHECK-NEXT: [[CALL20_US:%.*]] = tail call i32 @use_64(i64 [[CONV19_US]]) 417; CHECK-NEXT: [[INDVAR_NEXT:%.*]] = add i64 [[INDVAR]], 1 418; CHECK-NEXT: [[CMP6_US:%.*]] = icmp slt i64 [[INDVAR_NEXT]], [[TMP0]] 419; CHECK-NEXT: br label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] 420; CHECK: for.cond3.for.cond.cleanup8_crit_edge.us: 421; CHECK-NEXT: [[INDVAR_NEXT3]] = add i64 [[INDVAR2]], 1 422; CHECK-NEXT: [[CMP_US:%.*]] = icmp slt i64 [[INDVAR_NEXT3]], [[FLATTEN_TRIPCOUNT]] 423; CHECK-NEXT: br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 424; CHECK: for.cond3.preheader: 425; CHECK-NEXT: [[I_039:%.*]] = phi i16 [ [[INC22:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ] 426; CHECK-NEXT: [[INC22]] = add i16 [[I_039]], 1 427; CHECK-NEXT: [[CMP:%.*]] = icmp slt i16 [[INC22]], [[N]] 428; CHECK-NEXT: br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]] 429; CHECK: for.cond.cleanup.loopexit: 430; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 431; CHECK: for.cond.cleanup.loopexit1: 432; CHECK-NEXT: br label [[FOR_COND_CLEANUP]] 433; CHECK: for.cond.cleanup: 434; CHECK-NEXT: ret void 435; 436; DONTWIDEN-LABEL: @test4( 437; DONTWIDEN-NEXT: entry: 438; DONTWIDEN-NEXT: [[CMP38:%.*]] = icmp sgt i16 [[N:%.*]], 0 439; DONTWIDEN-NEXT: br i1 [[CMP38]], label [[FOR_COND3_PREHEADER_LR_PH:%.*]], label [[FOR_COND_CLEANUP:%.*]] 440; DONTWIDEN: for.cond3.preheader.lr.ph: 441; DONTWIDEN-NEXT: [[CMP636:%.*]] = icmp sgt i16 [[M:%.*]], 0 442; DONTWIDEN-NEXT: br i1 [[CMP636]], label [[FOR_COND3_PREHEADER_US_PREHEADER:%.*]], label [[FOR_COND3_PREHEADER_PREHEADER:%.*]] 443; DONTWIDEN: for.cond3.preheader.preheader: 444; DONTWIDEN-NEXT: br label [[FOR_COND3_PREHEADER:%.*]] 445; DONTWIDEN: for.cond3.preheader.us.preheader: 446; DONTWIDEN-NEXT: br label [[FOR_COND3_PREHEADER_US:%.*]] 447; DONTWIDEN: for.cond3.preheader.us: 448; DONTWIDEN-NEXT: [[I_039_US:%.*]] = phi i16 [ [[INC22_US:%.*]], [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US:%.*]] ], [ 0, [[FOR_COND3_PREHEADER_US_PREHEADER]] ] 449; DONTWIDEN-NEXT: [[MUL_US:%.*]] = mul i16 [[I_039_US]], [[M]] 450; DONTWIDEN-NEXT: br label [[FOR_BODY9_US:%.*]] 451; DONTWIDEN: for.body9.us: 452; DONTWIDEN-NEXT: [[J_037_US:%.*]] = phi i16 [ 0, [[FOR_COND3_PREHEADER_US]] ], [ [[INC_US:%.*]], [[FOR_BODY9_US]] ] 453; DONTWIDEN-NEXT: [[ADD_US:%.*]] = add i16 [[J_037_US]], [[MUL_US]] 454; DONTWIDEN-NEXT: [[CONV14_US:%.*]] = sext i16 [[ADD_US]] to i32 455; DONTWIDEN-NEXT: [[CALL_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 456; DONTWIDEN-NEXT: [[CALL15_US:%.*]] = tail call i32 @use_16(i16 [[ADD_US]]) 457; DONTWIDEN-NEXT: [[CALL17_US:%.*]] = tail call i32 @use_32(i32 [[CONV14_US]]) 458; DONTWIDEN-NEXT: [[CALL18_US:%.*]] = tail call i32 @use_16(i16 [[ADD_US]]) 459; DONTWIDEN-NEXT: [[CONV19_US:%.*]] = sext i16 [[ADD_US]] to i64 460; DONTWIDEN-NEXT: [[CALL20_US:%.*]] = tail call i32 @use_64(i64 [[CONV19_US]]) 461; DONTWIDEN-NEXT: [[INC_US]] = add nuw nsw i16 [[J_037_US]], 1 462; DONTWIDEN-NEXT: [[CMP6_US:%.*]] = icmp slt i16 [[INC_US]], [[M]] 463; DONTWIDEN-NEXT: br i1 [[CMP6_US]], label [[FOR_BODY9_US]], label [[FOR_COND3_FOR_COND_CLEANUP8_CRIT_EDGE_US]] 464; DONTWIDEN: for.cond3.for.cond.cleanup8_crit_edge.us: 465; DONTWIDEN-NEXT: [[INC22_US]] = add i16 [[I_039_US]], 1 466; DONTWIDEN-NEXT: [[CMP_US:%.*]] = icmp slt i16 [[INC22_US]], [[N]] 467; DONTWIDEN-NEXT: br i1 [[CMP_US]], label [[FOR_COND3_PREHEADER_US]], label [[FOR_COND_CLEANUP_LOOPEXIT:%.*]] 468; DONTWIDEN: for.cond3.preheader: 469; DONTWIDEN-NEXT: [[I_039:%.*]] = phi i16 [ [[INC22:%.*]], [[FOR_COND3_PREHEADER]] ], [ 0, [[FOR_COND3_PREHEADER_PREHEADER]] ] 470; DONTWIDEN-NEXT: [[INC22]] = add i16 [[I_039]], 1 471; DONTWIDEN-NEXT: [[CMP:%.*]] = icmp slt i16 [[INC22]], [[N]] 472; DONTWIDEN-NEXT: br i1 [[CMP]], label [[FOR_COND3_PREHEADER]], label [[FOR_COND_CLEANUP_LOOPEXIT1:%.*]] 473; DONTWIDEN: for.cond.cleanup.loopexit: 474; DONTWIDEN-NEXT: br label [[FOR_COND_CLEANUP]] 475; DONTWIDEN: for.cond.cleanup.loopexit1: 476; DONTWIDEN-NEXT: br label [[FOR_COND_CLEANUP]] 477; DONTWIDEN: for.cond.cleanup: 478; DONTWIDEN-NEXT: ret void 479; 480entry: 481 %cmp38 = icmp sgt i16 %n, 0 482 br i1 %cmp38, label %for.cond3.preheader.lr.ph, label %for.cond.cleanup 483 484for.cond3.preheader.lr.ph: 485 %cmp636 = icmp sgt i16 %m, 0 486 br i1 %cmp636, label %for.cond3.preheader.us.preheader, label %for.cond3.preheader.preheader 487 488for.cond3.preheader.preheader: 489 br label %for.cond3.preheader 490 491for.cond3.preheader.us.preheader: 492 br label %for.cond3.preheader.us 493 494for.cond3.preheader.us: 495 %i.039.us = phi i16 [ %inc22.us, %for.cond3.for.cond.cleanup8_crit_edge.us ], [ 0, %for.cond3.preheader.us.preheader ] 496 %mul.us = mul i16 %i.039.us, %m 497 br label %for.body9.us 498 499for.body9.us: 500 %j.037.us = phi i16 [ 0, %for.cond3.preheader.us ], [ %inc.us, %for.body9.us ] 501 %add.us = add i16 %j.037.us, %mul.us 502 %conv14.us = sext i16 %add.us to i32 503 %call.us = tail call i32 @use_32(i32 %conv14.us) #2 504 %call15.us = tail call i32 @use_16(i16 %add.us) #2 505 %call17.us = tail call i32 @use_32(i32 %conv14.us) #2 506 %call18.us = tail call i32 @use_16(i16 %add.us) #2 507 %conv19.us = sext i16 %add.us to i64 508 %call20.us = tail call i32 @use_64(i64 %conv19.us) #2 509 %inc.us = add nuw nsw i16 %j.037.us, 1 510 %cmp6.us = icmp slt i16 %inc.us, %m 511 br i1 %cmp6.us, label %for.body9.us, label %for.cond3.for.cond.cleanup8_crit_edge.us 512 513for.cond3.for.cond.cleanup8_crit_edge.us: 514 %inc22.us = add i16 %i.039.us, 1 515 %cmp.us = icmp slt i16 %inc22.us, %n 516 br i1 %cmp.us, label %for.cond3.preheader.us, label %for.cond.cleanup 517 518for.cond3.preheader: 519 %i.039 = phi i16 [ %inc22, %for.cond3.preheader ], [ 0, %for.cond3.preheader.preheader ] 520 %inc22 = add i16 %i.039, 1 521 %cmp = icmp slt i16 %inc22, %n 522 br i1 %cmp, label %for.cond3.preheader, label %for.cond.cleanup 523 524for.cond.cleanup: 525 ret void 526} 527 528declare dso_local i32 @use_32(i32) 529declare dso_local i32 @use_16(i16) 530declare dso_local i32 @use_64(i64) 531 532declare dso_local void @f(i32* %0) local_unnamed_addr #1 533