Index: llvm/lib/Transforms/Scalar/SROA.cpp =================================================================== --- llvm/lib/Transforms/Scalar/SROA.cpp +++ llvm/lib/Transforms/Scalar/SROA.cpp @@ -3524,13 +3524,16 @@ return false; PHINode *PHI = cast(GEPI.getPointerOperand()); + SmallPtrSet VisitedBlocks; if (GEPI.getParent() != PHI->getParent() || llvm::any_of(PHI->incoming_values(), [](Value *In) { Instruction *I = dyn_cast(In); return !I || isa(I) || isa(I) || succ_empty(I->getParent()) || !I->getParent()->isLegalToHoistInto(); - })) + }) || + llvm::any_of(PHI->blocks(), [&VisitedBlocks](BasicBlock *B) + { return !VisitedBlocks.insert(B).second; })) return false; LLVM_DEBUG(dbgs() << " Rewriting gep(phi) -> phi(gep):" Index: llvm/test/Transforms/SROA/phi-gep.ll =================================================================== --- llvm/test/Transforms/SROA/phi-gep.ll +++ llvm/test/Transforms/SROA/phi-gep.ll @@ -452,6 +452,35 @@ ret void } +define void @constant_value_phi() { +; CHECK-LABEL: @constant_value_phi( +; CHECK-NEXT: entry: +; CHECK-NEXT: br label [[LAND_LHS_TRUE_I:%.*]] +; CHECK: land.lhs.true.i: +; CHECK-NEXT: br i1 undef, label [[COND_END_I:%.*]], label [[COND_END_I]] +; CHECK: cond.end.i: +; CHECK-NEXT: unreachable +; +entry: + %s1 = alloca [3 x i16] + %s = alloca [3 x i16] + %cast = bitcast [3 x i16]* %s1 to i16* + br label %land.lhs.true.i + +land.lhs.true.i: ; preds = %entry + br i1 undef, label %cond.end.i, label %cond.end.i + +cond.end.i: ; preds = %land.lhs.true.i, %land.lhs.true.i + %.pre-phi1 = phi i16* [ %cast, %land.lhs.true.i ], [ %cast, %land.lhs.true.i ] + %cast2 = bitcast [3 x i16]* %s to i16* + call void @llvm.memcpy.p0i16.p0i16.i64(i16* %.pre-phi1, i16* %cast2, i64 3, i1 false) + %gep = getelementptr inbounds [3 x i16], [3 x i16]* %s, i32 0, i32 0 + %load = load i16, i16* %gep + unreachable +} + declare %pair* @foo() declare i32 @__gxx_personality_v0(...) + +declare void @llvm.memcpy.p0i16.p0i16.i64(i16* noalias nocapture writeonly, i16* noalias nocapture readonly, i64, i1 immarg)