Skip to content

Commit 00928a1

Browse files
committed
Fix SROA with a PHI mergig values from a same block
This fixes the bug 47945. It is legal to have a PHI with values from from the same block, but values must stay the same. In this case it is illegal to merge different values. Differential Revision: https://reviews.llvm.org/D89978
1 parent d071bba commit 00928a1

File tree

2 files changed

+82
-6
lines changed

2 files changed

+82
-6
lines changed

llvm/lib/Transforms/Scalar/SROA.cpp

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3545,13 +3545,20 @@ class AggLoadStoreRewriter : public InstVisitor<AggLoadStoreRewriter, bool> {
35453545
PHI->getNumIncomingValues(),
35463546
PHI->getName() + ".sroa.phi");
35473547
for (unsigned I = 0, E = PHI->getNumIncomingValues(); I != E; ++I) {
3548-
Instruction *In = cast<Instruction>(PHI->getIncomingValue(I));
3548+
BasicBlock *B = PHI->getIncomingBlock(I);
3549+
Value *NewVal = nullptr;
3550+
int Idx = NewPN->getBasicBlockIndex(B);
3551+
if (Idx >= 0) {
3552+
NewVal = NewPN->getIncomingValue(Idx);
3553+
} else {
3554+
Instruction *In = cast<Instruction>(PHI->getIncomingValue(I));
35493555

3550-
IRBuilderTy B(In->getParent(), std::next(In->getIterator()));
3551-
Value *NewVal = IsInBounds
3552-
? B.CreateInBoundsGEP(In, Index, In->getName() + ".sroa.gep")
3553-
: B.CreateGEP(In, Index, In->getName() + ".sroa.gep");
3554-
NewPN->addIncoming(NewVal, PHI->getIncomingBlock(I));
3556+
IRBuilderTy B(In->getParent(), std::next(In->getIterator()));
3557+
NewVal = IsInBounds
3558+
? B.CreateInBoundsGEP(In, Index, In->getName() + ".sroa.gep")
3559+
: B.CreateGEP(In, Index, In->getName() + ".sroa.gep");
3560+
}
3561+
NewPN->addIncoming(NewVal, B);
35553562
}
35563563

35573564
Visited.erase(&GEPI);

llvm/test/Transforms/SROA/phi-gep.ll

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -452,6 +452,75 @@ bb2:
452452
ret void
453453
}
454454

455+
define void @constant_value_phi() {
456+
; CHECK-LABEL: @constant_value_phi(
457+
; CHECK-NEXT: entry:
458+
; CHECK-NEXT: br label [[LAND_LHS_TRUE_I:%.*]]
459+
; CHECK: land.lhs.true.i:
460+
; CHECK-NEXT: br i1 undef, label [[COND_END_I:%.*]], label [[COND_END_I]]
461+
; CHECK: cond.end.i:
462+
; CHECK-NEXT: unreachable
463+
;
464+
entry:
465+
%s1 = alloca [3 x i16]
466+
%s = alloca [3 x i16]
467+
%cast = bitcast [3 x i16]* %s1 to i16*
468+
br label %land.lhs.true.i
469+
470+
land.lhs.true.i: ; preds = %entry
471+
br i1 undef, label %cond.end.i, label %cond.end.i
472+
473+
cond.end.i: ; preds = %land.lhs.true.i, %land.lhs.true.i
474+
%.pre-phi1 = phi i16* [ %cast, %land.lhs.true.i ], [ %cast, %land.lhs.true.i ]
475+
%cast2 = bitcast [3 x i16]* %s to i16*
476+
call void @llvm.memcpy.p0i16.p0i16.i64(i16* %.pre-phi1, i16* %cast2, i64 3, i1 false)
477+
%gep = getelementptr inbounds [3 x i16], [3 x i16]* %s, i32 0, i32 0
478+
%load = load i16, i16* %gep
479+
unreachable
480+
}
481+
482+
define i32 @test_sroa_phi_gep_multiple_values_from_same_block(i32 %arg) {
483+
; CHECK-LABEL: @test_sroa_phi_gep_multiple_values_from_same_block(
484+
; CHECK-NEXT: bb.1:
485+
; CHECK-NEXT: switch i32 [[ARG:%.*]], label [[BB_3:%.*]] [
486+
; CHECK-NEXT: i32 1, label [[BB_2:%.*]]
487+
; CHECK-NEXT: i32 2, label [[BB_2]]
488+
; CHECK-NEXT: i32 3, label [[BB_4:%.*]]
489+
; CHECK-NEXT: i32 4, label [[BB_4]]
490+
; CHECK-NEXT: ]
491+
; CHECK: bb.2:
492+
; CHECK-NEXT: br label [[BB_4]]
493+
; CHECK: bb.3:
494+
; CHECK-NEXT: br label [[BB_4]]
495+
; CHECK: bb.4:
496+
; CHECK-NEXT: [[PHI_SROA_PHI_SROA_SPECULATED:%.*]] = phi i32 [ undef, [[BB_3]] ], [ undef, [[BB_2]] ], [ undef, [[BB_1:%.*]] ], [ undef, [[BB_1]] ]
497+
; CHECK-NEXT: ret i32 [[PHI_SROA_PHI_SROA_SPECULATED]]
498+
;
499+
bb.1:
500+
%a = alloca %pair, align 4
501+
%b = alloca %pair, align 4
502+
switch i32 %arg, label %bb.3 [
503+
i32 1, label %bb.2
504+
i32 2, label %bb.2
505+
i32 3, label %bb.4
506+
i32 4, label %bb.4
507+
]
508+
509+
bb.2: ; preds = %bb.1, %bb.1
510+
br label %bb.4
511+
512+
bb.3: ; preds = %bb.1
513+
br label %bb.4
514+
515+
bb.4: ; preds = %bb.1, %bb.1, %bb.3, %bb.2
516+
%phi = phi %pair* [ %a, %bb.3 ], [ %a, %bb.2 ], [ %b, %bb.1 ], [ %b, %bb.1 ]
517+
%gep = getelementptr inbounds %pair, %pair* %phi, i32 0, i32 1
518+
%load = load i32, i32* %gep, align 4
519+
ret i32 %load
520+
}
521+
455522
declare %pair* @foo()
456523

457524
declare i32 @__gxx_personality_v0(...)
525+
526+
declare void @llvm.memcpy.p0i16.p0i16.i64(i16* noalias nocapture writeonly, i16* noalias nocapture readonly, i64, i1 immarg)

0 commit comments

Comments
 (0)