1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt -loop-interchange -S %s | FileCheck %s 3 4 5@global = external dso_local global [1000 x [1000 x i32]], align 16 6 7; Test that we support updating conditional branches where both targets are the same 8; in the predecessor of the outer loop header. 9 10define void @foo(i1 %cmp) { 11; CHECK-LABEL: @foo( 12; CHECK-NEXT: entry: 13; CHECK-NEXT: br i1 [[CMP:%.*]], label [[INNER_HEADER_PREHEADER:%.*]], label [[INNER_HEADER_PREHEADER]] 14; CHECK: bb1: 15; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 16; CHECK: outer.header: 17; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ 0, [[BB1:%.*]] ], [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ] 18; CHECK-NEXT: br label [[INNER_HEADER_SPLIT1:%.*]] 19; CHECK: inner.header.preheader: 20; CHECK-NEXT: br label [[INNER_HEADER:%.*]] 21; CHECK: inner.header: 22; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ [[TMP0:%.*]], [[INNER_HEADER_SPLIT:%.*]] ], [ 5, [[INNER_HEADER_PREHEADER]] ] 23; CHECK-NEXT: br label [[BB1]] 24; CHECK: inner.header.split1: 25; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [1000 x [1000 x i32]], [1000 x [1000 x i32]]* @global, i64 0, i64 [[INNER_IV]], i64 [[OUTER_IV]] 26; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR]] 27; CHECK-NEXT: [[V:%.*]] = mul i32 [[LV]], 100 28; CHECK-NEXT: store i32 [[V]], i32* [[PTR]] 29; CHECK-NEXT: [[INNER_IV_NEXT:%.*]] = add nsw i64 [[INNER_IV]], 1 30; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[INNER_IV_NEXT]], 1000 31; CHECK-NEXT: br label [[OUTER_LATCH]] 32; CHECK: inner.header.split: 33; CHECK-NEXT: [[TMP0]] = add nsw i64 [[INNER_IV]], 1 34; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 1000 35; CHECK-NEXT: br i1 [[TMP1]], label [[BB9:%.*]], label [[INNER_HEADER]] 36; CHECK: outer.latch: 37; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nuw nsw i64 [[OUTER_IV]], 1 38; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[OUTER_IV_NEXT]], 1000 39; CHECK-NEXT: br i1 [[COND2]], label [[INNER_HEADER_SPLIT]], label [[OUTER_HEADER]] 40; CHECK: bb9: 41; CHECK-NEXT: br label [[BB10:%.*]] 42; CHECK: bb10: 43; CHECK-NEXT: ret void 44; 45entry: 46 br i1 %cmp, label %bb1, label %bb1 47 48bb1: ; preds = %entry, %entry 49 br label %outer.header 50 51outer.header: ; preds = %outer.latch, %bb1 52 %outer.iv = phi i64 [ 0, %bb1], [ %outer.iv.next, %outer.latch ] 53 br label %inner.header 54 55inner.header: ; preds = %inner.header, %outer.header 56 %inner.iv = phi i64 [ %inner.iv.next, %inner.header ], [ 5, %outer.header ] 57 %ptr = getelementptr inbounds [1000 x [1000 x i32]], [1000 x [1000 x i32]]* @global, i64 0, i64 %inner.iv, i64 %outer.iv 58 %lv = load i32, i32* %ptr 59 %v = mul i32 %lv, 100 60 store i32 %v, i32* %ptr 61 %inner.iv.next = add nsw i64 %inner.iv, 1 62 %cond1 = icmp eq i64 %inner.iv.next , 1000 63 br i1 %cond1, label %outer.latch, label %inner.header 64 65outer.latch: ; preds = %inner.header 66 %outer.iv.next = add nuw nsw i64 %outer.iv, 1 67 %cond2 = icmp eq i64 %outer.iv.next, 1000 68 br i1 %cond2, label %bb9, label %outer.header 69 70bb9: ; preds = %outer.latch 71 br label %bb10 72 73bb10: ; preds = %bb9 74 ret void 75} 76 77 78define void @foo1(i1 %cmp) { 79; CHECK-LABEL: @foo1( 80; CHECK-NEXT: entry: 81; CHECK-NEXT: br i1 [[CMP:%.*]], label [[BB1:%.*]], label [[BB1]] 82; CHECK: bb1: 83; CHECK-NEXT: br i1 [[CMP]], label [[INNER_HEADER_PREHEADER:%.*]], label [[INNER_HEADER_PREHEADER]] 84; CHECK: outer.header.preheader: 85; CHECK-NEXT: br label [[OUTER_HEADER:%.*]] 86; CHECK: outer.header: 87; CHECK-NEXT: [[OUTER_IV:%.*]] = phi i64 [ [[OUTER_IV_NEXT:%.*]], [[OUTER_LATCH:%.*]] ], [ 0, [[OUTER_HEADER_PREHEADER:%.*]] ] 88; CHECK-NEXT: br i1 [[CMP]], label [[INNER_HEADER_SPLIT1:%.*]], label [[INNER_HEADER_SPLIT1]] 89; CHECK: inner.header.preheader: 90; CHECK-NEXT: br label [[INNER_HEADER:%.*]] 91; CHECK: inner.header: 92; CHECK-NEXT: [[INNER_IV:%.*]] = phi i64 [ [[TMP0:%.*]], [[INNER_HEADER_SPLIT:%.*]] ], [ 5, [[INNER_HEADER_PREHEADER]] ] 93; CHECK-NEXT: br label [[OUTER_HEADER_PREHEADER]] 94; CHECK: inner.header.split1: 95; CHECK-NEXT: [[PTR:%.*]] = getelementptr inbounds [1000 x [1000 x i32]], [1000 x [1000 x i32]]* @global, i64 0, i64 [[INNER_IV]], i64 [[OUTER_IV]] 96; CHECK-NEXT: [[LV:%.*]] = load i32, i32* [[PTR]] 97; CHECK-NEXT: [[V:%.*]] = mul i32 [[LV]], 100 98; CHECK-NEXT: store i32 [[V]], i32* [[PTR]] 99; CHECK-NEXT: [[INNER_IV_NEXT:%.*]] = add nsw i64 [[INNER_IV]], 1 100; CHECK-NEXT: [[COND1:%.*]] = icmp eq i64 [[INNER_IV_NEXT]], 1000 101; CHECK-NEXT: br label [[OUTER_LATCH]] 102; CHECK: inner.header.split: 103; CHECK-NEXT: [[TMP0]] = add nsw i64 [[INNER_IV]], 1 104; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i64 [[TMP0]], 1000 105; CHECK-NEXT: br i1 [[TMP1]], label [[BB9:%.*]], label [[INNER_HEADER]] 106; CHECK: outer.latch: 107; CHECK-NEXT: [[OUTER_IV_NEXT]] = add nuw nsw i64 [[OUTER_IV]], 1 108; CHECK-NEXT: [[COND2:%.*]] = icmp eq i64 [[OUTER_IV_NEXT]], 1000 109; CHECK-NEXT: br i1 [[COND2]], label [[INNER_HEADER_SPLIT]], label [[OUTER_HEADER]] 110; CHECK: bb9: 111; CHECK-NEXT: br label [[BB10:%.*]] 112; CHECK: bb10: 113; CHECK-NEXT: ret void 114; 115entry: 116 br i1 %cmp, label %bb1, label %bb1 117 118bb1: ; preds = %entry, %entry 119 br i1 %cmp, label %outer.header, label %outer.header 120 121outer.header: ; preds = %outer.latch, %bb1 122 %outer.iv = phi i64 [ 0, %bb1 ], [ 0, %bb1 ], [ %outer.iv.next, %outer.latch ] 123 br i1 %cmp, label %inner.header, label %inner.header 124 125inner.header: ; preds = %inner.header, %outer.header 126 %inner.iv = phi i64 [ %inner.iv.next, %inner.header ], [ 5, %outer.header ], [ 5, %outer.header ] 127 %ptr = getelementptr inbounds [1000 x [1000 x i32]], [1000 x [1000 x i32]]* @global, i64 0, i64 %inner.iv, i64 %outer.iv 128 %lv = load i32, i32* %ptr 129 %v = mul i32 %lv, 100 130 store i32 %v, i32* %ptr 131 %inner.iv.next = add nsw i64 %inner.iv, 1 132 %cond1 = icmp eq i64 %inner.iv.next , 1000 133 br i1 %cond1, label %outer.latch, label %inner.header 134 135outer.latch: ; preds = %inner.header 136 %outer.iv.next = add nuw nsw i64 %outer.iv, 1 137 %cond2 = icmp eq i64 %outer.iv.next, 1000 138 br i1 %cond2, label %bb9, label %outer.header 139 140bb9: ; preds = %outer.latch 141 br label %bb10 142 143bb10: ; preds = %bb9 144 ret void 145} 146