From 0d67f0c80f0295aa44f826ec1402ea73d6b4bd22 Mon Sep 17 00:00:00 2001 From: Chris Lattner Date: Wed, 11 May 2005 19:02:11 +0000 Subject: [PATCH] Fix the last remaining bug preventing us from switching the X86 BE over from the simple isel to the pattern isel. This forces inserted libcalls to serialize against other function calls, which was breaking UnitTests/2005-05-12-Int64ToFP. Hopefully this will fix issues on other targets as well. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@21872 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/CodeGen/SelectionDAG/LegalizeDAG.cpp | 98 ++++++++++++++++-------- 1 file changed, 68 insertions(+), 30 deletions(-) diff --git a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp index a19e6119a7c..a511202a534 100644 --- a/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp +++ b/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp @@ -908,6 +908,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } else { assert(0 && "Unknown op!"); } + // FIXME: THESE SHOULD USE ExpandLibCall ??!? std::pair CallResult = TLI.LowerCallTo(Tmp1, Type::VoidTy, false, DAG.getExternalSymbol(FnName, IntPtr), Args, DAG); @@ -1222,6 +1223,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) { } std::vector > Args; Args.push_back(std::make_pair(Tmp1, T)); + // FIXME: should use ExpandLibCall! std::pair CallResult = TLI.LowerCallTo(DAG.getEntryNode(), T, false, DAG.getExternalSymbol(FnName, VT), Args, DAG); @@ -1984,15 +1986,30 @@ static SDNode *FindAdjCallStackUp(SDNode *Node) { abort(); } +/// FindAdjCallStackDown - Given a chained node that is part of a call sequence, +/// find the ADJCALLSTACKDOWN node that initiates the call sequence. +static SDNode *FindAdjCallStackDown(SDNode *Node) { + assert(Node && "Didn't find adjcallstackdown for a call??"); + if (Node->getOpcode() == ISD::ADJCALLSTACKDOWN) return Node; + + assert(Node->getOperand(0).getValueType() == MVT::Other && + "Node doesn't have a token chain argument!"); + return FindAdjCallStackDown(Node->getOperand(0).Val); +} + + /// FindInputOutputChains - If we are replacing an operation with a call we need /// to find the call that occurs before and the call that occurs after it to -/// properly serialize the calls in the block. +/// properly serialize the calls in the block. The returned operand is the +/// input chain value for the new call (e.g. the entry node or the previous +/// call), and OutChain is set to be the chain node to update to point to the +/// end of the call chain. static SDOperand FindInputOutputChains(SDNode *OpNode, SDNode *&OutChain, SDOperand Entry) { SDNode *LatestAdjCallStackDown = Entry.Val; SDNode *LatestAdjCallStackUp = 0; FindLatestAdjCallStackDown(OpNode, LatestAdjCallStackDown); - //std::cerr << "Found node: "; LatestAdjCallStackDown->dump(); std::cerr <<"\n"; + //std::cerr<<"Found node: "; LatestAdjCallStackDown->dump(); std::cerr <<"\n"; // It is possible that no ISD::ADJCALLSTACKDOWN was found because there is no // previous call in the function. LatestCallStackDown may in that case be @@ -2004,17 +2021,33 @@ static SDOperand FindInputOutputChains(SDNode *OpNode, SDNode *&OutChain, LatestAdjCallStackUp = Entry.Val; assert(LatestAdjCallStackUp && "NULL return from FindAdjCallStackUp"); - SDNode *EarliestAdjCallStackUp = 0; - FindEarliestAdjCallStackUp(OpNode, EarliestAdjCallStackUp); + // Finally, find the first call that this must come before, first we find the + // adjcallstackup that ends the call. + OutChain = 0; + FindEarliestAdjCallStackUp(OpNode, OutChain); - if (EarliestAdjCallStackUp) { - //std::cerr << "Found node: "; - //EarliestAdjCallStackUp->dump(); std::cerr <<"\n"; - } + // If we found one, translate from the adj up to the adjdown. + if (OutChain) + OutChain = FindAdjCallStackDown(OutChain); return SDOperand(LatestAdjCallStackUp, 0); } +/// SpliceCallInto - Given the result chain of a libcall (CallResult), and a +static void SpliceCallInto(const SDOperand &CallResult, SDNode *OutChain, + SelectionDAG &DAG) { + // Nothing to splice it into? + if (OutChain == 0) return; + + assert(OutChain->getOperand(0).getValueType() == MVT::Other); + //OutChain->dump(); + + // Form a token factor node merging the old inval and the new inval. + SDOperand InToken = DAG.getNode(ISD::TokenFactor, MVT::Other, CallResult, + OutChain->getOperand(0)); + // Change the node to refer to the new token. + OutChain->setAdjCallChain(InToken); +} // ExpandLibCall - Expand a node into a call to a libcall. If the result value @@ -2037,21 +2070,21 @@ SDOperand SelectionDAGLegalize::ExpandLibCall(const char *Name, SDNode *Node, } SDOperand Callee = DAG.getExternalSymbol(Name, TLI.getPointerTy()); - // We don't care about token chains for libcalls. We just use the entry - // node as our input and ignore the output chain. This allows us to place - // calls wherever we need them to satisfy data dependences. + // Splice the libcall in wherever FindInputOutputChains tells us to. const Type *RetTy = MVT::getTypeForValueType(Node->getValueType(0)); - SDOperand Result = TLI.LowerCallTo(InChain, RetTy, false, Callee, - Args, DAG).first; - switch (getTypeAction(Result.getValueType())) { + std::pair CallInfo = + TLI.LowerCallTo(InChain, RetTy, false, Callee, Args, DAG); + SpliceCallInto(CallInfo.second, OutChain, DAG); + + switch (getTypeAction(CallInfo.first.getValueType())) { default: assert(0 && "Unknown thing"); case Legal: - return Result; + return CallInfo.first; case Promote: assert(0 && "Cannot promote this yet!"); case Expand: SDOperand Lo; - ExpandOp(Result, Lo, Hi); + ExpandOp(CallInfo.first, Lo, Hi); return Lo; } } @@ -2066,19 +2099,7 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { "This is not an expansion!"); assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!"); - SDNode *OutChain; - SDOperand InChain = FindInputOutputChains(Source.Val, OutChain, - DAG.getEntryNode()); - - const char *FnName = 0; - if (isSigned) { - if (DestTy == MVT::f32) - FnName = "__floatdisf"; - else { - assert(DestTy == MVT::f64 && "Unknown fp value type!"); - FnName = "__floatdidf"; - } - } else { + if (!isSigned) { // If this is unsigned, and not supported, first perform the conversion to // signed, then adjust the result if the sign bit is set. SDOperand SignedConv = ExpandIntToFP(true, DestTy, Source); @@ -2116,6 +2137,18 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { } return DAG.getNode(ISD::ADD, DestTy, SignedConv, FudgeInReg); } + + SDNode *OutChain = 0; + SDOperand InChain = FindInputOutputChains(Source.Val, OutChain, + DAG.getEntryNode()); + const char *FnName = 0; + if (DestTy == MVT::f32) + FnName = "__floatdisf"; + else { + assert(DestTy == MVT::f64 && "Unknown fp value type!"); + FnName = "__floatdidf"; + } + SDOperand Callee = DAG.getExternalSymbol(FnName, TLI.getPointerTy()); TargetLowering::ArgListTy Args; @@ -2126,7 +2159,12 @@ ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) { // node as our input and ignore the output chain. This allows us to place // calls wherever we need them to satisfy data dependences. const Type *RetTy = MVT::getTypeForValueType(DestTy); - return TLI.LowerCallTo(InChain, RetTy, false, Callee, Args, DAG).first; + + std::pair CallResult = + TLI.LowerCallTo(InChain, RetTy, false, Callee, Args, DAG); + + SpliceCallInto(CallResult.second, OutChain, DAG); + return CallResult.first; }