aboutsummaryrefslogtreecommitdiff
path: root/lib/Transforms
diff options
context:
space:
mode:
authorMark Seaborn <mseaborn@chromium.org>2013-03-29 17:42:10 -0700
committerMark Seaborn <mseaborn@chromium.org>2013-03-29 17:42:10 -0700
commitcd93e1afec966dba60433f8df5f78f10ef217f93 (patch)
tree97c1b68239f23dedd72f5283e37a4957af9d10a1 /lib/Transforms
parent946417b9fe7da9334c76182f28020ff4f46e11f8 (diff)
PNaCl: Fix ExpandTls to handle a couple of corner cases involving PHI nodes
ExpandTls's use of replaceUsesOfWith() didn't work for PHI nodes containing the same Constant twice (which needs to work for same or differing incoming BasicBlocks). The same applies to ExpandTlsConstantExpr. I noticed this while implementing ExpandConstantExpr. Fix this and factor out some common code that all three passes can use. BUG=https://code.google.com/p/nativeclient/issues/detail?id=2837 TEST=test/Transforms/NaCl/*.ll Review URL: https://codereview.chromium.org/13128002
Diffstat (limited to 'lib/Transforms')
-rw-r--r--lib/Transforms/NaCl/CMakeLists.txt1
-rw-r--r--lib/Transforms/NaCl/ExpandConstantExpr.cpp23
-rw-r--r--lib/Transforms/NaCl/ExpandTls.cpp13
-rw-r--r--lib/Transforms/NaCl/ExpandTlsConstantExpr.cpp13
-rw-r--r--lib/Transforms/NaCl/ExpandUtils.cpp40
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);
+ }
+}