1242 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -S -passes=licm -verify-memoryssa < %s | FileCheck %s3; RUN: opt -aa-pipeline=basic-aa -passes='require<opt-remark-emit>,loop-mssa(loop-simplifycfg,licm)' -verify-memoryssa -S < %s | FileCheck %s4 5target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6target triple = "x86_64-unknown-linux-gnu"7 8; This test represents the following function:9; void test1(int * __restrict__ a, int * __restrict__ b, int &c, int n) {10; for (int i = 0; i < n; ++i)11; if (a[i] > 0)12; a[i] = c*b[i];13; }14; and we want to hoist the load of %c out of the loop. This can be done only15; because the dereferenceable attribute is on %c.16 17define void @test1(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly nonnull dereferenceable(4) align 4 %c, i32 %n) #0 {18; CHECK-LABEL: @test1(19; CHECK-NEXT: entry:20; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 021; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]22; CHECK: for.body.preheader:23; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C:%.*]], align 424; CHECK-NEXT: br label [[FOR_BODY:%.*]]25; CHECK: for.body:26; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]27; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]28; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 429; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 030; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]31; CHECK: if.then:32; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]33; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 434; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]35; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 436; CHECK-NEXT: br label [[FOR_INC]]37; CHECK: for.inc:38; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 139; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i3240; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]41; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]42; CHECK: for.end.loopexit:43; CHECK-NEXT: br label [[FOR_END]]44; CHECK: for.end:45; CHECK-NEXT: ret void46;47entry:48 %cmp11 = icmp sgt i32 %n, 049 br i1 %cmp11, label %for.body, label %for.end50 51for.body: ; preds = %entry, %for.inc52 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]53 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv54 %0 = load i32, ptr %arrayidx, align 455 %cmp1 = icmp sgt i32 %0, 056 br i1 %cmp1, label %if.then, label %for.inc57 58if.then: ; preds = %for.body59 %1 = load i32, ptr %c, align 460 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv61 %2 = load i32, ptr %arrayidx3, align 462 %mul = mul nsw i32 %2, %163 store i32 %mul, ptr %arrayidx, align 464 br label %for.inc65 66for.inc: ; preds = %for.body, %if.then67 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 168 %lftr.wideiv = trunc i64 %indvars.iv.next to i3269 %exitcond = icmp eq i32 %lftr.wideiv, %n70 br i1 %exitcond, label %for.end, label %for.body71 72for.end: ; preds = %for.inc, %entry73 ret void74}75 76; This is the same as @test1, but without the dereferenceable attribute on %c.77; Without this attribute, we should not hoist the load of %c.78define void @test2(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly nonnull %c, i32 %n) #0 {79; CHECK-LABEL: @test2(80; CHECK-NEXT: entry:81; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 082; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]83; CHECK: for.body.preheader:84; CHECK-NEXT: br label [[FOR_BODY:%.*]]85; CHECK: for.body:86; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]87; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]88; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 489; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 090; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]91; CHECK: if.then:92; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C:%.*]], align 493; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]94; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 495; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]96; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 497; CHECK-NEXT: br label [[FOR_INC]]98; CHECK: for.inc:99; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1100; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32101; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]102; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]103; CHECK: for.end.loopexit:104; CHECK-NEXT: br label [[FOR_END]]105; CHECK: for.end:106; CHECK-NEXT: ret void107;108entry:109 %cmp11 = icmp sgt i32 %n, 0110 br i1 %cmp11, label %for.body, label %for.end111 112for.body: ; preds = %entry, %for.inc113 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]114 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv115 %0 = load i32, ptr %arrayidx, align 4116 %cmp1 = icmp sgt i32 %0, 0117 br i1 %cmp1, label %if.then, label %for.inc118 119if.then: ; preds = %for.body120 %1 = load i32, ptr %c, align 4121 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv122 %2 = load i32, ptr %arrayidx3, align 4123 %mul = mul nsw i32 %2, %1124 store i32 %mul, ptr %arrayidx, align 4125 br label %for.inc126 127for.inc: ; preds = %for.body, %if.then128 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1129 %lftr.wideiv = trunc i64 %indvars.iv.next to i32130 %exitcond = icmp eq i32 %lftr.wideiv, %n131 br i1 %exitcond, label %for.end, label %for.body132 133for.end: ; preds = %for.inc, %entry134 ret void135}136 137; This test represents the following function:138; void test3(int * restrict a, int * restrict b, int c[static 3], int n) {139; for (int i = 0; i < n; ++i)140; if (a[i] > 0)141; a[i] = cptr b[i];142; }143; and we want to hoist the load of c[2] out of the loop. This can be done only144; because the dereferenceable attribute is on %c.145define void @test3(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly dereferenceable(12) align 4 %c, i32 %n) #0 {146; CHECK-LABEL: @test3(147; CHECK-NEXT: entry:148; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0149; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]150; CHECK: for.body.preheader:151; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i64 2152; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C2]], align 4153; CHECK-NEXT: br label [[FOR_BODY:%.*]]154; CHECK: for.body:155; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]156; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]157; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4158; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0159; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]160; CHECK: if.then:161; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]162; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4163; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]164; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4165; CHECK-NEXT: br label [[FOR_INC]]166; CHECK: for.inc:167; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1168; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32169; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]170; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]171; CHECK: for.end.loopexit:172; CHECK-NEXT: br label [[FOR_END]]173; CHECK: for.end:174; CHECK-NEXT: ret void175;176entry:177 %cmp11 = icmp sgt i32 %n, 0178 br i1 %cmp11, label %for.body, label %for.end179 180for.body: ; preds = %entry, %for.inc181 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]182 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv183 %0 = load i32, ptr %arrayidx, align 4184 %cmp1 = icmp sgt i32 %0, 0185 br i1 %cmp1, label %if.then, label %for.inc186 187if.then: ; preds = %for.body188 %c2 = getelementptr inbounds i32, ptr %c, i64 2189 %1 = load i32, ptr %c2, align 4190 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv191 %2 = load i32, ptr %arrayidx3, align 4192 %mul = mul nsw i32 %2, %1193 store i32 %mul, ptr %arrayidx, align 4194 br label %for.inc195 196for.inc: ; preds = %for.body, %if.then197 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1198 %lftr.wideiv = trunc i64 %indvars.iv.next to i32199 %exitcond = icmp eq i32 %lftr.wideiv, %n200 br i1 %exitcond, label %for.end, label %for.body201 202for.end: ; preds = %for.inc, %entry203 ret void204}205 206; This is the same as @test3, but with a dereferenceable attribute on %c with a207; size too small to cover c[2] (and so we should not hoist it).208define void @test4(ptr noalias nocapture %a, ptr noalias nocapture readonly %b, ptr nocapture readonly dereferenceable(11) %c, i32 %n) #0 {209; CHECK-LABEL: @test4(210; CHECK-NEXT: entry:211; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0212; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]213; CHECK: for.body.preheader:214; CHECK-NEXT: [[C2:%.*]] = getelementptr inbounds i32, ptr [[C:%.*]], i64 2215; CHECK-NEXT: br label [[FOR_BODY:%.*]]216; CHECK: for.body:217; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]218; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]219; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4220; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0221; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]222; CHECK: if.then:223; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C2]], align 4224; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]225; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4226; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]227; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4228; CHECK-NEXT: br label [[FOR_INC]]229; CHECK: for.inc:230; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1231; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32232; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]233; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]234; CHECK: for.end.loopexit:235; CHECK-NEXT: br label [[FOR_END]]236; CHECK: for.end:237; CHECK-NEXT: ret void238;239entry:240 %cmp11 = icmp sgt i32 %n, 0241 br i1 %cmp11, label %for.body, label %for.end242 243for.body: ; preds = %entry, %for.inc244 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]245 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv246 %0 = load i32, ptr %arrayidx, align 4247 %cmp1 = icmp sgt i32 %0, 0248 br i1 %cmp1, label %if.then, label %for.inc249 250if.then: ; preds = %for.body251 %c2 = getelementptr inbounds i32, ptr %c, i64 2252 %1 = load i32, ptr %c2, align 4253 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv254 %2 = load i32, ptr %arrayidx3, align 4255 %mul = mul nsw i32 %2, %1256 store i32 %mul, ptr %arrayidx, align 4257 br label %for.inc258 259for.inc: ; preds = %for.body, %if.then260 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1261 %lftr.wideiv = trunc i64 %indvars.iv.next to i32262 %exitcond = icmp eq i32 %lftr.wideiv, %n263 br i1 %exitcond, label %for.end, label %for.body264 265for.end: ; preds = %for.inc, %entry266 ret void267}268 269; This test represents the following function:270; void test1(int * __restrict__ a, int *b, int &c, int n) {271; if (c != null)272; for (int i = 0; i < n; ++i)273; if (a[i] > 0)274; a[i] = c*b[i];275; }276; and we want to hoist the load of %c out of the loop. This can be done only277; because the dereferenceable_or_null attribute is on %c and there is a null278; check on %c.279define void @test5(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n) #0 {280; CHECK-LABEL: @test5(281; CHECK-NEXT: entry:282; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null283; CHECK-NEXT: br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]284; CHECK: not.null:285; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0286; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]287; CHECK: for.body.preheader:288; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4289; CHECK-NEXT: br label [[FOR_BODY:%.*]]290; CHECK: for.body:291; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]292; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]293; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4294; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0295; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]296; CHECK: if.then:297; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]298; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4299; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]300; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4301; CHECK-NEXT: br label [[FOR_INC]]302; CHECK: for.inc:303; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1304; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32305; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]306; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]307; CHECK: for.end.loopexit:308; CHECK-NEXT: br label [[FOR_END]]309; CHECK: for.end:310; CHECK-NEXT: ret void311;312entry:313 %not_null = icmp ne ptr %c, null314 br i1 %not_null, label %not.null, label %for.end315 316not.null:317 %cmp11 = icmp sgt i32 %n, 0318 br i1 %cmp11, label %for.body, label %for.end319 320for.body: ; preds = %not.null, %for.inc321 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]322 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv323 %0 = load i32, ptr %arrayidx, align 4324 %cmp1 = icmp sgt i32 %0, 0325 br i1 %cmp1, label %if.then, label %for.inc326 327if.then: ; preds = %for.body328 %1 = load i32, ptr %c, align 4329 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv330 %2 = load i32, ptr %arrayidx3, align 4331 %mul = mul nsw i32 %2, %1332 store i32 %mul, ptr %arrayidx, align 4333 br label %for.inc334 335for.inc: ; preds = %for.body, %if.then336 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1337 %lftr.wideiv = trunc i64 %indvars.iv.next to i32338 %exitcond = icmp eq i32 %lftr.wideiv, %n339 br i1 %exitcond, label %for.end, label %for.body340 341for.end: ; preds = %for.inc, %entry, %not.null342 ret void343}344 345; This is the same as @test5, but without the null check on %c.346; Without this check, we should not hoist the load of %c.347 348; This test case has an icmp on c but the use of this comparison is349; not a branch.350define i1 @test6(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n) #0 {351; CHECK-LABEL: @test6(352; CHECK-NEXT: entry:353; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null354; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0355; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]356; CHECK: for.body.preheader:357; CHECK-NEXT: br label [[FOR_BODY:%.*]]358; CHECK: for.body:359; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]360; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]361; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4362; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0363; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]364; CHECK: if.then:365; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4366; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]367; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4368; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]369; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4370; CHECK-NEXT: br label [[FOR_INC]]371; CHECK: for.inc:372; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1373; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32374; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]375; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]376; CHECK: for.end.loopexit:377; CHECK-NEXT: br label [[FOR_END]]378; CHECK: for.end:379; CHECK-NEXT: ret i1 [[NOT_NULL]]380;381entry:382 %not_null = icmp ne ptr %c, null383 %cmp11 = icmp sgt i32 %n, 0384 br i1 %cmp11, label %for.body, label %for.end385 386for.body: ; preds = %entry, %for.inc387 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]388 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv389 %0 = load i32, ptr %arrayidx, align 4390 %cmp1 = icmp sgt i32 %0, 0391 br i1 %cmp1, label %if.then, label %for.inc392 393if.then: ; preds = %for.body394 %1 = load i32, ptr %c, align 4395 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv396 %2 = load i32, ptr %arrayidx3, align 4397 %mul = mul nsw i32 %2, %1398 store i32 %mul, ptr %arrayidx, align 4399 br label %for.inc400 401for.inc: ; preds = %for.body, %if.then402 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1403 %lftr.wideiv = trunc i64 %indvars.iv.next to i32404 %exitcond = icmp eq i32 %lftr.wideiv, %n405 br i1 %exitcond, label %for.end, label %for.body406 407for.end: ; preds = %for.inc, %entry408 ret i1 %not_null409}410 411; This test represents the following function:412; void test1(int * __restrict__ a, int *b, int **cptr, int n) {413; c = *cptr;414; for (int i = 0; i < n; ++i)415; if (a[i] > 0)416; a[i] = (*c)*b[i];417; }418; and we want to hoist the load of %c out of the loop. This can be done only419; because the dereferenceable meatdata on the c = *cptr load.420define void @test7(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {421; CHECK-LABEL: @test7(422; CHECK-NEXT: entry:423; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0:![0-9]+]], !align [[META0]]424; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0425; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]426; CHECK: for.body.preheader:427; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4428; CHECK-NEXT: br label [[FOR_BODY:%.*]]429; CHECK: for.body:430; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]431; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]432; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4433; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0434; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]435; CHECK: if.then:436; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]437; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4438; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]439; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4440; CHECK-NEXT: br label [[FOR_INC]]441; CHECK: for.inc:442; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1443; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32444; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]445; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]446; CHECK: for.end.loopexit:447; CHECK-NEXT: br label [[FOR_END]]448; CHECK: for.end:449; CHECK-NEXT: ret void450;451entry:452 %c = load ptr, ptr %cptr, !dereferenceable !0, !align !{i64 4}453 %cmp11 = icmp sgt i32 %n, 0454 br i1 %cmp11, label %for.body, label %for.end455 456for.body: ; preds = %entry, %for.inc457 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]458 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv459 %0 = load i32, ptr %arrayidx, align 4460 %cmp1 = icmp sgt i32 %0, 0461 br i1 %cmp1, label %if.then, label %for.inc462 463if.then: ; preds = %for.body464 %1 = load i32, ptr %c, align 4465 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv466 %2 = load i32, ptr %arrayidx3, align 4467 %mul = mul nsw i32 %2, %1468 store i32 %mul, ptr %arrayidx, align 4469 br label %for.inc470 471for.inc: ; preds = %for.body, %if.then472 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1473 %lftr.wideiv = trunc i64 %indvars.iv.next to i32474 %exitcond = icmp eq i32 %lftr.wideiv, %n475 br i1 %exitcond, label %for.end, label %for.body476 477for.end: ; preds = %for.inc, %entry478 ret void479}480 481; This test represents the following function:482; void test1(int * __restrict__ a, int *b, int **cptr, int n) {483; c = *cptr;484; if (c != null)485; for (int i = 0; i < n; ++i)486; if (a[i] > 0)487; a[i] = (*c)*b[i];488; }489; and we want to hoist the load of %c out of the loop. This can be done only490; because the dereferenceable_or_null meatdata on the c = *cptr load and there491; is a null check on %c.492define void @test8(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {493; CHECK-LABEL: @test8(494; CHECK-NEXT: entry:495; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]], !align [[META0]]496; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C]], null497; CHECK-NEXT: br i1 [[NOT_NULL]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]498; CHECK: not.null:499; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0500; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]501; CHECK: for.body.preheader:502; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4503; CHECK-NEXT: br label [[FOR_BODY:%.*]]504; CHECK: for.body:505; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]506; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]507; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4508; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0509; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]510; CHECK: if.then:511; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]512; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4513; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]514; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4515; CHECK-NEXT: br label [[FOR_INC]]516; CHECK: for.inc:517; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1518; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32519; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]520; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]521; CHECK: for.end.loopexit:522; CHECK-NEXT: br label [[FOR_END]]523; CHECK: for.end:524; CHECK-NEXT: ret void525;526entry:527 %c = load ptr, ptr %cptr, !dereferenceable_or_null !0, !align !{i64 4}528 %not_null = icmp ne ptr %c, null529 br i1 %not_null, label %not.null, label %for.end530 531not.null:532 %cmp11 = icmp sgt i32 %n, 0533 br i1 %cmp11, label %for.body, label %for.end534 535for.body: ; preds = %not.null, %for.inc536 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]537 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv538 %0 = load i32, ptr %arrayidx, align 4539 %cmp1 = icmp sgt i32 %0, 0540 br i1 %cmp1, label %if.then, label %for.inc541 542if.then: ; preds = %for.body543 %1 = load i32, ptr %c, align 4544 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv545 %2 = load i32, ptr %arrayidx3, align 4546 %mul = mul nsw i32 %2, %1547 store i32 %mul, ptr %arrayidx, align 4548 br label %for.inc549 550for.inc: ; preds = %for.body, %if.then551 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1552 %lftr.wideiv = trunc i64 %indvars.iv.next to i32553 %exitcond = icmp eq i32 %lftr.wideiv, %n554 br i1 %exitcond, label %for.end, label %for.body555 556for.end: ; preds = %for.inc, %entry, %not.null557 ret void558}559 560; This is the same as @test8, but without the null check on %c.561; Without this check, we should not hoist the load of %c.562define void @test9(ptr noalias %a, ptr %b, ptr %cptr, i32 %n) #0 {563; CHECK-LABEL: @test9(564; CHECK-NEXT: entry:565; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable_or_null [[META0]]566; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0567; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]568; CHECK: for.body.preheader:569; CHECK-NEXT: br label [[FOR_BODY:%.*]]570; CHECK: for.body:571; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]572; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]573; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4574; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0575; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]576; CHECK: if.then:577; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4578; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]579; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4580; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]581; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4582; CHECK-NEXT: br label [[FOR_INC]]583; CHECK: for.inc:584; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1585; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32586; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]587; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]588; CHECK: for.end.loopexit:589; CHECK-NEXT: br label [[FOR_END]]590; CHECK: for.end:591; CHECK-NEXT: ret void592;593entry:594 %c = load ptr, ptr %cptr, !dereferenceable_or_null !0595 %cmp11 = icmp sgt i32 %n, 0596 br i1 %cmp11, label %for.body, label %for.end597 598for.body: ; preds = %entry, %for.inc599 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]600 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv601 %0 = load i32, ptr %arrayidx, align 4602 %cmp1 = icmp sgt i32 %0, 0603 br i1 %cmp1, label %if.then, label %for.inc604 605if.then: ; preds = %for.body606 %1 = load i32, ptr %c, align 4607 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv608 %2 = load i32, ptr %arrayidx3, align 4609 %mul = mul nsw i32 %2, %1610 store i32 %mul, ptr %arrayidx, align 4611 br label %for.inc612 613for.inc: ; preds = %for.body, %if.then614 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1615 %lftr.wideiv = trunc i64 %indvars.iv.next to i32616 %exitcond = icmp eq i32 %lftr.wideiv, %n617 br i1 %exitcond, label %for.end, label %for.body618 619for.end: ; preds = %for.inc, %entry620 ret void621}622 623; In this test we should be able to only hoist load from %cptr. We can't hoist624; load from %c because it's dereferenceability can depend on %cmp1 condition.625; By moving it out of the loop we break this dependency and can not rely626; on the dereferenceability anymore.627; In other words this test checks that we strip dereferenceability metadata628; after hoisting an instruction.629define void @test10(ptr noalias %a, ptr %b, ptr dereferenceable(8) align 8 %cptr, i32 %n) #0 {630; CHECK-LABEL: @test10(631; CHECK-NEXT: entry:632; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0633; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]634; CHECK: for.body.preheader:635; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8636; CHECK-NEXT: br label [[FOR_BODY:%.*]]637; CHECK: for.body:638; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]639; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]640; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4641; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0642; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]643; CHECK: if.then:644; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4645; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]646; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4647; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]648; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4649; CHECK-NEXT: br label [[FOR_INC]]650; CHECK: for.inc:651; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1652; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32653; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]654; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]655; CHECK: for.end.loopexit:656; CHECK-NEXT: br label [[FOR_END]]657; CHECK: for.end:658; CHECK-NEXT: ret void659;660entry:661 %cmp11 = icmp sgt i32 %n, 0662 br i1 %cmp11, label %for.body, label %for.end663 664for.body: ; preds = %entry, %for.inc665 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]666 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv667 %0 = load i32, ptr %arrayidx, align 4668 %cmp1 = icmp sgt i32 %0, 0669 br i1 %cmp1, label %if.then, label %for.inc670 671if.then: ; preds = %for.body672 %c = load ptr, ptr %cptr, !dereferenceable !0673 %1 = load i32, ptr %c, align 4674 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv675 %2 = load i32, ptr %arrayidx3, align 4676 %mul = mul nsw i32 %2, %1677 store i32 %mul, ptr %arrayidx, align 4678 br label %for.inc679 680for.inc: ; preds = %for.body, %if.then681 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1682 %lftr.wideiv = trunc i64 %indvars.iv.next to i32683 %exitcond = icmp eq i32 %lftr.wideiv, %n684 br i1 %exitcond, label %for.end, label %for.body685 686for.end: ; preds = %for.inc, %entry687 ret void688}689 690define void @test11(ptr noalias %a, ptr %b, ptr dereferenceable(8) %cptr, i32 %n) #0 {691; CHECK-LABEL: @test11(692; CHECK-NEXT: entry:693; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0694; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]695; CHECK: for.body.preheader:696; CHECK-NEXT: [[C:%.*]] = load ptr, ptr [[CPTR:%.*]], align 8, !dereferenceable [[META0]]697; CHECK-NEXT: br label [[FOR_BODY:%.*]]698; CHECK: for.body:699; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]700; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]701; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4702; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0703; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]704; CHECK: if.then:705; CHECK-NEXT: [[D:%.*]] = load i32, ptr [[C]], align 4706; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]707; CHECK-NEXT: [[E:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4708; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[E]], [[D]]709; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4710; CHECK-NEXT: br label [[FOR_INC]]711; CHECK: for.inc:712; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1713; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32714; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]715; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]716; CHECK: for.end.loopexit:717; CHECK-NEXT: br label [[FOR_END]]718; CHECK: for.end:719; CHECK-NEXT: ret void720;721entry:722 %cmp11 = icmp sgt i32 %n, 0723 br i1 %cmp11, label %for.body, label %for.end724 725 726 727for.body: ; preds = %entry, %for.inc728 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]729 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv730 %0 = load i32, ptr %arrayidx, align 4731 %cmp1 = icmp sgt i32 %0, 0732 %c = load ptr, ptr %cptr, !dereferenceable !0733 br i1 %cmp1, label %if.then, label %for.inc734 735if.then: ; preds = %for.body736 %d = load i32, ptr %c, align 4737 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv738 %e = load i32, ptr %arrayidx3, align 4739 %mul = mul nsw i32 %e, %d740 store i32 %mul, ptr %arrayidx, align 4741 br label %for.inc742 743for.inc: ; preds = %for.body, %if.then744 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1745 %lftr.wideiv = trunc i64 %indvars.iv.next to i32746 %exitcond = icmp eq i32 %lftr.wideiv, %n747 br i1 %exitcond, label %for.end, label %for.body748 749for.end: ; preds = %for.inc, %entry750 ret void751}752 753declare void @llvm.experimental.guard(i1, ...)754 755; Prove non-null ness of %c via a guard, not a branch.756define void @test12(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n) #0 {757; CHECK-LABEL: @test12(758; CHECK-NEXT: entry:759; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null760; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[NOT_NULL]]) [ "deopt"() ]761; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0762; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]763; CHECK: for.body.preheader:764; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4765; CHECK-NEXT: br label [[FOR_BODY:%.*]]766; CHECK: for.body:767; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]768; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]769; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4770; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0771; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]772; CHECK: if.then:773; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]774; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4775; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]776; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4777; CHECK-NEXT: br label [[FOR_INC]]778; CHECK: for.inc:779; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1780; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32781; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]782; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]783; CHECK: for.end.loopexit:784; CHECK-NEXT: br label [[FOR_END]]785; CHECK: for.end:786; CHECK-NEXT: ret void787;788entry:789 %not_null = icmp ne ptr %c, null790 call void(i1, ...) @llvm.experimental.guard(i1 %not_null) [ "deopt"() ]791 %cmp11 = icmp sgt i32 %n, 0792 br i1 %cmp11, label %for.body, label %for.end793 794 795 796for.body: ; preds = %entry, %for.inc797 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]798 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv799 %0 = load i32, ptr %arrayidx, align 4800 %cmp1 = icmp sgt i32 %0, 0801 br i1 %cmp1, label %if.then, label %for.inc802 803if.then: ; preds = %for.body804 %1 = load i32, ptr %c, align 4805 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv806 %2 = load i32, ptr %arrayidx3, align 4807 %mul = mul nsw i32 %2, %1808 store i32 %mul, ptr %arrayidx, align 4809 br label %for.inc810 811for.inc: ; preds = %for.body, %if.then812 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1813 %lftr.wideiv = trunc i64 %indvars.iv.next to i32814 %exitcond = icmp eq i32 %lftr.wideiv, %n815 br i1 %exitcond, label %for.end, label %for.body816 817for.end: ; preds = %for.inc, %entry, %entry818 ret void819}820 821; Like @test12, but has a post-dominating guard, which cannot be used822; to prove %c is nonnull at the point of the load.823define void @test13(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n) #0 {824; CHECK-LABEL: @test13(825; CHECK-NEXT: entry:826; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null827; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0828; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]829; CHECK: for.body.preheader:830; CHECK-NEXT: br label [[FOR_BODY:%.*]]831; CHECK: for.body:832; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]833; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]834; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 4835; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 0836; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]837; CHECK: if.then:838; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 4839; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]840; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4841; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]842; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4843; CHECK-NEXT: br label [[FOR_INC]]844; CHECK: for.inc:845; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1846; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32847; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]848; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]849; CHECK: for.end.loopexit:850; CHECK-NEXT: br label [[FOR_END]]851; CHECK: for.end:852; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[NOT_NULL]]) [ "deopt"() ]853; CHECK-NEXT: ret void854;855entry:856 %not_null = icmp ne ptr %c, null857 %cmp11 = icmp sgt i32 %n, 0858 br i1 %cmp11, label %for.body, label %for.end859 860 861for.body: ; preds = %entry, %for.inc862 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]863 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv864 %0 = load i32, ptr %arrayidx, align 4865 %cmp1 = icmp sgt i32 %0, 0866 br i1 %cmp1, label %if.then, label %for.inc867 868if.then: ; preds = %for.body869 %1 = load i32, ptr %c, align 4870 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv871 %2 = load i32, ptr %arrayidx3, align 4872 %mul = mul nsw i32 %2, %1873 store i32 %mul, ptr %arrayidx, align 4874 br label %for.inc875 876for.inc: ; preds = %for.body, %if.then877 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1878 %lftr.wideiv = trunc i64 %indvars.iv.next to i32879 %exitcond = icmp eq i32 %lftr.wideiv, %n880 br i1 %exitcond, label %for.end, label %for.body881 882for.end: ; preds = %for.inc, %entry, %entry883 call void(i1, ...) @llvm.experimental.guard(i1 %not_null) [ "deopt"() ]884 ret void885}886 887; Check that branch by condition "null check AND something" allows to hoist the888; load.889define void @test14(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n, i1 %dummy_cond) #0 {890; CHECK-LABEL: @test14(891; CHECK-NEXT: entry:892; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null893; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]894; CHECK-NEXT: br i1 [[DUMMY_AND]], label [[NOT_NULL:%.*]], label [[FOR_END:%.*]]895; CHECK: not.null:896; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0897; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]898; CHECK: for.body.preheader:899; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4900; CHECK-NEXT: br label [[FOR_BODY:%.*]]901; CHECK: for.body:902; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]903; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]904; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4905; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0906; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]907; CHECK: if.then:908; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]909; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4910; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]911; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4912; CHECK-NEXT: br label [[FOR_INC]]913; CHECK: for.inc:914; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1915; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32916; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]917; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]918; CHECK: for.end.loopexit:919; CHECK-NEXT: br label [[FOR_END]]920; CHECK: for.end:921; CHECK-NEXT: ret void922;923 924entry:925 %not_null = icmp ne ptr %c, null926 %dummy_and = and i1 %not_null, %dummy_cond927 br i1 %dummy_and, label %not.null, label %for.end928 929not.null:930 %cmp11 = icmp sgt i32 %n, 0931 br i1 %cmp11, label %for.body, label %for.end932 933for.body: ; preds = %not.null, %for.inc934 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]935 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv936 %0 = load i32, ptr %arrayidx, align 4937 %cmp1 = icmp sgt i32 %0, 0938 br i1 %cmp1, label %if.then, label %for.inc939 940if.then: ; preds = %for.body941 %1 = load i32, ptr %c, align 4942 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv943 %2 = load i32, ptr %arrayidx3, align 4944 %mul = mul nsw i32 %2, %1945 store i32 %mul, ptr %arrayidx, align 4946 br label %for.inc947 948for.inc: ; preds = %for.body, %if.then949 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 1950 %lftr.wideiv = trunc i64 %indvars.iv.next to i32951 %exitcond = icmp eq i32 %lftr.wideiv, %n952 br i1 %exitcond, label %for.end, label %for.body953 954for.end: ; preds = %for.inc, %entry, %not.null955 ret void956}957 958; Check that guard by condition "null check AND something" allows to hoist the959; load.960define void @test15(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) align 4 %c, i32 %n, i1 %dummy_cond) #0 {961; CHECK-LABEL: @test15(962; CHECK-NEXT: entry:963; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp ne ptr [[C:%.*]], null964; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]965; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[DUMMY_AND]]) [ "deopt"() ]966; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 0967; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END:%.*]]968; CHECK: for.body.preheader:969; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[C]], align 4970; CHECK-NEXT: br label [[FOR_BODY:%.*]]971; CHECK: for.body:972; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]973; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]974; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[ARRAYIDX]], align 4975; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP1]], 0976; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]977; CHECK: if.then:978; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]979; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 4980; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP0]]981; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 4982; CHECK-NEXT: br label [[FOR_INC]]983; CHECK: for.inc:984; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 1985; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i32986; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]987; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]988; CHECK: for.end.loopexit:989; CHECK-NEXT: br label [[FOR_END]]990; CHECK: for.end:991; CHECK-NEXT: ret void992;993 994entry:995 %not_null = icmp ne ptr %c, null996 %dummy_and = and i1 %not_null, %dummy_cond997 call void(i1, ...) @llvm.experimental.guard(i1 %dummy_and) [ "deopt"() ]998 %cmp11 = icmp sgt i32 %n, 0999 br i1 %cmp11, label %for.body, label %for.end1000 1001for.body: ; preds = %entry, %for.inc1002 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]1003 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv1004 %0 = load i32, ptr %arrayidx, align 41005 %cmp1 = icmp sgt i32 %0, 01006 br i1 %cmp1, label %if.then, label %for.inc1007 1008if.then: ; preds = %for.body1009 %1 = load i32, ptr %c, align 41010 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv1011 %2 = load i32, ptr %arrayidx3, align 41012 %mul = mul nsw i32 %2, %11013 store i32 %mul, ptr %arrayidx, align 41014 br label %for.inc1015 1016for.inc: ; preds = %for.body, %if.then1017 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 11018 %lftr.wideiv = trunc i64 %indvars.iv.next to i321019 %exitcond = icmp eq i32 %lftr.wideiv, %n1020 br i1 %exitcond, label %for.end, label %for.body1021 1022for.end: ; preds = %for.inc, %entry1023 ret void1024}1025 1026; Ensure that (c == null && other_cond) does not automatically mean that c is1027; non-null in false branch. So the condition ((c == null && other_cond) == false)1028; is not sufficient to conclude that c != null.1029define void @test16(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n, i1 %dummy_cond) #0 {1030; CHECK-LABEL: @test16(1031; CHECK-NEXT: entry:1032; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq ptr [[C:%.*]], null1033; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]1034; CHECK-NEXT: br i1 [[DUMMY_AND]], label [[FOR_END:%.*]], label [[NOT_NULL:%.*]]1035; CHECK: not.null:1036; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 01037; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_BODY_PREHEADER:%.*]], label [[FOR_END]]1038; CHECK: for.body.preheader:1039; CHECK-NEXT: br label [[FOR_BODY:%.*]]1040; CHECK: for.body:1041; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]1042; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]1043; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 41044; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 01045; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]1046; CHECK: if.then:1047; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 41048; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]1049; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 41050; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]1051; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 41052; CHECK-NEXT: br label [[FOR_INC]]1053; CHECK: for.inc:1054; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 11055; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i321056; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]1057; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]1058; CHECK: for.end.loopexit:1059; CHECK-NEXT: br label [[FOR_END]]1060; CHECK: for.end:1061; CHECK-NEXT: ret void1062;1063 1064entry:1065 %not_null = icmp eq ptr %c, null1066 %dummy_and = and i1 %not_null, %dummy_cond1067 br i1 %dummy_and, label %for.end, label %not.null1068 1069not.null:1070 %cmp11 = icmp sgt i32 %n, 01071 br i1 %cmp11, label %for.body, label %for.end1072 1073for.body: ; preds = %not.null, %for.inc1074 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %not.null ]1075 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv1076 %0 = load i32, ptr %arrayidx, align 41077 %cmp1 = icmp sgt i32 %0, 01078 br i1 %cmp1, label %if.then, label %for.inc1079 1080if.then: ; preds = %for.body1081 %1 = load i32, ptr %c, align 41082 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv1083 %2 = load i32, ptr %arrayidx3, align 41084 %mul = mul nsw i32 %2, %11085 store i32 %mul, ptr %arrayidx, align 41086 br label %for.inc1087 1088for.inc: ; preds = %for.body, %if.then1089 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 11090 %lftr.wideiv = trunc i64 %indvars.iv.next to i321091 %exitcond = icmp eq i32 %lftr.wideiv, %n1092 br i1 %exitcond, label %for.end, label %for.body1093 1094for.end: ; preds = %for.inc, %entry, %not.null1095 ret void1096}1097 1098; Ensure that (c == null && other_cond) does not automatically mean that c is1099; non-null in false branch. So the condition ((c == null && other_cond) == false)1100; is not sufficient to conclude that c != null.1101define void @test17(ptr noalias %a, ptr %b, ptr dereferenceable_or_null(4) %c, i32 %n, i1 %dummy_cond) #0 {1102; CHECK-LABEL: @test17(1103; CHECK-NEXT: entry:1104; CHECK-NEXT: [[NOT_NULL:%.*]] = icmp eq ptr [[C:%.*]], null1105; CHECK-NEXT: [[DUMMY_AND:%.*]] = and i1 [[NOT_NULL]], [[DUMMY_COND:%.*]]1106; CHECK-NEXT: call void (i1, ...) @llvm.experimental.guard(i1 [[DUMMY_AND]]) [ "deopt"() ]1107; CHECK-NEXT: [[CMP11:%.*]] = icmp sgt i32 [[N:%.*]], 01108; CHECK-NEXT: br i1 [[CMP11]], label [[FOR_END:%.*]], label [[FOR_BODY_PREHEADER:%.*]]1109; CHECK: for.body.preheader:1110; CHECK-NEXT: br label [[FOR_BODY:%.*]]1111; CHECK: for.body:1112; CHECK-NEXT: [[INDVARS_IV:%.*]] = phi i64 [ [[INDVARS_IV_NEXT:%.*]], [[FOR_INC:%.*]] ], [ 0, [[FOR_BODY_PREHEADER]] ]1113; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds i32, ptr [[A:%.*]], i64 [[INDVARS_IV]]1114; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[ARRAYIDX]], align 41115; CHECK-NEXT: [[CMP1:%.*]] = icmp sgt i32 [[TMP0]], 01116; CHECK-NEXT: br i1 [[CMP1]], label [[IF_THEN:%.*]], label [[FOR_INC]]1117; CHECK: if.then:1118; CHECK-NEXT: [[TMP1:%.*]] = load i32, ptr [[C]], align 41119; CHECK-NEXT: [[ARRAYIDX3:%.*]] = getelementptr inbounds i32, ptr [[B:%.*]], i64 [[INDVARS_IV]]1120; CHECK-NEXT: [[TMP2:%.*]] = load i32, ptr [[ARRAYIDX3]], align 41121; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[TMP2]], [[TMP1]]1122; CHECK-NEXT: store i32 [[MUL]], ptr [[ARRAYIDX]], align 41123; CHECK-NEXT: br label [[FOR_INC]]1124; CHECK: for.inc:1125; CHECK-NEXT: [[INDVARS_IV_NEXT]] = add nuw nsw i64 [[INDVARS_IV]], 11126; CHECK-NEXT: [[LFTR_WIDEIV:%.*]] = trunc i64 [[INDVARS_IV_NEXT]] to i321127; CHECK-NEXT: [[EXITCOND:%.*]] = icmp eq i32 [[LFTR_WIDEIV]], [[N]]1128; CHECK-NEXT: br i1 [[EXITCOND]], label [[FOR_END_LOOPEXIT:%.*]], label [[FOR_BODY]]1129; CHECK: for.end.loopexit:1130; CHECK-NEXT: br label [[FOR_END]]1131; CHECK: for.end:1132; CHECK-NEXT: ret void1133;1134 1135entry:1136 %not_null = icmp eq ptr %c, null1137 %dummy_and = and i1 %not_null, %dummy_cond1138 call void(i1, ...) @llvm.experimental.guard(i1 %dummy_and) [ "deopt"() ]1139 %cmp11 = icmp sgt i32 %n, 01140 br i1 %cmp11, label %for.end, label %for.body1141 1142for.body: ; preds = %entry, %for.inc1143 %indvars.iv = phi i64 [ %indvars.iv.next, %for.inc ], [ 0, %entry ]1144 %arrayidx = getelementptr inbounds i32, ptr %a, i64 %indvars.iv1145 %0 = load i32, ptr %arrayidx, align 41146 %cmp1 = icmp sgt i32 %0, 01147 br i1 %cmp1, label %if.then, label %for.inc1148 1149if.then: ; preds = %for.body1150 %1 = load i32, ptr %c, align 41151 %arrayidx3 = getelementptr inbounds i32, ptr %b, i64 %indvars.iv1152 %2 = load i32, ptr %arrayidx3, align 41153 %mul = mul nsw i32 %2, %11154 store i32 %mul, ptr %arrayidx, align 41155 br label %for.inc1156 1157for.inc: ; preds = %for.body, %if.then1158 %indvars.iv.next = add nuw nsw i64 %indvars.iv, 11159 %lftr.wideiv = trunc i64 %indvars.iv.next to i321160 %exitcond = icmp eq i32 %lftr.wideiv, %n1161 br i1 %exitcond, label %for.end, label %for.body1162 1163for.end: ; preds = %for.inc, %entry1164 ret void1165}1166 1167declare void @use(i64)1168 1169define void @licm_deref_no_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {1170; CHECK-LABEL: @licm_deref_no_hoist(1171; CHECK-NEXT: entry:1172; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !align [[META1:![0-9]+]]1173; CHECK-NEXT: br label [[LOOP:%.*]]1174; CHECK: loop:1175; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]1176; CHECK: if:1177; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 81178; CHECK-NEXT: call void @use(i64 [[V]]) #[[ATTR1:[0-9]+]]1179; CHECK-NEXT: br label [[LOOP_LATCH]]1180; CHECK: loop.latch:1181; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]1182; CHECK: exit:1183; CHECK-NEXT: ret void1184;1185entry:1186 br label %loop1187 1188loop:1189 br i1 %c1, label %if, label %loop.latch1190 1191if:1192 %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !11193 %v = load i64, ptr %p2, align 81194 call void @use(i64 %v) memory(none)1195 br label %loop.latch1196 1197loop.latch:1198 br i1 %c2, label %loop, label %exit1199 1200exit:1201 ret void1202}1203 1204define void @licm_deref_hoist(i1 %c1, i1 %c2, ptr align 8 dereferenceable(8) %p1) {1205; CHECK-LABEL: @licm_deref_hoist(1206; CHECK-NEXT: entry:1207; CHECK-NEXT: [[P2:%.*]] = load ptr, ptr [[P1:%.*]], align 8, !dereferenceable [[META1]], !align [[META1]]1208; CHECK-NEXT: [[V:%.*]] = load i64, ptr [[P2]], align 81209; CHECK-NEXT: br label [[LOOP:%.*]]1210; CHECK: loop:1211; CHECK-NEXT: br i1 [[C1:%.*]], label [[IF:%.*]], label [[LOOP_LATCH:%.*]]1212; CHECK: if:1213; CHECK-NEXT: call void @use(i64 [[V]]) #[[ATTR1]]1214; CHECK-NEXT: br label [[LOOP_LATCH]]1215; CHECK: loop.latch:1216; CHECK-NEXT: br i1 [[C2:%.*]], label [[LOOP]], label [[EXIT:%.*]]1217; CHECK: exit:1218; CHECK-NEXT: ret void1219;1220entry:1221 %p2 = load ptr, ptr %p1, align 8, !dereferenceable !1, !align !11222 br label %loop1223 1224loop:1225 br i1 %c1, label %if, label %loop.latch1226 1227if:1228 %v = load i64, ptr %p2, align 81229 call void @use(i64 %v) memory(none)1230 br label %loop.latch1231 1232loop.latch:1233 br i1 %c2, label %loop, label %exit1234 1235exit:1236 ret void1237}1238 1239attributes #0 = { nounwind uwtable nofree nosync }1240!0 = !{i64 4}1241!1 = !{i64 8}1242