1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -indvars -scalar-evolution-use-expensive-range-sharpening -S | FileCheck %s 3 4target triple = "aarch64--linux-gnu" 5 6; Provide legal integer types. 7target datalayout = "n8:16:32:64" 8 9 10; Check the loop exit i32 compare instruction and operand are widened to i64 11; instead of truncating IV before its use in the i32 compare instruction. 12 13@idx = common global i32 0, align 4 14@e = common global i32 0, align 4 15@ptr = common global i32* null, align 8 16 17 18define i32 @test1() { 19; CHECK-LABEL: @test1( 20; CHECK-NEXT: entry: 21; CHECK-NEXT: store i32 -1, i32* @idx, align 4 22; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* @e, align 4 23; CHECK-NEXT: [[CMP4:%.*]] = icmp slt i32 [[TMP0]], 0 24; CHECK-NEXT: br i1 [[CMP4]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY_LR_PH:%.*]] 25; CHECK: for.body.lr.ph: 26; CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** @ptr, align 8 27; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* @e, align 4 28; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[TMP2]], i32 0) 29; CHECK-NEXT: [[TMP3:%.*]] = add nuw i32 [[SMAX]], 1 30; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP3]] to i64 31; CHECK-NEXT: br label [[FOR_BODY:%.*]] 32; CHECK: for.cond: 33; CHECK-NEXT: [[INDVARS_IV_NEXT:%.*]] = add nuw nsw i64 [[INDVARS_IV:%.*]], 1 34; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] 35; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_COND_FOR_END_LOOPEXIT_CRIT_EDGE:%.*]] 36; CHECK: for.body: 37; CHECK-NEXT: [[INDVARS_IV]] = phi i64 [ [[INDVARS_IV_NEXT]], [[FOR_COND:%.*]] ], [ 0, [[FOR_BODY_LR_PH]] ] 38; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[TMP1]], i64 [[INDVARS_IV]] 39; CHECK-NEXT: [[TMP4:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 40; CHECK-NEXT: [[TOBOOL:%.*]] = icmp eq i32 [[TMP4]], 0 41; CHECK-NEXT: br i1 [[TOBOOL]], label [[IF_THEN:%.*]], label [[FOR_COND]] 42; CHECK: if.then: 43; CHECK-NEXT: [[I_05_LCSSA_WIDE:%.*]] = phi i64 [ [[INDVARS_IV]], [[FOR_BODY]] ] 44; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[I_05_LCSSA_WIDE]] to i32 45; CHECK-NEXT: store i32 [[TMP5]], i32* @idx, align 4 46; CHECK-NEXT: br label [[FOR_END:%.*]] 47; CHECK: for.cond.for.end.loopexit_crit_edge: 48; CHECK-NEXT: br label [[FOR_END_LOOPEXIT]] 49; CHECK: for.end.loopexit: 50; CHECK-NEXT: br label [[FOR_END]] 51; CHECK: for.end: 52; CHECK-NEXT: [[TMP6:%.*]] = load i32, i32* @idx, align 4 53; CHECK-NEXT: ret i32 [[TMP6]] 54; 55entry: 56 store i32 -1, i32* @idx, align 4 57 %0 = load i32, i32* @e, align 4 58 %cmp4 = icmp slt i32 %0, 0 59 br i1 %cmp4, label %for.end.loopexit, label %for.body.lr.ph 60 61for.body.lr.ph: 62 %1 = load i32*, i32** @ptr, align 8 63 %2 = load i32, i32* @e, align 4 64 br label %for.body 65 66for.cond: 67 %inc = add nsw i32 %i.05, 1 68 %cmp = icmp slt i32 %i.05, %2 69 br i1 %cmp, label %for.body, label %for.cond.for.end.loopexit_crit_edge 70 71for.body: 72 %i.05 = phi i32 [ 0, %for.body.lr.ph ], [ %inc, %for.cond ] 73 %idxprom = sext i32 %i.05 to i64 74 %arrayidx = getelementptr inbounds i32, i32* %1, i64 %idxprom 75 %3 = load i32, i32* %arrayidx, align 4 76 %tobool = icmp eq i32 %3, 0 77 br i1 %tobool, label %if.then, label %for.cond 78 79if.then: 80 %i.05.lcssa = phi i32 [ %i.05, %for.body ] 81 store i32 %i.05.lcssa, i32* @idx, align 4 82 br label %for.end 83 84for.cond.for.end.loopexit_crit_edge: 85 br label %for.end.loopexit 86 87for.end.loopexit: 88 br label %for.end 89 90for.end: 91 %4 = load i32, i32* @idx, align 4 92 ret i32 %4 93} 94 95 96define void @test2([8 x i8]* %a, i8* %b, i8 %limit) { 97; CHECK-LABEL: @test2( 98; CHECK-NEXT: entry: 99; CHECK-NEXT: [[CONV:%.*]] = zext i8 [[LIMIT:%.*]] to i32 100; CHECK-NEXT: br i1 undef, label [[FOR_COND1_PREHEADER_PREHEADER:%.*]], label [[FOR_COND1_PREHEADER_US_PREHEADER:%.*]] 101; CHECK: for.cond1.preheader.us.preheader: 102; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[CONV]], i32 1) 103; CHECK-NEXT: br label [[FOR_COND1_PREHEADER_US:%.*]] 104; CHECK: for.cond1.preheader.preheader: 105; CHECK-NEXT: br label [[FOR_COND1_PREHEADER:%.*]] 106; CHECK: for.cond1.preheader.us: 107; CHECK-NEXT: [[INDVARS_IV3:%.*]] = phi i64 [ 0, [[FOR_COND1_PREHEADER_US_PREHEADER]] ], [ [[INDVARS_IV_NEXT4:%.*]], [[FOR_INC13_US:%.*]] ] 108; CHECK-NEXT: br i1 true, label [[FOR_BODY4_LR_PH_US:%.*]], label [[FOR_INC13_US]] 109; CHECK: for.inc13.us.loopexit: 110; CHECK-NEXT: br label [[FOR_INC13_US]] 111; CHECK: for.inc13.us: 112; CHECK-NEXT: [[INDVARS_IV_NEXT4]] = add nuw nsw i64 [[INDVARS_IV3]], 1 113; CHECK-NEXT: [[EXITCOND6:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT4]], 4 114; CHECK-NEXT: br i1 [[EXITCOND6]], label [[FOR_COND1_PREHEADER_US]], label [[FOR_END_LOOPEXIT1:%.*]] 115; CHECK: for.body4.us: 116; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ 0, [[FOR_BODY4_LR_PH_US]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY4_US:%.*]] ] 117; CHECK-NEXT: [[ARRAYIDX6_US:%.*]] = getelementptr inbounds [8 x i8], [8 x i8]* [[A:%.*]], i64 [[INDVARS_IV3]], i64 [[INDVARS_IV]] 118; CHECK-NEXT: [[TMP0:%.*]] = load i8, i8* [[ARRAYIDX6_US]], align 1 119; CHECK-NEXT: [[IDXPROM7_US:%.*]] = zext i8 [[TMP0]] to i64 120; CHECK-NEXT: [[ARRAYIDX8_US:%.*]] = getelementptr inbounds i8, i8* [[B:%.*]], i64 [[IDXPROM7_US]] 121; CHECK-NEXT: [[TMP1:%.*]] = load i8, i8* [[ARRAYIDX8_US]], align 1 122; CHECK-NEXT: store i8 [[TMP1]], i8* [[ARRAYIDX6_US]], align 1 123; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 124; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT:%.*]] 125; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY4_US]], label [[FOR_INC13_US_LOOPEXIT:%.*]] 126; CHECK: for.body4.lr.ph.us: 127; CHECK-NEXT: [[WIDE_TRIP_COUNT]] = zext i32 [[SMAX]] to i64 128; CHECK-NEXT: br label [[FOR_BODY4_US]] 129; CHECK: for.cond1.preheader: 130; CHECK-NEXT: br i1 false, label [[FOR_INC13:%.*]], label [[FOR_INC13]] 131; CHECK: for.inc13: 132; CHECK-NEXT: br i1 false, label [[FOR_COND1_PREHEADER]], label [[FOR_END_LOOPEXIT:%.*]] 133; CHECK: for.end.loopexit: 134; CHECK-NEXT: br label [[FOR_END:%.*]] 135; CHECK: for.end.loopexit1: 136; CHECK-NEXT: br label [[FOR_END]] 137; CHECK: for.end: 138; CHECK-NEXT: ret void 139; 140entry: 141 %conv = zext i8 %limit to i32 142 br i1 undef, label %for.cond1.preheader, label %for.cond1.preheader.us 143 144for.cond1.preheader.us: 145 %storemerge5.us = phi i32 [ 0, %entry ], [ %inc14.us, %for.inc13.us ] 146 br i1 true, label %for.body4.lr.ph.us, label %for.inc13.us 147 148for.inc13.us: 149 %inc14.us = add nsw i32 %storemerge5.us, 1 150 %cmp.us = icmp slt i32 %inc14.us, 4 151 br i1 %cmp.us, label %for.cond1.preheader.us, label %for.end 152 153for.body4.us: 154 %storemerge14.us = phi i32 [ 0, %for.body4.lr.ph.us ], [ %inc.us, %for.body4.us ] 155 %idxprom.us = sext i32 %storemerge14.us to i64 156 %arrayidx6.us = getelementptr inbounds [8 x i8], [8 x i8]* %a, i64 %idxprom5.us, i64 %idxprom.us 157 %0 = load i8, i8* %arrayidx6.us, align 1 158 %idxprom7.us = zext i8 %0 to i64 159 %arrayidx8.us = getelementptr inbounds i8, i8* %b, i64 %idxprom7.us 160 %1 = load i8, i8* %arrayidx8.us, align 1 161 store i8 %1, i8* %arrayidx6.us, align 1 162 %inc.us = add nsw i32 %storemerge14.us, 1 163 %cmp2.us = icmp slt i32 %inc.us, %conv 164 br i1 %cmp2.us, label %for.body4.us, label %for.inc13.us 165 166for.body4.lr.ph.us: 167 %idxprom5.us = sext i32 %storemerge5.us to i64 168 br label %for.body4.us 169 170for.cond1.preheader: 171 %storemerge5 = phi i32 [ 0, %entry ], [ %inc14, %for.inc13 ] 172 br i1 false, label %for.inc13, label %for.inc13 173 174for.inc13: 175 %inc14 = add nsw i32 %storemerge5, 1 176 %cmp = icmp slt i32 %inc14, 4 177 br i1 %cmp, label %for.cond1.preheader, label %for.end 178 179for.end: 180 ret void 181} 182 183 184define i32 @test3(i32* %a, i32 %b) { 185; CHECK-LABEL: @test3( 186; CHECK-NEXT: entry: 187; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B:%.*]], i32 0) 188; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 189; CHECK-NEXT: br label [[FOR_COND:%.*]] 190; CHECK: for.cond: 191; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ] 192; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 193; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]] 194; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]] 195; CHECK: for.body: 196; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] 197; CHECK-NEXT: [[TMP0:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 198; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP0]] 199; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 200; CHECK-NEXT: br label [[FOR_COND]] 201; CHECK: for.end: 202; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ] 203; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] 204; 205entry: 206 br label %for.cond 207 208for.cond: 209 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] 210 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 211 %cmp = icmp slt i32 %i.0, %b 212 br i1 %cmp, label %for.body, label %for.end 213 214for.body: 215 %idxprom = sext i32 %i.0 to i64 216 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 217 %0 = load i32, i32* %arrayidx, align 4 218 %add = add nsw i32 %sum.0, %0 219 %inc = add nsw i32 %i.0, 1 220 br label %for.cond 221 222for.end: 223 ret i32 %sum.0 224} 225 226declare i32 @fn1(i8 signext) 227 228; PR21030 229 230define i32 @test4(i32 %a) { 231; CHECK-LABEL: @test4( 232; CHECK-NEXT: entry: 233; CHECK-NEXT: br label [[FOR_BODY:%.*]] 234; CHECK: for.body: 235; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i32 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY]] ], [ 253, [[ENTRY:%.*]] ] 236; CHECK-NEXT: [[OR:%.*]] = or i32 [[A:%.*]], [[INDVARS_IV]] 237; CHECK-NEXT: [[CONV3:%.*]] = trunc i32 [[OR]] to i8 238; CHECK-NEXT: [[CALL:%.*]] = call i32 @fn1(i8 signext [[CONV3]]) 239; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i32 [[INDVARS_IV]], -1 240; CHECK-NEXT: [[TMP0:%.*]] = trunc i32 [[INDVARS_IV_NEXT]] to i8 241; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i8 [[TMP0]], -14 242; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 243; CHECK: for.end: 244; CHECK-NEXT: ret i32 0 245; 246entry: 247 br label %for.body 248 249for.body: 250 %c.07 = phi i8 [ -3, %entry ], [ %dec, %for.body ] 251 %conv6 = zext i8 %c.07 to i32 252 %or = or i32 %a, %conv6 253 %conv3 = trunc i32 %or to i8 254 %call = call i32 @fn1(i8 signext %conv3) 255 %dec = add i8 %c.07, -1 256 %cmp = icmp sgt i8 %dec, -14 257 br i1 %cmp, label %for.body, label %for.end 258 259for.end: 260 ret i32 0 261} 262 263 264define i32 @test5(i32* %a, i32 %b) { 265; CHECK-LABEL: @test5( 266; CHECK-NEXT: entry: 267; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64 268; CHECK-NEXT: br label [[FOR_COND:%.*]] 269; CHECK: for.cond: 270; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ] 271; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 272; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP0]] 273; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 274; CHECK: for.body: 275; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] 276; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 277; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]] 278; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw i64 [[INDVARS_IV]], 1 279; CHECK-NEXT: br label [[FOR_COND]] 280; CHECK: for.end: 281; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ] 282; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] 283; 284entry: 285 br label %for.cond 286 287for.cond: 288 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] 289 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 290 %cmp = icmp ule i32 %i.0, %b 291 br i1 %cmp, label %for.body, label %for.end 292 293for.body: 294 %idxprom = zext i32 %i.0 to i64 295 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 296 %0 = load i32, i32* %arrayidx, align 4 297 %add = add nsw i32 %sum.0, %0 298 %inc = add nsw i32 %i.0, 1 299 br label %for.cond 300 301for.end: 302 ret i32 %sum.0 303} 304 305define i32 @test6(i32* %a, i32 %b) { 306; CHECK-LABEL: @test6( 307; CHECK-NEXT: entry: 308; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B:%.*]], i32 -1) 309; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[SMAX]], 1 310; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP0]] to i64 311; CHECK-NEXT: br label [[FOR_COND:%.*]] 312; CHECK: for.cond: 313; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ] 314; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 315; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]] 316; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]] 317; CHECK: for.body: 318; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] 319; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 320; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]] 321; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 322; CHECK-NEXT: br label [[FOR_COND]] 323; CHECK: for.end: 324; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_COND]] ] 325; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] 326; 327entry: 328 br label %for.cond 329 330for.cond: 331 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] 332 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 333 %cmp = icmp sle i32 %i.0, %b 334 br i1 %cmp, label %for.body, label %for.end 335 336for.body: 337 %idxprom = zext i32 %i.0 to i64 338 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 339 %0 = load i32, i32* %arrayidx, align 4 340 %add = add nsw i32 %sum.0, %0 341 %inc = add nsw i32 %i.0, 1 342 br label %for.cond 343 344for.end: 345 ret i32 %sum.0 346} 347 348define i32 @test7(i32* %a, i32 %b) { 349; CHECK-LABEL: @test7( 350; CHECK-NEXT: entry: 351; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[B:%.*]] to i64 352; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[B]], i32 -1) 353; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[SMAX]], 2 354; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[TMP1]] to i64 355; CHECK-NEXT: br label [[FOR_COND:%.*]] 356; CHECK: for.cond: 357; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ], [ 0, [[ENTRY:%.*]] ] 358; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ 0, [[ENTRY]] ], [ [[ADD:%.*]], [[FOR_BODY]] ] 359; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP0]] 360; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 361; CHECK: for.body: 362; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] 363; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 364; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]] 365; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 366; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], [[WIDE_TRIP_COUNT]] 367; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_COND]], label [[FOR_END]] 368; CHECK: for.end: 369; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ] 370; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] 371; 372entry: 373 br label %for.cond 374 375for.cond: 376 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] 377 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.body ] 378 %cmp = icmp ule i32 %i.0, %b 379 br i1 %cmp, label %for.body, label %for.end 380 381for.body: 382 %idxprom = sext i32 %i.0 to i64 383 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 384 %0 = load i32, i32* %arrayidx, align 4 385 %add = add nsw i32 %sum.0, %0 386 %inc = add nsw i32 %i.0, 1 387 %cmp2 = icmp sle i32 %i.0, %b 388 br i1 %cmp2, label %for.cond, label %for.end 389 390for.end: 391 ret i32 %sum.0 392} 393 394define i32 @test8(i32* %a, i32 %b, i32 %init) { 395; Note: %indvars.iv is the sign extension of %i.0 396; CHECK-LABEL: @test8( 397; CHECK-NEXT: entry: 398; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0 399; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]] 400; CHECK: for.cond.preheader: 401; CHECK-NEXT: [[TMP0:%.*]] = sext i32 [[INIT]] to i64 402; CHECK-NEXT: [[TMP1:%.*]] = zext i32 [[B:%.*]] to i64 403; CHECK-NEXT: br label [[FOR_COND:%.*]] 404; CHECK: for.cond: 405; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ] 406; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ] 407; CHECK-NEXT: [[CMP:%.*]] = icmp ule i64 [[INDVARS_IV]], [[TMP1]] 408; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY]], label [[FOR_END:%.*]] 409; CHECK: for.body: 410; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] 411; CHECK-NEXT: [[TMP2:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 412; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP2]] 413; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add i64 [[INDVARS_IV]], 1 414; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i64 0, [[INDVARS_IV_NEXT]] 415; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]] 416; CHECK: for.end: 417; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ] 418; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] 419; CHECK: leave: 420; CHECK-NEXT: ret i32 0 421; 422entry: 423 %e = icmp sgt i32 %init, 0 424 br i1 %e, label %for.cond, label %leave 425 426for.cond: 427 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] 428 %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ] 429 %cmp = icmp ule i32 %i.0, %b 430 br i1 %cmp, label %for.body, label %for.end 431 432for.body: 433 %idxprom = sext i32 %i.0 to i64 434 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 435 %0 = load i32, i32* %arrayidx, align 4 436 %add = add nsw i32 %sum.0, %0 437 %inc = add nsw i32 %i.0, 1 438 %cmp2 = icmp slt i32 0, %inc 439 br i1 %cmp2, label %for.cond, label %for.end 440 441for.end: 442 ret i32 %sum.0 443 444leave: 445 ret i32 0 446} 447 448define i32 @test9(i32* %a, i32 %b, i32 %init) { 449; Note: %indvars.iv is the zero extension of %i.0 450; CHECK-LABEL: @test9( 451; CHECK-NEXT: entry: 452; CHECK-NEXT: [[E:%.*]] = icmp sgt i32 [[INIT:%.*]], 0 453; CHECK-NEXT: br i1 [[E]], label [[FOR_COND_PREHEADER:%.*]], label [[LEAVE:%.*]] 454; CHECK: for.cond.preheader: 455; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[INIT]] to i64 456; CHECK-NEXT: [[SMAX:%.*]] = call i32 @llvm.smax.i32(i32 [[INIT]], i32 [[B:%.*]]) 457; CHECK-NEXT: [[WIDE_TRIP_COUNT:%.*]] = zext i32 [[SMAX]] to i64 458; CHECK-NEXT: br label [[FOR_COND:%.*]] 459; CHECK: for.cond: 460; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[TMP0]], [[FOR_COND_PREHEADER]] ], [ [[INDVARS_IV_NEXT:%.*]], [[FOR_BODY:%.*]] ] 461; CHECK-NEXT: [[SUM_0:%.*]] = phi i32 [ [[ADD:%.*]], [[FOR_BODY]] ], [ 0, [[FOR_COND_PREHEADER]] ] 462; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV]], [[WIDE_TRIP_COUNT]] 463; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_BODY]], label [[FOR_END:%.*]] 464; CHECK: for.body: 465; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, i32* [[A:%.*]], i64 [[INDVARS_IV]] 466; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[ARRAYIDX]], align 4 467; CHECK-NEXT: [[ADD]] = add nsw i32 [[SUM_0]], [[TMP1]] 468; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 469; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 470; CHECK-NEXT: [[CMP2:%.*]] = icmp slt i32 0, [[TMP2]] 471; CHECK-NEXT: br i1 [[CMP2]], label [[FOR_COND]], label [[FOR_END]] 472; CHECK: for.end: 473; CHECK-NEXT: [[SUM_0_LCSSA:%.*]] = phi i32 [ [[SUM_0]], [[FOR_BODY]] ], [ [[SUM_0]], [[FOR_COND]] ] 474; CHECK-NEXT: ret i32 [[SUM_0_LCSSA]] 475; CHECK: leave: 476; CHECK-NEXT: ret i32 0 477; 478entry: 479 %e = icmp sgt i32 %init, 0 480 br i1 %e, label %for.cond, label %leave 481 482for.cond: 483 %sum.0 = phi i32 [ 0, %entry ], [ %add, %for.body ] 484 %i.0 = phi i32 [ %init, %entry ], [ %inc, %for.body ] 485 %cmp = icmp slt i32 %i.0, %b 486 br i1 %cmp, label %for.body, label %for.end 487 488for.body: 489 %idxprom = zext i32 %i.0 to i64 490 %arrayidx = getelementptr inbounds i32, i32* %a, i64 %idxprom 491 %0 = load i32, i32* %arrayidx, align 4 492 %add = add nsw i32 %sum.0, %0 493 %inc = add nsw i32 %i.0, 1 494 %cmp2 = icmp slt i32 0, %inc 495 br i1 %cmp2, label %for.cond, label %for.end 496 497for.end: 498 ret i32 %sum.0 499 500leave: 501 ret i32 0 502} 503 504declare void @consume.i64(i64) 505declare void @consume.i1(i1) 506 507define i32 @test10(i32 %v) { 508; CHECK-LABEL: @test10( 509; CHECK-NEXT: entry: 510; CHECK-NEXT: [[SEXT:%.*]] = sext i32 [[V:%.*]] to i64 511; CHECK-NEXT: br label [[LOOP:%.*]] 512; CHECK: loop: 513; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 514; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 515; CHECK-NEXT: [[TMP0:%.*]] = mul nsw i64 [[INDVARS_IV]], -1 516; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], [[SEXT]] 517; CHECK-NEXT: call void @consume.i1(i1 [[TMP1]]) 518; CHECK-NEXT: call void @consume.i64(i64 [[TMP0]]) 519; CHECK-NEXT: [[EXITCOND:%.*]] = icmp ne i64 [[INDVARS_IV_NEXT]], 11 520; CHECK-NEXT: br i1 [[EXITCOND]], label [[LOOP]], label [[LEAVE:%.*]] 521; CHECK: leave: 522; CHECK-NEXT: ret i32 22 523; 524 entry: 525 br label %loop 526 527 loop: 528 529 %i = phi i32 [ 0, %entry ], [ %i.inc, %loop ] 530 %i.inc = add i32 %i, 1 531 %iv = mul i32 %i, -1 532 %cmp = icmp eq i32 %iv, %v 533 call void @consume.i1(i1 %cmp) 534 %be.cond = icmp slt i32 %i.inc, 11 535 %ext = sext i32 %iv to i64 536 call void @consume.i64(i64 %ext) 537 br i1 %be.cond, label %loop, label %leave 538 539 leave: 540 ret i32 22 541} 542 543; TODO: We don't really need trunc/zext here because when iv.next overflows, 544; its value is not used. 545define i32 @test11(i32 %start, i32* %p, i32* %q) { 546; CHECK-LABEL: @test11( 547; CHECK-NEXT: entry: 548; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 549; CHECK-NEXT: br label [[LOOP:%.*]] 550; CHECK: loop: 551; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 552; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 553; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 554; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 555; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]] 556; CHECK: backedge: 557; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]] 558; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 559; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 560; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 561; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 562; CHECK: exit: 563; CHECK-NEXT: ret i32 0 564; CHECK: failure: 565; CHECK-NEXT: unreachable 566; 567entry: 568 br label %loop 569 570loop: 571 %iv = phi i32 [%start, %entry], [%iv.next, %backedge] 572 %iv.next = add i32 %iv, -1 573 %cond = icmp eq i32 %iv, 0 574 br i1 %cond, label %exit, label %backedge 575 576backedge: 577 %index = zext i32 %iv.next to i64 578 %store.addr = getelementptr i32, i32* %p, i64 %index 579 store i32 1, i32* %store.addr 580 %load.addr = getelementptr i32, i32* %q, i64 %index 581 %stop = load i32, i32* %q 582 %loop.cond = icmp eq i32 %stop, 0 583 br i1 %loop.cond, label %loop, label %failure 584 585exit: 586 ret i32 0 587 588failure: 589 unreachable 590} 591 592define i32 @test12(i32 %start, i32* %p, i32* %q) { 593; CHECK-LABEL: @test12( 594; CHECK-NEXT: entry: 595; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 596; CHECK-NEXT: br label [[LOOP:%.*]] 597; CHECK: loop: 598; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 599; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 600; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]] 601; CHECK: backedge: 602; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 603; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 604; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]] 605; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 606; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 607; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 608; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 609; CHECK: exit: 610; CHECK-NEXT: ret i32 0 611; CHECK: failure: 612; CHECK-NEXT: unreachable 613; 614entry: 615 br label %loop 616 617loop: 618 %iv = phi i32 [%start, %entry], [%iv.next, %backedge] 619 %cond = icmp eq i32 %iv, 0 620 br i1 %cond, label %exit, label %backedge 621 622backedge: 623 %iv.next = add i32 %iv, -1 624 %index = zext i32 %iv.next to i64 625 %store.addr = getelementptr i32, i32* %p, i64 %index 626 store i32 1, i32* %store.addr 627 %load.addr = getelementptr i32, i32* %q, i64 %index 628 %stop = load i32, i32* %q 629 %loop.cond = icmp eq i32 %stop, 0 630 br i1 %loop.cond, label %loop, label %failure 631 632exit: 633 ret i32 0 634 635failure: 636 unreachable 637} 638 639define i32 @test13(i32 %start, i32* %p, i32* %q) { 640; CHECK-LABEL: @test13( 641; CHECK-NEXT: entry: 642; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 643; CHECK-NEXT: br label [[LOOP:%.*]] 644; CHECK: loop: 645; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 646; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 647; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]] 648; CHECK: backedge: 649; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 650; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]] 651; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 652; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 653; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 654; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 655; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 656; CHECK: exit: 657; CHECK-NEXT: ret i32 0 658; CHECK: failure: 659; CHECK-NEXT: unreachable 660; 661entry: 662 br label %loop 663 664loop: 665 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 666 %cond = icmp eq i32 %iv, 0 667 br i1 %cond, label %exit, label %backedge 668 669backedge: 670 %foo = add i32 %iv, -1 671 %index = zext i32 %foo to i64 672 %store.addr = getelementptr i32, i32* %p, i64 %index 673 store i32 1, i32* %store.addr 674 %load.addr = getelementptr i32, i32* %q, i64 %index 675 %stop = load i32, i32* %q 676 %loop.cond = icmp eq i32 %stop, 0 677 %iv.next.1 = add i32 %iv, -1 678 br i1 %loop.cond, label %loop, label %failure 679 680exit: 681 ret i32 0 682 683failure: 684 unreachable 685} 686 687define i32 @test14(i32 %start, i32* %p, i32* %q) { 688; CHECK-LABEL: @test14( 689; CHECK-NEXT: entry: 690; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 691; CHECK-NEXT: br label [[LOOP:%.*]] 692; CHECK: loop: 693; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 694; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 695; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 696; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]] 697; CHECK: backedge: 698; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]] 699; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 700; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 701; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 702; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 703; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 704; CHECK: exit: 705; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32 706; CHECK-NEXT: ret i32 [[TMP2]] 707; CHECK: failure: 708; CHECK-NEXT: unreachable 709; 710entry: 711 br label %loop 712 713loop: 714 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 715 %cond = icmp eq i32 %iv, 0 716 %foo = add i32 %iv, -1 717 br i1 %cond, label %exit, label %backedge 718 719backedge: 720 %index = zext i32 %foo to i64 721 %store.addr = getelementptr i32, i32* %p, i64 %index 722 store i32 1, i32* %store.addr 723 %load.addr = getelementptr i32, i32* %q, i64 %index 724 %stop = load i32, i32* %q 725 %loop.cond = icmp eq i32 %stop, 0 726 %iv.next.1 = add i32 %iv, -1 727 br i1 %loop.cond, label %loop, label %failure 728 729exit: 730 ret i32 %foo 731 732failure: 733 unreachable 734} 735 736declare void @test14a-callee(i1 %cond) 737 738; Same as @test14 but with unwind exit. 739; Trunc instructions must be added below the landing pad. 740define i32 @test14a(i32 %start, i32* %p, i32* %q, i1 %c) personality i1 1 { 741; CHECK-LABEL: @test14a( 742; CHECK-NEXT: entry: 743; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 744; CHECK-NEXT: br label [[LOOP:%.*]] 745; CHECK: loop: 746; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 747; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 748; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 749; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]] 750; CHECK: backedge: 751; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]] 752; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 753; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 754; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 755; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 756; CHECK-NEXT: invoke void @test14a-callee(i1 [[LOOP_COND]]) 757; CHECK-NEXT: to label [[LOOP]] unwind label [[EXCEPTION:%.*]] 758; CHECK: exit: 759; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32 760; CHECK-NEXT: ret i32 [[TMP2]] 761; CHECK: exception: 762; CHECK-NEXT: [[FOO_LCSSA1_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ] 763; CHECK-NEXT: [[TMP3:%.*]] = landingpad i1 764; CHECK-NEXT: cleanup 765; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 [[FOO_LCSSA1_WIDE]] to i32 766; CHECK-NEXT: ret i32 [[TMP4]] 767; 768entry: 769 br label %loop 770 771loop: 772 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 773 %cond = icmp eq i32 %iv, 0 774 %foo = add i32 %iv, -1 775 br i1 %cond, label %exit, label %backedge 776 777backedge: 778 %index = zext i32 %foo to i64 779 %store.addr = getelementptr i32, i32* %p, i64 %index 780 store i32 1, i32* %store.addr 781 %load.addr = getelementptr i32, i32* %q, i64 %index 782 %stop = load i32, i32* %q 783 %loop.cond = icmp eq i32 %stop, 0 784 %iv.next.1 = add i32 %iv, -1 785 invoke void @test14a-callee(i1 %loop.cond) to label %loop unwind label %exception 786 787exit: 788 ret i32 %foo 789 790exception: 791 landingpad i1 792 cleanup 793 ret i32 %foo 794} 795 796declare void @use(i32 %arg) 797 798define i32 @test15(i32 %start, i32* %p, i32* %q) { 799; CHECK-LABEL: @test15( 800; CHECK-NEXT: entry: 801; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 802; CHECK-NEXT: br label [[LOOP:%.*]] 803; CHECK: loop: 804; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 805; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 806; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 807; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[BACKEDGE]] 808; CHECK: backedge: 809; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP1]] 810; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 811; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 812; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 813; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 814; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 815; CHECK: exit: 816; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32 817; CHECK-NEXT: call void @use(i32 [[TMP2]]) 818; CHECK-NEXT: ret i32 [[TMP2]] 819; CHECK: failure: 820; CHECK-NEXT: [[FOO_LCSSA1_WIDE:%.*]] = phi i64 [ [[TMP1]], [[BACKEDGE]] ] 821; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[FOO_LCSSA1_WIDE]] to i32 822; CHECK-NEXT: call void @use(i32 [[TMP3]]) 823; CHECK-NEXT: unreachable 824; 825entry: 826 br label %loop 827 828loop: 829 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 830 %cond = icmp eq i32 %iv, 0 831 %foo = add i32 %iv, -1 832 br i1 %cond, label %exit, label %backedge 833 834backedge: 835 %index = zext i32 %foo to i64 836 %store.addr = getelementptr i32, i32* %p, i64 %index 837 store i32 1, i32* %store.addr 838 %load.addr = getelementptr i32, i32* %q, i64 %index 839 %stop = load i32, i32* %q 840 %loop.cond = icmp eq i32 %stop, 0 841 %iv.next.1 = add i32 %iv, -1 842 br i1 %loop.cond, label %loop, label %failure 843 844exit: 845 call void @use(i32 %foo) 846 ret i32 %foo 847 848failure: 849 call void @use(i32 %foo) 850 unreachable 851} 852 853define i32 @test16_unsigned_pos1(i32 %start, i32* %p, i32* %q, i32 %x) { 854; CHECK-LABEL: @test16_unsigned_pos1( 855; CHECK-NEXT: entry: 856; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 857; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[TMP0]], -1 858; CHECK-NEXT: [[TMP2:%.*]] = zext i32 [[X:%.*]] to i64 859; CHECK-NEXT: br label [[LOOP:%.*]] 860; CHECK: loop: 861; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 862; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 863; CHECK-NEXT: [[TMP3:%.*]] = add nsw i64 [[INDVARS_IV]], -1 864; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]] 865; CHECK: guarded: 866; CHECK-NEXT: [[ICMP_USER_WIDE5:%.*]] = icmp ult i64 [[TMP1]], [[TMP2]] 867; CHECK-NEXT: br i1 [[ICMP_USER_WIDE5]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]] 868; CHECK: backedge: 869; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[TMP3]] 870; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 871; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q:%.*]], align 4 872; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 873; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 874; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 875; CHECK: exit: 876; CHECK-NEXT: [[TMP4:%.*]] = trunc i64 -1 to i32 877; CHECK-NEXT: call void @use(i32 [[TMP4]]) 878; CHECK-NEXT: ret i32 [[TMP4]] 879; CHECK: failure: 880; CHECK-NEXT: [[FOO_LCSSA2_WIDE:%.*]] = phi i64 [ [[TMP3]], [[BACKEDGE]] ] 881; CHECK-NEXT: [[TMP5:%.*]] = trunc i64 [[FOO_LCSSA2_WIDE]] to i32 882; CHECK-NEXT: call void @use(i32 [[TMP5]]) 883; CHECK-NEXT: unreachable 884; CHECK: side_exit: 885; CHECK-NEXT: ret i32 0 886; 887entry: 888 br label %loop 889 890loop: 891 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 892 %cond = icmp eq i32 %iv, 0 893 %foo = add i32 %iv, -1 894 br i1 %cond, label %exit, label %guarded 895 896guarded: 897 %icmp_user = icmp ult i32 %foo, %x 898 br i1 %icmp_user, label %backedge, label %side_exit 899 900backedge: 901 %index = zext i32 %foo to i64 902 %store.addr = getelementptr i32, i32* %p, i64 %index 903 store i32 1, i32* %store.addr 904 %load.addr = getelementptr i32, i32* %q, i64 %index 905 %stop = load i32, i32* %q 906 %loop.cond = icmp eq i32 %stop, 0 907 %iv.next.1 = add i32 %iv, -1 908 br i1 %loop.cond, label %loop, label %failure 909 910exit: 911 call void @use(i32 %foo) 912 ret i32 %foo 913 914failure: 915 call void @use(i32 %foo) 916 unreachable 917 918side_exit: 919 ret i32 0 920} 921 922; TODO: We can widen here despite the icmp user of %foo in guarded block. 923define i32 @test16_unsigned_pos2(i32 %start, i32* %p, i32* %q, i32 %x) { 924; CHECK-LABEL: @test16_unsigned_pos2( 925; CHECK-NEXT: entry: 926; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 927; CHECK-NEXT: br label [[LOOP:%.*]] 928; CHECK: loop: 929; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 930; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 931; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32 932; CHECK-NEXT: [[FOO:%.*]] = add i32 [[TMP1]], -1 933; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]] 934; CHECK: guarded: 935; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp ne i32 [[FOO]], [[X:%.*]] 936; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]] 937; CHECK: backedge: 938; CHECK-NEXT: [[INDEX:%.*]] = zext i32 [[FOO]] to i64 939; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[INDEX]] 940; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 941; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 [[INDEX]] 942; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q]], align 4 943; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 944; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 945; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 946; CHECK: exit: 947; CHECK-NEXT: call void @use(i32 -1) 948; CHECK-NEXT: ret i32 -1 949; CHECK: failure: 950; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ] 951; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]]) 952; CHECK-NEXT: unreachable 953; CHECK: side_exit: 954; CHECK-NEXT: ret i32 0 955; 956entry: 957 br label %loop 958 959loop: 960 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 961 %cond = icmp eq i32 %iv, 0 962 %foo = add i32 %iv, -1 963 br i1 %cond, label %exit, label %guarded 964 965guarded: 966 %icmp_user = icmp ne i32 %foo, %x 967 br i1 %icmp_user, label %backedge, label %side_exit 968 969backedge: 970 %index = zext i32 %foo to i64 971 %store.addr = getelementptr i32, i32* %p, i64 %index 972 store i32 1, i32* %store.addr 973 %load.addr = getelementptr i32, i32* %q, i64 %index 974 %stop = load i32, i32* %q 975 %loop.cond = icmp eq i32 %stop, 0 976 %iv.next.1 = add i32 %iv, -1 977 br i1 %loop.cond, label %loop, label %failure 978 979exit: 980 call void @use(i32 %foo) 981 ret i32 %foo 982 983failure: 984 call void @use(i32 %foo) 985 unreachable 986 987side_exit: 988 ret i32 0 989} 990 991; icmp slt user in guarded block prevents widening. 992define i32 @test16_unsigned_neg(i32 %start, i32* %p, i32* %q, i32 %x) { 993; CHECK-LABEL: @test16_unsigned_neg( 994; CHECK-NEXT: entry: 995; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[START:%.*]] to i64 996; CHECK-NEXT: br label [[LOOP:%.*]] 997; CHECK: loop: 998; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 999; CHECK-NEXT: [[COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 1000; CHECK-NEXT: [[TMP1:%.*]] = trunc i64 [[INDVARS_IV]] to i32 1001; CHECK-NEXT: [[FOO:%.*]] = add i32 [[TMP1]], -1 1002; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]] 1003; CHECK: guarded: 1004; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp slt i32 [[FOO]], [[X:%.*]] 1005; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]] 1006; CHECK: backedge: 1007; CHECK-NEXT: [[INDEX:%.*]] = zext i32 [[FOO]] to i64 1008; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[INDEX]] 1009; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 1010; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 [[INDEX]] 1011; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q]], align 4 1012; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 1013; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 1014; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 1015; CHECK: exit: 1016; CHECK-NEXT: call void @use(i32 -1) 1017; CHECK-NEXT: ret i32 -1 1018; CHECK: failure: 1019; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ] 1020; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]]) 1021; CHECK-NEXT: unreachable 1022; CHECK: side_exit: 1023; CHECK-NEXT: ret i32 0 1024; 1025entry: 1026 br label %loop 1027 1028loop: 1029 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 1030 %cond = icmp eq i32 %iv, 0 1031 %foo = add i32 %iv, -1 1032 br i1 %cond, label %exit, label %guarded 1033 1034guarded: 1035 %icmp_user = icmp slt i32 %foo, %x 1036 br i1 %icmp_user, label %backedge, label %side_exit 1037 1038backedge: 1039 %index = zext i32 %foo to i64 1040 %store.addr = getelementptr i32, i32* %p, i64 %index 1041 store i32 1, i32* %store.addr 1042 %load.addr = getelementptr i32, i32* %q, i64 %index 1043 %stop = load i32, i32* %q 1044 %loop.cond = icmp eq i32 %stop, 0 1045 %iv.next.1 = add i32 %iv, -1 1046 br i1 %loop.cond, label %loop, label %failure 1047 1048exit: 1049 call void @use(i32 %foo) 1050 ret i32 %foo 1051 1052failure: 1053 call void @use(i32 %foo) 1054 unreachable 1055 1056side_exit: 1057 ret i32 0 1058} 1059 1060; TODO: We can widen here despite the icmp user of %foo in guarded block. 1061define i32 @test16_signed_pos1(i32 %start, i32* %p, i32* %q, i32 %x) { 1062; CHECK-LABEL: @test16_signed_pos1( 1063; CHECK-NEXT: entry: 1064; CHECK-NEXT: br label [[LOOP:%.*]] 1065; CHECK: loop: 1066; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ] 1067; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0 1068; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1 1069; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]] 1070; CHECK: guarded: 1071; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp slt i32 [[FOO]], [[X:%.*]] 1072; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]] 1073; CHECK: backedge: 1074; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64 1075; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[INDEX]] 1076; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 1077; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 [[INDEX]] 1078; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q]], align 4 1079; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 1080; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1 1081; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 1082; CHECK: exit: 1083; CHECK-NEXT: call void @use(i32 -1) 1084; CHECK-NEXT: ret i32 -1 1085; CHECK: failure: 1086; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ] 1087; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]]) 1088; CHECK-NEXT: unreachable 1089; CHECK: side_exit: 1090; CHECK-NEXT: ret i32 0 1091; 1092entry: 1093 br label %loop 1094 1095loop: 1096 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 1097 %cond = icmp eq i32 %iv, 0 1098 %foo = add i32 %iv, -1 1099 br i1 %cond, label %exit, label %guarded 1100 1101guarded: 1102 %icmp_user = icmp slt i32 %foo, %x 1103 br i1 %icmp_user, label %backedge, label %side_exit 1104 1105backedge: 1106 %index = sext i32 %foo to i64 1107 %store.addr = getelementptr i32, i32* %p, i64 %index 1108 store i32 1, i32* %store.addr 1109 %load.addr = getelementptr i32, i32* %q, i64 %index 1110 %stop = load i32, i32* %q 1111 %loop.cond = icmp eq i32 %stop, 0 1112 %iv.next.1 = add i32 %iv, -1 1113 br i1 %loop.cond, label %loop, label %failure 1114 1115exit: 1116 call void @use(i32 %foo) 1117 ret i32 %foo 1118 1119failure: 1120 call void @use(i32 %foo) 1121 unreachable 1122 1123side_exit: 1124 ret i32 0 1125} 1126 1127; TODO: We can widen here despite the icmp user of %foo in guarded block. 1128define i32 @test16_signed_pos2(i32 %start, i32* %p, i32* %q, i32 %x) { 1129; CHECK-LABEL: @test16_signed_pos2( 1130; CHECK-NEXT: entry: 1131; CHECK-NEXT: br label [[LOOP:%.*]] 1132; CHECK: loop: 1133; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START:%.*]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ] 1134; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0 1135; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1 1136; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]] 1137; CHECK: guarded: 1138; CHECK-NEXT: [[ICMP_USER:%.*]] = icmp ne i32 [[FOO]], [[X:%.*]] 1139; CHECK-NEXT: br i1 [[ICMP_USER]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]] 1140; CHECK: backedge: 1141; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64 1142; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[INDEX]] 1143; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 1144; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 [[INDEX]] 1145; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q]], align 4 1146; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 1147; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1 1148; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 1149; CHECK: exit: 1150; CHECK-NEXT: call void @use(i32 -1) 1151; CHECK-NEXT: ret i32 -1 1152; CHECK: failure: 1153; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ] 1154; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]]) 1155; CHECK-NEXT: unreachable 1156; CHECK: side_exit: 1157; CHECK-NEXT: ret i32 0 1158; 1159entry: 1160 br label %loop 1161 1162loop: 1163 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 1164 %cond = icmp eq i32 %iv, 0 1165 %foo = add i32 %iv, -1 1166 br i1 %cond, label %exit, label %guarded 1167 1168guarded: 1169 %icmp_user = icmp ne i32 %foo, %x 1170 br i1 %icmp_user, label %backedge, label %side_exit 1171 1172backedge: 1173 %index = sext i32 %foo to i64 1174 %store.addr = getelementptr i32, i32* %p, i64 %index 1175 store i32 1, i32* %store.addr 1176 %load.addr = getelementptr i32, i32* %q, i64 %index 1177 %stop = load i32, i32* %q 1178 %loop.cond = icmp eq i32 %stop, 0 1179 %iv.next.1 = add i32 %iv, -1 1180 br i1 %loop.cond, label %loop, label %failure 1181 1182exit: 1183 call void @use(i32 %foo) 1184 ret i32 %foo 1185 1186failure: 1187 call void @use(i32 %foo) 1188 unreachable 1189 1190side_exit: 1191 ret i32 0 1192} 1193 1194; icmp ult user in guarded block prevents widening. 1195define i32 @test16_signed_neg(i32 %start, i32* %p, i32* %q, i32 %x) { 1196; CHECK-LABEL: @test16_signed_neg( 1197; CHECK-NEXT: entry: 1198; CHECK-NEXT: [[TMP0:%.*]] = add i32 [[START:%.*]], -1 1199; CHECK-NEXT: br label [[LOOP:%.*]] 1200; CHECK: loop: 1201; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[START]], [[ENTRY:%.*]] ], [ [[IV_NEXT_1:%.*]], [[BACKEDGE:%.*]] ] 1202; CHECK-NEXT: [[COND:%.*]] = icmp eq i32 [[IV]], 0 1203; CHECK-NEXT: [[FOO:%.*]] = add i32 [[IV]], -1 1204; CHECK-NEXT: br i1 [[COND]], label [[EXIT:%.*]], label [[GUARDED:%.*]] 1205; CHECK: guarded: 1206; CHECK-NEXT: [[ICMP_USER3:%.*]] = icmp ult i32 [[TMP0]], [[X:%.*]] 1207; CHECK-NEXT: br i1 [[ICMP_USER3]], label [[BACKEDGE]], label [[SIDE_EXIT:%.*]] 1208; CHECK: backedge: 1209; CHECK-NEXT: [[INDEX:%.*]] = sext i32 [[FOO]] to i64 1210; CHECK-NEXT: [[STORE_ADDR:%.*]] = getelementptr i32, i32* [[P:%.*]], i64 [[INDEX]] 1211; CHECK-NEXT: store i32 1, i32* [[STORE_ADDR]], align 4 1212; CHECK-NEXT: [[LOAD_ADDR:%.*]] = getelementptr i32, i32* [[Q:%.*]], i64 [[INDEX]] 1213; CHECK-NEXT: [[STOP:%.*]] = load i32, i32* [[Q]], align 4 1214; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[STOP]], 0 1215; CHECK-NEXT: [[IV_NEXT_1]] = add i32 [[IV]], -1 1216; CHECK-NEXT: br i1 [[LOOP_COND]], label [[LOOP]], label [[FAILURE:%.*]] 1217; CHECK: exit: 1218; CHECK-NEXT: call void @use(i32 -1) 1219; CHECK-NEXT: ret i32 -1 1220; CHECK: failure: 1221; CHECK-NEXT: [[FOO_LCSSA2:%.*]] = phi i32 [ [[FOO]], [[BACKEDGE]] ] 1222; CHECK-NEXT: call void @use(i32 [[FOO_LCSSA2]]) 1223; CHECK-NEXT: unreachable 1224; CHECK: side_exit: 1225; CHECK-NEXT: ret i32 0 1226; 1227entry: 1228 br label %loop 1229 1230loop: 1231 %iv = phi i32 [%start, %entry], [%iv.next.1, %backedge] 1232 %cond = icmp eq i32 %iv, 0 1233 %foo = add i32 %iv, -1 1234 br i1 %cond, label %exit, label %guarded 1235 1236guarded: 1237 %icmp_user = icmp ult i32 %foo, %x 1238 br i1 %icmp_user, label %backedge, label %side_exit 1239 1240backedge: 1241 %index = sext i32 %foo to i64 1242 %store.addr = getelementptr i32, i32* %p, i64 %index 1243 store i32 1, i32* %store.addr 1244 %load.addr = getelementptr i32, i32* %q, i64 %index 1245 %stop = load i32, i32* %q 1246 %loop.cond = icmp eq i32 %stop, 0 1247 %iv.next.1 = add i32 %iv, -1 1248 br i1 %loop.cond, label %loop, label %failure 1249 1250exit: 1251 call void @use(i32 %foo) 1252 ret i32 %foo 1253 1254failure: 1255 call void @use(i32 %foo) 1256 unreachable 1257 1258side_exit: 1259 ret i32 0 1260} 1261 1262define i32 @test17(i32* %p, i32 %len) { 1263; CHECK-LABEL: @test17( 1264; CHECK-NEXT: entry: 1265; CHECK-NEXT: [[TMP0:%.*]] = zext i32 [[LEN:%.*]] to i64 1266; CHECK-NEXT: br label [[LOOP:%.*]] 1267; CHECK: loop: 1268; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[BACKEDGE:%.*]] ], [ [[TMP0]], [[ENTRY:%.*]] ] 1269; CHECK-NEXT: [[TMP1:%.*]] = add nsw i64 [[INDVARS_IV]], -1 1270; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nsw i64 [[INDVARS_IV]], -1 1271; CHECK-NEXT: [[COND_1:%.*]] = icmp eq i64 [[INDVARS_IV]], 0 1272; CHECK-NEXT: br i1 [[COND_1]], label [[EXIT:%.*]], label [[BACKEDGE]] 1273; CHECK: backedge: 1274; CHECK-NEXT: [[ADDR:%.*]] = getelementptr inbounds i32, i32* [[P:%.*]], i64 [[TMP1]] 1275; CHECK-NEXT: [[LOADED:%.*]] = load atomic i32, i32* [[ADDR]] unordered, align 4 1276; CHECK-NEXT: [[COND_2:%.*]] = icmp eq i32 [[LOADED]], 0 1277; CHECK-NEXT: br i1 [[COND_2]], label [[FAILURE:%.*]], label [[LOOP]] 1278; CHECK: exit: 1279; CHECK-NEXT: [[TMP2:%.*]] = trunc i64 -1 to i32 1280; CHECK-NEXT: ret i32 [[TMP2]] 1281; CHECK: failure: 1282; CHECK-NEXT: unreachable 1283; 1284entry: 1285 br label %loop 1286 1287loop: 1288 %iv = phi i32 [ %iv.next, %backedge ], [ %len, %entry ] 1289 %iv.next = add i32 %iv, -1 1290 %cond_1 = icmp eq i32 %iv, 0 1291 br i1 %cond_1, label %exit, label %backedge 1292 1293backedge: 1294 %iv.next.wide = zext i32 %iv.next to i64 1295 %addr = getelementptr inbounds i32, i32* %p, i64 %iv.next.wide 1296 %loaded = load atomic i32, i32* %addr unordered, align 4 1297 %cond_2 = icmp eq i32 %loaded, 0 1298 br i1 %cond_2, label %failure, label %loop 1299 1300exit: 1301 ret i32 %iv.next 1302 1303failure: 1304 unreachable 1305} 1306 1307declare void @foo(i64 %v) 1308declare void @bar(i32 %v) 1309 1310define void @test18() { 1311; CHECK-LABEL: @test18( 1312; CHECK-NEXT: entry: 1313; CHECK-NEXT: br label [[LOOP:%.*]] 1314; CHECK: loop: 1315; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 1316; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 1317; CHECK-NEXT: [[INDVARS2:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 1318; CHECK-NEXT: call void @bar(i32 [[INDVARS2]]) 1319; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]]) 1320; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000 1321; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]] 1322; CHECK: exit: 1323; CHECK-NEXT: ret void 1324; 1325entry: 1326 br label %loop 1327 1328loop: ; preds = %loop, %entry 1329 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ] 1330 %val1 = phi i32 [ %val1.inc, %loop ], [ 0, %entry ] 1331 %val1.inc = add i32 %val1, 1 1332 %iv.next = add i32 %iv, 1 1333 call void @bar(i32 %val1.inc) 1334 %iv.wide = zext i32 %iv to i64 1335 call void @foo(i64 %iv.wide) 1336 %loop.cond = icmp eq i32 %iv, 1000 1337 br i1 %loop.cond, label %exit, label %loop 1338 1339exit: ; preds = %loop 1340 ret void 1341} 1342 1343define void @test19() { 1344; CHECK-LABEL: @test19( 1345; CHECK-NEXT: entry: 1346; CHECK-NEXT: br label [[LOOP:%.*]] 1347; CHECK: loop: 1348; CHECK-NEXT: [[VAL1:%.*]] = phi i64 [ [[VAL1_INC:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 1349; CHECK-NEXT: [[VAL1_INC]] = add nuw nsw i64 [[VAL1]], 1 1350; CHECK-NEXT: call void @foo(i64 [[VAL1_INC]]) 1351; CHECK-NEXT: call void @foo(i64 [[VAL1]]) 1352; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[VAL1]], 1000 1353; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]] 1354; CHECK: exit: 1355; CHECK-NEXT: ret void 1356; 1357entry: 1358 br label %loop 1359 1360loop: ; preds = %loop, %entry 1361 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ] 1362 %val1 = phi i64 [ %val1.inc, %loop ], [ 0, %entry ] 1363 %val1.inc = add i64 %val1, 1 1364 %iv.next = add i32 %iv, 1 1365 call void @foo(i64 %val1.inc) 1366 %iv.wide = zext i32 %iv to i64 1367 call void @foo(i64 %iv.wide) 1368 %loop.cond = icmp eq i32 %iv, 1000 1369 br i1 %loop.cond, label %exit, label %loop 1370 1371exit: ; preds = %loop 1372 ret void 1373} 1374 1375define void @test20() { 1376; CHECK-LABEL: @test20( 1377; CHECK-NEXT: entry: 1378; CHECK-NEXT: br label [[LOOP:%.*]] 1379; CHECK: loop: 1380; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 1381; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 1382; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]]) 1383; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]]) 1384; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000 1385; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]] 1386; CHECK: exit: 1387; CHECK-NEXT: ret void 1388; 1389entry: 1390 br label %loop 1391 1392loop: ; preds = %loop, %entry 1393 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ] 1394 %val1 = phi i32 [ %val1.inc, %loop ], [ 0, %entry ] 1395 %val1.inc = add i32 %val1, 1 1396 %iv.next = add i32 %iv, 1 1397 %val1.wide = zext i32 %val1 to i64 1398 call void @foo(i64 %val1.wide) 1399 %iv.wide = zext i32 %iv to i64 1400 call void @foo(i64 %iv.wide) 1401 %loop.cond = icmp eq i32 %iv, 1000 1402 br i1 %loop.cond, label %exit, label %loop 1403 1404exit: ; preds = %loop 1405 ret void 1406} 1407 1408define void @test21(i32* %ptr) { 1409; CHECK-LABEL: @test21( 1410; CHECK-NEXT: entry: 1411; CHECK-NEXT: store i32 0, i32* [[PTR:%.*]], align 4 1412; CHECK-NEXT: br label [[LOOP:%.*]] 1413; CHECK: loop: 1414; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 1415; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1 1416; CHECK-NEXT: [[INDVARS:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32 1417; CHECK-NEXT: store i32 [[INDVARS]], i32* [[PTR]], align 4 1418; CHECK-NEXT: call void @foo(i64 [[INDVARS_IV]]) 1419; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i64 [[INDVARS_IV]], 1000 1420; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]] 1421; CHECK: exit: 1422; CHECK-NEXT: ret void 1423; 1424entry: 1425 store i32 0, i32* %ptr, align 4 1426 br label %loop 1427 1428loop: ; preds = %loop, %entry 1429 %val = phi i32 [ %val.inc, %loop ], [ 0, %entry ] 1430 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ] 1431 %val.inc = add i32 %val, 1 1432 store i32 %val.inc, i32* %ptr, align 4 1433 %iv.wide = zext i32 %iv to i64 1434 call void @foo(i64 %iv.wide) 1435 %iv.next = add i32 %iv, 1 1436 %loop.cond = icmp eq i32 %iv, 1000 1437 br i1 %loop.cond, label %exit, label %loop 1438 1439exit: ; preds = %loop 1440 ret void 1441} 1442 1443define void @test22(i16* %ptr) { 1444; CHECK-LABEL: @test22( 1445; CHECK-NEXT: entry: 1446; CHECK-NEXT: store i16 0, i16* [[PTR:%.*]], align 4 1447; CHECK-NEXT: br label [[LOOP:%.*]] 1448; CHECK: loop: 1449; CHECK-NEXT: [[IV:%.*]] = phi i32 [ [[IV_NEXT:%.*]], [[LOOP]] ], [ 0, [[ENTRY:%.*]] ] 1450; CHECK-NEXT: [[INDVARS:%.*]] = trunc i32 [[IV]] to i16 1451; CHECK-NEXT: [[VAL_INC:%.*]] = add i16 [[INDVARS]], 1 1452; CHECK-NEXT: store i16 [[VAL_INC]], i16* [[PTR]], align 4 1453; CHECK-NEXT: [[IV_WIDE:%.*]] = zext i32 [[IV]] to i64 1454; CHECK-NEXT: call void @foo(i64 [[IV_WIDE]]) 1455; CHECK-NEXT: [[IV_NEXT]] = zext i16 [[VAL_INC]] to i32 1456; CHECK-NEXT: [[LOOP_COND:%.*]] = icmp eq i32 [[IV]], 1000 1457; CHECK-NEXT: br i1 [[LOOP_COND]], label [[EXIT:%.*]], label [[LOOP]] 1458; CHECK: exit: 1459; CHECK-NEXT: ret void 1460; 1461entry: 1462 store i16 0, i16* %ptr, align 4 1463 br label %loop 1464 1465loop: ; preds = %loop, %entry 1466 %val = phi i16 [ %val.inc, %loop ], [ 0, %entry ] 1467 %iv = phi i32 [ %iv.next, %loop ], [ 0, %entry ] 1468 %val.inc = add i16 %val, 1 1469 store i16 %val.inc, i16* %ptr, align 4 1470 %iv.wide = zext i32 %iv to i64 1471 call void @foo(i64 %iv.wide) 1472 %iv.next = zext i16 %val.inc to i32 1473 %loop.cond = icmp eq i32 %iv, 1000 1474 br i1 %loop.cond, label %exit, label %loop 1475 1476exit: ; preds = %loop 1477 ret void 1478} 1479