summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2018-05-17 07:21:41 +0000
committerBjorn Pettersson <bjorn.a.pettersson@ericsson.com>2018-05-17 07:21:41 +0000
commit81a76a388a35e4f58c897df328852f7b6482b9eb (patch)
tree38318467f5e82bada34bf972d02621497440a79d
parent1b7bbb72f94762e6747adf5636bb9aa599f7a1fb (diff)
downloadbcm5719-llvm-81a76a388a35e4f58c897df328852f7b6482b9eb.tar.gz
bcm5719-llvm-81a76a388a35e4f58c897df328852f7b6482b9eb.zip
[SROA] Handle PHI with multiple duplicate predecessors
Summary: The verifier accepts PHI nodes with multiple entries for the same basic block, as long as the value is the same. As seen in PR37203, SROA did not handle such PHI nodes properly when speculating loads over the PHI, since it inserted multiple loads in the predecessor block and changed the PHI into having multiple entries for the same basic block, but with different values. This patch teaches SROA to reuse the same speculated load for each PHI duplicate entry in such situations. Resolves: https://bugs.llvm.org/show_bug.cgi?id=37203 Reviewers: uabelho, chandlerc, hfinkel, bkramer, efriedma Reviewed By: efriedma Subscribers: dberlin, efriedma, llvm-commits Differential Revision: https://reviews.llvm.org/D46426 llvm-svn: 332577
-rw-r--r--llvm/lib/Transforms/Scalar/SROA.cpp14
-rw-r--r--llvm/test/Transforms/SROA/phi-with-duplicate-pred.ll51
2 files changed, 64 insertions, 1 deletions
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 7c2fb4b788d..07780f15a58 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -1261,10 +1261,21 @@ static void speculatePHINodeLoads(PHINode &PN) {
}
// Inject loads into all of the pred blocks.
+ DenseMap<BasicBlock*, Value*> InjectedLoads;
for (unsigned Idx = 0, Num = PN.getNumIncomingValues(); Idx != Num; ++Idx) {
BasicBlock *Pred = PN.getIncomingBlock(Idx);
- TerminatorInst *TI = Pred->getTerminator();
Value *InVal = PN.getIncomingValue(Idx);
+
+ // A PHI node is allowed to have multiple (duplicated) entries for the same
+ // basic block, as long as the value is the same. So if we already injected
+ // a load in the predecessor, then we should reuse the same load for all
+ // duplicated entries.
+ if (Value* V = InjectedLoads.lookup(Pred)) {
+ NewPN->addIncoming(V, Pred);
+ continue;
+ }
+
+ TerminatorInst *TI = Pred->getTerminator();
IRBuilderTy PredBuilder(TI);
LoadInst *Load = PredBuilder.CreateLoad(
@@ -1274,6 +1285,7 @@ static void speculatePHINodeLoads(PHINode &PN) {
if (AATags)
Load->setAAMetadata(AATags);
NewPN->addIncoming(Load, Pred);
+ InjectedLoads[Pred] = Load;
}
LLVM_DEBUG(dbgs() << " speculated to: " << *NewPN << "\n");
diff --git a/llvm/test/Transforms/SROA/phi-with-duplicate-pred.ll b/llvm/test/Transforms/SROA/phi-with-duplicate-pred.ll
new file mode 100644
index 00000000000..64963fd6634
--- /dev/null
+++ b/llvm/test/Transforms/SROA/phi-with-duplicate-pred.ll
@@ -0,0 +1,51 @@
+; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
+; RUN: opt < %s -sroa -S | FileCheck %s
+target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-n8:16:32:64"
+
+@a = external global i16, align 1
+
+define void @f2() {
+; CHECK-LABEL: @f2(
+; CHECK-NEXT: entry:
+; CHECK-NEXT: br i1 undef, label [[IF_THEN:%.*]], label [[IF_ELSE:%.*]]
+; CHECK: if.then:
+; CHECK-NEXT: br label [[CLEANUP:%.*]]
+; CHECK: cleanup:
+; CHECK-NEXT: [[G_0_SROA_SPECULATE_LOAD_CLEANUP:%.*]] = load i16, i16* @a, align 1
+; CHECK-NEXT: switch i32 2, label [[CLEANUP7:%.*]] [
+; CHECK-NEXT: i32 0, label [[LBL1:%.*]]
+; CHECK-NEXT: i32 2, label [[LBL1]]
+; CHECK-NEXT: ]
+; CHECK: if.else:
+; CHECK-NEXT: br label [[LBL1]]
+; CHECK: lbl1:
+; CHECK-NEXT: [[G_0_SROA_SPECULATED:%.*]] = phi i16 [ [[G_0_SROA_SPECULATE_LOAD_CLEANUP]], [[CLEANUP]] ], [ [[G_0_SROA_SPECULATE_LOAD_CLEANUP]], [[CLEANUP]] ], [ undef, [[IF_ELSE]] ]
+; CHECK-NEXT: unreachable
+; CHECK: cleanup7:
+; CHECK-NEXT: ret void
+;
+entry:
+ %e = alloca i16, align 1
+ br i1 undef, label %if.then, label %if.else
+
+if.then: ; preds = %entry
+ br label %cleanup
+
+cleanup: ; preds = %if.then
+ switch i32 2, label %cleanup7 [
+ i32 0, label %lbl1
+ i32 2, label %lbl1
+ ]
+
+if.else: ; preds = %entry
+ br label %lbl1
+
+lbl1: ; preds = %if.else, %cleanup, %cleanup
+ %g.0 = phi i16* [ @a, %cleanup ], [ @a, %cleanup ], [ %e, %if.else ]
+ %0 = load i16, i16* %g.0, align 1
+ unreachable
+
+cleanup7: ; preds = %cleanup
+ ret void
+}
+
OpenPOWER on IntegriCloud