forked from OSchip/llvm-project
Change the interface to the type legalization method
ReplaceNodeResults: rather than returning a node which must have the same number of results as the original node (which means mucking around with MERGE_VALUES, and which is also easy to get wrong since SelectionDAG folding may mean you don't get the node you expect), return the results in a vector. llvm-svn: 60348
This commit is contained in:
parent
47f733e4ea
commit
6ed40141f7
|
@ -1130,17 +1130,18 @@ public:
|
||||||
/// implement this. The default implementation of this aborts.
|
/// implement this. The default implementation of this aborts.
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
/// ReplaceNodeResults - This callback is invoked for operations that are
|
/// ReplaceNodeResults - This callback is invoked when a node result type is
|
||||||
/// unsupported by the target, which are registered to use 'custom' lowering,
|
/// illegal for the target, and the operation was registered to use 'custom'
|
||||||
/// and whose result type is illegal. This must return a node whose results
|
/// lowering for that result type. The target places new result values for
|
||||||
/// precisely match the results of the input node. This typically involves a
|
/// the node in Results (their number and types must exactly match those of
|
||||||
/// MERGE_VALUES node and/or BUILD_PAIR.
|
/// the original return values of the node), or leaves Results empty, which
|
||||||
|
/// indicates that the node is not to be custom lowered after all.
|
||||||
///
|
///
|
||||||
/// If the target has no operations that require custom lowering, it need not
|
/// If the target has no operations that require custom lowering, it need not
|
||||||
/// implement this. The default implementation aborts.
|
/// implement this. The default implementation aborts.
|
||||||
virtual SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue> &Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
assert(0 && "ReplaceNodeResults not implemented for this target!");
|
assert(0 && "ReplaceNodeResults not implemented for this target!");
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// IsEligibleForTailCallOptimization - Check whether the call is eligible for
|
/// IsEligibleForTailCallOptimization - Check whether the call is eligible for
|
||||||
|
|
|
@ -6083,8 +6083,10 @@ SDValue SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDValue LegalOp,
|
||||||
// the target lowering hooks to expand it. Just keep the low part of the
|
// the target lowering hooks to expand it. Just keep the low part of the
|
||||||
// expanded operation, we know that we're truncating anyway.
|
// expanded operation, we know that we're truncating anyway.
|
||||||
if (getTypeAction(NewOutTy) == Expand) {
|
if (getTypeAction(NewOutTy) == Expand) {
|
||||||
Operation = SDValue(TLI.ReplaceNodeResults(Operation.getNode(), DAG), 0);
|
SmallVector<SDValue, 2> Results;
|
||||||
assert(Operation.getNode() && "Didn't return anything");
|
TLI.ReplaceNodeResults(Operation.getNode(), Results, DAG);
|
||||||
|
assert(Results.size() == 1 && "Incorrect FP_TO_XINT lowering!");
|
||||||
|
Operation = Results[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
// Truncate the result of the extended FP_TO_*INT operation to the desired
|
// Truncate the result of the extended FP_TO_*INT operation to the desired
|
||||||
|
|
|
@ -727,16 +727,8 @@ void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
|
||||||
Lo = Hi = SDValue();
|
Lo = Hi = SDValue();
|
||||||
|
|
||||||
// See if the target wants to custom expand this node.
|
// See if the target wants to custom expand this node.
|
||||||
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
|
if (CustomLowerResults(N, ResNo))
|
||||||
TargetLowering::Custom) {
|
return;
|
||||||
// If the target wants to, allow it to lower this itself.
|
|
||||||
if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
|
|
||||||
// Everything that once used N now uses P. We are guaranteed that the
|
|
||||||
// result value types of N and the result value types of P match.
|
|
||||||
ReplaceNodeWith(N, P);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -34,16 +34,8 @@ void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
|
||||||
SDValue Result = SDValue();
|
SDValue Result = SDValue();
|
||||||
|
|
||||||
// See if the target wants to custom expand this node.
|
// See if the target wants to custom expand this node.
|
||||||
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
|
if (CustomLowerResults(N, ResNo))
|
||||||
TargetLowering::Custom) {
|
return;
|
||||||
// If the target wants to, allow it to lower this itself.
|
|
||||||
if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
|
|
||||||
// Everything that once used N now uses P. We are guaranteed that the
|
|
||||||
// result value types of N and the result value types of P match.
|
|
||||||
ReplaceNodeWith(N, P);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
|
@ -949,16 +941,8 @@ void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
|
||||||
Lo = Hi = SDValue();
|
Lo = Hi = SDValue();
|
||||||
|
|
||||||
// See if the target wants to custom expand this node.
|
// See if the target wants to custom expand this node.
|
||||||
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) ==
|
if (CustomLowerResults(N, ResNo))
|
||||||
TargetLowering::Custom) {
|
return;
|
||||||
// If the target wants to, allow it to lower this itself.
|
|
||||||
if (SDNode *P = TLI.ReplaceNodeResults(N, DAG)) {
|
|
||||||
// Everything that once used N now uses P. We are guaranteed that the
|
|
||||||
// result value types of N and the result value types of P match.
|
|
||||||
ReplaceNodeWith(N, P);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -376,45 +376,6 @@ void DAGTypeLegalizer::ReplaceValueWith(SDValue From, SDValue To) {
|
||||||
ReplacedValues[From] = To;
|
ReplacedValues[From] = To;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ReplaceNodeWith - Replace uses of the 'from' node's results with the 'to'
|
|
||||||
/// node's results. The from and to node must define identical result types.
|
|
||||||
void DAGTypeLegalizer::ReplaceNodeWith(SDNode *From, SDNode *To) {
|
|
||||||
if (From == To) return;
|
|
||||||
|
|
||||||
// If expansion produced new nodes, make sure they are properly marked.
|
|
||||||
ExpungeNode(From);
|
|
||||||
|
|
||||||
To = AnalyzeNewNode(To); // Expunges To.
|
|
||||||
// If To morphed into an already processed node, its values may need
|
|
||||||
// remapping. This is done below.
|
|
||||||
|
|
||||||
assert(From->getNumValues() == To->getNumValues() &&
|
|
||||||
"Node results don't match");
|
|
||||||
|
|
||||||
// Anything that used the old node should now use the new one. Note that this
|
|
||||||
// can potentially cause recursive merging.
|
|
||||||
NodeUpdateListener NUL(*this);
|
|
||||||
for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
|
|
||||||
SDValue FromVal(From, i);
|
|
||||||
SDValue ToVal(To, i);
|
|
||||||
|
|
||||||
// AnalyzeNewNode may have morphed a new node into a processed node. Remap
|
|
||||||
// values now.
|
|
||||||
if (To->getNodeId() == Processed)
|
|
||||||
RemapValue(ToVal);
|
|
||||||
|
|
||||||
assert(FromVal.getValueType() == ToVal.getValueType() &&
|
|
||||||
"Node results don't match!");
|
|
||||||
|
|
||||||
// Make anything that used the old value use the new value.
|
|
||||||
DAG.ReplaceAllUsesOfValueWith(FromVal, ToVal, &NUL);
|
|
||||||
|
|
||||||
// The old node may still be present in a map like ExpandedIntegers or
|
|
||||||
// PromotedIntegers. Inform maps about the replacement.
|
|
||||||
ReplacedValues[FromVal] = ToVal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// RemapValue - If the specified value was already legalized to another value,
|
/// RemapValue - If the specified value was already legalized to another value,
|
||||||
/// replace it by that value.
|
/// replace it by that value.
|
||||||
void DAGTypeLegalizer::RemapValue(SDValue &N) {
|
void DAGTypeLegalizer::RemapValue(SDValue &N) {
|
||||||
|
@ -621,6 +582,28 @@ SDValue DAGTypeLegalizer::CreateStackStoreLoad(SDValue Op,
|
||||||
return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0);
|
return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// CustomLowerResults - Replace the node's results with custom code provided
|
||||||
|
/// by the target and return "true", or do nothing and return "false".
|
||||||
|
bool DAGTypeLegalizer::CustomLowerResults(SDNode *N, unsigned ResNo) {
|
||||||
|
// See if the target wants to custom lower this node.
|
||||||
|
if (TLI.getOperationAction(N->getOpcode(), N->getValueType(ResNo)) !=
|
||||||
|
TargetLowering::Custom)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
SmallVector<SDValue, 8> Results;
|
||||||
|
TLI.ReplaceNodeResults(N, Results, DAG);
|
||||||
|
if (Results.empty())
|
||||||
|
// The target didn't want to custom lower it after all.
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Make everything that once used N's values now use those in Results instead.
|
||||||
|
assert(Results.size() == N->getNumValues() &&
|
||||||
|
"Custom lowering returned the wrong number of results!");
|
||||||
|
for (unsigned i = 0, e = Results.size(); i != e; ++i)
|
||||||
|
ReplaceValueWith(SDValue(N, i), Results[i]);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/// JoinIntegers - Build an integer with low bits Lo and high bits Hi.
|
/// JoinIntegers - Build an integer with low bits Lo and high bits Hi.
|
||||||
SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) {
|
SDValue DAGTypeLegalizer::JoinIntegers(SDValue Lo, SDValue Hi) {
|
||||||
MVT LVT = Lo.getValueType();
|
MVT LVT = Lo.getValueType();
|
||||||
|
|
|
@ -185,12 +185,13 @@ private:
|
||||||
void AnalyzeNewValue(SDValue &Val);
|
void AnalyzeNewValue(SDValue &Val);
|
||||||
|
|
||||||
void ReplaceValueWith(SDValue From, SDValue To);
|
void ReplaceValueWith(SDValue From, SDValue To);
|
||||||
void ReplaceNodeWith(SDNode *From, SDNode *To);
|
|
||||||
|
|
||||||
void RemapValue(SDValue &N);
|
void RemapValue(SDValue &N);
|
||||||
void ExpungeNode(SDNode *N);
|
void ExpungeNode(SDNode *N);
|
||||||
|
|
||||||
// Common routines.
|
// Common routines.
|
||||||
|
bool CustomLowerResults(SDNode *N, unsigned ResNo);
|
||||||
|
|
||||||
SDValue CreateStackStoreLoad(SDValue Op, MVT DestVT);
|
SDValue CreateStackStoreLoad(SDValue Op, MVT DestVT);
|
||||||
SDValue MakeLibCall(RTLIB::Libcall LC, MVT RetVT,
|
SDValue MakeLibCall(RTLIB::Libcall LC, MVT RetVT,
|
||||||
const SDValue *Ops, unsigned NumOps, bool isSigned);
|
const SDValue *Ops, unsigned NumOps, bool isSigned);
|
||||||
|
|
|
@ -1344,7 +1344,7 @@ ARMTargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG,
|
||||||
return DAG.getNode(ISD::TokenFactor, MVT::Other, &TFOps[0], i);
|
return DAG.getNode(ISD::TokenFactor, MVT::Other, &TFOps[0], i);
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDNode *ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
|
static SDValue ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
|
||||||
SDValue Op = N->getOperand(0);
|
SDValue Op = N->getOperand(0);
|
||||||
if (N->getValueType(0) == MVT::f64) {
|
if (N->getValueType(0) == MVT::f64) {
|
||||||
// Turn i64->f64 into FMDRR.
|
// Turn i64->f64 into FMDRR.
|
||||||
|
@ -1352,7 +1352,7 @@ static SDNode *ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
|
||||||
DAG.getConstant(0, MVT::i32));
|
DAG.getConstant(0, MVT::i32));
|
||||||
SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
|
SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op,
|
||||||
DAG.getConstant(1, MVT::i32));
|
DAG.getConstant(1, MVT::i32));
|
||||||
return DAG.getNode(ARMISD::FMDRR, MVT::f64, Lo, Hi).getNode();
|
return DAG.getNode(ARMISD::FMDRR, MVT::f64, Lo, Hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Turn f64->i64 into FMRRD.
|
// Turn f64->i64 into FMRRD.
|
||||||
|
@ -1360,10 +1360,10 @@ static SDNode *ExpandBIT_CONVERT(SDNode *N, SelectionDAG &DAG) {
|
||||||
&Op, 1);
|
&Op, 1);
|
||||||
|
|
||||||
// Merge the pieces into a single i64 value.
|
// Merge the pieces into a single i64 value.
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Cvt, Cvt.getValue(1)).getNode();
|
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Cvt, Cvt.getValue(1));
|
||||||
}
|
}
|
||||||
|
|
||||||
static SDNode *ExpandSRx(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST) {
|
static SDValue ExpandSRx(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST) {
|
||||||
assert(N->getValueType(0) == MVT::i64 &&
|
assert(N->getValueType(0) == MVT::i64 &&
|
||||||
(N->getOpcode() == ISD::SRL || N->getOpcode() == ISD::SRA) &&
|
(N->getOpcode() == ISD::SRL || N->getOpcode() == ISD::SRA) &&
|
||||||
"Unknown shift to lower!");
|
"Unknown shift to lower!");
|
||||||
|
@ -1371,10 +1371,10 @@ static SDNode *ExpandSRx(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST) {
|
||||||
// We only lower SRA, SRL of 1 here, all others use generic lowering.
|
// We only lower SRA, SRL of 1 here, all others use generic lowering.
|
||||||
if (!isa<ConstantSDNode>(N->getOperand(1)) ||
|
if (!isa<ConstantSDNode>(N->getOperand(1)) ||
|
||||||
cast<ConstantSDNode>(N->getOperand(1))->getZExtValue() != 1)
|
cast<ConstantSDNode>(N->getOperand(1))->getZExtValue() != 1)
|
||||||
return 0;
|
return SDValue();
|
||||||
|
|
||||||
// If we are in thumb mode, we don't have RRX.
|
// If we are in thumb mode, we don't have RRX.
|
||||||
if (ST->isThumb()) return 0;
|
if (ST->isThumb()) return SDValue();
|
||||||
|
|
||||||
// Okay, we have a 64-bit SRA or SRL of 1. Lower this to an RRX expr.
|
// Okay, we have a 64-bit SRA or SRL of 1. Lower this to an RRX expr.
|
||||||
SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(0),
|
SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(0),
|
||||||
|
@ -1391,7 +1391,7 @@ static SDNode *ExpandSRx(SDNode *N, SelectionDAG &DAG, const ARMSubtarget *ST) {
|
||||||
Lo = DAG.getNode(ARMISD::RRX, MVT::i32, Lo, Hi.getValue(1));
|
Lo = DAG.getNode(ARMISD::RRX, MVT::i32, Lo, Hi.getValue(1));
|
||||||
|
|
||||||
// Merge the pieces into a single i64 value.
|
// Merge the pieces into a single i64 value.
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi).getNode();
|
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1419,22 +1419,34 @@ SDValue ARMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
case ISD::FRAMEADDR: break;
|
case ISD::FRAMEADDR: break;
|
||||||
case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
|
case ISD::GLOBAL_OFFSET_TABLE: return LowerGLOBAL_OFFSET_TABLE(Op, DAG);
|
||||||
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
case ISD::INTRINSIC_WO_CHAIN: return LowerINTRINSIC_WO_CHAIN(Op, DAG);
|
||||||
case ISD::BIT_CONVERT: return SDValue(ExpandBIT_CONVERT(Op.getNode(), DAG), 0);
|
case ISD::BIT_CONVERT: return ExpandBIT_CONVERT(Op.getNode(), DAG);
|
||||||
case ISD::SRL:
|
case ISD::SRL:
|
||||||
case ISD::SRA: return SDValue(ExpandSRx(Op.getNode(), DAG,Subtarget),0);
|
case ISD::SRA: return ExpandSRx(Op.getNode(), DAG,Subtarget);
|
||||||
}
|
}
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// ReplaceNodeResults - Provide custom lowering hooks for nodes with illegal
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
/// result types.
|
/// type with new values built out of custom code.
|
||||||
SDNode *ARMTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
|
///
|
||||||
|
void ARMTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default: assert(0 && "Don't know how to custom expand this!"); abort();
|
default:
|
||||||
case ISD::BIT_CONVERT: return ExpandBIT_CONVERT(N, DAG);
|
assert(0 && "Don't know how to custom expand this!");
|
||||||
|
return;
|
||||||
|
case ISD::BIT_CONVERT:
|
||||||
|
Results.push_back(ExpandBIT_CONVERT(N, DAG));
|
||||||
|
return;
|
||||||
case ISD::SRL:
|
case ISD::SRL:
|
||||||
case ISD::SRA: return ExpandSRx(N, DAG, Subtarget);
|
case ISD::SRA: {
|
||||||
|
SDValue Res = ExpandSRx(N, DAG, Subtarget);
|
||||||
|
if (Res.getNode())
|
||||||
|
Results.push_back(Res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,12 @@ namespace llvm {
|
||||||
explicit ARMTargetLowering(TargetMachine &TM);
|
explicit ARMTargetLowering(TargetMachine &TM);
|
||||||
|
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
virtual SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
|
||||||
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
|
/// type with new values built out of custom code.
|
||||||
|
///
|
||||||
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
|
||||||
|
|
|
@ -612,15 +612,18 @@ SDValue AlphaTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *AlphaTargetLowering::ReplaceNodeResults(SDNode *N,
|
void AlphaTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
SelectionDAG &DAG) {
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
assert(N->getValueType(0) == MVT::i32 &&
|
assert(N->getValueType(0) == MVT::i32 &&
|
||||||
N->getOpcode() == ISD::VAARG &&
|
N->getOpcode() == ISD::VAARG &&
|
||||||
"Unknown node to custom promote!");
|
"Unknown node to custom promote!");
|
||||||
|
|
||||||
SDValue Chain, DataPtr;
|
SDValue Chain, DataPtr;
|
||||||
LowerVAARG(N, Chain, DataPtr, DAG);
|
LowerVAARG(N, Chain, DataPtr, DAG);
|
||||||
return DAG.getLoad(N->getValueType(0), Chain, DataPtr, NULL, 0).getNode();
|
SDValue Res = DAG.getLoad(N->getValueType(0), Chain, DataPtr, NULL, 0);
|
||||||
|
Results.push_back(Res);
|
||||||
|
Results.push_back(SDValue(Res.getNode(), 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -72,7 +72,12 @@ namespace llvm {
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
///
|
///
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
virtual SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
|
||||||
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
|
/// type with new values built out of custom code.
|
||||||
|
///
|
||||||
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
// Friendly names for dumps
|
// Friendly names for dumps
|
||||||
const char *getTargetNodeName(unsigned Opcode) const;
|
const char *getTargetNodeName(unsigned Opcode) const;
|
||||||
|
|
|
@ -2866,7 +2866,9 @@ SPUTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG)
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
|
void SPUTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG)
|
||||||
{
|
{
|
||||||
#if 0
|
#if 0
|
||||||
unsigned Opc = (unsigned) N->getOpcode();
|
unsigned Opc = (unsigned) N->getOpcode();
|
||||||
|
@ -2885,7 +2887,6 @@ SDNode *SPUTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Otherwise, return unchanged */
|
/* Otherwise, return unchanged */
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//===----------------------------------------------------------------------===//
|
//===----------------------------------------------------------------------===//
|
||||||
|
|
|
@ -113,8 +113,9 @@ namespace llvm {
|
||||||
//! Custom lowering hooks
|
//! Custom lowering hooks
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
//! Provide custom lowering hooks for nodes with illegal result types.
|
//! Custom lowering hook for nodes with illegal result types.
|
||||||
SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
|
||||||
|
|
|
@ -90,24 +90,35 @@ const char *PIC16TargetLowering::getTargetNodeName(unsigned Opcode) const {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *PIC16TargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
|
void PIC16TargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
case ISD::GlobalAddress:
|
case ISD::GlobalAddress:
|
||||||
return ExpandGlobalAddress(N, DAG);
|
Results.push_back(ExpandGlobalAddress(N, DAG));
|
||||||
|
return;
|
||||||
case ISD::STORE:
|
case ISD::STORE:
|
||||||
return ExpandStore(N, DAG);
|
Results.push_back(ExpandStore(N, DAG));
|
||||||
|
return;
|
||||||
case ISD::LOAD:
|
case ISD::LOAD:
|
||||||
return ExpandLoad(N, DAG);
|
Results.push_back(ExpandLoad(N, DAG));
|
||||||
|
return;
|
||||||
case ISD::ADD:
|
case ISD::ADD:
|
||||||
return ExpandAdd(N, DAG);
|
// return ExpandAdd(N, DAG);
|
||||||
case ISD::SHL:
|
return;
|
||||||
return ExpandShift(N, DAG);
|
case ISD::SHL: {
|
||||||
|
SDValue Res = ExpandShift(N, DAG);
|
||||||
|
if (Res.getNode())
|
||||||
|
Results.push_back(Res);
|
||||||
|
return;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
assert (0 && "not implemented");
|
assert (0 && "not implemented");
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
|
SDValue PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
|
||||||
StoreSDNode *St = cast<StoreSDNode>(N);
|
StoreSDNode *St = cast<StoreSDNode>(N);
|
||||||
SDValue Chain = St->getChain();
|
SDValue Chain = St->getChain();
|
||||||
SDValue Src = St->getValue();
|
SDValue Src = St->getValue();
|
||||||
|
@ -119,9 +130,8 @@ SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
|
||||||
LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset);
|
LegalizeAddress(Ptr, DAG, PtrLo, PtrHi, StoreOffset);
|
||||||
|
|
||||||
if (ValueType == MVT::i8) {
|
if (ValueType == MVT::i8) {
|
||||||
SDValue Store = DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, Chain, Src,
|
return DAG.getNode (PIC16ISD::PIC16Store, MVT::Other, Chain, Src,
|
||||||
PtrLo, PtrHi, DAG.getConstant (0, MVT::i8));
|
PtrLo, PtrHi, DAG.getConstant (0, MVT::i8));
|
||||||
return Store.getNode();
|
|
||||||
}
|
}
|
||||||
else if (ValueType == MVT::i16) {
|
else if (ValueType == MVT::i16) {
|
||||||
// Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
|
// Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
|
||||||
|
@ -142,7 +152,7 @@ SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
|
||||||
DAG.getConstant (1 + StoreOffset, MVT::i8));
|
DAG.getConstant (1 + StoreOffset, MVT::i8));
|
||||||
|
|
||||||
return DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1),
|
return DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store1),
|
||||||
getChain(Store2)).getNode();
|
getChain(Store2));
|
||||||
}
|
}
|
||||||
else if (ValueType == MVT::i32) {
|
else if (ValueType == MVT::i32) {
|
||||||
// Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
|
// Get the Lo and Hi parts from MERGE_VALUE or BUILD_PAIR.
|
||||||
|
@ -190,16 +200,16 @@ SDNode *PIC16TargetLowering::ExpandStore(SDNode *N, SelectionDAG &DAG) {
|
||||||
getChain(Store2));
|
getChain(Store2));
|
||||||
SDValue RetHi = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store3),
|
SDValue RetHi = DAG.getNode(ISD::TokenFactor, MVT::Other, getChain(Store3),
|
||||||
getChain(Store4));
|
getChain(Store4));
|
||||||
return DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi).getNode();
|
return DAG.getNode(ISD::TokenFactor, MVT::Other, RetLo, RetHi);
|
||||||
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
assert (0 && "value type not supported");
|
assert (0 && "value type not supported");
|
||||||
|
return SDValue();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// ExpandGlobalAddress -
|
// ExpandGlobalAddress -
|
||||||
SDNode *PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) {
|
SDValue PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) {
|
||||||
GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0));
|
GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(SDValue(N, 0));
|
||||||
|
|
||||||
SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8,
|
SDValue TGA = DAG.getTargetGlobalAddress(G->getGlobal(), MVT::i8,
|
||||||
|
@ -209,7 +219,7 @@ SDNode *PIC16TargetLowering::ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG) {
|
||||||
SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TGA);
|
SDValue Hi = DAG.getNode(PIC16ISD::Hi, MVT::i8, TGA);
|
||||||
|
|
||||||
SDValue BP = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi);
|
SDValue BP = DAG.getNode(ISD::BUILD_PAIR, MVT::i16, Lo, Hi);
|
||||||
return BP.getNode();
|
return BP;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) {
|
bool PIC16TargetLowering::isDirectAddress(const SDValue &Op) {
|
||||||
|
@ -351,20 +361,20 @@ void PIC16TargetLowering:: LegalizeAddress(SDValue Ptr, SelectionDAG &DAG,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *PIC16TargetLowering::ExpandAdd(SDNode *N, SelectionDAG &DAG) {
|
//SDNode *PIC16TargetLowering::ExpandAdd(SDNode *N, SelectionDAG &DAG) {
|
||||||
SDValue OperLeft = N->getOperand(0);
|
// SDValue OperLeft = N->getOperand(0);
|
||||||
SDValue OperRight = N->getOperand(1);
|
// SDValue OperRight = N->getOperand(1);
|
||||||
|
//
|
||||||
|
// if((OperLeft.getOpcode() == ISD::Constant) ||
|
||||||
|
// (OperRight.getOpcode() == ISD::Constant)) {
|
||||||
|
// return NULL;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// // These case are yet to be handled
|
||||||
|
// return NULL;
|
||||||
|
//}
|
||||||
|
|
||||||
if((OperLeft.getOpcode() == ISD::Constant) ||
|
SDValue PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
|
||||||
(OperRight.getOpcode() == ISD::Constant)) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
// These case are yet to be handled
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
SDNode *PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
|
|
||||||
LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0));
|
LoadSDNode *LD = dyn_cast<LoadSDNode>(SDValue(N, 0));
|
||||||
SDValue Chain = LD->getChain();
|
SDValue Chain = LD->getChain();
|
||||||
SDValue Ptr = LD->getBasePtr();
|
SDValue Ptr = LD->getBasePtr();
|
||||||
|
@ -438,7 +448,7 @@ SDNode *PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
|
||||||
|
|
||||||
if (VT == MVT::i8) {
|
if (VT == MVT::i8) {
|
||||||
// Operand of Load is illegal -- Load itself is legal
|
// Operand of Load is illegal -- Load itself is legal
|
||||||
return PICLoads[0].getNode();
|
return PICLoads[0];
|
||||||
}
|
}
|
||||||
else if (VT == MVT::i16) {
|
else if (VT == MVT::i16) {
|
||||||
BP = DAG.getNode(ISD::BUILD_PAIR, VT, PICLoads[0], PICLoads[1]);
|
BP = DAG.getNode(ISD::BUILD_PAIR, VT, PICLoads[0], PICLoads[1]);
|
||||||
|
@ -467,12 +477,10 @@ SDNode *PIC16TargetLowering::ExpandLoad(SDNode *N, SelectionDAG &DAG) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Tys = DAG.getVTList(VT, MVT::Other);
|
Tys = DAG.getVTList(VT, MVT::Other);
|
||||||
SDValue MergeV = DAG.getNode(ISD::MERGE_VALUES, Tys, BP, Chain);
|
return DAG.getNode(ISD::MERGE_VALUES, Tys, BP, Chain);
|
||||||
return MergeV.getNode();
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *PIC16TargetLowering::ExpandShift(SDNode *N, SelectionDAG &DAG) {
|
SDValue PIC16TargetLowering::ExpandShift(SDNode *N, SelectionDAG &DAG) {
|
||||||
SDValue Value = N->getOperand(0);
|
SDValue Value = N->getOperand(0);
|
||||||
SDValue Amt = N->getOperand(1);
|
SDValue Amt = N->getOperand(1);
|
||||||
SDValue BCF, BCFInput;
|
SDValue BCF, BCFInput;
|
||||||
|
@ -483,11 +491,11 @@ SDNode *PIC16TargetLowering::ExpandShift(SDNode *N, SelectionDAG &DAG) {
|
||||||
|
|
||||||
// Currently handling Constant shift only
|
// Currently handling Constant shift only
|
||||||
if (Amt.getOpcode() != ISD::Constant)
|
if (Amt.getOpcode() != ISD::Constant)
|
||||||
return NULL;
|
return SDValue();
|
||||||
|
|
||||||
// Following code considers 16 bit left-shift only
|
// Following code considers 16 bit left-shift only
|
||||||
if (N->getValueType(0) != MVT::i16)
|
if (N->getValueType(0) != MVT::i16)
|
||||||
return NULL;
|
return SDValue();
|
||||||
|
|
||||||
if (N->getOpcode() == ISD::SHL) {
|
if (N->getOpcode() == ISD::SHL) {
|
||||||
ShfNode = PIC16ISD::LSLF;
|
ShfNode = PIC16ISD::LSLF;
|
||||||
|
@ -515,8 +523,7 @@ SDNode *PIC16TargetLowering::ExpandShift(SDNode *N, SelectionDAG &DAG) {
|
||||||
BCFInput = RotCom.getValue(1);
|
BCFInput = RotCom.getValue(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue BP = DAG.getNode(ISD::BUILD_PAIR, N->getValueType(0), ShfCom, RotCom);
|
return DAG.getNode(ISD::BUILD_PAIR, N->getValueType(0), ShfCom, RotCom);
|
||||||
return BP.getNode();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
|
@ -532,11 +539,11 @@ SDValue PIC16TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
case ISD::SUBC:
|
case ISD::SUBC:
|
||||||
return LowerSUBC(Op, DAG);
|
return LowerSUBC(Op, DAG);
|
||||||
case ISD::LOAD:
|
case ISD::LOAD:
|
||||||
return SDValue(ExpandLoad(Op.getNode(), DAG), Op.getResNo());
|
return ExpandLoad(Op.getNode(), DAG);
|
||||||
case ISD::STORE:
|
case ISD::STORE:
|
||||||
return SDValue(ExpandStore(Op.getNode(), DAG), Op.getResNo());
|
return ExpandStore(Op.getNode(), DAG);
|
||||||
case ISD::SHL:
|
case ISD::SHL:
|
||||||
return SDValue(ExpandShift(Op.getNode(), DAG), Op.getResNo());
|
return ExpandShift(Op.getNode(), DAG);
|
||||||
case ISD::OR:
|
case ISD::OR:
|
||||||
case ISD::AND:
|
case ISD::AND:
|
||||||
case ISD::XOR:
|
case ISD::XOR:
|
||||||
|
|
|
@ -66,12 +66,17 @@ namespace llvm {
|
||||||
SDValue LowerSUBC(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerSUBC(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerBinOp(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
SDNode *ExpandStore(SDNode *N, SelectionDAG &DAG);
|
/// type with new values built out of custom code.
|
||||||
SDNode *ExpandLoad(SDNode *N, SelectionDAG &DAG);
|
///
|
||||||
SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG);
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
SDNode *ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
|
SelectionDAG &DAG);
|
||||||
SDNode *ExpandShift(SDNode *N, SelectionDAG &DAG);
|
|
||||||
|
SDValue ExpandStore(SDNode *N, SelectionDAG &DAG);
|
||||||
|
SDValue ExpandLoad(SDNode *N, SelectionDAG &DAG);
|
||||||
|
// SDNode *ExpandAdd(SDNode *N, SelectionDAG &DAG);
|
||||||
|
SDValue ExpandGlobalAddress(SDNode *N, SelectionDAG &DAG);
|
||||||
|
SDValue ExpandShift(SDNode *N, SelectionDAG &DAG);
|
||||||
|
|
||||||
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
SDValue PerformPIC16LoadCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
|
|
@ -2874,66 +2874,6 @@ SDValue PPCTargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
|
||||||
return DAG.getLoad(Op.getValueType(), Chain, FIPtr, NULL, 0);
|
return DAG.getLoad(Op.getValueType(), Chain, FIPtr, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue PPCTargetLowering::LowerFP_ROUND_INREG(SDValue Op,
|
|
||||||
SelectionDAG &DAG) {
|
|
||||||
assert(Op.getValueType() == MVT::ppcf128);
|
|
||||||
SDNode *Node = Op.getNode();
|
|
||||||
assert(Node->getOperand(0).getValueType() == MVT::ppcf128);
|
|
||||||
SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::f64, Node->getOperand(0),
|
|
||||||
DAG.getIntPtrConstant(0));
|
|
||||||
SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::f64, Node->getOperand(0),
|
|
||||||
DAG.getIntPtrConstant(1));
|
|
||||||
|
|
||||||
// This sequence changes FPSCR to do round-to-zero, adds the two halves
|
|
||||||
// of the long double, and puts FPSCR back the way it was. We do not
|
|
||||||
// actually model FPSCR.
|
|
||||||
std::vector<MVT> NodeTys;
|
|
||||||
SDValue Ops[4], Result, MFFSreg, InFlag, FPreg;
|
|
||||||
|
|
||||||
NodeTys.push_back(MVT::f64); // Return register
|
|
||||||
NodeTys.push_back(MVT::Flag); // Returns a flag for later insns
|
|
||||||
Result = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0);
|
|
||||||
MFFSreg = Result.getValue(0);
|
|
||||||
InFlag = Result.getValue(1);
|
|
||||||
|
|
||||||
NodeTys.clear();
|
|
||||||
NodeTys.push_back(MVT::Flag); // Returns a flag
|
|
||||||
Ops[0] = DAG.getConstant(31, MVT::i32);
|
|
||||||
Ops[1] = InFlag;
|
|
||||||
Result = DAG.getNode(PPCISD::MTFSB1, NodeTys, Ops, 2);
|
|
||||||
InFlag = Result.getValue(0);
|
|
||||||
|
|
||||||
NodeTys.clear();
|
|
||||||
NodeTys.push_back(MVT::Flag); // Returns a flag
|
|
||||||
Ops[0] = DAG.getConstant(30, MVT::i32);
|
|
||||||
Ops[1] = InFlag;
|
|
||||||
Result = DAG.getNode(PPCISD::MTFSB0, NodeTys, Ops, 2);
|
|
||||||
InFlag = Result.getValue(0);
|
|
||||||
|
|
||||||
NodeTys.clear();
|
|
||||||
NodeTys.push_back(MVT::f64); // result of add
|
|
||||||
NodeTys.push_back(MVT::Flag); // Returns a flag
|
|
||||||
Ops[0] = Lo;
|
|
||||||
Ops[1] = Hi;
|
|
||||||
Ops[2] = InFlag;
|
|
||||||
Result = DAG.getNode(PPCISD::FADDRTZ, NodeTys, Ops, 3);
|
|
||||||
FPreg = Result.getValue(0);
|
|
||||||
InFlag = Result.getValue(1);
|
|
||||||
|
|
||||||
NodeTys.clear();
|
|
||||||
NodeTys.push_back(MVT::f64);
|
|
||||||
Ops[0] = DAG.getConstant(1, MVT::i32);
|
|
||||||
Ops[1] = MFFSreg;
|
|
||||||
Ops[2] = FPreg;
|
|
||||||
Ops[3] = InFlag;
|
|
||||||
Result = DAG.getNode(PPCISD::MTFSF, NodeTys, Ops, 4);
|
|
||||||
FPreg = Result.getValue(0);
|
|
||||||
|
|
||||||
// We know the low half is about to be thrown away, so just use something
|
|
||||||
// convenient.
|
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::ppcf128, FPreg, FPreg);
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
|
SDValue PPCTargetLowering::LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG) {
|
||||||
// Don't handle ppc_fp128 here; let it be lowered to a libcall.
|
// Don't handle ppc_fp128 here; let it be lowered to a libcall.
|
||||||
if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64)
|
if (Op.getValueType() != MVT::f32 && Op.getValueType() != MVT::f64)
|
||||||
|
@ -3874,7 +3814,6 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
case ISD::SELECT_CC: return LowerSELECT_CC(Op, DAG);
|
||||||
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
|
case ISD::FP_TO_SINT: return LowerFP_TO_SINT(Op, DAG);
|
||||||
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
|
case ISD::SINT_TO_FP: return LowerSINT_TO_FP(Op, DAG);
|
||||||
case ISD::FP_ROUND_INREG: return LowerFP_ROUND_INREG(Op, DAG);
|
|
||||||
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
|
case ISD::FLT_ROUNDS_: return LowerFLT_ROUNDS_(Op, DAG);
|
||||||
|
|
||||||
// Lower 64-bit shifts.
|
// Lower 64-bit shifts.
|
||||||
|
@ -3896,17 +3835,74 @@ SDValue PPCTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
return SDValue();
|
return SDValue();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *PPCTargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
|
void PPCTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
return PPCTargetLowering::LowerOperation(SDValue (N, 0), DAG).getNode();
|
assert(false && "Do not know how to custom type legalize this operation!");
|
||||||
case ISD::FP_TO_SINT: {
|
return;
|
||||||
SDValue Res = LowerFP_TO_SINT(SDValue(N, 0), DAG);
|
case ISD::FP_ROUND_INREG: {
|
||||||
// Use MERGE_VALUES to drop the chain result value and get a node with one
|
assert(N->getValueType(0) == MVT::ppcf128);
|
||||||
// result. This requires turning off getMergeValues simplification, since
|
assert(N->getOperand(0).getValueType() == MVT::ppcf128);
|
||||||
// otherwise it will give us Res back.
|
SDValue Lo = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::f64, N->getOperand(0),
|
||||||
return DAG.getMergeValues(&Res, 1, false).getNode();
|
DAG.getIntPtrConstant(0));
|
||||||
|
SDValue Hi = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::f64, N->getOperand(0),
|
||||||
|
DAG.getIntPtrConstant(1));
|
||||||
|
|
||||||
|
// This sequence changes FPSCR to do round-to-zero, adds the two halves
|
||||||
|
// of the long double, and puts FPSCR back the way it was. We do not
|
||||||
|
// actually model FPSCR.
|
||||||
|
std::vector<MVT> NodeTys;
|
||||||
|
SDValue Ops[4], Result, MFFSreg, InFlag, FPreg;
|
||||||
|
|
||||||
|
NodeTys.push_back(MVT::f64); // Return register
|
||||||
|
NodeTys.push_back(MVT::Flag); // Returns a flag for later insns
|
||||||
|
Result = DAG.getNode(PPCISD::MFFS, NodeTys, &InFlag, 0);
|
||||||
|
MFFSreg = Result.getValue(0);
|
||||||
|
InFlag = Result.getValue(1);
|
||||||
|
|
||||||
|
NodeTys.clear();
|
||||||
|
NodeTys.push_back(MVT::Flag); // Returns a flag
|
||||||
|
Ops[0] = DAG.getConstant(31, MVT::i32);
|
||||||
|
Ops[1] = InFlag;
|
||||||
|
Result = DAG.getNode(PPCISD::MTFSB1, NodeTys, Ops, 2);
|
||||||
|
InFlag = Result.getValue(0);
|
||||||
|
|
||||||
|
NodeTys.clear();
|
||||||
|
NodeTys.push_back(MVT::Flag); // Returns a flag
|
||||||
|
Ops[0] = DAG.getConstant(30, MVT::i32);
|
||||||
|
Ops[1] = InFlag;
|
||||||
|
Result = DAG.getNode(PPCISD::MTFSB0, NodeTys, Ops, 2);
|
||||||
|
InFlag = Result.getValue(0);
|
||||||
|
|
||||||
|
NodeTys.clear();
|
||||||
|
NodeTys.push_back(MVT::f64); // result of add
|
||||||
|
NodeTys.push_back(MVT::Flag); // Returns a flag
|
||||||
|
Ops[0] = Lo;
|
||||||
|
Ops[1] = Hi;
|
||||||
|
Ops[2] = InFlag;
|
||||||
|
Result = DAG.getNode(PPCISD::FADDRTZ, NodeTys, Ops, 3);
|
||||||
|
FPreg = Result.getValue(0);
|
||||||
|
InFlag = Result.getValue(1);
|
||||||
|
|
||||||
|
NodeTys.clear();
|
||||||
|
NodeTys.push_back(MVT::f64);
|
||||||
|
Ops[0] = DAG.getConstant(1, MVT::i32);
|
||||||
|
Ops[1] = MFFSreg;
|
||||||
|
Ops[2] = FPreg;
|
||||||
|
Ops[3] = InFlag;
|
||||||
|
Result = DAG.getNode(PPCISD::MTFSF, NodeTys, Ops, 4);
|
||||||
|
FPreg = Result.getValue(0);
|
||||||
|
|
||||||
|
// We know the low half is about to be thrown away, so just use something
|
||||||
|
// convenient.
|
||||||
|
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::ppcf128, FPreg, FPreg));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
case ISD::FP_TO_SINT:
|
||||||
|
Results.push_back(LowerFP_TO_SINT(SDValue(N, 0), DAG));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -269,7 +269,11 @@ namespace llvm {
|
||||||
///
|
///
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
|
/// type with new values built out of custom code.
|
||||||
|
///
|
||||||
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
|
||||||
|
@ -372,7 +376,6 @@ namespace llvm {
|
||||||
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerSINT_TO_FP(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerFP_ROUND_INREG(SDValue Op, SelectionDAG &DAG);
|
|
||||||
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerFLT_ROUNDS_(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerSHL_PARTS(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerSRL_PARTS(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
|
@ -4863,22 +4863,6 @@ SDValue X86TargetLowering::LowerFP_TO_SINT(SDValue Op, SelectionDAG &DAG) {
|
||||||
return DAG.getLoad(Op.getValueType(), FIST, StackSlot, NULL, 0);
|
return DAG.getLoad(Op.getValueType(), FIST, StackSlot, NULL, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *X86TargetLowering::ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG) {
|
|
||||||
std::pair<SDValue,SDValue> Vals = FP_TO_SINTHelper(SDValue(N, 0), DAG);
|
|
||||||
SDValue FIST = Vals.first, StackSlot = Vals.second;
|
|
||||||
if (FIST.getNode() == 0) return 0;
|
|
||||||
|
|
||||||
MVT VT = N->getValueType(0);
|
|
||||||
|
|
||||||
// Return a load from the stack slot.
|
|
||||||
SDValue Res = DAG.getLoad(VT, FIST, StackSlot, NULL, 0);
|
|
||||||
|
|
||||||
// Use MERGE_VALUES to drop the chain result value and get a node with one
|
|
||||||
// result. This requires turning off getMergeValues simplification, since
|
|
||||||
// otherwise it will give us Res back.
|
|
||||||
return DAG.getMergeValues(&Res, 1, false).getNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) {
|
SDValue X86TargetLowering::LowerFABS(SDValue Op, SelectionDAG &DAG) {
|
||||||
MVT VT = Op.getValueType();
|
MVT VT = Op.getValueType();
|
||||||
MVT EltVT = VT;
|
MVT EltVT = VT;
|
||||||
|
@ -5550,36 +5534,6 @@ X86TargetLowering::EmitTargetCodeForMemcpy(SelectionDAG &DAG,
|
||||||
return DAG.getNode(ISD::TokenFactor, MVT::Other, &Results[0], Results.size());
|
return DAG.getNode(ISD::TokenFactor, MVT::Other, &Results[0], Results.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Expand the result of: i64,outchain = READCYCLECOUNTER inchain
|
|
||||||
SDNode *X86TargetLowering::ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG){
|
|
||||||
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
|
|
||||||
SDValue TheChain = N->getOperand(0);
|
|
||||||
SDValue rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheChain, 1);
|
|
||||||
if (Subtarget->is64Bit()) {
|
|
||||||
SDValue rax = DAG.getCopyFromReg(rd, X86::RAX, MVT::i64, rd.getValue(1));
|
|
||||||
SDValue rdx = DAG.getCopyFromReg(rax.getValue(1), X86::RDX,
|
|
||||||
MVT::i64, rax.getValue(2));
|
|
||||||
SDValue Tmp = DAG.getNode(ISD::SHL, MVT::i64, rdx,
|
|
||||||
DAG.getConstant(32, MVT::i8));
|
|
||||||
SDValue Ops[] = {
|
|
||||||
DAG.getNode(ISD::OR, MVT::i64, rax, Tmp), rdx.getValue(1)
|
|
||||||
};
|
|
||||||
|
|
||||||
return DAG.getMergeValues(Ops, 2).getNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue eax = DAG.getCopyFromReg(rd, X86::EAX, MVT::i32, rd.getValue(1));
|
|
||||||
SDValue edx = DAG.getCopyFromReg(eax.getValue(1), X86::EDX,
|
|
||||||
MVT::i32, eax.getValue(2));
|
|
||||||
// Use a buildpair to merge the two 32-bit values into a 64-bit one.
|
|
||||||
SDValue Ops[] = { eax, edx };
|
|
||||||
Ops[0] = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Ops, 2);
|
|
||||||
|
|
||||||
// Use a MERGE_VALUES to return the value and chain.
|
|
||||||
Ops[1] = edx.getValue(1);
|
|
||||||
return DAG.getMergeValues(Ops, 2).getNode();
|
|
||||||
}
|
|
||||||
|
|
||||||
SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) {
|
SDValue X86TargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) {
|
||||||
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
|
const Value *SV = cast<SrcValueSDNode>(Op.getOperand(2))->getValue();
|
||||||
|
|
||||||
|
@ -6186,10 +6140,8 @@ SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) {
|
||||||
case MVT::i16: Reg = X86::AX; size = 2; break;
|
case MVT::i16: Reg = X86::AX; size = 2; break;
|
||||||
case MVT::i32: Reg = X86::EAX; size = 4; break;
|
case MVT::i32: Reg = X86::EAX; size = 4; break;
|
||||||
case MVT::i64:
|
case MVT::i64:
|
||||||
if (Subtarget->is64Bit()) {
|
assert(Subtarget->is64Bit() && "Node not type legal!");
|
||||||
Reg = X86::RAX; size = 8;
|
Reg = X86::RAX; size = 8;
|
||||||
} else //Should go away when LegalizeType stuff lands
|
|
||||||
return SDValue(ExpandATOMIC_CMP_SWAP(Op.getNode(), DAG), 0);
|
|
||||||
break;
|
break;
|
||||||
};
|
};
|
||||||
SDValue cpIn = DAG.getCopyToReg(Op.getOperand(0), Reg,
|
SDValue cpIn = DAG.getCopyToReg(Op.getOperand(0), Reg,
|
||||||
|
@ -6206,66 +6158,22 @@ SDValue X86TargetLowering::LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG) {
|
||||||
return cpOut;
|
return cpOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode* X86TargetLowering::ExpandATOMIC_CMP_SWAP(SDNode* Op,
|
SDValue X86TargetLowering::LowerREADCYCLECOUNTER(SDValue Op,
|
||||||
SelectionDAG &DAG) {
|
SelectionDAG &DAG) {
|
||||||
MVT T = Op->getValueType(0);
|
assert(Subtarget->is64Bit() && "Result not type legalized?");
|
||||||
assert (T == MVT::i64 && "Only know how to expand i64 Cmp and Swap");
|
|
||||||
SDValue cpInL, cpInH;
|
|
||||||
cpInL = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op->getOperand(2),
|
|
||||||
DAG.getConstant(0, MVT::i32));
|
|
||||||
cpInH = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op->getOperand(2),
|
|
||||||
DAG.getConstant(1, MVT::i32));
|
|
||||||
cpInL = DAG.getCopyToReg(Op->getOperand(0), X86::EAX,
|
|
||||||
cpInL, SDValue());
|
|
||||||
cpInH = DAG.getCopyToReg(cpInL.getValue(0), X86::EDX,
|
|
||||||
cpInH, cpInL.getValue(1));
|
|
||||||
SDValue swapInL, swapInH;
|
|
||||||
swapInL = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op->getOperand(3),
|
|
||||||
DAG.getConstant(0, MVT::i32));
|
|
||||||
swapInH = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, Op->getOperand(3),
|
|
||||||
DAG.getConstant(1, MVT::i32));
|
|
||||||
swapInL = DAG.getCopyToReg(cpInH.getValue(0), X86::EBX,
|
|
||||||
swapInL, cpInH.getValue(1));
|
|
||||||
swapInH = DAG.getCopyToReg(swapInL.getValue(0), X86::ECX,
|
|
||||||
swapInH, swapInL.getValue(1));
|
|
||||||
SDValue Ops[] = { swapInH.getValue(0),
|
|
||||||
Op->getOperand(1),
|
|
||||||
swapInH.getValue(1) };
|
|
||||||
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
|
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||||
SDValue Result = DAG.getNode(X86ISD::LCMPXCHG8_DAG, Tys, Ops, 3);
|
SDValue TheChain = Op.getOperand(0);
|
||||||
SDValue cpOutL = DAG.getCopyFromReg(Result.getValue(0), X86::EAX, MVT::i32,
|
SDValue rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheChain, 1);
|
||||||
Result.getValue(1));
|
SDValue rax = DAG.getCopyFromReg(rd, X86::RAX, MVT::i64, rd.getValue(1));
|
||||||
SDValue cpOutH = DAG.getCopyFromReg(cpOutL.getValue(1), X86::EDX, MVT::i32,
|
SDValue rdx = DAG.getCopyFromReg(rax.getValue(1), X86::RDX, MVT::i64,
|
||||||
cpOutL.getValue(2));
|
rax.getValue(2));
|
||||||
SDValue OpsF[] = { cpOutL.getValue(0), cpOutH.getValue(0)};
|
SDValue Tmp = DAG.getNode(ISD::SHL, MVT::i64, rdx,
|
||||||
SDValue ResultVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OpsF, 2);
|
DAG.getConstant(32, MVT::i8));
|
||||||
SDValue Vals[2] = { ResultVal, cpOutH.getValue(1) };
|
SDValue Ops[] = {
|
||||||
return DAG.getMergeValues(Vals, 2).getNode();
|
DAG.getNode(ISD::OR, MVT::i64, rax, Tmp),
|
||||||
}
|
rdx.getValue(1)
|
||||||
|
};
|
||||||
SDValue X86TargetLowering::LowerATOMIC_BINARY_64(SDValue Op,
|
return DAG.getMergeValues(Ops, 2);
|
||||||
SelectionDAG &DAG,
|
|
||||||
unsigned NewOp) {
|
|
||||||
SDNode *Node = Op.getNode();
|
|
||||||
MVT T = Node->getValueType(0);
|
|
||||||
assert (T == MVT::i64 && "Only know how to expand i64 atomics");
|
|
||||||
|
|
||||||
SDValue Chain = Node->getOperand(0);
|
|
||||||
SDValue In1 = Node->getOperand(1);
|
|
||||||
SDValue In2L = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
|
||||||
Node->getOperand(2), DAG.getIntPtrConstant(0));
|
|
||||||
SDValue In2H = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
|
||||||
Node->getOperand(2), DAG.getIntPtrConstant(1));
|
|
||||||
// This is a generalized SDNode, not an AtomicSDNode, so it doesn't
|
|
||||||
// have a MemOperand. Pass the info through as a normal operand.
|
|
||||||
SDValue LSI = DAG.getMemOperand(cast<MemSDNode>(Node)->getMemOperand());
|
|
||||||
SDValue Ops[] = { Chain, In1, In2L, In2H, LSI };
|
|
||||||
SDVTList Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
|
|
||||||
SDValue Result = DAG.getNode(NewOp, Tys, Ops, 5);
|
|
||||||
SDValue OpsF[] = { Result.getValue(0), Result.getValue(1)};
|
|
||||||
SDValue ResultVal = DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OpsF, 2);
|
|
||||||
SDValue Vals[2] = { ResultVal, Result.getValue(2) };
|
|
||||||
return SDValue(DAG.getMergeValues(Vals, 2).getNode(), 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) {
|
SDValue X86TargetLowering::LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG) {
|
||||||
|
@ -6298,22 +6206,7 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
case ISD::ATOMIC_LOAD_SUB_8:
|
case ISD::ATOMIC_LOAD_SUB_8:
|
||||||
case ISD::ATOMIC_LOAD_SUB_16:
|
case ISD::ATOMIC_LOAD_SUB_16:
|
||||||
case ISD::ATOMIC_LOAD_SUB_32: return LowerLOAD_SUB(Op,DAG);
|
case ISD::ATOMIC_LOAD_SUB_32: return LowerLOAD_SUB(Op,DAG);
|
||||||
case ISD::ATOMIC_LOAD_SUB_64: return (Subtarget->is64Bit()) ?
|
case ISD::ATOMIC_LOAD_SUB_64: return LowerLOAD_SUB(Op,DAG);
|
||||||
LowerLOAD_SUB(Op,DAG) :
|
|
||||||
LowerATOMIC_BINARY_64(Op,DAG,
|
|
||||||
X86ISD::ATOMSUB64_DAG);
|
|
||||||
case ISD::ATOMIC_LOAD_AND_64: return LowerATOMIC_BINARY_64(Op,DAG,
|
|
||||||
X86ISD::ATOMAND64_DAG);
|
|
||||||
case ISD::ATOMIC_LOAD_OR_64: return LowerATOMIC_BINARY_64(Op, DAG,
|
|
||||||
X86ISD::ATOMOR64_DAG);
|
|
||||||
case ISD::ATOMIC_LOAD_XOR_64: return LowerATOMIC_BINARY_64(Op,DAG,
|
|
||||||
X86ISD::ATOMXOR64_DAG);
|
|
||||||
case ISD::ATOMIC_LOAD_NAND_64:return LowerATOMIC_BINARY_64(Op,DAG,
|
|
||||||
X86ISD::ATOMNAND64_DAG);
|
|
||||||
case ISD::ATOMIC_LOAD_ADD_64: return LowerATOMIC_BINARY_64(Op,DAG,
|
|
||||||
X86ISD::ATOMADD64_DAG);
|
|
||||||
case ISD::ATOMIC_SWAP_64: return LowerATOMIC_BINARY_64(Op,DAG,
|
|
||||||
X86ISD::ATOMSWAP64_DAG);
|
|
||||||
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
|
case ISD::BUILD_VECTOR: return LowerBUILD_VECTOR(Op, DAG);
|
||||||
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
|
case ISD::VECTOR_SHUFFLE: return LowerVECTOR_SHUFFLE(Op, DAG);
|
||||||
case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG);
|
case ISD::EXTRACT_VECTOR_ELT: return LowerEXTRACT_VECTOR_ELT(Op, DAG);
|
||||||
|
@ -6356,22 +6249,120 @@ SDValue X86TargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
case ISD::CTTZ: return LowerCTTZ(Op, DAG);
|
case ISD::CTTZ: return LowerCTTZ(Op, DAG);
|
||||||
case ISD::SADDO: return LowerXADDO(Op, DAG, ISD::SADDO);
|
case ISD::SADDO: return LowerXADDO(Op, DAG, ISD::SADDO);
|
||||||
case ISD::UADDO: return LowerXADDO(Op, DAG, ISD::UADDO);
|
case ISD::UADDO: return LowerXADDO(Op, DAG, ISD::UADDO);
|
||||||
|
case ISD::READCYCLECOUNTER: return LowerREADCYCLECOUNTER(Op, DAG);
|
||||||
// FIXME: REMOVE THIS WHEN LegalizeDAGTypes lands.
|
|
||||||
case ISD::READCYCLECOUNTER:
|
|
||||||
return SDValue(ExpandREADCYCLECOUNTER(Op.getNode(), DAG), 0);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void X86TargetLowering::
|
||||||
|
ReplaceATOMIC_BINARY_64(SDNode *Node, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG, unsigned NewOp) {
|
||||||
|
MVT T = Node->getValueType(0);
|
||||||
|
assert (T == MVT::i64 && "Only know how to expand i64 atomics");
|
||||||
|
|
||||||
|
SDValue Chain = Node->getOperand(0);
|
||||||
|
SDValue In1 = Node->getOperand(1);
|
||||||
|
SDValue In2L = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
||||||
|
Node->getOperand(2), DAG.getIntPtrConstant(0));
|
||||||
|
SDValue In2H = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32,
|
||||||
|
Node->getOperand(2), DAG.getIntPtrConstant(1));
|
||||||
|
// This is a generalized SDNode, not an AtomicSDNode, so it doesn't
|
||||||
|
// have a MemOperand. Pass the info through as a normal operand.
|
||||||
|
SDValue LSI = DAG.getMemOperand(cast<MemSDNode>(Node)->getMemOperand());
|
||||||
|
SDValue Ops[] = { Chain, In1, In2L, In2H, LSI };
|
||||||
|
SDVTList Tys = DAG.getVTList(MVT::i32, MVT::i32, MVT::Other);
|
||||||
|
SDValue Result = DAG.getNode(NewOp, Tys, Ops, 5);
|
||||||
|
SDValue OpsF[] = { Result.getValue(0), Result.getValue(1)};
|
||||||
|
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OpsF, 2));
|
||||||
|
Results.push_back(Result.getValue(2));
|
||||||
|
}
|
||||||
|
|
||||||
/// ReplaceNodeResults - Replace a node with an illegal result type
|
/// ReplaceNodeResults - Replace a node with an illegal result type
|
||||||
/// with a new node built out of custom code.
|
/// with a new node built out of custom code.
|
||||||
SDNode *X86TargetLowering::ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
|
void X86TargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
return X86TargetLowering::LowerOperation(SDValue (N, 0), DAG).getNode();
|
assert(false && "Do not know how to custom type legalize this operation!");
|
||||||
case ISD::FP_TO_SINT: return ExpandFP_TO_SINT(N, DAG);
|
return;
|
||||||
case ISD::READCYCLECOUNTER: return ExpandREADCYCLECOUNTER(N, DAG);
|
case ISD::FP_TO_SINT: {
|
||||||
case ISD::ATOMIC_CMP_SWAP_64: return ExpandATOMIC_CMP_SWAP(N, DAG);
|
std::pair<SDValue,SDValue> Vals = FP_TO_SINTHelper(SDValue(N, 0), DAG);
|
||||||
|
SDValue FIST = Vals.first, StackSlot = Vals.second;
|
||||||
|
if (FIST.getNode() != 0) {
|
||||||
|
MVT VT = N->getValueType(0);
|
||||||
|
// Return a load from the stack slot.
|
||||||
|
Results.push_back(DAG.getLoad(VT, FIST, StackSlot, NULL, 0));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ISD::READCYCLECOUNTER: {
|
||||||
|
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||||
|
SDValue TheChain = N->getOperand(0);
|
||||||
|
SDValue rd = DAG.getNode(X86ISD::RDTSC_DAG, Tys, &TheChain, 1);
|
||||||
|
SDValue eax = DAG.getCopyFromReg(rd, X86::EAX, MVT::i32, rd.getValue(1));
|
||||||
|
SDValue edx = DAG.getCopyFromReg(eax.getValue(1), X86::EDX, MVT::i32,
|
||||||
|
eax.getValue(2));
|
||||||
|
// Use a buildpair to merge the two 32-bit values into a 64-bit one.
|
||||||
|
SDValue Ops[] = { eax, edx };
|
||||||
|
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Ops, 2));
|
||||||
|
Results.push_back(edx.getValue(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ISD::ATOMIC_CMP_SWAP_64: {
|
||||||
|
MVT T = N->getValueType(0);
|
||||||
|
assert (T == MVT::i64 && "Only know how to expand i64 Cmp and Swap");
|
||||||
|
SDValue cpInL, cpInH;
|
||||||
|
cpInL = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(2),
|
||||||
|
DAG.getConstant(0, MVT::i32));
|
||||||
|
cpInH = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(2),
|
||||||
|
DAG.getConstant(1, MVT::i32));
|
||||||
|
cpInL = DAG.getCopyToReg(N->getOperand(0), X86::EAX, cpInL, SDValue());
|
||||||
|
cpInH = DAG.getCopyToReg(cpInL.getValue(0), X86::EDX, cpInH,
|
||||||
|
cpInL.getValue(1));
|
||||||
|
SDValue swapInL, swapInH;
|
||||||
|
swapInL = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(3),
|
||||||
|
DAG.getConstant(0, MVT::i32));
|
||||||
|
swapInH = DAG.getNode(ISD::EXTRACT_ELEMENT, MVT::i32, N->getOperand(3),
|
||||||
|
DAG.getConstant(1, MVT::i32));
|
||||||
|
swapInL = DAG.getCopyToReg(cpInH.getValue(0), X86::EBX, swapInL,
|
||||||
|
cpInH.getValue(1));
|
||||||
|
swapInH = DAG.getCopyToReg(swapInL.getValue(0), X86::ECX, swapInH,
|
||||||
|
swapInL.getValue(1));
|
||||||
|
SDValue Ops[] = { swapInH.getValue(0),
|
||||||
|
N->getOperand(1),
|
||||||
|
swapInH.getValue(1) };
|
||||||
|
SDVTList Tys = DAG.getVTList(MVT::Other, MVT::Flag);
|
||||||
|
SDValue Result = DAG.getNode(X86ISD::LCMPXCHG8_DAG, Tys, Ops, 3);
|
||||||
|
SDValue cpOutL = DAG.getCopyFromReg(Result.getValue(0), X86::EAX, MVT::i32,
|
||||||
|
Result.getValue(1));
|
||||||
|
SDValue cpOutH = DAG.getCopyFromReg(cpOutL.getValue(1), X86::EDX, MVT::i32,
|
||||||
|
cpOutL.getValue(2));
|
||||||
|
SDValue OpsF[] = { cpOutL.getValue(0), cpOutH.getValue(0)};
|
||||||
|
Results.push_back(DAG.getNode(ISD::BUILD_PAIR, MVT::i64, OpsF, 2));
|
||||||
|
Results.push_back(cpOutH.getValue(1));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
case ISD::ATOMIC_LOAD_ADD_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMADD64_DAG);
|
||||||
|
return;
|
||||||
|
case ISD::ATOMIC_LOAD_AND_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMAND64_DAG);
|
||||||
|
return;
|
||||||
|
case ISD::ATOMIC_LOAD_NAND_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMNAND64_DAG);
|
||||||
|
return;
|
||||||
|
case ISD::ATOMIC_LOAD_OR_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMOR64_DAG);
|
||||||
|
return;
|
||||||
|
case ISD::ATOMIC_LOAD_SUB_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSUB64_DAG);
|
||||||
|
return;
|
||||||
|
case ISD::ATOMIC_LOAD_XOR_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMXOR64_DAG);
|
||||||
|
return;
|
||||||
|
case ISD::ATOMIC_SWAP_64:
|
||||||
|
ReplaceATOMIC_BINARY_64(N, Results, DAG, X86ISD::ATOMSWAP64_DAG);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -375,10 +375,11 @@ namespace llvm {
|
||||||
///
|
///
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
/// ReplaceNodeResults - Replace a node with an illegal result type
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
/// with a new node built out of custom code.
|
/// type with new values built out of custom code.
|
||||||
///
|
///
|
||||||
virtual SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
|
|
||||||
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
virtual SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const;
|
||||||
|
@ -596,11 +597,10 @@ namespace llvm {
|
||||||
|
|
||||||
SDValue LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerCMP_SWAP(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG);
|
SDValue LowerLOAD_SUB(SDValue Op, SelectionDAG &DAG);
|
||||||
SDValue LowerATOMIC_BINARY_64(SDValue Op, SelectionDAG &DAG,
|
SDValue LowerREADCYCLECOUNTER(SDValue Op, SelectionDAG &DAG);
|
||||||
unsigned NewOp);
|
|
||||||
SDNode *ExpandFP_TO_SINT(SDNode *N, SelectionDAG &DAG);
|
void ReplaceATOMIC_BINARY_64(SDNode *N, SmallVectorImpl<SDValue> &Results,
|
||||||
SDNode *ExpandREADCYCLECOUNTER(SDNode *N, SelectionDAG &DAG);
|
SelectionDAG &DAG, unsigned NewOp);
|
||||||
SDNode *ExpandATOMIC_CMP_SWAP(SDNode *N, SelectionDAG &DAG);
|
|
||||||
|
|
||||||
SDValue EmitTargetCodeForMemset(SelectionDAG &DAG,
|
SDValue EmitTargetCodeForMemset(SelectionDAG &DAG,
|
||||||
SDValue Chain,
|
SDValue Chain,
|
||||||
|
|
|
@ -161,7 +161,7 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
case ISD::VASTART: return LowerVASTART(Op, DAG);
|
case ISD::VASTART: return LowerVASTART(Op, DAG);
|
||||||
// FIXME: Remove these when LegalizeDAGTypes lands.
|
// FIXME: Remove these when LegalizeDAGTypes lands.
|
||||||
case ISD::ADD:
|
case ISD::ADD:
|
||||||
case ISD::SUB: return SDValue(ExpandADDSUB(Op.getNode(), DAG),0);
|
case ISD::SUB: return ExpandADDSUB(Op.getNode(), DAG);
|
||||||
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
case ISD::FRAMEADDR: return LowerFRAMEADDR(Op, DAG);
|
||||||
default:
|
default:
|
||||||
assert(0 && "unimplemented operand");
|
assert(0 && "unimplemented operand");
|
||||||
|
@ -169,16 +169,19 @@ LowerOperation(SDValue Op, SelectionDAG &DAG) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// ReplaceNodeResults - Provide custom lowering hooks for nodes with illegal
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
/// result types.
|
/// type with new values built out of custom code.
|
||||||
SDNode *XCoreTargetLowering::
|
void XCoreTargetLowering::ReplaceNodeResults(SDNode *N,
|
||||||
ReplaceNodeResults(SDNode *N, SelectionDAG &DAG) {
|
SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG) {
|
||||||
switch (N->getOpcode()) {
|
switch (N->getOpcode()) {
|
||||||
default:
|
default:
|
||||||
assert(0 && "Don't know how to custom expand this!");
|
assert(0 && "Don't know how to custom expand this!");
|
||||||
return NULL;
|
return;
|
||||||
case ISD::ADD:
|
case ISD::ADD:
|
||||||
case ISD::SUB: return ExpandADDSUB(N, DAG);
|
case ISD::SUB:
|
||||||
|
Results.push_back(ExpandADDSUB(N, DAG));
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +299,7 @@ LowerJumpTable(SDValue Op, SelectionDAG &DAG)
|
||||||
return DAG.getNode(XCoreISD::DPRelativeWrapper, MVT::i32, JTI);
|
return DAG.getNode(XCoreISD::DPRelativeWrapper, MVT::i32, JTI);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDNode *XCoreTargetLowering::
|
SDValue XCoreTargetLowering::
|
||||||
ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
|
ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
|
||||||
{
|
{
|
||||||
assert(N->getValueType(0) == MVT::i64 &&
|
assert(N->getValueType(0) == MVT::i64 &&
|
||||||
|
@ -326,7 +329,7 @@ ExpandADDSUB(SDNode *N, SelectionDAG &DAG)
|
||||||
LHSH, RHSH, Carry);
|
LHSH, RHSH, Carry);
|
||||||
SDValue Hi(Ignored.getNode(), 1);
|
SDValue Hi(Ignored.getNode(), 1);
|
||||||
// Merge the pieces
|
// Merge the pieces
|
||||||
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi).getNode();
|
return DAG.getNode(ISD::BUILD_PAIR, MVT::i64, Lo, Hi);
|
||||||
}
|
}
|
||||||
|
|
||||||
SDValue XCoreTargetLowering::
|
SDValue XCoreTargetLowering::
|
||||||
|
|
|
@ -68,7 +68,11 @@ namespace llvm {
|
||||||
/// LowerOperation - Provide custom lowering hooks for some operations.
|
/// LowerOperation - Provide custom lowering hooks for some operations.
|
||||||
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
virtual SDValue LowerOperation(SDValue Op, SelectionDAG &DAG);
|
||||||
|
|
||||||
virtual SDNode *ReplaceNodeResults(SDNode *N, SelectionDAG &DAG);
|
/// ReplaceNodeResults - Replace the results of node with an illegal result
|
||||||
|
/// type with new values built out of custom code.
|
||||||
|
///
|
||||||
|
virtual void ReplaceNodeResults(SDNode *N, SmallVectorImpl<SDValue>&Results,
|
||||||
|
SelectionDAG &DAG);
|
||||||
|
|
||||||
/// getTargetNodeName - This method returns the name of a target specific
|
/// getTargetNodeName - This method returns the name of a target specific
|
||||||
// DAG node.
|
// DAG node.
|
||||||
|
@ -112,7 +116,7 @@ namespace llvm {
|
||||||
MVT VT) const;
|
MVT VT) const;
|
||||||
|
|
||||||
// Expand specifics
|
// Expand specifics
|
||||||
SDNode *ExpandADDSUB(SDNode *Op, SelectionDAG &DAG);
|
SDValue ExpandADDSUB(SDNode *Op, SelectionDAG &DAG);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue