1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7define i32 @foo(ptr nocapture readnone %match, i32 %cur_match, i32 %best_len, i32 %scan_end, ptr nocapture readonly %prev, i32 %limit, i32 %chain_length, ptr nocapture readonly %win, i32 %wmask) { 8; CHECK-LABEL: @foo( 9; CHECK-NEXT: entry: 10; CHECK-NEXT: [[IDX_EXT2:%.*]] = zext i32 [[CUR_MATCH:%.*]] to i64 11; CHECK-NEXT: [[ADD_PTR4:%.*]] = getelementptr inbounds nuw i8, ptr [[WIN:%.*]], i64 [[IDX_EXT2]] 12; CHECK-NEXT: [[IDX_EXT1:%.*]] = zext i32 [[BEST_LEN:%.*]] to i64 13; CHECK-NEXT: [[ADD_PTR25:%.*]] = getelementptr inbounds nuw i8, ptr [[ADD_PTR4]], i64 [[IDX_EXT1]] 14; CHECK-NEXT: [[ADD_PTR36:%.*]] = getelementptr inbounds i8, ptr [[ADD_PTR25]], i64 -1 15; CHECK-NEXT: [[I1:%.*]] = load i32, ptr [[ADD_PTR36]], align 4 16; CHECK-NEXT: [[CMP7:%.*]] = icmp eq i32 [[I1]], [[SCAN_END:%.*]] 17; CHECK-NEXT: br i1 [[CMP7]], label [[DO_END:%.*]], label [[IF_THEN_LR_PH:%.*]] 18; CHECK: if.then.lr.ph: 19; CHECK-NEXT: br label [[IF_THEN:%.*]] 20; CHECK: do.body: 21; CHECK-NEXT: [[IDX_EXT:%.*]] = zext i32 [[I4:%.*]] to i64 22; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds nuw i8, ptr [[WIN]], i64 [[IDX_EXT]] 23; CHECK-NEXT: [[ADD_PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[ADD_PTR]], i64 [[IDX_EXT1]] 24; CHECK-NEXT: [[ADD_PTR3:%.*]] = getelementptr inbounds i8, ptr [[ADD_PTR2]], i64 -1 25; CHECK-NEXT: [[I3:%.*]] = load i32, ptr [[ADD_PTR3]], align 4 26; CHECK-NEXT: [[CMP:%.*]] = icmp eq i32 [[I3]], [[SCAN_END]] 27; CHECK-NEXT: br i1 [[CMP]], label [[DO_END]], label [[IF_THEN]] 28; CHECK: if.then: 29; CHECK-NEXT: [[CUR_MATCH_ADDR_09:%.*]] = phi i32 [ [[CUR_MATCH]], [[IF_THEN_LR_PH]] ], [ [[I4]], [[DO_BODY:%.*]] ] 30; CHECK-NEXT: [[CHAIN_LENGTH_ADDR_08:%.*]] = phi i32 [ [[CHAIN_LENGTH:%.*]], [[IF_THEN_LR_PH]] ], [ [[DEC:%.*]], [[DO_BODY]] ] 31; CHECK-NEXT: [[AND:%.*]] = and i32 [[CUR_MATCH_ADDR_09]], [[WMASK:%.*]] 32; CHECK-NEXT: [[IDXPROM:%.*]] = zext i32 [[AND]] to i64 33; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds nuw i32, ptr [[PREV:%.*]], i64 [[IDXPROM]] 34; CHECK-NEXT: [[I4]] = load i32, ptr [[ARRAYIDX]], align 4 35; CHECK-NEXT: [[CMP4:%.*]] = icmp ugt i32 [[I4]], [[LIMIT:%.*]] 36; CHECK-NEXT: br i1 [[CMP4]], label [[LAND_LHS_TRUE:%.*]], label [[DO_END]] 37; CHECK: land.lhs.true: 38; CHECK-NEXT: [[DEC]] = add i32 [[CHAIN_LENGTH_ADDR_08]], -1 39; CHECK-NEXT: [[CMP5:%.*]] = icmp eq i32 [[DEC]], 0 40; CHECK-NEXT: br i1 [[CMP5]], label [[DO_END]], label [[DO_BODY]] 41; CHECK: do.end: 42; CHECK-NEXT: [[CONT_0:%.*]] = phi i32 [ 1, [[ENTRY:%.*]] ], [ 0, [[IF_THEN]] ], [ 0, [[LAND_LHS_TRUE]] ], [ 1, [[DO_BODY]] ] 43; CHECK-NEXT: ret i32 [[CONT_0]] 44; 45entry: 46 %idx.ext2 = zext i32 %cur_match to i64 47 %add.ptr4 = getelementptr inbounds i8, ptr %win, i64 %idx.ext2 48 %idx.ext1 = zext i32 %best_len to i64 49 %add.ptr25 = getelementptr inbounds i8, ptr %add.ptr4, i64 %idx.ext1 50 %add.ptr36 = getelementptr inbounds i8, ptr %add.ptr25, i64 -1 51 %i1 = load i32, ptr %add.ptr36, align 4 52 %cmp7 = icmp eq i32 %i1, %scan_end 53 br i1 %cmp7, label %do.end, label %if.then.lr.ph 54 55if.then.lr.ph: ; preds = %entry 56 br label %if.then 57 58do.body: ; preds = %land.lhs.true 59 %chain_length.addr.0 = phi i32 [ %dec, %land.lhs.true ] 60 %cur_match.addr.0 = phi i32 [ %i4, %land.lhs.true ] 61 %idx.ext = zext i32 %cur_match.addr.0 to i64 62 %add.ptr = getelementptr inbounds i8, ptr %win, i64 %idx.ext 63 %add.ptr2 = getelementptr inbounds i8, ptr %add.ptr, i64 %idx.ext1 64 %add.ptr3 = getelementptr inbounds i8, ptr %add.ptr2, i64 -1 65 %i3 = load i32, ptr %add.ptr3, align 4 66 %cmp = icmp eq i32 %i3, %scan_end 67 br i1 %cmp, label %do.end, label %if.then 68 69if.then: ; preds = %do.body, %if.then.lr.ph 70 %cur_match.addr.09 = phi i32 [ %cur_match, %if.then.lr.ph ], [ %cur_match.addr.0, %do.body ] 71 %chain_length.addr.08 = phi i32 [ %chain_length, %if.then.lr.ph ], [ %chain_length.addr.0, %do.body ] 72 %and = and i32 %cur_match.addr.09, %wmask 73 %idxprom = zext i32 %and to i64 74 %arrayidx = getelementptr inbounds i32, ptr %prev, i64 %idxprom 75 %i4 = load i32, ptr %arrayidx, align 4 76 %cmp4 = icmp ugt i32 %i4, %limit 77 br i1 %cmp4, label %land.lhs.true, label %do.end 78 79land.lhs.true: ; preds = %if.then 80 %dec = add i32 %chain_length.addr.08, -1 81 %cmp5 = icmp eq i32 %dec, 0 82 br i1 %cmp5, label %do.end, label %do.body 83 84do.end: ; preds = %land.lhs.true, %if.then, %do.body, %entry 85 %cont.0 = phi i32 [ 1, %entry ], [ 0, %if.then ], [ 0, %land.lhs.true ], [ 1, %do.body ] 86 ret i32 %cont.0 87} 88 89declare void @blackhole(<2 x ptr>) 90 91define void @PR37005(ptr %base, ptr %in) { 92; CHECK-LABEL: @PR37005( 93; CHECK-NEXT: entry: 94; CHECK-NEXT: br label [[LOOP:%.*]] 95; CHECK: loop: 96; CHECK-NEXT: [[E1:%.*]] = getelementptr inbounds ptr, ptr [[IN:%.*]], i64 undef 97; CHECK-NEXT: [[E2:%.*]] = getelementptr inbounds nuw i8, ptr [[E1]], i64 48 98; CHECK-NEXT: [[E4:%.*]] = getelementptr inbounds ptr, ptr [[E2]], <2 x i64> <i64 0, i64 1> 99; CHECK-NEXT: [[PI1:%.*]] = ptrtoint <2 x ptr> [[E4]] to <2 x i64> 100; CHECK-NEXT: [[TMP0:%.*]] = lshr <2 x i64> [[PI1]], splat (i64 14) 101; CHECK-NEXT: [[SL1:%.*]] = and <2 x i64> [[TMP0]], splat (i64 1125899906842496) 102; CHECK-NEXT: [[E5:%.*]] = getelementptr inbounds i8, ptr [[BASE:%.*]], <2 x i64> [[SL1]] 103; CHECK-NEXT: [[E6:%.*]] = getelementptr inbounds i8, <2 x ptr> [[E5]], i64 80 104; CHECK-NEXT: call void @blackhole(<2 x ptr> [[E6]]) 105; CHECK-NEXT: br label [[LOOP]] 106; 107entry: 108 br label %loop 109 110loop: ; preds = %loop, %entry 111 %e1 = getelementptr inbounds ptr, ptr %in, i64 undef 112 %e2 = getelementptr inbounds ptr, ptr %e1, i64 6 113 %e4 = getelementptr inbounds ptr, ptr %e2, <2 x i64> <i64 0, i64 1> 114 %pi1 = ptrtoint <2 x ptr> %e4 to <2 x i64> 115 %lr1 = lshr <2 x i64> %pi1, <i64 21, i64 21> 116 %sl1 = shl nuw nsw <2 x i64> %lr1, <i64 7, i64 7> 117 %e5 = getelementptr inbounds i8, ptr %base, <2 x i64> %sl1 118 %e6 = getelementptr inbounds i8, <2 x ptr> %e5, i64 80 119 call void @blackhole(<2 x ptr> %e6) 120 br label %loop 121} 122 123define void @PR37005_2(ptr %base, ptr %in) { 124; CHECK-LABEL: @PR37005_2( 125; CHECK-NEXT: entry: 126; CHECK-NEXT: br label [[LOOP:%.*]] 127; CHECK: loop: 128; CHECK-NEXT: [[E1:%.*]] = getelementptr inbounds ptr, ptr [[IN:%.*]], i64 undef 129; CHECK-NEXT: [[E2:%.*]] = getelementptr inbounds nuw i8, ptr [[E1]], i64 48 130; CHECK-NEXT: [[PI1:%.*]] = ptrtoint ptr [[E2]] to i64 131; CHECK-NEXT: [[TMP0:%.*]] = lshr i64 [[PI1]], 14 132; CHECK-NEXT: [[SL1:%.*]] = and i64 [[TMP0]], 1125899906842496 133; CHECK-NEXT: [[E5:%.*]] = getelementptr inbounds nuw i8, ptr [[BASE:%.*]], i64 [[SL1]] 134; CHECK-NEXT: [[E6:%.*]] = getelementptr inbounds i8, ptr [[E5]], <2 x i64> <i64 80, i64 60> 135; CHECK-NEXT: call void @blackhole(<2 x ptr> [[E6]]) 136; CHECK-NEXT: br label [[LOOP]] 137; 138entry: 139 br label %loop 140 141loop: ; preds = %loop, %entry 142 %e1 = getelementptr inbounds ptr, ptr %in, i64 undef 143 %e2 = getelementptr inbounds ptr, ptr %e1, i64 6 144 %pi1 = ptrtoint ptr %e2 to i64 145 %lr1 = lshr i64 %pi1, 21 146 %sl1 = shl nuw nsw i64 %lr1, 7 147 %e5 = getelementptr inbounds i8, ptr %base, i64 %sl1 148 %e6 = getelementptr inbounds i8, ptr %e5, <2 x i64> <i64 80, i64 60> 149 call void @blackhole(<2 x ptr> %e6) 150 br label %loop 151} 152 153define void @PR37005_3(<2 x ptr> %base, ptr %in) { 154; CHECK-LABEL: @PR37005_3( 155; CHECK-NEXT: entry: 156; CHECK-NEXT: br label [[LOOP:%.*]] 157; CHECK: loop: 158; CHECK-NEXT: [[E1:%.*]] = getelementptr inbounds ptr, ptr [[IN:%.*]], i64 undef 159; CHECK-NEXT: [[E2:%.*]] = getelementptr inbounds nuw i8, ptr [[E1]], i64 48 160; CHECK-NEXT: [[E4:%.*]] = getelementptr inbounds ptr, ptr [[E2]], <2 x i64> <i64 0, i64 1> 161; CHECK-NEXT: [[PI1:%.*]] = ptrtoint <2 x ptr> [[E4]] to <2 x i64> 162; CHECK-NEXT: [[TMP0:%.*]] = lshr <2 x i64> [[PI1]], splat (i64 14) 163; CHECK-NEXT: [[SL1:%.*]] = and <2 x i64> [[TMP0]], splat (i64 1125899906842496) 164; CHECK-NEXT: [[E5:%.*]] = getelementptr inbounds i8, <2 x ptr> [[BASE:%.*]], <2 x i64> [[SL1]] 165; CHECK-NEXT: [[E6:%.*]] = getelementptr inbounds i8, <2 x ptr> [[E5]], i64 80 166; CHECK-NEXT: call void @blackhole(<2 x ptr> [[E6]]) 167; CHECK-NEXT: br label [[LOOP]] 168; 169entry: 170 br label %loop 171 172loop: ; preds = %loop, %entry 173 %e1 = getelementptr inbounds ptr, ptr %in, i64 undef 174 %e2 = getelementptr inbounds ptr, ptr %e1, i64 6 175 %e4 = getelementptr inbounds ptr, ptr %e2, <2 x i64> <i64 0, i64 1> 176 %pi1 = ptrtoint <2 x ptr> %e4 to <2 x i64> 177 %lr1 = lshr <2 x i64> %pi1, <i64 21, i64 21> 178 %sl1 = shl nuw nsw <2 x i64> %lr1, <i64 7, i64 7> 179 %e5 = getelementptr inbounds i8, <2 x ptr> %base, <2 x i64> %sl1 180 %e6 = getelementptr inbounds i8, <2 x ptr> %e5, i64 80 181 call void @blackhole(<2 x ptr> %e6) 182 br label %loop 183} 184 185; This would crash because we did not expect to be able to constant fold a GEP. 186 187define void @PR51485(<2 x i64> %v) { 188; CHECK-LABEL: @PR51485( 189; CHECK-NEXT: entry: 190; CHECK-NEXT: br label [[LOOP:%.*]] 191; CHECK: loop: 192; CHECK-NEXT: [[SL1:%.*]] = shl nuw nsw <2 x i64> [[V:%.*]], splat (i64 7) 193; CHECK-NEXT: [[E5:%.*]] = getelementptr inbounds i8, ptr @PR51485, <2 x i64> [[SL1]] 194; CHECK-NEXT: [[E6:%.*]] = getelementptr inbounds i8, <2 x ptr> [[E5]], i64 80 195; CHECK-NEXT: call void @blackhole(<2 x ptr> [[E6]]) 196; CHECK-NEXT: br label [[LOOP]] 197; 198entry: 199 br label %loop 200 201loop: ; preds = %loop, %entry 202 %sl1 = shl nuw nsw <2 x i64> %v, <i64 7, i64 7> 203 %e5 = getelementptr inbounds i8, ptr @PR51485, <2 x i64> %sl1 204 %e6 = getelementptr inbounds i8, <2 x ptr> %e5, i64 80 205 call void @blackhole(<2 x ptr> %e6) 206 br label %loop 207} 208 209; Avoid folding the GEP outside the loop to inside, and increasing loop 210; instruction count. 211define float @gep_cross_loop(ptr %_arg_, ptr %_arg_3, float %_arg_8) { 212; CHECK-LABEL: @gep_cross_loop( 213; CHECK-NEXT: entry: 214; CHECK-NEXT: [[I:%.*]] = load i64, ptr [[_ARG_:%.*]], align 8 215; CHECK-NEXT: [[ADD_PTR:%.*]] = getelementptr inbounds float, ptr [[_ARG_3:%.*]], i64 [[I]] 216; CHECK-NEXT: br label [[FOR_COND_I:%.*]] 217; CHECK: for.cond.i: 218; CHECK-NEXT: [[IDX:%.*]] = phi i64 [ 0, [[ENTRY:%.*]] ], [ [[ADD11_I:%.*]], [[FOR_BODY_I:%.*]] ] 219; CHECK-NEXT: [[SUM:%.*]] = phi float [ 0.000000e+00, [[ENTRY]] ], [ [[ADD_I:%.*]], [[FOR_BODY_I]] ] 220; CHECK-NEXT: [[CMP:%.*]] = icmp samesign ult i64 [[IDX]], 17 221; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_I]], label [[FOR_COND_I_I_I_PREHEADER:%.*]] 222; CHECK: for.cond.i.i.i.preheader: 223; CHECK-NEXT: ret float [[SUM]] 224; CHECK: for.body.i: 225; CHECK-NEXT: [[ARRAYIDX_I84_I:%.*]] = getelementptr inbounds nuw float, ptr [[ADD_PTR]], i64 [[IDX]] 226; CHECK-NEXT: [[I1:%.*]] = load float, ptr [[ARRAYIDX_I84_I]], align 4 227; CHECK-NEXT: [[ADD_I]] = fadd fast float [[SUM]], [[I1]] 228; CHECK-NEXT: [[ADD11_I]] = add nuw nsw i64 [[IDX]], 1 229; CHECK-NEXT: br label [[FOR_COND_I]] 230; 231entry: 232 %i = load i64, ptr %_arg_, align 8 233 %add.ptr = getelementptr inbounds float, ptr %_arg_3, i64 %i 234 br label %for.cond.i 235 236for.cond.i: ; preds = %for.body.i, %entry 237 %idx = phi i64 [ 0, %entry ], [ %add11.i, %for.body.i ] 238 %sum = phi float [ 0.000000e+00, %entry ], [ %add.i, %for.body.i ] 239 %cmp = icmp ule i64 %idx, 16 240 br i1 %cmp, label %for.body.i, label %for.cond.i.i.i.preheader 241 242for.cond.i.i.i.preheader: ; preds = %for.cond.i 243 ret float %sum 244 245for.body.i: ; preds = %for.cond.i 246 %arrayidx.i84.i = getelementptr inbounds float, ptr %add.ptr, i64 %idx 247 %i1 = load float, ptr %arrayidx.i84.i, align 4 248 %add.i = fadd fast float %sum, %i1 249 %add11.i = add nsw i64 %idx, 1 250 br label %for.cond.i 251} 252 253declare void @use(ptr) 254 255define void @only_one_inbounds(ptr %ptr, i1 %c, i32 noundef %arg1, i32 noundef %arg2) { 256; CHECK-LABEL: @only_one_inbounds( 257; CHECK-NEXT: entry: 258; CHECK-NEXT: [[ARG2_EXT:%.*]] = zext i32 [[ARG2:%.*]] to i64 259; CHECK-NEXT: br label [[LOOP:%.*]] 260; CHECK: loop: 261; CHECK-NEXT: [[ARG1_EXT:%.*]] = zext i32 [[ARG1:%.*]] to i64 262; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR:%.*]], i64 [[ARG1_EXT]] 263; CHECK-NEXT: [[PTR3:%.*]] = getelementptr i8, ptr [[PTR2]], i64 [[ARG2_EXT]] 264; CHECK-NEXT: call void @use(ptr [[PTR3]]) 265; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP]], label [[EXIT:%.*]] 266; CHECK: exit: 267; CHECK-NEXT: ret void 268; 269entry: 270 %arg2.ext = zext i32 %arg2 to i64 271 br label %loop 272 273loop: ; preds = %loop, %entry 274 %arg1.ext = zext i32 %arg1 to i64 275 %ptr2 = getelementptr inbounds i8, ptr %ptr, i64 %arg1.ext 276 %ptr3 = getelementptr i8, ptr %ptr2, i64 %arg2.ext 277 call void @use(ptr %ptr3) 278 br i1 %c, label %loop, label %exit 279 280exit: ; preds = %loop 281 ret void 282} 283 284define void @both_inbounds_one_neg(ptr %ptr, i1 %c, i32 noundef %arg) { 285; CHECK-LABEL: @both_inbounds_one_neg( 286; CHECK-NEXT: entry: 287; CHECK-NEXT: br label [[LOOP:%.*]] 288; CHECK: loop: 289; CHECK-NEXT: [[ARG_EXT:%.*]] = zext i32 [[ARG:%.*]] to i64 290; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR:%.*]], i64 [[ARG_EXT]] 291; CHECK-NEXT: [[PTR3:%.*]] = getelementptr inbounds i8, ptr [[PTR2]], i64 -1 292; CHECK-NEXT: call void @use(ptr nonnull [[PTR3]]) 293; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP]], label [[EXIT:%.*]] 294; CHECK: exit: 295; CHECK-NEXT: ret void 296; 297entry: 298 br label %loop 299 300loop: ; preds = %loop, %entry 301 %arg.ext = zext i32 %arg to i64 302 %ptr2 = getelementptr inbounds i8, ptr %ptr, i64 %arg.ext 303 %ptr3 = getelementptr inbounds i8, ptr %ptr2, i64 -1 304 call void @use(ptr %ptr3) 305 br i1 %c, label %loop, label %exit 306 307exit: ; preds = %loop 308 ret void 309} 310 311define void @both_inbounds_pos(ptr %ptr, i1 %c, i32 noundef %arg) { 312; CHECK-LABEL: @both_inbounds_pos( 313; CHECK-NEXT: entry: 314; CHECK-NEXT: br label [[LOOP:%.*]] 315; CHECK: loop: 316; CHECK-NEXT: [[ARG_EXT:%.*]] = zext i32 [[ARG:%.*]] to i64 317; CHECK-NEXT: [[PTR2:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR:%.*]], i64 [[ARG_EXT]] 318; CHECK-NEXT: [[PTR3:%.*]] = getelementptr inbounds nuw i8, ptr [[PTR2]], i64 1 319; CHECK-NEXT: call void @use(ptr nonnull [[PTR3]]) 320; CHECK-NEXT: br i1 [[C:%.*]], label [[LOOP]], label [[EXIT:%.*]] 321; CHECK: exit: 322; CHECK-NEXT: ret void 323; 324entry: 325 br label %loop 326 327loop: ; preds = %loop, %entry 328 %arg.ext = zext i32 %arg to i64 329 %ptr2 = getelementptr inbounds i8, ptr %ptr, i64 %arg.ext 330 %ptr3 = getelementptr inbounds i8, ptr %ptr2, i64 1 331 call void @use(ptr %ptr3) 332 br i1 %c, label %loop, label %exit 333 334exit: ; preds = %loop 335 ret void 336} 337