diff --git a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp --- a/llvm/lib/Transforms/Scalar/LoopInterchange.cpp +++ b/llvm/lib/Transforms/Scalar/LoopInterchange.cpp @@ -661,6 +661,14 @@ // Check V's users to see if it is involved in a reduction in L. static PHINode *findInnerReductionPhi(Loop *L, Value *V) { + if (isa(V)) { + // The function is looking for reduction variables, which cannot be + // constants; also walking users of some Constants (particularly + // ConstantData) doesn't make semantic sense in a function pass since + // its users can be spread among different functions or modules + // that happens to be in the same LLVMContext + return nullptr; + } for (Value *User : V->users()) { if (PHINode *PHI = dyn_cast(User)) { if (PHI->getNumIncomingValues() == 1) diff --git a/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll b/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll --- a/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll +++ b/llvm/test/Transforms/LoopInterchange/reductions-across-inner-and-outer-loop.ll @@ -150,3 +150,42 @@ %sum.inc.lcssa2 = phi i64 [ %sum.inc.lcssa, %for1.inc ] ret i64 %sum.inc.lcssa2 } + +; Check that we do not interchange or crush if PHI in the outer loop gets +; a constant from the inner loop +; REMARKS: --- !Missed +; REMARKS-NEXT: Pass: loop-interchange +; REMARKS-NEXT: Name: UnsupportedPHIOuter +; REMARKS-NEXT: Function: test_constant_inner_loop_res + +define i64 @test_constant_inner_loop_res([100 x [100 x i64]]* %Arr) { +entry: + br label %for1.header + +for1.header: ; preds = %for1.inc, %entry + %indvars.iv23 = phi i64 [ 0, %entry ], [ %indvars.iv.next24, %for1.inc ] + %sum.outer = phi i64 [ 0, %entry ], [ %sum.inc.amend, %for1.inc ] + br label %for2 + +for2: ; preds = %for2, %for1.header + %indvars.iv = phi i64 [ 0, %for1.header ], [ %indvars.iv.next.3, %for2 ] + %sum.inner = phi i64 [ %sum.outer, %for1.header ], [ %sum.inc, %for2 ] + %arrayidx = getelementptr inbounds [100 x [100 x i64]], [100 x [100 x i64]]* %Arr, i64 0, i64 %indvars.iv, i64 %indvars.iv23 + %lv = load i64, i64* %arrayidx, align 4 + %sum.inc = add i64 %sum.inner, %lv + %indvars.iv.next.3 = add nuw nsw i64 %indvars.iv, 1 + %exit1 = icmp eq i64 %indvars.iv.next.3, 100 + br i1 %exit1, label %for1.inc, label %for2 + +for1.inc: ; preds = %for2 + %sum.inc.lcssa = phi i64 [ %sum.inc, %for2 ] + %const.lcssa = phi i64 [ 0, %for2 ] + %sum.inc.amend = add i64 %const.lcssa, %sum.inc.lcssa + %indvars.iv.next24 = add nuw nsw i64 %indvars.iv23, 1 + %exit2 = icmp eq i64 %indvars.iv.next24, 100 + br i1 %exit2, label %for1.loopexit, label %for1.header + +for1.loopexit: ; preds = %for1.inc + %il.res.lcssa2 = phi i64 [ %sum.inc.amend, %for1.inc ] + ret i64 %il.res.lcssa2 +}