[llvm-commits] CVS: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
Chris Lattner
lattner at cs.uiuc.edu
Sat Jan 28 00:26:10 PST 2006
Changes in directory llvm/lib/CodeGen/SelectionDAG:
LegalizeDAG.cpp updated: 1.286 -> 1.287
---
Log message:
move a bunch of code, no other change.
---
Diffs of the changes: (+415 -417)
LegalizeDAG.cpp | 832 +++++++++++++++++++++++++++-----------------------------
1 files changed, 415 insertions(+), 417 deletions(-)
Index: llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp
diff -u llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.286 llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.287
--- llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp:1.286 Sat Jan 28 02:22:56 2006
+++ llvm/lib/CodeGen/SelectionDAG/LegalizeDAG.cpp Sat Jan 28 02:25:58 2006
@@ -152,332 +152,6 @@
"Too many value types for ValueTypeActions to hold!");
}
-/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a
-/// INT_TO_FP operation of the specified operand when the target requests that
-/// we expand it. At this point, we know that the result and operand types are
-/// legal for the target.
-SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
- SDOperand Op0,
- MVT::ValueType DestVT) {
- if (Op0.getValueType() == MVT::i32) {
- // simple 32-bit [signed|unsigned] integer to float/double expansion
-
- // get the stack frame index of a 8 byte buffer
- MachineFunction &MF = DAG.getMachineFunction();
- int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
- // get address of 8 byte buffer
- SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
- // word offset constant for Hi/Lo address computation
- SDOperand WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy());
- // set up Hi and Lo (into buffer) address based on endian
- SDOperand Hi, Lo;
- if (TLI.isLittleEndian()) {
- Hi = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff);
- Lo = StackSlot;
- } else {
- Hi = StackSlot;
- Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff);
- }
- // if signed map to unsigned space
- SDOperand Op0Mapped;
- if (isSigned) {
- // constant used to invert sign bit (signed to unsigned mapping)
- SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32);
- Op0Mapped = DAG.getNode(ISD::XOR, MVT::i32, Op0, SignBit);
- } else {
- Op0Mapped = Op0;
- }
- // store the lo of the constructed double - based on integer input
- SDOperand Store1 = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
- Op0Mapped, Lo, DAG.getSrcValue(NULL));
- // initial hi portion of constructed double
- SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32);
- // store the hi of the constructed double - biased exponent
- SDOperand Store2 = DAG.getNode(ISD::STORE, MVT::Other, Store1,
- InitialHi, Hi, DAG.getSrcValue(NULL));
- // load the constructed double
- SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot,
- DAG.getSrcValue(NULL));
- // FP constant to bias correct the final result
- SDOperand Bias = DAG.getConstantFP(isSigned ?
- BitsToDouble(0x4330000080000000ULL)
- : BitsToDouble(0x4330000000000000ULL),
- MVT::f64);
- // subtract the bias
- SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias);
- // final result
- SDOperand Result;
- // handle final rounding
- if (DestVT == MVT::f64) {
- // do nothing
- Result = Sub;
- } else {
- // if f32 then cast to f32
- Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub);
- }
- return Result;
- }
- assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
- SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op0);
-
- SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Op0,
- DAG.getConstant(0, Op0.getValueType()),
- ISD::SETLT);
- SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
- SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
- SignSet, Four, Zero);
-
- // If the sign bit of the integer is set, the large number will be treated
- // as a negative number. To counteract this, the dynamic code adds an
- // offset depending on the data type.
- uint64_t FF;
- switch (Op0.getValueType()) {
- default: assert(0 && "Unsupported integer type!");
- case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float)
- case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float)
- case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float)
- case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float)
- }
- if (TLI.isLittleEndian()) FF <<= 32;
- static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF);
-
- SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
- CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
- SDOperand FudgeInReg;
- if (DestVT == MVT::f32)
- FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
- DAG.getSrcValue(NULL));
- else {
- assert(DestVT == MVT::f64 && "Unexpected conversion");
- FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, MVT::f64,
- DAG.getEntryNode(), CPIdx,
- DAG.getSrcValue(NULL), MVT::f32));
- }
-
- return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg);
-}
-
-/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a
-/// *INT_TO_FP operation of the specified operand when the target requests that
-/// we promote it. At this point, we know that the result and operand types are
-/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP
-/// operation that takes a larger input.
-SDOperand SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDOperand LegalOp,
- MVT::ValueType DestVT,
- bool isSigned) {
- // First step, figure out the appropriate *INT_TO_FP operation to use.
- MVT::ValueType NewInTy = LegalOp.getValueType();
-
- unsigned OpToUse = 0;
-
- // Scan for the appropriate larger type to use.
- while (1) {
- NewInTy = (MVT::ValueType)(NewInTy+1);
- assert(MVT::isInteger(NewInTy) && "Ran out of possibilities!");
-
- // If the target supports SINT_TO_FP of this type, use it.
- switch (TLI.getOperationAction(ISD::SINT_TO_FP, NewInTy)) {
- default: break;
- case TargetLowering::Legal:
- if (!TLI.isTypeLegal(NewInTy))
- break; // Can't use this datatype.
- // FALL THROUGH.
- case TargetLowering::Custom:
- OpToUse = ISD::SINT_TO_FP;
- break;
- }
- if (OpToUse) break;
- if (isSigned) continue;
-
- // If the target supports UINT_TO_FP of this type, use it.
- switch (TLI.getOperationAction(ISD::UINT_TO_FP, NewInTy)) {
- default: break;
- case TargetLowering::Legal:
- if (!TLI.isTypeLegal(NewInTy))
- break; // Can't use this datatype.
- // FALL THROUGH.
- case TargetLowering::Custom:
- OpToUse = ISD::UINT_TO_FP;
- break;
- }
- if (OpToUse) break;
-
- // Otherwise, try a larger type.
- }
-
- // Okay, we found the operation and type to use. Zero extend our input to the
- // desired type then run the operation on it.
- return DAG.getNode(OpToUse, DestVT,
- DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
- NewInTy, LegalOp));
-}
-
-/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a
-/// FP_TO_*INT operation of the specified operand when the target requests that
-/// we promote it. At this point, we know that the result and operand types are
-/// legal for the target, and that there is a legal FP_TO_UINT or FP_TO_SINT
-/// operation that returns a larger result.
-SDOperand SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDOperand LegalOp,
- MVT::ValueType DestVT,
- bool isSigned) {
- // First step, figure out the appropriate FP_TO*INT operation to use.
- MVT::ValueType NewOutTy = DestVT;
-
- unsigned OpToUse = 0;
-
- // Scan for the appropriate larger type to use.
- while (1) {
- NewOutTy = (MVT::ValueType)(NewOutTy+1);
- assert(MVT::isInteger(NewOutTy) && "Ran out of possibilities!");
-
- // If the target supports FP_TO_SINT returning this type, use it.
- switch (TLI.getOperationAction(ISD::FP_TO_SINT, NewOutTy)) {
- default: break;
- case TargetLowering::Legal:
- if (!TLI.isTypeLegal(NewOutTy))
- break; // Can't use this datatype.
- // FALL THROUGH.
- case TargetLowering::Custom:
- OpToUse = ISD::FP_TO_SINT;
- break;
- }
- if (OpToUse) break;
-
- // If the target supports FP_TO_UINT of this type, use it.
- switch (TLI.getOperationAction(ISD::FP_TO_UINT, NewOutTy)) {
- default: break;
- case TargetLowering::Legal:
- if (!TLI.isTypeLegal(NewOutTy))
- break; // Can't use this datatype.
- // FALL THROUGH.
- case TargetLowering::Custom:
- OpToUse = ISD::FP_TO_UINT;
- break;
- }
- if (OpToUse) break;
-
- // Otherwise, try a larger type.
- }
-
- // Okay, we found the operation and type to use. Truncate the result of the
- // extended FP_TO_*INT operation to the desired size.
- return DAG.getNode(ISD::TRUNCATE, DestVT,
- DAG.getNode(OpToUse, NewOutTy, LegalOp));
-}
-
-/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation.
-///
-SDOperand SelectionDAGLegalize::ExpandBSWAP(SDOperand Op) {
- MVT::ValueType VT = Op.getValueType();
- MVT::ValueType SHVT = TLI.getShiftAmountTy();
- SDOperand Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8;
- switch (VT) {
- default: assert(0 && "Unhandled Expand type in BSWAP!"); abort();
- case MVT::i16:
- Tmp2 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT));
- Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT));
- return DAG.getNode(ISD::OR, VT, Tmp1, Tmp2);
- case MVT::i32:
- Tmp4 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT));
- Tmp3 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT));
- Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT));
- Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT));
- Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(0xFF0000, VT));
- Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(0xFF00, VT));
- Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3);
- Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1);
- return DAG.getNode(ISD::OR, VT, Tmp4, Tmp2);
- case MVT::i64:
- Tmp8 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(56, SHVT));
- Tmp7 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(40, SHVT));
- Tmp6 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT));
- Tmp5 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT));
- Tmp4 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT));
- Tmp3 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT));
- Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(40, SHVT));
- Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(56, SHVT));
- Tmp7 = DAG.getNode(ISD::AND, VT, Tmp7, DAG.getConstant(255ULL<<48, VT));
- Tmp6 = DAG.getNode(ISD::AND, VT, Tmp6, DAG.getConstant(255ULL<<40, VT));
- Tmp5 = DAG.getNode(ISD::AND, VT, Tmp5, DAG.getConstant(255ULL<<32, VT));
- Tmp4 = DAG.getNode(ISD::AND, VT, Tmp4, DAG.getConstant(255ULL<<24, VT));
- Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(255ULL<<16, VT));
- Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT));
- Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp7);
- Tmp6 = DAG.getNode(ISD::OR, VT, Tmp6, Tmp5);
- Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3);
- Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1);
- Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp6);
- Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp2);
- return DAG.getNode(ISD::OR, VT, Tmp8, Tmp4);
- }
-}
-
-/// ExpandBitCount - Expand the specified bitcount instruction into operations.
-///
-SDOperand SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDOperand Op) {
- switch (Opc) {
- default: assert(0 && "Cannot expand this yet!");
- case ISD::CTPOP: {
- static const uint64_t mask[6] = {
- 0x5555555555555555ULL, 0x3333333333333333ULL,
- 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
- 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
- };
- MVT::ValueType VT = Op.getValueType();
- MVT::ValueType ShVT = TLI.getShiftAmountTy();
- unsigned len = getSizeInBits(VT);
- for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
- //x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8])
- SDOperand Tmp2 = DAG.getConstant(mask[i], VT);
- SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT);
- Op = DAG.getNode(ISD::ADD, VT, DAG.getNode(ISD::AND, VT, Op, Tmp2),
- DAG.getNode(ISD::AND, VT,
- DAG.getNode(ISD::SRL, VT, Op, Tmp3),Tmp2));
- }
- return Op;
- }
- case ISD::CTLZ: {
- // for now, we do this:
- // x = x | (x >> 1);
- // x = x | (x >> 2);
- // ...
- // x = x | (x >>16);
- // x = x | (x >>32); // for 64-bit input
- // return popcount(~x);
- //
- // but see also: http://www.hackersdelight.org/HDcode/nlz.cc
- MVT::ValueType VT = Op.getValueType();
- MVT::ValueType ShVT = TLI.getShiftAmountTy();
- unsigned len = getSizeInBits(VT);
- for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
- SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT);
- Op = DAG.getNode(ISD::OR, VT, Op, DAG.getNode(ISD::SRL, VT, Op, Tmp3));
- }
- Op = DAG.getNode(ISD::XOR, VT, Op, DAG.getConstant(~0ULL, VT));
- return DAG.getNode(ISD::CTPOP, VT, Op);
- }
- case ISD::CTTZ: {
- // for now, we use: { return popcount(~x & (x - 1)); }
- // unless the target has ctlz but not ctpop, in which case we use:
- // { return 32 - nlz(~x & (x-1)); }
- // see also http://www.hackersdelight.org/HDcode/ntz.cc
- MVT::ValueType VT = Op.getValueType();
- SDOperand Tmp2 = DAG.getConstant(~0ULL, VT);
- SDOperand Tmp3 = DAG.getNode(ISD::AND, VT,
- DAG.getNode(ISD::XOR, VT, Op, Tmp2),
- DAG.getNode(ISD::SUB, VT, Op, DAG.getConstant(1, VT)));
- // If ISD::CTLZ is legal and CTPOP isn't, then do that instead.
- if (!TLI.isOperationLegal(ISD::CTPOP, VT) &&
- TLI.isOperationLegal(ISD::CTLZ, VT))
- return DAG.getNode(ISD::SUB, VT,
- DAG.getConstant(getSizeInBits(VT), VT),
- DAG.getNode(ISD::CTLZ, VT, Tmp3));
- return DAG.getNode(ISD::CTPOP, VT, Tmp3);
- }
- }
-}
-
-
/// ComputeTopDownOrdering - Add the specified node to the Order list if it has
/// not been visited yet and if all of its operands have already been visited.
static void ComputeTopDownOrdering(SDNode *N, std::vector<SDNode*> &Order,
@@ -3416,111 +3090,435 @@
break;
}
- CallInfo.second = LegalizeOp(CallInfo.second);
- SpliceCallInto(CallInfo.second, OutChain);
- return Result;
+ CallInfo.second = LegalizeOp(CallInfo.second);
+ SpliceCallInto(CallInfo.second, OutChain);
+ return Result;
+}
+
+
+/// 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(isTypeLegal(DestTy) && "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!");
+
+ if (!isSigned) {
+ assert(Source.getValueType() == MVT::i64 &&
+ "This only works for 64-bit -> FP");
+ // The 64-bit value loaded will be incorrectly if the 'sign bit' of the
+ // incoming integer is set. To handle this, we dynamically test to see if
+ // it is set, and, if so, add a fudge factor.
+ SDOperand Lo, Hi;
+ ExpandOp(Source, Lo, Hi);
+
+ // 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,
+ DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), Lo, Hi));
+
+ SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Hi,
+ DAG.getConstant(0, Hi.getValueType()),
+ ISD::SETLT);
+ SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
+ SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
+ SignSet, Four, Zero);
+ uint64_t FF = 0x5f800000ULL;
+ if (TLI.isLittleEndian()) FF <<= 32;
+ static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF);
+
+ SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
+ CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
+ SDOperand FudgeInReg;
+ if (DestTy == MVT::f32)
+ FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
+ DAG.getSrcValue(NULL));
+ else {
+ assert(DestTy == MVT::f64 && "Unexpected conversion");
+ FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
+ CPIdx, DAG.getSrcValue(NULL), MVT::f32);
+ }
+ return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
+ }
+
+ // Check to see if the target has a custom way to lower this. If so, use it.
+ switch (TLI.getOperationAction(ISD::SINT_TO_FP, Source.getValueType())) {
+ default: assert(0 && "This action not implemented for this operation!");
+ case TargetLowering::Legal:
+ case TargetLowering::Expand:
+ break; // This case is handled below.
+ case TargetLowering::Custom: {
+ SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy,
+ Source), DAG);
+ if (NV.Val)
+ return LegalizeOp(NV);
+ break; // The target decided this was legal after all
+ }
+ }
+
+ // Expand the source, then glue it back together for the call. We must expand
+ // the source in case it is shared (this pass of legalize must traverse it).
+ SDOperand SrcLo, SrcHi;
+ ExpandOp(Source, SrcLo, SrcHi);
+ Source = DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), SrcLo, SrcHi);
+
+ 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;
+ 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);
+
+ std::pair<SDOperand,SDOperand> CallResult =
+ TLI.LowerCallTo(InChain, RetTy, false, CallingConv::C, true,
+ Callee, Args, DAG);
+
+ SpliceCallInto(CallResult.second, OutChain);
+ return CallResult.first;
+}
+
+/// ExpandLegalINT_TO_FP - This function is responsible for legalizing a
+/// INT_TO_FP operation of the specified operand when the target requests that
+/// we expand it. At this point, we know that the result and operand types are
+/// legal for the target.
+SDOperand SelectionDAGLegalize::ExpandLegalINT_TO_FP(bool isSigned,
+ SDOperand Op0,
+ MVT::ValueType DestVT) {
+ if (Op0.getValueType() == MVT::i32) {
+ // simple 32-bit [signed|unsigned] integer to float/double expansion
+
+ // get the stack frame index of a 8 byte buffer
+ MachineFunction &MF = DAG.getMachineFunction();
+ int SSFI = MF.getFrameInfo()->CreateStackObject(8, 8);
+ // get address of 8 byte buffer
+ SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
+ // word offset constant for Hi/Lo address computation
+ SDOperand WordOff = DAG.getConstant(sizeof(int), TLI.getPointerTy());
+ // set up Hi and Lo (into buffer) address based on endian
+ SDOperand Hi, Lo;
+ if (TLI.isLittleEndian()) {
+ Hi = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff);
+ Lo = StackSlot;
+ } else {
+ Hi = StackSlot;
+ Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, WordOff);
+ }
+ // if signed map to unsigned space
+ SDOperand Op0Mapped;
+ if (isSigned) {
+ // constant used to invert sign bit (signed to unsigned mapping)
+ SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32);
+ Op0Mapped = DAG.getNode(ISD::XOR, MVT::i32, Op0, SignBit);
+ } else {
+ Op0Mapped = Op0;
+ }
+ // store the lo of the constructed double - based on integer input
+ SDOperand Store1 = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
+ Op0Mapped, Lo, DAG.getSrcValue(NULL));
+ // initial hi portion of constructed double
+ SDOperand InitialHi = DAG.getConstant(0x43300000u, MVT::i32);
+ // store the hi of the constructed double - biased exponent
+ SDOperand Store2 = DAG.getNode(ISD::STORE, MVT::Other, Store1,
+ InitialHi, Hi, DAG.getSrcValue(NULL));
+ // load the constructed double
+ SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot,
+ DAG.getSrcValue(NULL));
+ // FP constant to bias correct the final result
+ SDOperand Bias = DAG.getConstantFP(isSigned ?
+ BitsToDouble(0x4330000080000000ULL)
+ : BitsToDouble(0x4330000000000000ULL),
+ MVT::f64);
+ // subtract the bias
+ SDOperand Sub = DAG.getNode(ISD::FSUB, MVT::f64, Load, Bias);
+ // final result
+ SDOperand Result;
+ // handle final rounding
+ if (DestVT == MVT::f64) {
+ // do nothing
+ Result = Sub;
+ } else {
+ // if f32 then cast to f32
+ Result = DAG.getNode(ISD::FP_ROUND, MVT::f32, Sub);
+ }
+ return Result;
+ }
+ assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
+ SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op0);
+
+ SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Op0,
+ DAG.getConstant(0, Op0.getValueType()),
+ ISD::SETLT);
+ SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
+ SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
+ SignSet, Four, Zero);
+
+ // If the sign bit of the integer is set, the large number will be treated
+ // as a negative number. To counteract this, the dynamic code adds an
+ // offset depending on the data type.
+ uint64_t FF;
+ switch (Op0.getValueType()) {
+ default: assert(0 && "Unsupported integer type!");
+ case MVT::i8 : FF = 0x43800000ULL; break; // 2^8 (as a float)
+ case MVT::i16: FF = 0x47800000ULL; break; // 2^16 (as a float)
+ case MVT::i32: FF = 0x4F800000ULL; break; // 2^32 (as a float)
+ case MVT::i64: FF = 0x5F800000ULL; break; // 2^64 (as a float)
+ }
+ if (TLI.isLittleEndian()) FF <<= 32;
+ static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF);
+
+ SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
+ CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
+ SDOperand FudgeInReg;
+ if (DestVT == MVT::f32)
+ FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
+ DAG.getSrcValue(NULL));
+ else {
+ assert(DestVT == MVT::f64 && "Unexpected conversion");
+ FudgeInReg = LegalizeOp(DAG.getExtLoad(ISD::EXTLOAD, MVT::f64,
+ DAG.getEntryNode(), CPIdx,
+ DAG.getSrcValue(NULL), MVT::f32));
+ }
+
+ return DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg);
+}
+
+/// PromoteLegalINT_TO_FP - This function is responsible for legalizing a
+/// *INT_TO_FP operation of the specified operand when the target requests that
+/// we promote it. At this point, we know that the result and operand types are
+/// legal for the target, and that there is a legal UINT_TO_FP or SINT_TO_FP
+/// operation that takes a larger input.
+SDOperand SelectionDAGLegalize::PromoteLegalINT_TO_FP(SDOperand LegalOp,
+ MVT::ValueType DestVT,
+ bool isSigned) {
+ // First step, figure out the appropriate *INT_TO_FP operation to use.
+ MVT::ValueType NewInTy = LegalOp.getValueType();
+
+ unsigned OpToUse = 0;
+
+ // Scan for the appropriate larger type to use.
+ while (1) {
+ NewInTy = (MVT::ValueType)(NewInTy+1);
+ assert(MVT::isInteger(NewInTy) && "Ran out of possibilities!");
+
+ // If the target supports SINT_TO_FP of this type, use it.
+ switch (TLI.getOperationAction(ISD::SINT_TO_FP, NewInTy)) {
+ default: break;
+ case TargetLowering::Legal:
+ if (!TLI.isTypeLegal(NewInTy))
+ break; // Can't use this datatype.
+ // FALL THROUGH.
+ case TargetLowering::Custom:
+ OpToUse = ISD::SINT_TO_FP;
+ break;
+ }
+ if (OpToUse) break;
+ if (isSigned) continue;
+
+ // If the target supports UINT_TO_FP of this type, use it.
+ switch (TLI.getOperationAction(ISD::UINT_TO_FP, NewInTy)) {
+ default: break;
+ case TargetLowering::Legal:
+ if (!TLI.isTypeLegal(NewInTy))
+ break; // Can't use this datatype.
+ // FALL THROUGH.
+ case TargetLowering::Custom:
+ OpToUse = ISD::UINT_TO_FP;
+ break;
+ }
+ if (OpToUse) break;
+
+ // Otherwise, try a larger type.
+ }
+
+ // Okay, we found the operation and type to use. Zero extend our input to the
+ // desired type then run the operation on it.
+ return DAG.getNode(OpToUse, DestVT,
+ DAG.getNode(isSigned ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND,
+ NewInTy, LegalOp));
}
+/// PromoteLegalFP_TO_INT - This function is responsible for legalizing a
+/// FP_TO_*INT operation of the specified operand when the target requests that
+/// we promote it. At this point, we know that the result and operand types are
+/// legal for the target, and that there is a legal FP_TO_UINT or FP_TO_SINT
+/// operation that returns a larger result.
+SDOperand SelectionDAGLegalize::PromoteLegalFP_TO_INT(SDOperand LegalOp,
+ MVT::ValueType DestVT,
+ bool isSigned) {
+ // First step, figure out the appropriate FP_TO*INT operation to use.
+ MVT::ValueType NewOutTy = DestVT;
-/// 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(isTypeLegal(DestTy) && "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!");
-
- if (!isSigned) {
- assert(Source.getValueType() == MVT::i64 &&
- "This only works for 64-bit -> FP");
- // The 64-bit value loaded will be incorrectly if the 'sign bit' of the
- // incoming integer is set. To handle this, we dynamically test to see if
- // it is set, and, if so, add a fudge factor.
- SDOperand Lo, Hi;
- ExpandOp(Source, Lo, Hi);
+ unsigned OpToUse = 0;
- // 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,
- DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), Lo, Hi));
+ // Scan for the appropriate larger type to use.
+ while (1) {
+ NewOutTy = (MVT::ValueType)(NewOutTy+1);
+ assert(MVT::isInteger(NewOutTy) && "Ran out of possibilities!");
- SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultTy(), Hi,
- DAG.getConstant(0, Hi.getValueType()),
- ISD::SETLT);
- SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
- SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
- SignSet, Four, Zero);
- uint64_t FF = 0x5f800000ULL;
- if (TLI.isLittleEndian()) FF <<= 32;
- static Constant *FudgeFactor = ConstantUInt::get(Type::ULongTy, FF);
+ // If the target supports FP_TO_SINT returning this type, use it.
+ switch (TLI.getOperationAction(ISD::FP_TO_SINT, NewOutTy)) {
+ default: break;
+ case TargetLowering::Legal:
+ if (!TLI.isTypeLegal(NewOutTy))
+ break; // Can't use this datatype.
+ // FALL THROUGH.
+ case TargetLowering::Custom:
+ OpToUse = ISD::FP_TO_SINT;
+ break;
+ }
+ if (OpToUse) break;
- SDOperand CPIdx = DAG.getConstantPool(FudgeFactor, TLI.getPointerTy());
- CPIdx = DAG.getNode(ISD::ADD, TLI.getPointerTy(), CPIdx, CstOffset);
- SDOperand FudgeInReg;
- if (DestTy == MVT::f32)
- FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx,
- DAG.getSrcValue(NULL));
- else {
- assert(DestTy == MVT::f64 && "Unexpected conversion");
- FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, MVT::f64, DAG.getEntryNode(),
- CPIdx, DAG.getSrcValue(NULL), MVT::f32);
+ // If the target supports FP_TO_UINT of this type, use it.
+ switch (TLI.getOperationAction(ISD::FP_TO_UINT, NewOutTy)) {
+ default: break;
+ case TargetLowering::Legal:
+ if (!TLI.isTypeLegal(NewOutTy))
+ break; // Can't use this datatype.
+ // FALL THROUGH.
+ case TargetLowering::Custom:
+ OpToUse = ISD::FP_TO_UINT;
+ break;
}
- return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
- }
+ if (OpToUse) break;
- // Check to see if the target has a custom way to lower this. If so, use it.
- switch (TLI.getOperationAction(ISD::SINT_TO_FP, Source.getValueType())) {
- default: assert(0 && "This action not implemented for this operation!");
- case TargetLowering::Legal:
- case TargetLowering::Expand:
- break; // This case is handled below.
- case TargetLowering::Custom: {
- SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy,
- Source), DAG);
- if (NV.Val)
- return LegalizeOp(NV);
- break; // The target decided this was legal after all
- }
+ // Otherwise, try a larger type.
}
- // Expand the source, then glue it back together for the call. We must expand
- // the source in case it is shared (this pass of legalize must traverse it).
- SDOperand SrcLo, SrcHi;
- ExpandOp(Source, SrcLo, SrcHi);
- Source = DAG.getNode(ISD::BUILD_PAIR, Source.getValueType(), SrcLo, SrcHi);
+ // Okay, we found the operation and type to use. Truncate the result of the
+ // extended FP_TO_*INT operation to the desired size.
+ return DAG.getNode(ISD::TRUNCATE, DestVT,
+ DAG.getNode(OpToUse, NewOutTy, LegalOp));
+}
- 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";
+/// ExpandBSWAP - Open code the operations for BSWAP of the specified operation.
+///
+SDOperand SelectionDAGLegalize::ExpandBSWAP(SDOperand Op) {
+ MVT::ValueType VT = Op.getValueType();
+ MVT::ValueType SHVT = TLI.getShiftAmountTy();
+ SDOperand Tmp1, Tmp2, Tmp3, Tmp4, Tmp5, Tmp6, Tmp7, Tmp8;
+ switch (VT) {
+ default: assert(0 && "Unhandled Expand type in BSWAP!"); abort();
+ case MVT::i16:
+ Tmp2 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT));
+ Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT));
+ return DAG.getNode(ISD::OR, VT, Tmp1, Tmp2);
+ case MVT::i32:
+ Tmp4 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT));
+ Tmp3 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT));
+ Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT));
+ Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT));
+ Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(0xFF0000, VT));
+ Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(0xFF00, VT));
+ Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3);
+ Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1);
+ return DAG.getNode(ISD::OR, VT, Tmp4, Tmp2);
+ case MVT::i64:
+ Tmp8 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(56, SHVT));
+ Tmp7 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(40, SHVT));
+ Tmp6 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(24, SHVT));
+ Tmp5 = DAG.getNode(ISD::SHL, VT, Op, DAG.getConstant(8, SHVT));
+ Tmp4 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(8, SHVT));
+ Tmp3 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(24, SHVT));
+ Tmp2 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(40, SHVT));
+ Tmp1 = DAG.getNode(ISD::SRL, VT, Op, DAG.getConstant(56, SHVT));
+ Tmp7 = DAG.getNode(ISD::AND, VT, Tmp7, DAG.getConstant(255ULL<<48, VT));
+ Tmp6 = DAG.getNode(ISD::AND, VT, Tmp6, DAG.getConstant(255ULL<<40, VT));
+ Tmp5 = DAG.getNode(ISD::AND, VT, Tmp5, DAG.getConstant(255ULL<<32, VT));
+ Tmp4 = DAG.getNode(ISD::AND, VT, Tmp4, DAG.getConstant(255ULL<<24, VT));
+ Tmp3 = DAG.getNode(ISD::AND, VT, Tmp3, DAG.getConstant(255ULL<<16, VT));
+ Tmp2 = DAG.getNode(ISD::AND, VT, Tmp2, DAG.getConstant(255ULL<<8 , VT));
+ Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp7);
+ Tmp6 = DAG.getNode(ISD::OR, VT, Tmp6, Tmp5);
+ Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp3);
+ Tmp2 = DAG.getNode(ISD::OR, VT, Tmp2, Tmp1);
+ Tmp8 = DAG.getNode(ISD::OR, VT, Tmp8, Tmp6);
+ Tmp4 = DAG.getNode(ISD::OR, VT, Tmp4, Tmp2);
+ return DAG.getNode(ISD::OR, VT, Tmp8, Tmp4);
}
-
- 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);
-
- std::pair<SDOperand,SDOperand> CallResult =
- TLI.LowerCallTo(InChain, RetTy, false, CallingConv::C, true,
- Callee, Args, DAG);
-
- SpliceCallInto(CallResult.second, OutChain);
- return CallResult.first;
}
+/// ExpandBitCount - Expand the specified bitcount instruction into operations.
+///
+SDOperand SelectionDAGLegalize::ExpandBitCount(unsigned Opc, SDOperand Op) {
+ switch (Opc) {
+ default: assert(0 && "Cannot expand this yet!");
+ case ISD::CTPOP: {
+ static const uint64_t mask[6] = {
+ 0x5555555555555555ULL, 0x3333333333333333ULL,
+ 0x0F0F0F0F0F0F0F0FULL, 0x00FF00FF00FF00FFULL,
+ 0x0000FFFF0000FFFFULL, 0x00000000FFFFFFFFULL
+ };
+ MVT::ValueType VT = Op.getValueType();
+ MVT::ValueType ShVT = TLI.getShiftAmountTy();
+ unsigned len = getSizeInBits(VT);
+ for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
+ //x = (x & mask[i][len/8]) + (x >> (1 << i) & mask[i][len/8])
+ SDOperand Tmp2 = DAG.getConstant(mask[i], VT);
+ SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT);
+ Op = DAG.getNode(ISD::ADD, VT, DAG.getNode(ISD::AND, VT, Op, Tmp2),
+ DAG.getNode(ISD::AND, VT,
+ DAG.getNode(ISD::SRL, VT, Op, Tmp3),Tmp2));
+ }
+ return Op;
+ }
+ case ISD::CTLZ: {
+ // for now, we do this:
+ // x = x | (x >> 1);
+ // x = x | (x >> 2);
+ // ...
+ // x = x | (x >>16);
+ // x = x | (x >>32); // for 64-bit input
+ // return popcount(~x);
+ //
+ // but see also: http://www.hackersdelight.org/HDcode/nlz.cc
+ MVT::ValueType VT = Op.getValueType();
+ MVT::ValueType ShVT = TLI.getShiftAmountTy();
+ unsigned len = getSizeInBits(VT);
+ for (unsigned i = 0; (1U << i) <= (len / 2); ++i) {
+ SDOperand Tmp3 = DAG.getConstant(1ULL << i, ShVT);
+ Op = DAG.getNode(ISD::OR, VT, Op, DAG.getNode(ISD::SRL, VT, Op, Tmp3));
+ }
+ Op = DAG.getNode(ISD::XOR, VT, Op, DAG.getConstant(~0ULL, VT));
+ return DAG.getNode(ISD::CTPOP, VT, Op);
+ }
+ case ISD::CTTZ: {
+ // for now, we use: { return popcount(~x & (x - 1)); }
+ // unless the target has ctlz but not ctpop, in which case we use:
+ // { return 32 - nlz(~x & (x-1)); }
+ // see also http://www.hackersdelight.org/HDcode/ntz.cc
+ MVT::ValueType VT = Op.getValueType();
+ SDOperand Tmp2 = DAG.getConstant(~0ULL, VT);
+ SDOperand Tmp3 = DAG.getNode(ISD::AND, VT,
+ DAG.getNode(ISD::XOR, VT, Op, Tmp2),
+ DAG.getNode(ISD::SUB, VT, Op, DAG.getConstant(1, VT)));
+ // If ISD::CTLZ is legal and CTPOP isn't, then do that instead.
+ if (!TLI.isOperationLegal(ISD::CTPOP, VT) &&
+ TLI.isOperationLegal(ISD::CTLZ, VT))
+ return DAG.getNode(ISD::SUB, VT,
+ DAG.getConstant(getSizeInBits(VT), VT),
+ DAG.getNode(ISD::CTLZ, VT, Tmp3));
+ return DAG.getNode(ISD::CTPOP, VT, Tmp3);
+ }
+ }
+}
/// ExpandOp - Expand the specified SDOperand into its two component pieces
More information about the llvm-commits
mailing list