diff options
Diffstat (limited to 'lib/Transforms')
-rw-r--r-- | lib/Transforms/NaCl/CMakeLists.txt | 1 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandConstantExpr.cpp | 23 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandTls.cpp | 13 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp | 13 | ||||
-rw-r--r-- | lib/Transforms/NaCl/ExpandUtils.cpp | 40 |
5 files changed, 49 insertions, 41 deletions
diff --git a/lib/Transforms/NaCl/CMakeLists.txt b/lib/Transforms/NaCl/CMakeLists.txt index 1ca8e3d59e..5d630bb111 100644 --- a/lib/Transforms/NaCl/CMakeLists.txt +++ b/lib/Transforms/NaCl/CMakeLists.txt @@ -4,6 +4,7 @@ add_llvm_library(LLVMTransformsNaCl ExpandGetElementPtr.cpp ExpandTls.cpp ExpandTlsConstantExpr.cpp + ExpandUtils.cpp ExpandVarArgs.cpp GlobalCleanup.cpp StripMetadata.cpp diff --git a/lib/Transforms/NaCl/ExpandConstantExpr.cpp b/lib/Transforms/NaCl/ExpandConstantExpr.cpp index 5ff47cb00c..2856a9d7e4 100644 --- a/lib/Transforms/NaCl/ExpandConstantExpr.cpp +++ b/lib/Transforms/NaCl/ExpandConstantExpr.cpp @@ -63,31 +63,12 @@ static bool expandInstruction(Instruction *Inst) { return false; bool Modified = false; - if (PHINode *PN = dyn_cast<PHINode>(Inst)) { - // PHI nodes require special treatment. A incoming block may be - // listed twice, but its incoming values must match so they must - // be converted only once. - std::map<BasicBlock*,Value*> Converted; - for (unsigned OpNum = 0; OpNum < Inst->getNumOperands(); OpNum++) { - if (ConstantExpr *Expr = - dyn_cast<ConstantExpr>(Inst->getOperand(OpNum))) { - Modified = true; - BasicBlock *Incoming = PN->getIncomingBlock(OpNum); - if (Converted.count(Incoming) == 0) { - Converted[Incoming] = expandConstantExpr(Incoming->getTerminator(), - Expr); - } - Inst->setOperand(OpNum, Converted[Incoming]); - } - } - return Modified; - } - for (unsigned OpNum = 0; OpNum < Inst->getNumOperands(); OpNum++) { if (ConstantExpr *Expr = dyn_cast<ConstantExpr>(Inst->getOperand(OpNum))) { Modified = true; - Inst->setOperand(OpNum, expandConstantExpr(Inst, Expr)); + Use *U = &Inst->getOperandUse(OpNum); + PhiSafeReplaceUses(U, expandConstantExpr(PhiSafeInsertPt(U), Expr)); } } return Modified; diff --git a/lib/Transforms/NaCl/ExpandTls.cpp b/lib/Transforms/NaCl/ExpandTls.cpp index 929b2e0a15..53e1c92a96 100644 --- a/lib/Transforms/NaCl/ExpandTls.cpp +++ b/lib/Transforms/NaCl/ExpandTls.cpp @@ -250,15 +250,8 @@ static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars, ++VarInfo) { GlobalVariable *Var = VarInfo->TlsVar; while (!Var->use_empty()) { - Instruction *U = cast<Instruction>(*Var->use_begin()); - Instruction *InsertPt = U; - if (PHINode *PN = dyn_cast<PHINode>(InsertPt)) { - // We cannot insert instructions before a PHI node, so insert - // before the incoming block's terminator. Note that if the - // terminator is conditional, this could be suboptimal, - // because we might be calling ReadTpFunc unnecessarily. - InsertPt = PN->getIncomingBlock(Var->use_begin())->getTerminator(); - } + Use *U = &Var->use_begin().getUse(); + Instruction *InsertPt = PhiSafeInsertPt(U); Value *RawThreadPtr = CallInst::Create(ReadTpFunc, "tls_raw", InsertPt); Value *TypedThreadPtr = new BitCastInst(RawThreadPtr, TemplatePtrType, "tls_struct", InsertPt); @@ -279,7 +272,7 @@ static void rewriteTlsVars(Module &M, std::vector<VarInfo> *TlsVars, M.getContext(), APInt(32, VarInfo->TemplateIndex))); Value *TlsField = GetElementPtrInst::Create(TypedThreadPtr, Indexes, "field", InsertPt); - U->replaceUsesOfWith(Var, TlsField); + PhiSafeReplaceUses(U, TlsField); } VarInfo->TlsVar->eraseFromParent(); } diff --git a/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp b/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp index 51b21cbf2a..328e5e08e6 100644 --- a/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp +++ b/lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp @@ -78,18 +78,11 @@ static void expandConstExpr(Constant *Expr) { if (ConstantExpr *CE = dyn_cast<ConstantExpr>(Expr)) { while (!Expr->use_empty()) { - Instruction *U = cast<Instruction>(*Expr->use_begin()); - Instruction *InsertPt = U; - if (PHINode *PN = dyn_cast<PHINode>(InsertPt)) { - // We cannot insert instructions before a PHI node, so insert - // before the incoming block's terminator. This could be - // suboptimal if the terminator is a conditional. - InsertPt = PN->getIncomingBlock(Expr->use_begin())->getTerminator(); - } + Use *U = &Expr->use_begin().getUse(); Instruction *NewInst = CE->getAsInstruction(); - NewInst->insertBefore(InsertPt); + NewInst->insertBefore(PhiSafeInsertPt(U)); NewInst->setName("expanded"); - U->replaceUsesOfWith(CE, NewInst); + PhiSafeReplaceUses(U, NewInst); } } } diff --git a/lib/Transforms/NaCl/ExpandUtils.cpp b/lib/Transforms/NaCl/ExpandUtils.cpp new file mode 100644 index 0000000000..0670ff75ce --- /dev/null +++ b/lib/Transforms/NaCl/ExpandUtils.cpp @@ -0,0 +1,40 @@ +//===-- ExpandUtils.cpp - Helper functions for expansion passes -----------===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "llvm/IR/BasicBlock.h" +#include "llvm/IR/Instructions.h" +#include "llvm/Transforms/NaCl.h" + +using namespace llvm; + +Instruction *llvm::PhiSafeInsertPt(Use *U) { + Instruction *InsertPt = cast<Instruction>(U->getUser()); + if (PHINode *PN = dyn_cast<PHINode>(InsertPt)) { + // We cannot insert instructions before a PHI node, so insert + // before the incoming block's terminator. This could be + // suboptimal if the terminator is a conditional. + InsertPt = PN->getIncomingBlock(*U)->getTerminator(); + } + return InsertPt; +} + +void llvm::PhiSafeReplaceUses(Use *U, Value *NewVal) { + if (PHINode *PN = dyn_cast<PHINode>(U->getUser())) { + // A PHI node can have multiple incoming edges from the same + // block, in which case all these edges must have the same + // incoming value. + BasicBlock *BB = PN->getIncomingBlock(*U); + for (unsigned I = 0; I < PN->getNumIncomingValues(); ++I) { + if (PN->getIncomingBlock(I) == BB) + PN->setIncomingValue(I, NewVal); + } + } else { + U->getUser()->replaceUsesOfWith(U->get(), NewVal); + } +} |