[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Chris Lattner
lattner at cs.uiuc.edu
Thu Jan 20 22:05:38 PST 2005
Changes in directory llvm/lib/CodeGen/SelectionDAG:
LegalizeDAG.cpp updated: 1.49 -> 1.50
---
Log message:
Refactor libcall code a bit. Initial implementation of expanding int -> FP
operations for 64-bit integers.
---
Diffs of the changes: (+121 -50)
Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.49 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.50
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.49 Thu Jan 20 14:29:23 2005
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Fri Jan 21 00:05:23 2005
@@ -119,6 +119,10 @@
void ExpandOp(SDOperand O, SDOperand &Lo, SDOperand &Hi);
SDOperand PromoteOp(SDOperand O);
+ SDOperand ExpandLibCall(const char *Name, SDNode *Node,
+ SDOperand &Hi);
+ SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
+ SDOperand Source);
bool ExpandShift(unsigned Opc, SDOperand Op, SDOperand Amt,
SDOperand &Lo, SDOperand &Hi);
void ExpandAddSub(bool isAdd, SDOperand Op, SDOperand Amt,
@@ -802,10 +806,13 @@
Result = DAG.getNode(Node->getOpcode(), Node->getValueType(0), Tmp1);
break;
case Expand:
- assert(Node->getOpcode() != ISD::SINT_TO_FP &&
- Node->getOpcode() != ISD::UINT_TO_FP &&
- "Cannot lower Xint_to_fp to a call yet!");
-
+ if (Node->getOpcode() == ISD::SINT_TO_FP ||
+ Node->getOpcode() == ISD::UINT_TO_FP) {
+ Result = ExpandIntToFP(Node->getOpcode() == ISD::SINT_TO_FP,
+ Node->getValueType(0), Node->getOperand(0));
+ Result = LegalizeOp(Result);
+ break;
+ }
// In the expand case, we must be dealing with a truncate, because
// otherwise the result would be larger than the source.
assert(Node->getOpcode() == ISD::TRUNCATE &&
@@ -1043,6 +1050,8 @@
switch (getTypeAction(Node->getOperand(0).getValueType())) {
case Legal:
Result = LegalizeOp(Node->getOperand(0));
+ // No extra round required here.
+ Result = DAG.getNode(Node->getOpcode(), NVT, Result);
break;
case Promote:
@@ -1053,12 +1062,19 @@
else
Result = DAG.getNode(ISD::ZERO_EXTEND_INREG, Result.getValueType(),
Result, Node->getOperand(0).getValueType());
+ // No extra round required here.
+ Result = DAG.getNode(Node->getOpcode(), NVT, Result);
break;
case Expand:
- assert(0 && "Unimplemented");
+ Result = ExpandIntToFP(Node->getOpcode() == ISD::SINT_TO_FP, NVT,
+ Node->getOperand(0));
+ Result = LegalizeOp(Result);
+
+ // Round if we cannot tolerate excess precision.
+ if (NoExcessFPPrecision)
+ Result = DAG.getNode(ISD::FP_ROUND_INREG, NVT, Result, VT);
+ break;
}
- // No extra round required here.
- Result = DAG.getNode(Node->getOpcode(), NVT, Result);
break;
case ISD::FP_TO_SINT:
@@ -1263,15 +1279,21 @@
Hi = DAG.getNode(ISD::SELECT, NVT, Cond, T2, T1);
Lo = DAG.getNode(ISD::SELECT, NVT, Cond, DAG.getConstant(0, NVT), T2);
} else {
+ SDOperand HiLoPart = DAG.getNode(ISD::SELECT, NVT,
+ DAG.getSetCC(ISD::SETEQ,
+ TLI.getSetCCResultTy(), NAmt,
+ DAG.getConstant(32, ShTy)),
+ DAG.getConstant(0, NVT),
+ DAG.getNode(ISD::SHL, NVT, InH, NAmt));
SDOperand T1 = DAG.getNode(ISD::OR, NVT,// T1 = (Hi << NAmt) | (Lo >> Amt)
- DAG.getNode(ISD::SHL, NVT, InH, NAmt),
+ HiLoPart,
DAG.getNode(ISD::SRL, NVT, InL, ShAmt));
- bool isSign = Opc == ISD::SRA;
SDOperand T2 = DAG.getNode(Opc, NVT, InH, ShAmt); // T2 = InH >> ShAmt&31
SDOperand HiPart;
- if (isSign)
- HiPart = DAG.getNode(Opc, NVT, InH, DAG.getConstant(NVTBits-1, ShTy));
+ if (Opc == ISD::SRA)
+ HiPart = DAG.getNode(ISD::SRA, NVT, InH,
+ DAG.getConstant(NVTBits-1, ShTy));
else
HiPart = DAG.getConstant(0, NVT);
Lo = DAG.getNode(ISD::SELECT, NVT, Cond, T2, T1);
@@ -1279,7 +1301,79 @@
}
return true;
}
-
+
+
+// ExpandLibCall - Expand a node into a call to a libcall. If the result value
+// does not fit into a register, return the lo part and set the hi part to the
+// by-reg argument. If it does fit into a single register, return the result
+// and leave the Hi part unset.
+SDOperand SelectionDAGLegalize::ExpandLibCall(const char *Name, SDNode *Node,
+ SDOperand &Hi) {
+ TargetLowering::ArgListTy Args;
+ for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
+ MVT::ValueType ArgVT = Node->getOperand(i).getValueType();
+ const Type *ArgTy = MVT::getTypeForValueType(ArgVT);
+ Args.push_back(std::make_pair(Node->getOperand(i), ArgTy));
+ }
+ 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.
+ const Type *RetTy = MVT::getTypeForValueType(Node->getValueType(0));
+ SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(), RetTy, Callee,
+ Args, DAG).first;
+ switch (getTypeAction(Result.getValueType())) {
+ default: assert(0 && "Unknown thing");
+ case Legal:
+ return Result;
+ case Promote:
+ assert(0 && "Cannot promote this yet!");
+ case Expand:
+ SDOperand Lo;
+ ExpandOp(Result, Lo, Hi);
+ return Lo;
+ }
+}
+
+/// ExpandIntToFP - Expand a [US]INT_TO_FP operation, assuming that the
+/// destination type is legal.
+SDOperand SelectionDAGLegalize::
+ExpandIntToFP(bool isSigned, MVT::ValueType DestTy, SDOperand Source) {
+ assert(getTypeAction(DestTy) == Legal && "Destination type is not legal!");
+ assert(getTypeAction(Source.getValueType()) == Expand &&
+ "This is not an expansion!");
+ assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!");
+
+ const char *FnName;
+ if (isSigned) {
+ if (DestTy == MVT::f32)
+ FnName = "__floatdisf";
+ else {
+ assert(DestTy == MVT::f64 && "Unknown fp value type!");
+ FnName = "__floatdidf";
+ }
+ } else {
+ // 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(false, DestTy, Source);
+
+ assert(0 && "Unsigned casts not supported yet!");
+ }
+ SDOperand Callee = DAG.getExternalSymbol(FnName, TLI.getPointerTy());
+
+ TargetLowering::ArgListTy Args;
+ const Type *ArgTy = MVT::getTypeForValueType(Source.getValueType());
+ Args.push_back(std::make_pair(Source, ArgTy));
+
+ // 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.
+ const Type *RetTy = MVT::getTypeForValueType(DestTy);
+ return TLI.LowerCallTo(DAG.getEntryNode(), RetTy, Callee,
+ Args, DAG).first;
+}
+
/// ExpandOp - Expand the specified SDOperand into its two component pieces
@@ -1313,7 +1407,6 @@
// is not careful to avoid operations the target does not support. Make sure
// that all generated operations are legalized in the next iteration.
NeedsAnotherIteration = true;
- const char *LibCallName = 0;
switch (Node->getOpcode()) {
default:
@@ -1441,41 +1534,38 @@
// library functions.
case ISD::FP_TO_SINT:
if (Node->getOperand(0).getValueType() == MVT::f32)
- LibCallName = "__fixsfdi";
+ Lo = ExpandLibCall("__fixsfdi", Node, Hi);
else
- LibCallName = "__fixdfdi";
+ Lo = ExpandLibCall("__fixdfdi", Node, Hi);
break;
case ISD::FP_TO_UINT:
if (Node->getOperand(0).getValueType() == MVT::f32)
- LibCallName = "__fixunssfdi";
+ Lo = ExpandLibCall("__fixunssfdi", Node, Hi);
else
- LibCallName = "__fixunsdfdi";
+ Lo = ExpandLibCall("__fixunsdfdi", Node, Hi);
break;
case ISD::SHL:
// If we can emit an efficient shift operation, do so now.
- if (ExpandShift(ISD::SHL, Node->getOperand(0), Node->getOperand(1),
- Lo, Hi))
+ if (ExpandShift(ISD::SHL, Node->getOperand(0), Node->getOperand(1), Lo, Hi))
break;
// Otherwise, emit a libcall.
- LibCallName = "__ashldi3";
+ Lo = ExpandLibCall("__ashldi3", Node, Hi);
break;
case ISD::SRA:
// If we can emit an efficient shift operation, do so now.
- if (ExpandShift(ISD::SRA, Node->getOperand(0), Node->getOperand(1),
- Lo, Hi))
+ if (ExpandShift(ISD::SRA, Node->getOperand(0), Node->getOperand(1), Lo, Hi))
break;
// Otherwise, emit a libcall.
- LibCallName = "__ashrdi3";
+ Lo = ExpandLibCall("__ashrdi3", Node, Hi);
break;
case ISD::SRL:
// If we can emit an efficient shift operation, do so now.
- if (ExpandShift(ISD::SRL, Node->getOperand(0), Node->getOperand(1),
- Lo, Hi))
+ if (ExpandShift(ISD::SRL, Node->getOperand(0), Node->getOperand(1), Lo, Hi))
break;
// Otherwise, emit a libcall.
- LibCallName = "__lshrdi3";
+ Lo = ExpandLibCall("__lshrdi3", Node, Hi);
break;
case ISD::ADD:
@@ -1484,30 +1574,11 @@
case ISD::SUB:
ExpandAddSub(false, Node->getOperand(0), Node->getOperand(1), Lo, Hi);
break;
- case ISD::MUL: LibCallName = "__muldi3"; break;
- case ISD::SDIV: LibCallName = "__divdi3"; break;
- case ISD::UDIV: LibCallName = "__udivdi3"; break;
- case ISD::SREM: LibCallName = "__moddi3"; break;
- case ISD::UREM: LibCallName = "__umoddi3"; break;
- }
-
- // Int2FP -> __floatdisf/__floatdidf
-
- // If this is to be expanded into a libcall... do so now.
- if (LibCallName) {
- TargetLowering::ArgListTy Args;
- for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i)
- Args.push_back(std::make_pair(Node->getOperand(i),
- MVT::getTypeForValueType(Node->getOperand(i).getValueType())));
- SDOperand Callee = DAG.getExternalSymbol(LibCallName, 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.
- SDOperand Result = TLI.LowerCallTo(DAG.getEntryNode(),
- MVT::getTypeForValueType(Op.getValueType()), Callee,
- Args, DAG).first;
- ExpandOp(Result, Lo, Hi);
+ case ISD::MUL: Lo = ExpandLibCall("__muldi3" , Node, Hi); break;
+ case ISD::SDIV: Lo = ExpandLibCall("__divdi3" , Node, Hi); break;
+ case ISD::UDIV: Lo = ExpandLibCall("__udivdi3", Node, Hi); break;
+ case ISD::SREM: Lo = ExpandLibCall("__moddi3" , Node, Hi); break;
+ case ISD::UREM: Lo = ExpandLibCall("__umoddi3", Node, Hi); break;
}
// Remember in a map if the values will be reused later.
More information about the llvm-commits
mailing list