142 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt -passes=loop-interchange -cache-line-size=64 -S %s | FileCheck %s3 4@global = external local_unnamed_addr global [400 x [400 x i32]], align 165 6; We need to move %tmp4 from the inner loop pre header to the outer loop header7; before interchanging.8define void @test1() local_unnamed_addr #0 {9; CHECK-LABEL: @test1(10; CHECK-NEXT: bb:11; CHECK-NEXT: br label [[INNER_PH:%.*]]12; CHECK: outer.header.preheader:13; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]14; CHECK: outer.header:15; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ], [ 0, [[OUTER_HEADER_PREHEADER:%.*]] ]16; CHECK-NEXT: [[INNER_RED:%.*]] = phi i32 [ [[OUTER_RED:%.*]], [[OUTER_HEADER_PREHEADER]] ], [ [[RED_NEXT:%.*]], [[OUTER_LATCH]] ]17; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[OUTER_IV]], 918; CHECK-NEXT: br label [[INNER_SPLIT1:%.*]]19; CHECK: inner.ph:20; CHECK-NEXT: br label [[INNER:%.*]]21; CHECK: inner:22; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[INNER_PH]] ], [ [[TMP0:%.*]], [[INNER_SPLIT:%.*]] ]23; CHECK-NEXT: [[OUTER_RED]] = phi i32 [ [[RED_NEXT_LCSSA:%.*]], [[INNER_SPLIT]] ], [ 0, [[INNER_PH]] ]24; CHECK-NEXT: br label [[OUTER_HEADER_PREHEADER]]25; CHECK: inner.split1:26; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [400 x [400 x i32]], ptr @global, i64 0, i64 [[INNER_IV]], i64 [[TMP4]]27; CHECK-NEXT: store i32 0, ptr [[PTR]], align 428; CHECK-NEXT: [[RED_NEXT]] = or i32 [[INNER_RED]], 2029; CHECK-NEXT: [[INNER_IV_NEXT:%.*]] = add nsw i64 [[INNER_IV]], 130; CHECK-NEXT: [[EC_1:%.*]] = icmp eq i64 [[INNER_IV_NEXT]], 40031; CHECK-NEXT: br label [[OUTER_LATCH]]32; CHECK: inner.split:33; CHECK-NEXT: [[RED_NEXT_LCSSA]] = phi i32 [ [[RED_NEXT]], [[OUTER_LATCH]] ]34; CHECK-NEXT: [[TMP0]] = add nsw i64 [[INNER_IV]], 135; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 40036; CHECK-NEXT: br i1 [[TMP1]], label [[EXIT:%.*]], label [[INNER]]37; CHECK: outer.latch:38; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 139; CHECK-NEXT: [[EC_2:%.*]] = icmp eq i64 [[OUTER_IV_NEXT]], 40040; CHECK-NEXT: br i1 [[EC_2]], label [[INNER_SPLIT]], label [[OUTER_HEADER]]41; CHECK: exit:42; CHECK-NEXT: ret void43;44bb:45 br label %outer.header46 47outer.header: ; preds = %bb11, %bb48 %outer.iv = phi i64 [ 0, %bb ], [ %outer.iv.next, %outer.latch ]49 %outer.red = phi i32 [ 0, %bb ], [ %red.next.lcssa, %outer.latch ]50 br label %inner.ph51 52inner.ph: ; preds = %bb153 %tmp4 = add nsw i64 %outer.iv, 954 br label %inner55 56inner: ; preds = %bb5, %bb357 %inner.iv = phi i64 [ 0, %inner.ph ], [ %inner.iv.next, %inner ]58 %inner.red = phi i32 [ %outer.red, %inner.ph ], [ %red.next, %inner ]59 %ptr = getelementptr inbounds [400 x [400 x i32]], ptr @global, i64 0, i64 %inner.iv, i64 %tmp460 store i32 0, ptr %ptr61 %red.next = or i32 %inner.red, 2062 %inner.iv.next = add nsw i64 %inner.iv, 163 %ec.1 = icmp eq i64 %inner.iv.next, 40064 br i1 %ec.1, label %outer.latch, label %inner65 66outer.latch: ; preds = %bb567 %red.next.lcssa = phi i32 [ %red.next, %inner ]68 %outer.iv.next = add nsw i64 %outer.iv, 169 %ec.2 = icmp eq i64 %outer.iv.next, 40070 br i1 %ec.2, label %exit, label %outer.header71 72exit: ; preds = %bb1173 ret void74}75 76declare void @side_effect()77 78; Cannot interchange, as the inner loop preheader contains a call to a function79; with side effects.80 81define void @test2() {82; CHECK-LABEL: @test2(83; CHECK-NEXT: bb:84; CHECK-NEXT: br label [[OUTER_HEADER:%.*]]85; CHECK: outer.header:86; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ 0, [[BB:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ]87; CHECK-NEXT: [[OUTER_RED:%.*]] = phi i32 [ 0, [[BB]] ], [ [[RED_NEXT_LCSSA:%.*]], [[OUTER_LATCH]] ]88; CHECK-NEXT: br label [[INNER_PH:%.*]]89; CHECK: inner.ph:90; CHECK-NEXT: [[TMP4:%.*]] = add nsw i64 [[OUTER_IV]], 991; CHECK-NEXT: call void @side_effect()92; CHECK-NEXT: br label [[INNER:%.*]]93; CHECK: inner:94; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ 0, [[INNER_PH]] ], [ [[INNER_IV_NEXT:%.*]], [[INNER]] ]95; CHECK-NEXT: [[INNER_RED:%.*]] = phi i32 [ [[OUTER_RED]], [[INNER_PH]] ], [ [[RED_NEXT:%.*]], [[INNER]] ]96; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [400 x [400 x i32]], ptr @global, i64 0, i64 [[INNER_IV]], i64 [[TMP4]]97; CHECK-NEXT: store i32 0, ptr [[PTR]], align 498; CHECK-NEXT: [[RED_NEXT]] = or i32 [[INNER_RED]], 2099; CHECK-NEXT: [[INNER_IV_NEXT]] = add nsw i64 [[INNER_IV]], 1100; CHECK-NEXT: [[EC_1:%.*]] = icmp eq i64 [[INNER_IV_NEXT]], 400101; CHECK-NEXT: br i1 [[EC_1]], label [[OUTER_LATCH]], label [[INNER]]102; CHECK: outer.latch:103; CHECK-NEXT: [[RED_NEXT_LCSSA]] = phi i32 [ [[RED_NEXT]], [[INNER]] ]104; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nsw i64 [[OUTER_IV]], 1105; CHECK-NEXT: [[EC_2:%.*]] = icmp eq i64 [[OUTER_IV_NEXT]], 400106; CHECK-NEXT: br i1 [[EC_2]], label [[EXIT:%.*]], label [[OUTER_HEADER]]107; CHECK: exit:108; CHECK-NEXT: ret void109;110bb:111 br label %outer.header112 113outer.header: ; preds = %bb11, %bb114 %outer.iv = phi i64 [ 0, %bb ], [ %outer.iv.next, %outer.latch ]115 %outer.red = phi i32 [ 0, %bb ], [ %red.next.lcssa, %outer.latch ]116 br label %inner.ph117 118inner.ph: ; preds = %bb1119 %tmp4 = add nsw i64 %outer.iv, 9120 call void @side_effect()121 br label %inner122 123inner: ; preds = %bb5, %bb3124 %inner.iv = phi i64 [ 0, %inner.ph ], [ %inner.iv.next, %inner ]125 %inner.red = phi i32 [ %outer.red, %inner.ph ], [ %red.next, %inner ]126 %ptr = getelementptr inbounds [400 x [400 x i32]], ptr @global, i64 0, i64 %inner.iv, i64 %tmp4127 store i32 0, ptr %ptr128 %red.next = or i32 %inner.red, 20129 %inner.iv.next = add nsw i64 %inner.iv, 1130 %ec.1 = icmp eq i64 %inner.iv.next, 400131 br i1 %ec.1, label %outer.latch, label %inner132 133outer.latch: ; preds = %bb5134 %red.next.lcssa = phi i32 [ %red.next, %inner ]135 %outer.iv.next = add nsw i64 %outer.iv, 1136 %ec.2 = icmp eq i64 %outer.iv.next, 400137 br i1 %ec.2, label %exit, label %outer.header138 139exit: ; preds = %bb11140 ret void141}142