From 8a59de408a576ae41a16837bb82bae5b51aebca1 Mon Sep 17 00:00:00 2001 From: Alon Zakai Date: Sun, 23 Mar 2014 18:53:14 -0700 Subject: handle switches that reach phis appearing before them; fixes emscripen issue 2244 --- lib/Target/JSBackend/ExpandI64.cpp | 31 ++++++++++++++++++++++++------- 1 file changed, 24 insertions(+), 7 deletions(-) diff --git a/lib/Target/JSBackend/ExpandI64.cpp b/lib/Target/JSBackend/ExpandI64.cpp index e595594e41..9929033169 100644 --- a/lib/Target/JSBackend/ExpandI64.cpp +++ b/lib/Target/JSBackend/ExpandI64.cpp @@ -42,6 +42,7 @@ #include "llvm/Target/TargetLibraryInfo.h" #include "llvm/Transforms/Utils/Local.h" #include +#include #include "llvm/Support/raw_ostream.h" @@ -54,6 +55,10 @@ using namespace llvm; namespace { + struct PhiBlockChange { + BasicBlock *DD, *SwitchBB, *NewBB; + }; + typedef SmallVector ChunksVec; typedef std::map SplitsMap; @@ -69,6 +74,7 @@ namespace { SplitsMap Splits; // old illegal value to new insts PHIVec Phis; + std::vector PhiBlockChanges; // If the function has an illegal return or argument, create a legal version void ensureLegalFunc(Function *F); @@ -890,13 +896,12 @@ bool ExpandI64::splitInst(Instruction *I) { // We used to go SwitchBB->DD, but now go SwitchBB->NewBB->DD, fix that like with BB above. However here we do not replace, // as the switch BB is still possible to arrive from - we can arrive at the default if either the lower bits were wrong (we // arrive from the switchBB) or from the NewBB if the high bits were wrong. - for (BasicBlock::iterator I = DD->begin(); I != DD->end(); ++I) { - PHINode *Phi = dyn_cast(I); - if (!Phi) break; - Phi->addIncoming(Phi->getIncomingValue(Phi->getBasicBlockIndex(SwitchBB)), NewBB); - // XXX note that we add a new i64 thing here. now the phi was already an i64 operation, and is being legalized anyhow, but we only notice the original inputs! - // we seem to be safe for now due to order of operation (phis show up after switches, but FIXME - } + // We cannot do this here right now, as phis we encounter may be in the middle of processing (empty), so we queue these. + PhiBlockChange Change; + Change.DD = DD; + Change.SwitchBB = SwitchBB; + Change.NewBB = NewBB; + PhiBlockChanges.push_back(Change); } break; } @@ -1091,6 +1096,18 @@ bool ExpandI64::runOnModule(Module &M) { PN->dropAllReferences(); } + // Apply basic block changes to phis, now that phis are all processed + for (unsigned i = 0; i < PhiBlockChanges.size(); i++) { + PhiBlockChange &Change = PhiBlockChanges[i]; + for (BasicBlock::iterator I = Change.DD->begin(); I != Change.DD->end(); ++I) { + PHINode *Phi = dyn_cast(I); + if (!Phi) break; + int Index = Phi->getBasicBlockIndex(Change.SwitchBB); + assert(Index >= 0); + Phi->addIncoming(Phi->getIncomingValue(Index), Change.NewBB); + } + } + // Delete instructions which were replaced. We do this after the full walk // of the instructions so that all uses are replaced first. while (!Dead.empty()) { -- cgit v1.2.3-18-g5258