329 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -aa-pipeline=basic-aa,globals-aa -S -passes='require<globals-aa>,function(loop-mssa(licm))' | FileCheck %s3 4;Reference C code:5;struct str {6; void **p;7;};8;static struct str obj;9;extern void nocapture_nocallback_func(struct str *);10;void test(void *p) {11; nocapture_nocallback_func(&obj);12; for (int i = 0; i < 1000; ++i) {13; unknown_call(); // optional14; obj.p[i] = p;15; }16;}17 18target datalayout = "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-f80:128-n8:16:32:64-S128"19 20%struct.str = type { ptr }21 22@obj0 = internal global %struct.str zeroinitializer, align 823@obj1 = internal global %struct.str zeroinitializer, align 824@obj2 = internal global %struct.str zeroinitializer, align 825@obj3 = internal global %struct.str zeroinitializer, align 826@obj4 = internal global %struct.str zeroinitializer, align 827@obj5 = internal global %struct.str zeroinitializer, align 828 29define dso_local void @test0(ptr %p) {30; Check that load from @obj0 is hoisted from the loop, meaning31; that it does not conflict with the store inside the loop:32; CHECK-LABEL: @test0(33; CHECK-NEXT: entry:34; CHECK-NEXT: call void @nocapture_nocallback_func(ptr @obj0)35; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @obj0, align 836; CHECK-NEXT: br label [[FOR_COND:%.*]]37; CHECK: for.cond:38; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]39; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 100040; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]41; CHECK: for.body:42; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i6443; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]44; CHECK-NEXT: store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 845; CHECK-NEXT: br label [[FOR_INC]]46; CHECK: for.inc:47; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 148; CHECK-NEXT: br label [[FOR_COND]]49; CHECK: for.end:50; CHECK-NEXT: ret void51;52 53entry:54 call void @nocapture_nocallback_func(ptr @obj0)55 br label %for.cond56 57for.cond: ; preds = %for.inc, %entry58 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]59 %cmp = icmp slt i32 %i.0, 100060 br i1 %cmp, label %for.body, label %for.end61 62for.body: ; preds = %for.cond63 %0 = load ptr, ptr @obj0, align 864 %idxprom = sext i32 %i.0 to i6465 %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom66 store ptr %p, ptr %arrayidx, align 867 br label %for.inc68 69for.inc: ; preds = %for.body70 %inc = add nsw i32 %i.0, 171 br label %for.cond72 73for.end: ; preds = %for.cond74 ret void75}76 77define dso_local void @test1(ptr %p) {78; Check that load from @obj1 is not hoisted from the loop,79; because 'nocallback' is missing:80; CHECK-LABEL: @test1(81; CHECK-NEXT: entry:82; CHECK-NEXT: call void @nocapture_func(ptr @obj1)83; CHECK-NEXT: br label [[FOR_COND:%.*]]84; CHECK: for.cond:85; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]86; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 100087; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]88; CHECK: for.body:89; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @obj1, align 890; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i6491; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]92; CHECK-NEXT: store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 893; CHECK-NEXT: br label [[FOR_INC]]94; CHECK: for.inc:95; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 196; CHECK-NEXT: br label [[FOR_COND]]97; CHECK: for.end:98; CHECK-NEXT: ret void99;100 101entry:102 call void @nocapture_func(ptr @obj1)103 br label %for.cond104 105for.cond: ; preds = %for.inc, %entry106 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]107 %cmp = icmp slt i32 %i.0, 1000108 br i1 %cmp, label %for.body, label %for.end109 110for.body: ; preds = %for.cond111 %0 = load ptr, ptr @obj1, align 8112 %idxprom = sext i32 %i.0 to i64113 %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom114 store ptr %p, ptr %arrayidx, align 8115 br label %for.inc116 117for.inc: ; preds = %for.body118 %inc = add nsw i32 %i.0, 1119 br label %for.cond120 121for.end: ; preds = %for.cond122 ret void123}124 125define dso_local void @test2(ptr %p) {126; Check that load from @obj2 is not hoisted from the loop,127; because 'nocapture' is missing:128; CHECK-LABEL: @test2(129; CHECK-NEXT: entry:130; CHECK-NEXT: call void @nocallback_func(ptr @obj2)131; CHECK-NEXT: br label [[FOR_COND:%.*]]132; CHECK: for.cond:133; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]134; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000135; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]136; CHECK: for.body:137; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @obj2, align 8138; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64139; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]140; CHECK-NEXT: store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8141; CHECK-NEXT: br label [[FOR_INC]]142; CHECK: for.inc:143; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1144; CHECK-NEXT: br label [[FOR_COND]]145; CHECK: for.end:146; CHECK-NEXT: ret void147;148 149entry:150 call void @nocallback_func(ptr @obj2)151 br label %for.cond152 153for.cond: ; preds = %for.inc, %entry154 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]155 %cmp = icmp slt i32 %i.0, 1000156 br i1 %cmp, label %for.body, label %for.end157 158for.body: ; preds = %for.cond159 %0 = load ptr, ptr @obj2, align 8160 %idxprom = sext i32 %i.0 to i64161 %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom162 store ptr %p, ptr %arrayidx, align 8163 br label %for.inc164 165for.inc: ; preds = %for.body166 %inc = add nsw i32 %i.0, 1167 br label %for.cond168 169for.end: ; preds = %for.cond170 ret void171}172 173define dso_local void @test3(ptr %p) {174; Check that load from @obj3 is hoisted from the loop, even though175; there is unknown call in the loop.176; CHECK-LABEL: @test3(177; CHECK-NEXT: entry:178; CHECK-NEXT: call void @nocapture_nocallback_func(ptr @obj3)179; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @obj3, align 8180; CHECK-NEXT: br label [[FOR_COND:%.*]]181; CHECK: for.cond:182; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]183; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000184; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]185; CHECK: for.body:186; CHECK-NEXT: call void @unknown_call()187; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64188; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]189; CHECK-NEXT: store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8190; CHECK-NEXT: br label [[FOR_INC]]191; CHECK: for.inc:192; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1193; CHECK-NEXT: br label [[FOR_COND]]194; CHECK: for.end:195; CHECK-NEXT: ret void196;197 198entry:199 call void @nocapture_nocallback_func(ptr @obj3)200 br label %for.cond201 202for.cond: ; preds = %for.inc, %entry203 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]204 %cmp = icmp slt i32 %i.0, 1000205 br i1 %cmp, label %for.body, label %for.end206 207for.body: ; preds = %for.cond208 %0 = load ptr, ptr @obj3, align 8209 call void @unknown_call()210 %idxprom = sext i32 %i.0 to i64211 %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom212 store ptr %p, ptr %arrayidx, align 8213 br label %for.inc214 215for.inc: ; preds = %for.body216 %inc = add nsw i32 %i.0, 1217 br label %for.cond218 219for.end: ; preds = %for.cond220 ret void221}222 223define dso_local void @test4(ptr %p) {224; Check that load from @obj4 is not hoisted from the loop,225; because 'nocallback' is missing:226; CHECK-LABEL: @test4(227; CHECK-NEXT: entry:228; CHECK-NEXT: call void @nocapture_func(ptr @obj4)229; CHECK-NEXT: br label [[FOR_COND:%.*]]230; CHECK: for.cond:231; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]232; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000233; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]234; CHECK: for.body:235; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @obj4, align 8236; CHECK-NEXT: call void @unknown_call()237; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64238; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]239; CHECK-NEXT: store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8240; CHECK-NEXT: br label [[FOR_INC]]241; CHECK: for.inc:242; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1243; CHECK-NEXT: br label [[FOR_COND]]244; CHECK: for.end:245; CHECK-NEXT: ret void246;247 248entry:249 call void @nocapture_func(ptr @obj4)250 br label %for.cond251 252for.cond: ; preds = %for.inc, %entry253 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]254 %cmp = icmp slt i32 %i.0, 1000255 br i1 %cmp, label %for.body, label %for.end256 257for.body: ; preds = %for.cond258 %0 = load ptr, ptr @obj4, align 8259 call void @unknown_call()260 %idxprom = sext i32 %i.0 to i64261 %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom262 store ptr %p, ptr %arrayidx, align 8263 br label %for.inc264 265for.inc: ; preds = %for.body266 %inc = add nsw i32 %i.0, 1267 br label %for.cond268 269for.end: ; preds = %for.cond270 ret void271}272 273define dso_local void @test5(ptr %p) {274; Check that load from @obj5 is not hoisted from the loop,275; because 'nocapture' is missing:276; CHECK-LABEL: @test5(277; CHECK-NEXT: entry:278; CHECK-NEXT: call void @nocallback_func(ptr @obj5)279; CHECK-NEXT: br label [[FOR_COND:%.*]]280; CHECK: for.cond:281; CHECK-NEXT: [[I_0:%.*]] = phi i32 [ 0, [[ENTRY:%.*]] ], [ [[INC:%.*]], [[FOR_INC:%.*]] ]282; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[I_0]], 1000283; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]284; CHECK: for.body:285; CHECK-NEXT: [[TMP0:%.*]] = load ptr, ptr @obj5, align 8286; CHECK-NEXT: call void @unknown_call()287; CHECK-NEXT: [[IDXPROM:%.*]] = sext i32 [[I_0]] to i64288; CHECK-NEXT: [[ARRAYIDX:%.*]] = getelementptr inbounds ptr, ptr [[TMP0]], i64 [[IDXPROM]]289; CHECK-NEXT: store ptr [[P:%.*]], ptr [[ARRAYIDX]], align 8290; CHECK-NEXT: br label [[FOR_INC]]291; CHECK: for.inc:292; CHECK-NEXT: [[INC]] = add nsw i32 [[I_0]], 1293; CHECK-NEXT: br label [[FOR_COND]]294; CHECK: for.end:295; CHECK-NEXT: ret void296;297 298entry:299 call void @nocallback_func(ptr @obj5)300 br label %for.cond301 302for.cond: ; preds = %for.inc, %entry303 %i.0 = phi i32 [ 0, %entry ], [ %inc, %for.inc ]304 %cmp = icmp slt i32 %i.0, 1000305 br i1 %cmp, label %for.body, label %for.end306 307for.body: ; preds = %for.cond308 %0 = load ptr, ptr @obj5, align 8309 call void @unknown_call()310 %idxprom = sext i32 %i.0 to i64311 %arrayidx = getelementptr inbounds ptr, ptr %0, i64 %idxprom312 store ptr %p, ptr %arrayidx, align 8313 br label %for.inc314 315for.inc: ; preds = %for.body316 %inc = add nsw i32 %i.0, 1317 br label %for.cond318 319for.end: ; preds = %for.cond320 ret void321}322 323declare void @nocapture_nocallback_func(ptr nocapture) nocallback324declare void @nocapture_func(ptr nocapture)325declare void @nocallback_func(ptr) nocallback326; nosync and nocallback are required, otherwise the call327; will by ModRef for any global:328declare void @unknown_call() nosync nocallback329