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 4 target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 5 target 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 20 define void @lcssa_01(){ 21 entry: 22 %cmp21 = icmp sgt i64 100, 1 23 br i1 %cmp21, label %outer.ph, label %for.end16 24 25 outer.ph: 26 %cmp218 = icmp sgt i64 100, 1 27 br label %outer.header 28 29 outer.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 33 for.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 45 outer.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 50 for.exit: 51 store i64 %iv.outer.next, i64 * @Y 52 br label %for.end16 53 54 for.end16: 55 ret void 56 } 57 58 ; REMARK: UnsupportedExitPHI 59 ; REMARK-NEXT: lcssa_02 60 define void @lcssa_02(){ 61 entry: 62 %cmp21 = icmp sgt i64 100, 1 63 br i1 %cmp21, label %outer.ph, label %for.end16 64 65 outer.ph: 66 %cmp218 = icmp sgt i64 100, 1 67 br label %outer.header 68 69 outer.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 73 for.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 85 outer.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 91 for.exit: 92 store i64 %iv.inner.end, i64 * @Y 93 br label %for.end16 94 95 for.end16: 96 ret void 97 } 98 99 100 ; REMARK: Interchanged 101 ; REMARK-NEXT: lcssa_03 102 define void @lcssa_03(){ 103 entry: 104 br label %outer.header 105 106 outer.header: 107 %iv.outer= phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 108 br label %for.body3 109 110 for.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 122 outer.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 127 for.exit: 128 store i64 %iv.inner, i64 * @Y 129 br label %for.end16 130 131 for.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 139 define void @lcssa_04(){ 140 entry: 141 br label %outer.header 142 143 outer.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 148 for.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 160 outer.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 165 for.exit: 166 store float %float.outer, float* @F 167 br label %for.end16 168 169 for.end16: 170 ret void 171 } 172