[llvm] r332577 - [SROA] Handle PHI with multiple duplicate predecessors
Bjorn Pettersson via llvm-commits
llvm-commits at lists.llvm.org
Thu May 17 00:21:42 PDT 2018
Author: bjope
Date: Thu May 17 00:21:41 2018
New Revision: 332577
URL: http://llvm.org/viewvc/llvm-project?rev=332577&view=rev
Log:
[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
Added:
llvm/trunk/test/Transforms/SROA/phi-with-duplicate-pred.ll
Modified:
llvm/trunk/lib/Transforms/Scalar/SROA.cpp
Modified: llvm/trunk/lib/Transforms/Scalar/SROA.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Transforms/Scalar/SROA.cpp?rev=332577&r1=332576&r2=332577&view=diff
==============================================================================
--- llvm/trunk/lib/Transforms/Scalar/SROA.cpp (original)
+++ llvm/trunk/lib/Transforms/Scalar/SROA.cpp Thu May 17 00:21:41 2018
@@ -1261,10 +1261,21 @@ static void speculatePHINodeLoads(PHINod
}
// 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(PHINod
if (AATags)
Load->setAAMetadata(AATags);
NewPN->addIncoming(Load, Pred);
+ InjectedLoads[Pred] = Load;
}
LLVM_DEBUG(dbgs() << " speculated to: " << *NewPN << "\n");
Added: llvm/trunk/test/Transforms/SROA/phi-with-duplicate-pred.ll
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/Transforms/SROA/phi-with-duplicate-pred.ll?rev=332577&view=auto
==============================================================================
--- llvm/trunk/test/Transforms/SROA/phi-with-duplicate-pred.ll (added)
+++ llvm/trunk/test/Transforms/SROA/phi-with-duplicate-pred.ll Thu May 17 00:21:41 2018
@@ -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"
+
+ at 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
+}
+
More information about the llvm-commits
mailing list