aboutsummaryrefslogtreecommitdiff
path: root/lib/Target
diff options
context:
space:
mode:
authorEvan Cheng <evan.cheng@apple.com>2012-10-05 01:48:22 +0000
committerEvan Cheng <evan.cheng@apple.com>2012-10-05 01:48:22 +0000
commit2a2947885aea4e96eb6b776c1558f625506a26d2 (patch)
tree830efc9ca51a00f341e89699c55a43d7aa46a703 /lib/Target
parentfca3f4021ae9a561edb6d2fcb4a282b6f25ab144 (diff)
Follow up to r165072. Try a different approach: only move the load when it's going to be folded into the call. rdar://12437604
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@165287 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Target')
-rw-r--r--lib/Target/X86/X86ISelDAGToDAG.cpp20
1 files changed, 9 insertions, 11 deletions
diff --git a/lib/Target/X86/X86ISelDAGToDAG.cpp b/lib/Target/X86/X86ISelDAGToDAG.cpp
index 98778c3091..b79dd99d8f 100644
--- a/lib/Target/X86/X86ISelDAGToDAG.cpp
+++ b/lib/Target/X86/X86ISelDAGToDAG.cpp
@@ -387,21 +387,12 @@ static void MoveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load,
CurDAG->UpdateNodeOperands(Load.getNode(), Call.getOperand(0),
Load.getOperand(1), Load.getOperand(2));
- bool IsGlued = Call.getOperand(0).getNode()->getGluedUser() == Call.getNode();
unsigned NumOps = Call.getNode()->getNumOperands();
Ops.clear();
Ops.push_back(SDValue(Load.getNode(), 1));
for (unsigned i = 1, e = NumOps; i != e; ++i)
Ops.push_back(Call.getOperand(i));
- if (!IsGlued)
- CurDAG->UpdateNodeOperands(Call.getNode(), &Ops[0], NumOps);
- else
- // If call's chain was glued to the call (tailcall), and now the load
- // is moved between them. Remove the glue to avoid a cycle (where the
- // call is glued to its old chain and the load is using the old chain
- // as its new chain).
- CurDAG->MorphNodeTo(Call.getNode(), Call.getOpcode(),
- Call.getNode()->getVTList(), &Ops[0], NumOps-1);
+ CurDAG->UpdateNodeOperands(Call.getNode(), &Ops[0], NumOps);
}
/// isCalleeLoad - Return true if call address is a load and it can be
@@ -410,6 +401,10 @@ static void MoveBelowOrigChain(SelectionDAG *CurDAG, SDValue Load,
/// In the case of a tail call, there isn't a callseq node between the call
/// chain and the load.
static bool isCalleeLoad(SDValue Callee, SDValue &Chain, bool HasCallSeq) {
+ // The transformation is somewhat dangerous if the call's chain was glued to
+ // the call. After MoveBelowOrigChain the load is moved between the call and
+ // the chain, this can create a cycle if the load is not folded. So it is
+ // *really* important that we are sure the load will be folded.
if (Callee.getNode() == Chain.getNode() || !Callee.hasOneUse())
return false;
LoadSDNode *LD = dyn_cast<LoadSDNode>(Callee.getNode());
@@ -447,7 +442,10 @@ void X86DAGToDAGISel::PreprocessISelDAG() {
if (OptLevel != CodeGenOpt::None &&
(N->getOpcode() == X86ISD::CALL ||
- N->getOpcode() == X86ISD::TC_RETURN)) {
+ (N->getOpcode() == X86ISD::TC_RETURN &&
+ // Only does this if load can be foled into TC_RETURN.
+ (Subtarget->is64Bit() ||
+ getTargetMachine().getRelocationModel() != Reloc::PIC_)))) {
/// Also try moving call address load from outside callseq_start to just
/// before the call to allow it to be folded.
///