1; RUN: opt < %s -basicaa -loop-interchange -pass-remarks-missed='loop-interchange' -pass-remarks-output=%t 2; RUN: cat %t | FileCheck --check-prefix REMARK %s 3 4target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 5target triple = "x86_64-unknown-linux-gnu" 6 7@A = common global [100 x [100 x i32]] zeroinitializer 8@C = common global [100 x [100 x i32]] zeroinitializer 9@X = common global i32 0 10@Y = common global i64 0 11@F = common global float 0.0 12 13; We cannot interchange this loop at the moment, because iv.outer.next is 14; produced in the outer loop latch and used in the loop exit block. If the inner 15; loop body is not executed, the outer loop latch won't be executed either 16; after interchanging. 17; REMARK: UnsupportedExitPHI 18; REMARK-NEXT: lcssa_01 19 20define void @lcssa_01(){ 21entry: 22 %cmp21 = icmp sgt i64 100, 1 23 br i1 %cmp21, label %outer.ph, label %for.end16 24 25outer.ph: 26 %cmp218 = icmp sgt i64 100, 1 27 br label %outer.header 28 29outer.header: 30 %iv.outer= phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ] 31 br i1 %cmp218, label %for.body3, label %outer.inc 32 33for.body3: 34 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 35 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer 36 %vA = load i32, i32* %arrayidx5 37 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer 38 %vC = load i32, i32* %arrayidx9 39 %add = add nsw i32 %vA, %vC 40 store i32 %add, i32* %arrayidx5 41 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 42 %exitcond = icmp eq i64 %iv.inner.next, 100 43 br i1 %exitcond, label %outer.inc, label %for.body3 44 45outer.inc: 46 %iv.outer.next = add nsw i64 %iv.outer, 1 47 %cmp = icmp eq i64 %iv.outer.next, 100 48 br i1 %cmp, label %outer.header, label %for.exit 49 50for.exit: 51 store i64 %iv.outer.next, i64 * @Y 52 br label %for.end16 53 54for.end16: 55 ret void 56} 57 58; REMARK: UnsupportedExitPHI 59; REMARK-NEXT: lcssa_02 60define void @lcssa_02(){ 61entry: 62 %cmp21 = icmp sgt i64 100, 1 63 br i1 %cmp21, label %outer.ph, label %for.end16 64 65outer.ph: 66 %cmp218 = icmp sgt i64 100, 1 67 br label %outer.header 68 69outer.header: 70 %iv.outer= phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ] 71 br i1 %cmp218, label %for.body3, label %outer.inc 72 73for.body3: 74 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 75 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer 76 %vA = load i32, i32* %arrayidx5 77 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer 78 %vC = load i32, i32* %arrayidx9 79 %add = add nsw i32 %vA, %vC 80 store i32 %add, i32* %arrayidx5 81 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 82 %exitcond = icmp eq i64 %iv.inner.next, 100 83 br i1 %exitcond, label %outer.inc, label %for.body3 84 85outer.inc: 86 %iv.inner.end = phi i64 [ 0, %outer.header ], [ %iv.inner.next, %for.body3 ] 87 %iv.outer.next = add nsw i64 %iv.outer, 1 88 %cmp = icmp eq i64 %iv.outer.next, 100 89 br i1 %cmp, label %outer.header, label %for.exit 90 91for.exit: 92 store i64 %iv.inner.end, i64 * @Y 93 br label %for.end16 94 95for.end16: 96 ret void 97} 98 99 100; REMARK: Interchanged 101; REMARK-NEXT: lcssa_03 102define void @lcssa_03(){ 103entry: 104 br label %outer.header 105 106outer.header: 107 %iv.outer= phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 108 br label %for.body3 109 110for.body3: 111 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 112 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer 113 %vA = load i32, i32* %arrayidx5 114 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer 115 %vC = load i32, i32* %arrayidx9 116 %add = add nsw i32 %vA, %vC 117 store i32 %add, i32* %arrayidx5 118 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 119 %exitcond = icmp eq i64 %iv.inner.next, 100 120 br i1 %exitcond, label %outer.inc, label %for.body3 121 122outer.inc: 123 %iv.outer.next = add nsw i64 %iv.outer, 1 124 %cmp = icmp eq i64 %iv.outer.next, 100 125 br i1 %cmp, label %outer.header, label %for.exit 126 127for.exit: 128 store i64 %iv.inner, i64 * @Y 129 br label %for.end16 130 131for.end16: 132 ret void 133} 134 135; FIXME: We currently do not support LCSSA phi nodes involving floating point 136; types, as we fail to detect floating point reductions for now. 137; REMARK: UnsupportedPHIOuter 138; REMARK-NEXT: lcssa_04 139define void @lcssa_04(){ 140entry: 141 br label %outer.header 142 143outer.header: 144 %iv.outer= phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 145 %float.outer= phi float [ 1.0, %entry ], [ 2.0, %outer.inc ] 146 br label %for.body3 147 148for.body3: 149 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 150 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @A, i64 0, i64 %iv.inner, i64 %iv.outer 151 %vA = load i32, i32* %arrayidx5 152 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], [100 x [100 x i32]]* @C, i64 0, i64 %iv.inner, i64 %iv.outer 153 %vC = load i32, i32* %arrayidx9 154 %add = add nsw i32 %vA, %vC 155 store i32 %add, i32* %arrayidx5 156 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 157 %exitcond = icmp eq i64 %iv.inner.next, 100 158 br i1 %exitcond, label %outer.inc, label %for.body3 159 160outer.inc: 161 %iv.outer.next = add nsw i64 %iv.outer, 1 162 %cmp = icmp eq i64 %iv.outer.next, 100 163 br i1 %cmp, label %outer.header, label %for.exit 164 165for.exit: 166 store float %float.outer, float* @F 167 br label %for.end16 168 169for.end16: 170 ret void 171} 172