1; Remove 'S' Scalar Dependencies #119345 2; Scalar dependencies are not handled correctly, so they were removed to avoid 3; miscompiles. The loop nest in this test case used to be interchanged, but it's 4; no longer triggering. XFAIL'ing this test to indicate that this test should 5; interchanged if scalar deps are handled correctly. 6; 7; XFAIL: * 8 9; RUN: opt < %s -passes=loop-interchange -cache-line-size=64 -pass-remarks-missed='loop-interchange' -verify-loop-lcssa -pass-remarks-output=%t -S 10; RUN: FileCheck --input-file %t --check-prefix REMARK %s 11 12target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" 13 14@A = common global [100 x [100 x i32]] zeroinitializer 15@C = common global [100 x [100 x i32]] zeroinitializer 16@X = common global i32 0 17@Y = common global i64 0 18@F = common global float 0.0 19 20; We cannot interchange this loop at the moment, because iv.outer.next is 21; produced in the outer loop latch and used in the loop exit block. If the inner 22; loop body is not executed, the outer loop latch won't be executed either 23; after interchanging. 24; REMARK: UnsupportedExitPHI 25; REMARK-NEXT: lcssa_01 26 27define void @lcssa_01() { 28entry: 29 %cmp21 = icmp sgt i64 100, 1 30 br i1 %cmp21, label %outer.ph, label %for.end16 31 32outer.ph: ; preds = %entry 33 %cmp218 = icmp sgt i64 100, 1 34 br label %outer.header 35 36outer.header: ; preds = %outer.inc, %outer.ph 37 %iv.outer = phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ] 38 br i1 %cmp218, label %for.body3, label %outer.inc 39 40for.body3: ; preds = %for.body3, %outer.header 41 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 42 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 43 %vA = load i32, ptr %arrayidx5 44 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 45 %vC = load i32, ptr %arrayidx9 46 %add = add nsw i32 %vA, %vC 47 store i32 %add, ptr %arrayidx5 48 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 49 %exitcond = icmp eq i64 %iv.inner.next, 100 50 br i1 %exitcond, label %outer.inc, label %for.body3 51 52outer.inc: ; preds = %for.body3, %outer.header 53 %iv.outer.next = add nsw i64 %iv.outer, 1 54 %cmp = icmp eq i64 %iv.outer.next, 100 55 br i1 %cmp, label %outer.header, label %for.exit 56 57for.exit: ; preds = %outer.inc 58 %iv.outer.next.lcssa = phi i64 [ %iv.outer.next, %outer.inc ] 59 store i64 %iv.outer.next.lcssa, ptr @Y 60 br label %for.end16 61 62for.end16: ; preds = %for.exit, %entry 63 ret void 64} 65 66; REMARK: UnsupportedExitPHI 67; REMARK-NEXT: lcssa_02 68define void @lcssa_02() { 69entry: 70 %cmp21 = icmp sgt i64 100, 1 71 br i1 %cmp21, label %outer.ph, label %for.end16 72 73outer.ph: ; preds = %entry 74 %cmp218 = icmp sgt i64 100, 1 75 br label %outer.header 76 77outer.header: ; preds = %outer.inc, %outer.ph 78 %iv.outer = phi i64 [ 1, %outer.ph ], [ %iv.outer.next, %outer.inc ] 79 br i1 %cmp218, label %for.body3, label %outer.inc 80 81for.body3: ; preds = %for.body3, %outer.header 82 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 83 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 84 %vA = load i32, ptr %arrayidx5 85 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 86 %vC = load i32, ptr %arrayidx9 87 %add = add nsw i32 %vA, %vC 88 store i32 %add, ptr %arrayidx5 89 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 90 %exitcond = icmp eq i64 %iv.inner.next, 100 91 br i1 %exitcond, label %outer.inc, label %for.body3 92 93outer.inc: ; preds = %for.body3, %outer.header 94 %iv.inner.end = phi i64 [ 0, %outer.header ], [ %iv.inner.next, %for.body3 ] 95 %iv.outer.next = add nsw i64 %iv.outer, 1 96 %cmp = icmp eq i64 %iv.outer.next, 100 97 br i1 %cmp, label %outer.header, label %for.exit 98 99for.exit: ; preds = %outer.inc 100 %iv.inner.end.lcssa = phi i64 [ %iv.inner.end, %outer.inc ] 101 store i64 %iv.inner.end.lcssa, ptr @Y 102 br label %for.end16 103 104for.end16: ; preds = %for.exit, %entry 105 ret void 106} 107 108; REMARK: Interchanged 109; REMARK-NEXT: lcssa_03 110define void @lcssa_03() { 111entry: 112 br label %outer.header 113 114outer.header: ; preds = %outer.inc, %entry 115 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 116 br label %for.body3 117 118for.body3: ; preds = %for.body3, %outer.header 119 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 120 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 121 %vA = load i32, ptr %arrayidx5 122 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 123 %vC = load i32, ptr %arrayidx9 124 %add = add nsw i32 %vA, %vC 125 store i32 %add, ptr %arrayidx5 126 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 127 %exitcond = icmp eq i64 %iv.inner.next, 100 128 br i1 %exitcond, label %outer.inc, label %for.body3 129 130outer.inc: ; preds = %for.body3 131 %iv.inner.lcssa = phi i64 [ %iv.inner, %for.body3 ] 132 %iv.outer.next = add nsw i64 %iv.outer, 1 133 %cmp = icmp eq i64 %iv.outer.next, 100 134 br i1 %cmp, label %outer.header, label %for.exit 135 136for.exit: ; preds = %outer.inc 137 %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ] 138 store i64 %iv.inner.lcssa.lcssa, ptr @Y 139 br label %for.end16 140 141for.end16: ; preds = %for.exit 142 ret void 143} 144 145; Loops with floating point reductions are interchanged with fastmath. 146; REMARK: Interchanged 147; REMARK-NEXT: lcssa_04 148 149define void @lcssa_04() { 150entry: 151 br label %outer.header 152 153outer.header: ; preds = %outer.inc, %entry 154 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 155 %float.outer = phi float [ 1.000000e+00, %entry ], [ %float.outer.next, %outer.inc ] 156 br label %for.body3 157 158for.body3: ; preds = %for.body3, %outer.header 159 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 160 %float.inner = phi float [ %float.inner.next, %for.body3 ], [ %float.outer, %outer.header ] 161 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 162 %vA = load i32, ptr %arrayidx5 163 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 164 %vC = load i32, ptr %arrayidx9 165 %add = add nsw i32 %vA, %vC 166 %float.inner.next = fadd fast float %float.inner, 1.000000e+00 167 store i32 %add, ptr %arrayidx5 168 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 169 %exitcond = icmp eq i64 %iv.inner.next, 100 170 br i1 %exitcond, label %outer.inc, label %for.body3 171 172outer.inc: ; preds = %for.body3 173 %float.outer.next = phi float [ %float.inner.next, %for.body3 ] 174 %iv.outer.next = add nsw i64 %iv.outer, 1 175 %cmp = icmp eq i64 %iv.outer.next, 100 176 br i1 %cmp, label %outer.header, label %for.exit 177 178for.exit: ; preds = %outer.inc 179 %float.outer.lcssa = phi float [ %float.outer.next, %outer.inc ] 180 store float %float.outer.lcssa, ptr @F 181 br label %for.end16 182 183for.end16: ; preds = %for.exit 184 ret void 185} 186 187; PHI node in inner latch with multiple predecessors. 188; REMARK: Interchanged 189; REMARK-NEXT: lcssa_05 190 191define void @lcssa_05(ptr %ptr, i1 %arg) { 192entry: 193 br label %outer.header 194 195outer.header: ; preds = %outer.inc, %entry 196 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 197 br label %for.body3 198 199for.body3: ; preds = %bb3, %outer.header 200 %iv.inner = phi i64 [ %iv.inner.next, %bb3 ], [ 1, %outer.header ] 201 br i1 %arg, label %bb2, label %bb3 202 203bb2: ; preds = %for.body3 204 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 205 %vA = load i32, ptr %arrayidx5 206 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 207 %vC = load i32, ptr %arrayidx9 208 %add = add nsw i32 %vA, %vC 209 br label %bb3 210 211bb3: ; preds = %bb2, %for.body3 212 %addp = phi i32 [ %add, %bb2 ], [ 0, %for.body3 ] 213 store i32 %addp, ptr %ptr 214 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 215 %exitcond = icmp eq i64 %iv.inner.next, 100 216 br i1 %exitcond, label %outer.inc, label %for.body3 217 218outer.inc: ; preds = %bb3 219 %iv.inner.lcssa = phi i64 [ %iv.inner, %bb3 ] 220 %iv.outer.next = add nsw i64 %iv.outer, 1 221 %cmp = icmp eq i64 %iv.outer.next, 100 222 br i1 %cmp, label %outer.header, label %for.exit 223 224for.exit: ; preds = %outer.inc 225 %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ] 226 store i64 %iv.inner.lcssa.lcssa, ptr @Y 227 br label %for.end16 228 229for.end16: ; preds = %for.exit 230 ret void 231} 232 233; REMARK: UnsupportedExitPHI 234; REMARK-NEXT: lcssa_06 235 236define void @lcssa_06(ptr %ptr, ptr %ptr1, i1 %arg) { 237entry: 238 br label %outer.header 239 240outer.header: ; preds = %outer.inc, %entry 241 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 242 br i1 %arg, label %for.body3, label %outer.inc 243 244for.body3: ; preds = %for.body3, %outer.header 245 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 246 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 247 %vA = load i32, ptr %arrayidx5 248 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 249 %vC = load i32, ptr %arrayidx9 250 %add = add nsw i32 %vA, %vC 251 store i32 %add, ptr %ptr1 252 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 253 %exitcond = icmp eq i64 %iv.inner.next, 100 254 br i1 %exitcond, label %outer.inc, label %for.body3 255 256outer.inc: ; preds = %for.body3, %outer.header 257 %sv = phi i64 [ 0, %outer.header ], [ 1, %for.body3 ] 258 %iv.outer.next = add nsw i64 %iv.outer, 1 259 %cmp = icmp eq i64 %iv.outer.next, 100 260 br i1 %cmp, label %outer.header, label %for.exit 261 262for.exit: ; preds = %outer.inc 263 %sv.lcssa = phi i64 [ %sv, %outer.inc ] 264 store i64 %sv.lcssa, ptr @Y 265 br label %for.end16 266 267for.end16: ; preds = %for.exit 268 ret void 269} 270 271; REMARK: Interchanged 272; REMARK-NEXT: lcssa_07 273define void @lcssa_07() { 274entry: 275 br label %outer.header 276 277outer.header: ; preds = %outer.inc, %entry 278 %iv.outer = phi i64 [ 1, %entry ], [ %iv.outer.next, %outer.inc ] 279 br label %for.body3 280 281for.body3: ; preds = %for.body3, %outer.header 282 %iv.inner = phi i64 [ %iv.inner.next, %for.body3 ], [ 1, %outer.header ] 283 %arrayidx5 = getelementptr inbounds [100 x [100 x i32]], ptr @A, i64 0, i64 %iv.inner, i64 %iv.outer 284 %vA = load i32, ptr %arrayidx5 285 %arrayidx9 = getelementptr inbounds [100 x [100 x i32]], ptr @C, i64 0, i64 %iv.inner, i64 %iv.outer 286 %vC = load i32, ptr %arrayidx9 287 %add = add nsw i32 %vA, %vC 288 store i32 %add, ptr %arrayidx5 289 %iv.inner.next = add nuw nsw i64 %iv.inner, 1 290 %exitcond = icmp eq i64 %iv.inner.next, 100 291 br i1 %exitcond, label %outer.bb, label %for.body3 292 293outer.bb: ; preds = %for.body3 294 %iv.inner.lcssa = phi i64 [ %iv.inner, %for.body3 ] 295 br label %outer.inc 296 297outer.inc: ; preds = %outer.bb 298 %iv.outer.next = add nsw i64 %iv.outer, 1 299 %cmp = icmp eq i64 %iv.outer.next, 100 300 br i1 %cmp, label %outer.header, label %for.exit 301 302for.exit: ; preds = %outer.inc 303 %iv.inner.lcssa.lcssa = phi i64 [ %iv.inner.lcssa, %outer.inc ] 304 store i64 %iv.inner.lcssa.lcssa, ptr @Y 305 br label %for.end16 306 307for.end16: ; preds = %for.exit 308 ret void 309} 310 311; Should not crash when the outer header branches to 312; both the inner loop and the outer latch, and there 313; is an lcssa phi node outside the loopnest. 314; REMARK: Interchanged 315; REMARK-NEXT: lcssa_08 316define i64 @lcssa_08(ptr %Arr, i1 %arg) { 317entry: 318 br label %for1.header 319 320for1.header: ; preds = %for1.inc, %entry 321 %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc ] 322 br i1 %arg, label %for2, label %for1.inc 323 324for2: ; preds = %for2, %for1.header 325 %indvars.iv = phi i64 [ 0, %for1.header ], [ %indvars.iv.next.3, %for2 ] 326 %arrayidx = getelementptr inbounds [100 x [100 x i64]], ptr %Arr, i64 0, i64 %indvars.iv, i64 %indvars.iv23 327 %lv = load i64, ptr %arrayidx, align 4 328 %indvars.iv.next.3 = add nuw nsw i64 %indvars.iv, 1 329 %exit1 = icmp eq i64 %indvars.iv.next.3, 100 330 br i1 %exit1, label %for1.inc, label %for2 331 332for1.inc: ; preds = %for2, %for1.header 333 %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1 334 %exit2 = icmp eq i64 %indvars.iv.next24, 100 335 br i1 %exit2, label %for1.loopexit, label %for1.header 336 337for1.loopexit: ; preds = %for1.inc 338 %sum.outer.lcssa = phi i64 [ %indvars.iv23, %for1.inc ] 339 ret i64 %sum.outer.lcssa 340} 341 342