256 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -passes=loop-unroll -unroll-runtime -unroll-count=4 -S | FileCheck %s3; RUN: opt < %s -passes='require<opt-remark-emit>,loop-unroll' -unroll-runtime -unroll-count=4 -S | FileCheck %s4 5; Check that loop unroll pass correctly handle loops with6; single exiting block not the loop header or latch.7 8define void @test1(ptr noalias %A) {9; CHECK-LABEL: @test1(10; CHECK-NEXT: entry:11; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A:%.*]], align 412; CHECK-NEXT: call void @bar(i32 [[TMP0]])13; CHECK-NEXT: br label [[FOR_HEADER:%.*]]14; CHECK: for.header:15; CHECK-NEXT: call void @bar(i32 [[TMP0]])16; CHECK-NEXT: br label [[FOR_BODY:%.*]]17; CHECK: for.body:18; CHECK-NEXT: br label [[FOR_BODY_FOR_BODY_CRIT_EDGE:%.*]]19; CHECK: for.body.for.body_crit_edge:20; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 121; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT]], align 422; CHECK-NEXT: call void @bar(i32 [[DOTPRE]])23; CHECK-NEXT: br label [[FOR_BODY_1:%.*]]24; CHECK: for.body.1:25; CHECK-NEXT: br label [[FOR_BODY_FOR_BODY_CRIT_EDGE_1:%.*]]26; CHECK: for.body.for.body_crit_edge.1:27; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 228; CHECK-NEXT: [[DOTPRE_1:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_1]], align 429; CHECK-NEXT: call void @bar(i32 [[DOTPRE_1]])30; CHECK-NEXT: br label [[FOR_BODY_2:%.*]]31; CHECK: for.body.2:32; CHECK-NEXT: br label [[FOR_BODY_FOR_BODY_CRIT_EDGE_2:%.*]]33; CHECK: for.body.for.body_crit_edge.2:34; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 335; CHECK-NEXT: [[DOTPRE_2:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_2]], align 436; CHECK-NEXT: call void @bar(i32 [[DOTPRE_2]])37; CHECK-NEXT: br label [[FOR_BODY_3:%.*]]38; CHECK: for.body.3:39; CHECK-NEXT: br i1 false, label [[FOR_BODY_FOR_BODY_CRIT_EDGE_3:%.*]], label [[FOR_END:%.*]]40; CHECK: for.body.for.body_crit_edge.3:41; CHECK-NEXT: unreachable42; CHECK: for.end:43; CHECK-NEXT: ret void44;45entry:46 %0 = load i32, ptr %A, align 447 call void @bar(i32 %0)48 br label %for.header49 50for.header:51 %1 = phi i32 [ %0, %entry ], [ %.pre, %for.body.for.body_crit_edge ]52 %i = phi i64 [ 0, %entry ], [ %inc, %for.body.for.body_crit_edge ]53 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i54 call void @bar(i32 %1)55 br label %for.body56 57for.body:58 %inc = add nsw i64 %i, 159 %cmp = icmp slt i64 %inc, 460 br i1 %cmp, label %for.body.for.body_crit_edge, label %for.end61 62for.body.for.body_crit_edge:63 %arrayidx.phi.trans.insert = getelementptr inbounds i32, ptr %A, i64 %inc64 %.pre = load i32, ptr %arrayidx.phi.trans.insert, align 465 br label %for.header66 67for.end:68 ret void69}70 71; Check that loop unroll pass correctly handle loops with72; (1) exiting block not dominating the loop latch; and73; (2) exiting terminator instructions cannot be simplified to unconditional.74 75define void @test2(ptr noalias %A) {76; CHECK-LABEL: @test2(77; CHECK-NEXT: entry:78; CHECK-NEXT: br i1 true, label [[FOR_PREHEADER:%.*]], label [[FOR_END:%.*]]79; CHECK: for.preheader:80; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A:%.*]], align 481; CHECK-NEXT: call void @bar(i32 [[TMP0]])82; CHECK-NEXT: br label [[FOR_HEADER:%.*]]83; CHECK: for.header:84; CHECK-NEXT: [[TMP1:%.*]] = phi i32 [ [[TMP0]], [[FOR_PREHEADER]] ], [ [[DOTPRE_3:%.*]], [[FOR_BODY_FOR_BODY_CRIT_EDGE_3:%.*]] ]85; CHECK-NEXT: [[I:%.*]] = phi i64 [ 0, [[FOR_PREHEADER]] ], [ [[INC_3:%.*]], [[FOR_BODY_FOR_BODY_CRIT_EDGE_3]] ]86; CHECK-NEXT: call void @bar(i32 [[TMP1]])87; CHECK-NEXT: [[INC:%.*]] = add nuw nsw i64 [[I]], 188; CHECK-NEXT: br i1 true, label [[FOR_BODY:%.*]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE:%.*]]89; CHECK: for.body:90; CHECK-NEXT: [[CMP:%.*]] = call i1 @foo(i64 [[I]])91; CHECK-NEXT: br i1 [[CMP]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE]], label [[FOR_END_LOOPEXIT:%.*]]92; CHECK: for.body.for.body_crit_edge:93; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INC]]94; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT]], align 495; CHECK-NEXT: call void @bar(i32 [[DOTPRE]])96; CHECK-NEXT: [[INC_1:%.*]] = add nuw nsw i64 [[I]], 297; CHECK-NEXT: br i1 true, label [[FOR_BODY_1:%.*]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE_1:%.*]]98; CHECK: for.body.1:99; CHECK-NEXT: [[CMP_1:%.*]] = call i1 @foo(i64 [[INC]])100; CHECK-NEXT: br i1 [[CMP_1]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE_1]], label [[FOR_END_LOOPEXIT]]101; CHECK: for.body.for.body_crit_edge.1:102; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INC_1]]103; CHECK-NEXT: [[DOTPRE_1:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_1]], align 4104; CHECK-NEXT: call void @bar(i32 [[DOTPRE_1]])105; CHECK-NEXT: [[INC_2:%.*]] = add nuw nsw i64 [[I]], 3106; CHECK-NEXT: br i1 true, label [[FOR_BODY_2:%.*]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE_2:%.*]]107; CHECK: for.body.2:108; CHECK-NEXT: [[CMP_2:%.*]] = call i1 @foo(i64 [[INC_1]])109; CHECK-NEXT: br i1 [[CMP_2]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE_2]], label [[FOR_END_LOOPEXIT]]110; CHECK: for.body.for.body_crit_edge.2:111; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INC_2]]112; CHECK-NEXT: [[DOTPRE_2:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_2]], align 4113; CHECK-NEXT: call void @bar(i32 [[DOTPRE_2]])114; CHECK-NEXT: [[INC_3]] = add nsw i64 [[I]], 4115; CHECK-NEXT: br i1 true, label [[FOR_BODY_3:%.*]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE_3]]116; CHECK: for.body.3:117; CHECK-NEXT: [[CMP_3:%.*]] = call i1 @foo(i64 [[INC_2]])118; CHECK-NEXT: br i1 [[CMP_3]], label [[FOR_BODY_FOR_BODY_CRIT_EDGE_3]], label [[FOR_END_LOOPEXIT]]119; CHECK: for.body.for.body_crit_edge.3:120; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_3:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 [[INC_3]]121; CHECK-NEXT: [[DOTPRE_3]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_3]], align 4122; CHECK-NEXT: br label [[FOR_HEADER]], !llvm.loop [[LOOP0:![0-9]+]]123; CHECK: for.end.loopexit:124; CHECK-NEXT: br label [[FOR_END]]125; CHECK: for.end:126; CHECK-NEXT: ret void127;128entry:129 br i1 true, label %for.preheader, label %for.end130 131for.preheader:132 %0 = load i32, ptr %A, align 4133 call void @bar(i32 %0)134 br label %for.header135 136for.header:137 %1 = phi i32 [ %0, %for.preheader ], [ %.pre, %for.body.for.body_crit_edge ]138 %i = phi i64 [ 0, %for.preheader ], [ %inc, %for.body.for.body_crit_edge ]139 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i140 call void @bar(i32 %1)141 %inc = add nsw i64 %i, 1142 br i1 true, label %for.body, label %for.body.for.body_crit_edge143 144for.body:145 %cmp = call i1 @foo(i64 %i)146 br i1 %cmp, label %for.body.for.body_crit_edge, label %for.end147 148for.body.for.body_crit_edge:149 %arrayidx.phi.trans.insert = getelementptr inbounds i32, ptr %A, i64 %inc150 %.pre = load i32, ptr %arrayidx.phi.trans.insert, align 4151 br label %for.header152 153for.end:154 ret void155}156 157; Check that loop unroll pass correctly handle loops with158; (1) multiple exiting blocks; and159; (2) loop latch is not an exiting block.160 161define void @test3(ptr noalias %A, i1 %cond) {162; CHECK-LABEL: @test3(163; CHECK-NEXT: entry:164; CHECK-NEXT: [[TMP0:%.*]] = load i32, ptr [[A:%.*]], align 4165; CHECK-NEXT: call void @bar(i32 [[TMP0]])166; CHECK-NEXT: br label [[FOR_HEADER:%.*]]167; CHECK: for.header:168; CHECK-NEXT: call void @bar(i32 [[TMP0]])169; CHECK-NEXT: br i1 [[COND:%.*]], label [[FOR_BODY:%.*]], label [[FOR_END:%.*]]170; CHECK: for.body:171; CHECK-NEXT: br label [[FOR_BODY_FOR_BODY_CRIT_EDGE:%.*]]172; CHECK: for.body.for.body_crit_edge:173; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 1174; CHECK-NEXT: [[DOTPRE:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT]], align 4175; CHECK-NEXT: call void @bar(i32 [[DOTPRE]])176; CHECK-NEXT: br i1 [[COND]], label [[FOR_BODY_1:%.*]], label [[FOR_END]]177; CHECK: for.body.1:178; CHECK-NEXT: br label [[FOR_BODY_FOR_BODY_CRIT_EDGE_1:%.*]]179; CHECK: for.body.for.body_crit_edge.1:180; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_1:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 2181; CHECK-NEXT: [[DOTPRE_1:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_1]], align 4182; CHECK-NEXT: call void @bar(i32 [[DOTPRE_1]])183; CHECK-NEXT: br i1 [[COND]], label [[FOR_BODY_2:%.*]], label [[FOR_END]]184; CHECK: for.body.2:185; CHECK-NEXT: br label [[FOR_BODY_FOR_BODY_CRIT_EDGE_2:%.*]]186; CHECK: for.body.for.body_crit_edge.2:187; CHECK-NEXT: [[ARRAYIDX_PHI_TRANS_INSERT_2:%.*]] = getelementptr inbounds i32, ptr [[A]], i64 3188; CHECK-NEXT: [[DOTPRE_2:%.*]] = load i32, ptr [[ARRAYIDX_PHI_TRANS_INSERT_2]], align 4189; CHECK-NEXT: call void @bar(i32 [[DOTPRE_2]])190; CHECK-NEXT: br i1 [[COND]], label [[FOR_BODY_3:%.*]], label [[FOR_END]]191; CHECK: for.body.3:192; CHECK-NEXT: br i1 false, label [[FOR_BODY_FOR_BODY_CRIT_EDGE_3:%.*]], label [[FOR_END]]193; CHECK: for.body.for.body_crit_edge.3:194; CHECK-NEXT: unreachable195; CHECK: for.end:196; CHECK-NEXT: ret void197;198entry:199 %0 = load i32, ptr %A, align 4200 call void @bar(i32 %0)201 br label %for.header202 203for.header:204 %1 = phi i32 [ %0, %entry ], [ %.pre, %for.body.for.body_crit_edge ]205 %i = phi i64 [ 0, %entry ], [ %inc, %for.body.for.body_crit_edge ]206 %arrayidx = getelementptr inbounds i32, ptr %A, i64 %i207 call void @bar(i32 %1)208 br i1 %cond, label %for.body, label %for.end209 210for.body:211 %inc = add nsw i64 %i, 1212 %cmp = icmp slt i64 %inc, 4213 br i1 %cmp, label %for.body.for.body_crit_edge, label %for.end214 215for.body.for.body_crit_edge:216 %arrayidx.phi.trans.insert = getelementptr inbounds i32, ptr %A, i64 %inc217 %.pre = load i32, ptr %arrayidx.phi.trans.insert, align 4218 br label %for.header219 220for.end:221 ret void222}223 224; Test it doesn't crash.225define void @test4(i32 %arg) {226; CHECK-LABEL: @test4(227; CHECK-NEXT: bb:228; CHECK-NEXT: br label [[BB1:%.*]]229; CHECK: bb1:230; CHECK-NEXT: br i1 false, label [[BB4:%.*]], label [[BB1_1:%.*]]231; CHECK: bb1.1:232; CHECK-NEXT: br i1 false, label [[BB4]], label [[BB1_2:%.*]]233; CHECK: bb1.2:234; CHECK-NEXT: br i1 false, label [[BB4]], label [[BB1_3:%.*]]235; CHECK: bb1.3:236; CHECK-NEXT: br i1 false, label [[BB4]], label [[BB1]], !llvm.loop [[LOOP2:![0-9]+]]237; CHECK: bb4:238; CHECK-NEXT: unreachable239;240bb:241 br label %bb1242 243bb1: ; preds = %bb1, %bb244 %tmp = phi i64 [ 0, %bb ], [ 65, %bb1 ]245 %tmp2 = phi i32 [ %arg, %bb ], [ %tmp3, %bb1 ]246 %tmp3 = add i32 0, -1880031232247 br i1 false, label %bb4, label %bb1248 249bb4: ; preds = %bb1250 unreachable251}252 253 254declare void @bar(i32)255declare i1 @foo(i64)256