[llvm-commits] [llvm] r52408 - in /llvm/trunk/lib/CodeGen/SelectionDAG: LegalizeFloatTypes.cpp LegalizeIntegerTypes.cpp LegalizeTypes.cpp LegalizeTypes.h LegalizeTypesExpand.cpp LegalizeTypesFloatToInt.cpp LegalizeTypesPromote.cpp LegalizeTypesScalarize.cpp LegalizeTypesSplit.cpp LegalizeVectorTypes.cpp
Duncan Sands
baldrick at free.fr
Tue Jun 17 07:27:01 PDT 2008
Author: baldrick
Date: Tue Jun 17 09:27:01 2008
New Revision: 52408
URL: http://llvm.org/viewvc/llvm-project?rev=52408&view=rev
Log:
Split type expansion into ExpandInteger and ExpandFloat
rather than bundling them together. Rename FloatToInt
to PromoteFloat (better, if not perfect). Reorganize
files by types rather than by operations.
Added:
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
Removed:
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp
Modified:
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h
Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp?rev=52408&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp (added)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeFloatTypes.cpp Tue Jun 17 09:27:01 2008
@@ -0,0 +1,452 @@
+//===-------- LegalizeFloatTypes.cpp - Legalization of float types --------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements float type expansion and conversion of float types to
+// integer types on behalf of LegalizeTypes.
+// Converting to integer is the act of turning a computation in an illegal
+// floating point type into a computation in an integer type of the same size.
+// For example, turning f32 arithmetic into operations using i32. Also known as
+// "soft float". The result is equivalent to bitcasting the float value to the
+// integer type.
+// Expansion is the act of changing a computation in an illegal type to be a
+// computation in multiple registers of a smaller type. For example,
+// implementing ppcf128 arithmetic in two f64 registers.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LegalizeTypes.h"
+#include "llvm/CodeGen/PseudoSourceValue.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
+using namespace llvm;
+
+/// GetFPLibCall - Return the right libcall for the given floating point type.
+static RTLIB::Libcall GetFPLibCall(MVT VT,
+ RTLIB::Libcall Call_F32,
+ RTLIB::Libcall Call_F64,
+ RTLIB::Libcall Call_F80,
+ RTLIB::Libcall Call_PPCF128) {
+ return
+ VT == MVT::f32 ? Call_F32 :
+ VT == MVT::f64 ? Call_F64 :
+ VT == MVT::f80 ? Call_F80 :
+ VT == MVT::ppcf128 ? Call_PPCF128 :
+ RTLIB::UNKNOWN_LIBCALL;
+}
+
+//===----------------------------------------------------------------------===//
+// Result Float to Integer Conversion.
+//===----------------------------------------------------------------------===//
+
+void DAGTypeLegalizer::PromoteFloatResult(SDNode *N, unsigned ResNo) {
+ DEBUG(cerr << "Promote float result " << ResNo << ": "; N->dump(&DAG);
+ cerr << "\n");
+ SDOperand R = SDOperand();
+
+ // FIXME: Custom lowering for float-to-int?
+#if 0
+ // See if the target wants to custom convert this node to an integer.
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ if (SDNode *P = TLI.FloatToIntOperationResult(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;
+ }
+ }
+#endif
+
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "PromoteFloatResult #" << ResNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to convert the result of this operator!");
+ abort();
+
+ case ISD::BIT_CONVERT: R = PromoteFloatRes_BIT_CONVERT(N); break;
+ case ISD::BUILD_PAIR: R = PromoteFloatRes_BUILD_PAIR(N); break;
+ case ISD::ConstantFP:
+ R = PromoteFloatRes_ConstantFP(cast<ConstantFPSDNode>(N));
+ break;
+ case ISD::FCOPYSIGN: R = PromoteFloatRes_FCOPYSIGN(N); break;
+ case ISD::LOAD: R = PromoteFloatRes_LOAD(N); break;
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP: R = PromoteFloatRes_XINT_TO_FP(N); break;
+
+ case ISD::FADD: R = PromoteFloatRes_FADD(N); break;
+ case ISD::FMUL: R = PromoteFloatRes_FMUL(N); break;
+ case ISD::FSUB: R = PromoteFloatRes_FSUB(N); break;
+ }
+
+ // If R is null, the sub-method took care of registering the result.
+ if (R.Val)
+ SetPromotedFloat(SDOperand(N, ResNo), R);
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_BIT_CONVERT(SDNode *N) {
+ return BitConvertToInteger(N->getOperand(0));
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_BUILD_PAIR(SDNode *N) {
+ // Convert the inputs to integers, and build a new pair out of them.
+ return DAG.getNode(ISD::BUILD_PAIR,
+ TLI.getTypeToTransformTo(N->getValueType(0)),
+ BitConvertToInteger(N->getOperand(0)),
+ BitConvertToInteger(N->getOperand(1)));
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_ConstantFP(ConstantFPSDNode *N) {
+ return DAG.getConstant(N->getValueAPF().convertToAPInt(),
+ TLI.getTypeToTransformTo(N->getValueType(0)));
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_FADD(SDNode *N) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)),
+ GetPromotedFloat(N->getOperand(1)) };
+ return MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::ADD_F32,
+ RTLIB::ADD_F64,
+ RTLIB::ADD_F80,
+ RTLIB::ADD_PPCF128),
+ NVT, Ops, 2, false/*sign irrelevant*/);
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_FCOPYSIGN(SDNode *N) {
+ SDOperand LHS = GetPromotedFloat(N->getOperand(0));
+ SDOperand RHS = BitConvertToInteger(N->getOperand(1));
+
+ MVT LVT = LHS.getValueType();
+ MVT RVT = RHS.getValueType();
+
+ unsigned LSize = LVT.getSizeInBits();
+ unsigned RSize = RVT.getSizeInBits();
+
+ // First get the sign bit of second operand.
+ SDOperand SignBit = DAG.getNode(ISD::SHL, RVT, DAG.getConstant(1, RVT),
+ DAG.getConstant(RSize - 1,
+ TLI.getShiftAmountTy()));
+ SignBit = DAG.getNode(ISD::AND, RVT, RHS, SignBit);
+
+ // Shift right or sign-extend it if the two operands have different types.
+ int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
+ if (SizeDiff > 0) {
+ SignBit = DAG.getNode(ISD::SRL, RVT, SignBit,
+ DAG.getConstant(SizeDiff, TLI.getShiftAmountTy()));
+ SignBit = DAG.getNode(ISD::TRUNCATE, LVT, SignBit);
+ } else if (SizeDiff < 0) {
+ SignBit = DAG.getNode(ISD::ANY_EXTEND, LVT, SignBit);
+ SignBit = DAG.getNode(ISD::SHL, LVT, SignBit,
+ DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy()));
+ }
+
+ // Clear the sign bit of the first operand.
+ SDOperand Mask = DAG.getNode(ISD::SHL, LVT, DAG.getConstant(1, LVT),
+ DAG.getConstant(LSize - 1,
+ TLI.getShiftAmountTy()));
+ Mask = DAG.getNode(ISD::SUB, LVT, Mask, DAG.getConstant(1, LVT));
+ LHS = DAG.getNode(ISD::AND, LVT, LHS, Mask);
+
+ // Or the value with the sign bit.
+ return DAG.getNode(ISD::OR, LVT, LHS, SignBit);
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_FMUL(SDNode *N) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)),
+ GetPromotedFloat(N->getOperand(1)) };
+ return MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::MUL_F32,
+ RTLIB::MUL_F64,
+ RTLIB::MUL_F80,
+ RTLIB::MUL_PPCF128),
+ NVT, Ops, 2, false/*sign irrelevant*/);
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_FSUB(SDNode *N) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Ops[2] = { GetPromotedFloat(N->getOperand(0)),
+ GetPromotedFloat(N->getOperand(1)) };
+ return MakeLibCall(GetFPLibCall(N->getValueType(0),
+ RTLIB::SUB_F32,
+ RTLIB::SUB_F64,
+ RTLIB::SUB_F80,
+ RTLIB::SUB_PPCF128),
+ NVT, Ops, 2, false/*sign irrelevant*/);
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_LOAD(SDNode *N) {
+ LoadSDNode *L = cast<LoadSDNode>(N);
+ MVT VT = N->getValueType(0);
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+
+ if (L->getExtensionType() == ISD::NON_EXTLOAD)
+ return DAG.getLoad(L->getAddressingMode(), L->getExtensionType(),
+ NVT, L->getChain(), L->getBasePtr(), L->getOffset(),
+ L->getSrcValue(), L->getSrcValueOffset(), NVT,
+ L->isVolatile(), L->getAlignment());
+
+ // Do a non-extending load followed by FP_EXTEND.
+ SDOperand NL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD,
+ L->getMemoryVT(), L->getChain(),
+ L->getBasePtr(), L->getOffset(),
+ L->getSrcValue(), L->getSrcValueOffset(),
+ L->getMemoryVT(),
+ L->isVolatile(), L->getAlignment());
+ return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL));
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatRes_XINT_TO_FP(SDNode *N) {
+ bool isSigned = N->getOpcode() == ISD::SINT_TO_FP;
+ MVT DestVT = N->getValueType(0);
+ SDOperand Op = N->getOperand(0);
+
+ if (Op.getValueType() == MVT::i32) {
+ // simple 32-bit [signed|unsigned] integer to float/double expansion
+
+ // Get the stack frame index of a 8 byte buffer.
+ SDOperand StackSlot = DAG.CreateStackTemporary(MVT::f64);
+
+ // word offset constant for Hi/Lo address computation
+ SDOperand Offset =
+ DAG.getConstant(MVT(MVT::i32).getSizeInBits() / 8,
+ TLI.getPointerTy());
+ // set up Hi and Lo (into buffer) address based on endian
+ SDOperand Hi = StackSlot;
+ SDOperand Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, Offset);
+ if (TLI.isLittleEndian())
+ std::swap(Hi, Lo);
+
+ // if signed map to unsigned space
+ SDOperand OpMapped;
+ if (isSigned) {
+ // constant used to invert sign bit (signed to unsigned mapping)
+ SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32);
+ OpMapped = DAG.getNode(ISD::XOR, MVT::i32, Op, SignBit);
+ } else {
+ OpMapped = Op;
+ }
+ // store the lo of the constructed double - based on integer input
+ SDOperand Store1 = DAG.getStore(DAG.getEntryNode(),
+ OpMapped, Lo, NULL, 0);
+ // 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.getStore(Store1, InitialHi, Hi, NULL, 0);
+ // load the constructed double
+ SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot, NULL, 0);
+ // 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 (DestVT.bitsLT(MVT::f64)) {
+ Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub,
+ DAG.getIntPtrConstant(0));
+ } else if (DestVT.bitsGT(MVT::f64)) {
+ Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub);
+ }
+ return BitConvertToInteger(Result);
+ }
+ assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
+ SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op);
+
+ SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Op), Op,
+ DAG.getConstant(0, Op.getValueType()),
+ ISD::SETLT);
+ SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.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 (Op.getValueType().getSimpleVT()) {
+ 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 = ConstantInt::get(Type::Int64Ty, 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,
+ PseudoSourceValue::getConstantPool(), 0);
+ else {
+ FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestVT,
+ DAG.getEntryNode(), CPIdx,
+ PseudoSourceValue::getConstantPool(), 0,
+ MVT::f32);
+ }
+
+ return BitConvertToInteger(DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg));
+}
+
+
+//===----------------------------------------------------------------------===//
+// Operand Float to Integer Conversion..
+//===----------------------------------------------------------------------===//
+
+bool DAGTypeLegalizer::PromoteFloatOperand(SDNode *N, unsigned OpNo) {
+ DEBUG(cerr << "Promote float operand " << OpNo << ": "; N->dump(&DAG);
+ cerr << "\n");
+ SDOperand Res(0, 0);
+
+ // FIXME: Custom lowering for float-to-int?
+#if 0
+ if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+ == TargetLowering::Custom)
+ Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+#endif
+
+ if (Res.Val == 0) {
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "PromoteFloatOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to convert this operator's operand!");
+ abort();
+
+ case ISD::BIT_CONVERT: Res = PromoteFloatOp_BIT_CONVERT(N); break;
+ }
+ }
+
+ // If the result is null, the sub-method took care of registering results etc.
+ if (!Res.Val) return false;
+
+ // If the result is N, the sub-method updated N in place. Check to see if any
+ // operands are new, and if so, mark them.
+ if (Res.Val == N) {
+ // Mark N as new and remark N and its operands. This allows us to correctly
+ // revisit N if it needs another step of promotion and allows us to visit
+ // any new operands to N.
+ ReanalyzeNode(N);
+ return true;
+ }
+
+ assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+ "Invalid operand expansion");
+
+ ReplaceValueWith(SDOperand(N, 0), Res);
+ return false;
+}
+
+SDOperand DAGTypeLegalizer::PromoteFloatOp_BIT_CONVERT(SDNode *N) {
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
+ GetPromotedFloat(N->getOperand(0)));
+}
+
+
+//===----------------------------------------------------------------------===//
+// Float Result Expansion
+//===----------------------------------------------------------------------===//
+
+/// ExpandFloatResult - This method is called when the specified result of the
+/// specified node is found to need expansion. At this point, the node may also
+/// have invalid operands or may have other results that need promotion, we just
+/// know that (at least) one result needs expansion.
+void DAGTypeLegalizer::ExpandFloatResult(SDNode *N, unsigned ResNo) {
+ DEBUG(cerr << "Expand float result: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Lo, Hi;
+ Lo = Hi = SDOperand();
+
+ // See if the target wants to custom expand this node.
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ if (SDNode *P = TLI.ExpandOperationResult(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()) {
+ default:
+#ifndef NDEBUG
+ cerr << "ExpandFloatResult #" << ResNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to expand the result of this operator!");
+ abort();
+ }
+
+ // If Lo/Hi is null, the sub-method took care of registering results etc.
+ if (Lo.Val)
+ SetExpandedFloat(SDOperand(N, ResNo), Lo, Hi);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Float Operand Expansion
+//===----------------------------------------------------------------------===//
+
+/// ExpandFloatOperand - This method is called when the specified operand of the
+/// specified node is found to need expansion. At this point, all of the result
+/// types of the node are known to be legal, but other operands of the node may
+/// need promotion or expansion as well as the specified one.
+bool DAGTypeLegalizer::ExpandFloatOperand(SDNode *N, unsigned OpNo) {
+ DEBUG(cerr << "Expand float operand: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Res(0, 0);
+
+ if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+ == TargetLowering::Custom)
+ Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+
+ if (Res.Val == 0) {
+ switch (N->getOpcode()) {
+ default:
+ #ifndef NDEBUG
+ cerr << "ExpandFloatOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+ #endif
+ assert(0 && "Do not know how to expand this operator's operand!");
+ abort();
+ }
+ }
+
+ // If the result is null, the sub-method took care of registering results etc.
+ if (!Res.Val) return false;
+ // If the result is N, the sub-method updated N in place. Check to see if any
+ // operands are new, and if so, mark them.
+ if (Res.Val == N) {
+ // Mark N as new and remark N and its operands. This allows us to correctly
+ // revisit N if it needs another step of expansion and allows us to visit
+ // any new operands to N.
+ ReanalyzeNode(N);
+ return true;
+ }
+
+ assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+ "Invalid operand expansion");
+
+ ReplaceValueWith(SDOperand(N, 0), Res);
+ return false;
+}
Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp?rev=52408&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp (added)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeIntegerTypes.cpp Tue Jun 17 09:27:01 2008
@@ -0,0 +1,2174 @@
+//===----- LegalizeIntegerTypes.cpp - Legalization of integer types -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements integer type expansion and promotion for LegalizeTypes.
+// Promotion is the act of changing a computation in an illegal type into a
+// computation in a larger type. For example, implementing i8 arithmetic in an
+// i32 register (often needed on powerpc).
+// Expansion is the act of changing a computation in an illegal type into a
+// computation in multiple registers of a smaller type. For example,
+// implementing i64 arithmetic in two i32 registers (often needed on 32-bit
+// targets).
+//
+//===----------------------------------------------------------------------===//
+
+#include "LegalizeTypes.h"
+#include "llvm/Constants.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Integer Result Promotion
+//===----------------------------------------------------------------------===//
+
+/// PromoteIntegerResult - This method is called when a result of a node is
+/// found to be in need of promotion to a larger type. At this point, the node
+/// may also have invalid operands or may have other results that need
+/// expansion, we just know that (at least) one result needs promotion.
+void DAGTypeLegalizer::PromoteIntegerResult(SDNode *N, unsigned ResNo) {
+ DEBUG(cerr << "Promote integer result: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Result = SDOperand();
+
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "PromoteIntegerResult #" << ResNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to promote this operator!");
+ abort();
+ case ISD::UNDEF: Result = PromoteIntRes_UNDEF(N); break;
+ case ISD::Constant: Result = PromoteIntRes_Constant(N); break;
+
+ case ISD::TRUNCATE: Result = PromoteIntRes_TRUNCATE(N); break;
+ case ISD::SIGN_EXTEND:
+ case ISD::ZERO_EXTEND:
+ case ISD::ANY_EXTEND: Result = PromoteIntRes_INT_EXTEND(N); break;
+ case ISD::FP_ROUND: Result = PromoteIntRes_FP_ROUND(N); break;
+ case ISD::FP_TO_SINT:
+ case ISD::FP_TO_UINT: Result = PromoteIntRes_FP_TO_XINT(N); break;
+ case ISD::SETCC: Result = PromoteIntRes_SETCC(N); break;
+ case ISD::LOAD: Result = PromoteIntRes_LOAD(cast<LoadSDNode>(N)); break;
+ case ISD::BUILD_PAIR: Result = PromoteIntRes_BUILD_PAIR(N); break;
+ case ISD::BIT_CONVERT: Result = PromoteIntRes_BIT_CONVERT(N); break;
+
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR:
+ case ISD::ADD:
+ case ISD::SUB:
+ case ISD::MUL: Result = PromoteIntRes_SimpleIntBinOp(N); break;
+
+ case ISD::SDIV:
+ case ISD::SREM: Result = PromoteIntRes_SDIV(N); break;
+
+ case ISD::UDIV:
+ case ISD::UREM: Result = PromoteIntRes_UDIV(N); break;
+
+ case ISD::SHL: Result = PromoteIntRes_SHL(N); break;
+ case ISD::SRA: Result = PromoteIntRes_SRA(N); break;
+ case ISD::SRL: Result = PromoteIntRes_SRL(N); break;
+
+ case ISD::SELECT: Result = PromoteIntRes_SELECT(N); break;
+ case ISD::SELECT_CC: Result = PromoteIntRes_SELECT_CC(N); break;
+
+ case ISD::CTLZ: Result = PromoteIntRes_CTLZ(N); break;
+ case ISD::CTPOP: Result = PromoteIntRes_CTPOP(N); break;
+ case ISD::CTTZ: Result = PromoteIntRes_CTTZ(N); break;
+
+ case ISD::EXTRACT_VECTOR_ELT:
+ Result = PromoteIntRes_EXTRACT_VECTOR_ELT(N);
+ break;
+ }
+
+ // If Result is null, the sub-method took care of registering the result.
+ if (Result.Val)
+ SetPromotedInteger(SDOperand(N, ResNo), Result);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_UNDEF(SDNode *N) {
+ return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0)));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_Constant(SDNode *N) {
+ MVT VT = N->getValueType(0);
+ // Zero extend things like i1, sign extend everything else. It shouldn't
+ // matter in theory which one we pick, but this tends to give better code?
+ unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
+ SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT),
+ SDOperand(N, 0));
+ assert(isa<ConstantSDNode>(Result) && "Didn't constant fold ext?");
+ return Result;
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_TRUNCATE(SDNode *N) {
+ SDOperand Res;
+
+ switch (getTypeAction(N->getOperand(0).getValueType())) {
+ default: assert(0 && "Unknown type action!");
+ case Legal:
+ case ExpandInteger:
+ Res = N->getOperand(0);
+ break;
+ case PromoteInteger:
+ Res = GetPromotedInteger(N->getOperand(0));
+ break;
+ }
+
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() &&
+ "Truncation doesn't make sense!");
+ if (Res.getValueType() == NVT)
+ return Res;
+
+ // Truncate to NVT instead of VT
+ return DAG.getNode(ISD::TRUNCATE, NVT, Res);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_INT_EXTEND(SDNode *N) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+
+ if (getTypeAction(N->getOperand(0).getValueType()) == PromoteInteger) {
+ SDOperand Res = GetPromotedInteger(N->getOperand(0));
+ assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() &&
+ "Extension doesn't make sense!");
+
+ // If the result and operand types are the same after promotion, simplify
+ // to an in-register extension.
+ if (NVT == Res.getValueType()) {
+ // The high bits are not guaranteed to be anything. Insert an extend.
+ if (N->getOpcode() == ISD::SIGN_EXTEND)
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res,
+ DAG.getValueType(N->getOperand(0).getValueType()));
+ if (N->getOpcode() == ISD::ZERO_EXTEND)
+ return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType());
+ assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!");
+ return Res;
+ }
+ }
+
+ // Otherwise, just extend the original operand all the way to the larger type.
+ return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_FP_ROUND(SDNode *N) {
+ // NOTE: Assumes input is legal.
+ if (N->getConstantOperandVal(1) == 0)
+ return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(),
+ N->getOperand(0), DAG.getValueType(N->getValueType(0)));
+ // If the precision discard isn't needed, just return the operand unrounded.
+ return N->getOperand(0);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_FP_TO_XINT(SDNode *N) {
+ unsigned NewOpc = N->getOpcode();
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+
+ // If we're promoting a UINT to a larger size, check to see if the new node
+ // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since
+ // we can use that instead. This allows us to generate better code for
+ // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not
+ // legal, such as PowerPC.
+ if (N->getOpcode() == ISD::FP_TO_UINT) {
+ if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) &&
+ (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) ||
+ TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom))
+ NewOpc = ISD::FP_TO_SINT;
+ }
+
+ return DAG.getNode(NewOpc, NVT, N->getOperand(0));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SETCC(SDNode *N) {
+ assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0)))
+ && "SetCC type is not legal??");
+ return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)),
+ N->getOperand(0), N->getOperand(1), N->getOperand(2));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_LOAD(LoadSDNode *N) {
+ // FIXME: Add support for indexed loads.
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ ISD::LoadExtType ExtType =
+ ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType();
+ SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(),
+ N->getSrcValue(), N->getSrcValueOffset(),
+ N->getMemoryVT(), N->isVolatile(),
+ N->getAlignment());
+
+ // Legalized the chain result - switch anything that used the old chain to
+ // use the new one.
+ ReplaceValueWith(SDOperand(N, 1), Res.getValue(1));
+ return Res;
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_BUILD_PAIR(SDNode *N) {
+ // The pair element type may be legal, or may not promote to the same type as
+ // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases.
+ return DAG.getNode(ISD::ANY_EXTEND,
+ TLI.getTypeToTransformTo(N->getValueType(0)),
+ JoinIntegers(N->getOperand(0), N->getOperand(1)));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_BIT_CONVERT(SDNode *N) {
+ SDOperand InOp = N->getOperand(0);
+ MVT InVT = InOp.getValueType();
+ MVT NInVT = TLI.getTypeToTransformTo(InVT);
+ MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0));
+
+ switch (getTypeAction(InVT)) {
+ default:
+ assert(false && "Unknown type action!");
+ break;
+ case Legal:
+ break;
+ case PromoteInteger:
+ if (OutVT.getSizeInBits() == NInVT.getSizeInBits())
+ // The input promotes to the same size. Convert the promoted value.
+ return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedInteger(InOp));
+ break;
+ case PromoteFloat:
+ // Promote the integer operand by hand.
+ return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetPromotedFloat(InOp));
+ case ExpandInteger:
+ case ExpandFloat:
+ break;
+ case Scalarize:
+ // Convert the element to an integer and promote it by hand.
+ return DAG.getNode(ISD::ANY_EXTEND, OutVT,
+ BitConvertToInteger(GetScalarizedVector(InOp)));
+ case Split:
+ // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split
+ // pieces of the input into integers and reassemble in the final type.
+ SDOperand Lo, Hi;
+ GetSplitVector(N->getOperand(0), Lo, Hi);
+ Lo = BitConvertToInteger(Lo);
+ Hi = BitConvertToInteger(Hi);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ InOp = DAG.getNode(ISD::ANY_EXTEND,
+ MVT::getIntegerVT(OutVT.getSizeInBits()),
+ JoinIntegers(Lo, Hi));
+ return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
+ }
+
+ // Otherwise, lower the bit-convert to a store/load from the stack, then
+ // promote the load.
+ SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
+ return PromoteIntRes_LOAD(cast<LoadSDNode>(Op.Val));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SimpleIntBinOp(SDNode *N) {
+ // The input may have strange things in the top bits of the registers, but
+ // these operations don't care. They may have weird bits going out, but
+ // that too is okay if they are integer operations.
+ SDOperand LHS = GetPromotedInteger(N->getOperand(0));
+ SDOperand RHS = GetPromotedInteger(N->getOperand(1));
+ return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SDIV(SDNode *N) {
+ // Sign extend the input.
+ SDOperand LHS = GetPromotedInteger(N->getOperand(0));
+ SDOperand RHS = GetPromotedInteger(N->getOperand(1));
+ MVT VT = N->getValueType(0);
+ LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS,
+ DAG.getValueType(VT));
+ RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS,
+ DAG.getValueType(VT));
+
+ return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_UDIV(SDNode *N) {
+ // Zero extend the input.
+ SDOperand LHS = GetPromotedInteger(N->getOperand(0));
+ SDOperand RHS = GetPromotedInteger(N->getOperand(1));
+ MVT VT = N->getValueType(0);
+ LHS = DAG.getZeroExtendInReg(LHS, VT);
+ RHS = DAG.getZeroExtendInReg(RHS, VT);
+
+ return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SHL(SDNode *N) {
+ return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)),
+ GetPromotedInteger(N->getOperand(0)), N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SRA(SDNode *N) {
+ // The input value must be properly sign extended.
+ MVT VT = N->getValueType(0);
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+ SDOperand Res = GetPromotedInteger(N->getOperand(0));
+ Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT));
+ return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SRL(SDNode *N) {
+ // The input value must be properly zero extended.
+ MVT VT = N->getValueType(0);
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+ SDOperand Res = ZExtPromotedInteger(N->getOperand(0));
+ return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SELECT(SDNode *N) {
+ SDOperand LHS = GetPromotedInteger(N->getOperand(1));
+ SDOperand RHS = GetPromotedInteger(N->getOperand(2));
+ return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_SELECT_CC(SDNode *N) {
+ SDOperand LHS = GetPromotedInteger(N->getOperand(2));
+ SDOperand RHS = GetPromotedInteger(N->getOperand(3));
+ return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0),
+ N->getOperand(1), LHS, RHS, N->getOperand(4));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_CTLZ(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ MVT OVT = N->getValueType(0);
+ MVT NVT = Op.getValueType();
+ // Zero extend to the promoted type and do the count there.
+ Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT));
+ // Subtract off the extra leading bits in the bigger type.
+ return DAG.getNode(ISD::SUB, NVT, Op,
+ DAG.getConstant(NVT.getSizeInBits() -
+ OVT.getSizeInBits(), NVT));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_CTPOP(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ MVT OVT = N->getValueType(0);
+ MVT NVT = Op.getValueType();
+ // Zero extend to the promoted type and do the count there.
+ return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_CTTZ(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ MVT OVT = N->getValueType(0);
+ MVT NVT = Op.getValueType();
+ // The count is the same in the promoted type except if the original
+ // value was zero. This can be handled by setting the bit just off
+ // the top of the original type.
+ Op = DAG.getNode(ISD::OR, NVT, Op,
+ // FIXME: Do this using an APINT constant.
+ DAG.getConstant(1UL << OVT.getSizeInBits(), NVT));
+ return DAG.getNode(ISD::CTTZ, NVT, Op);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N) {
+ MVT OldVT = N->getValueType(0);
+ SDOperand OldVec = N->getOperand(0);
+ unsigned OldElts = OldVec.getValueType().getVectorNumElements();
+
+ if (OldElts == 1) {
+ assert(!isTypeLegal(OldVec.getValueType()) &&
+ "Legal one-element vector of a type needing promotion!");
+ // It is tempting to follow GetScalarizedVector by a call to
+ // GetPromotedInteger, but this would be wrong because the
+ // scalarized value may not yet have been processed.
+ return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT),
+ GetScalarizedVector(OldVec));
+ }
+
+ // Convert to a vector half as long with an element type of twice the width,
+ // for example <4 x i16> -> <2 x i32>.
+ assert(!(OldElts & 1) && "Odd length vectors not supported!");
+ MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
+ assert(OldVT.isSimple() && NewVT.isSimple());
+
+ SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
+ MVT::getVectorVT(NewVT, OldElts / 2),
+ OldVec);
+
+ // Extract the element at OldIdx / 2 from the new vector.
+ SDOperand OldIdx = N->getOperand(1);
+ SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx,
+ DAG.getConstant(1, TLI.getShiftAmountTy()));
+ SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx);
+
+ // Select the appropriate half of the element: Lo if OldIdx was even,
+ // Hi if it was odd.
+ SDOperand Lo = Elt;
+ SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt,
+ DAG.getConstant(OldVT.getSizeInBits(),
+ TLI.getShiftAmountTy()));
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx,
+ DAG.getConstant(1, TLI.getShiftAmountTy()));
+ return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
+}
+
+//===----------------------------------------------------------------------===//
+// Integer Operand Promotion
+//===----------------------------------------------------------------------===//
+
+/// PromoteIntegerOperand - This method is called when the specified operand of
+/// the specified node is found to need promotion. At this point, all of the
+/// result types of the node are known to be legal, but other operands of the
+/// node may need promotion or expansion as well as the specified one.
+bool DAGTypeLegalizer::PromoteIntegerOperand(SDNode *N, unsigned OpNo) {
+ DEBUG(cerr << "Promote integer operand: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Res;
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "PromoteIntegerOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to promote this operator's operand!");
+ abort();
+
+ case ISD::ANY_EXTEND: Res = PromoteIntOp_ANY_EXTEND(N); break;
+ case ISD::ZERO_EXTEND: Res = PromoteIntOp_ZERO_EXTEND(N); break;
+ case ISD::SIGN_EXTEND: Res = PromoteIntOp_SIGN_EXTEND(N); break;
+ case ISD::TRUNCATE: Res = PromoteIntOp_TRUNCATE(N); break;
+ case ISD::FP_EXTEND: Res = PromoteIntOp_FP_EXTEND(N); break;
+ case ISD::FP_ROUND: Res = PromoteIntOp_FP_ROUND(N); break;
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP: Res = PromoteIntOp_INT_TO_FP(N); break;
+ case ISD::BUILD_PAIR: Res = PromoteIntOp_BUILD_PAIR(N); break;
+
+ case ISD::SELECT: Res = PromoteIntOp_SELECT(N, OpNo); break;
+ case ISD::BRCOND: Res = PromoteIntOp_BRCOND(N, OpNo); break;
+ case ISD::BR_CC: Res = PromoteIntOp_BR_CC(N, OpNo); break;
+ case ISD::SETCC: Res = PromoteIntOp_SETCC(N, OpNo); break;
+
+ case ISD::STORE: Res = PromoteIntOp_STORE(cast<StoreSDNode>(N),
+ OpNo); break;
+
+ case ISD::BUILD_VECTOR: Res = PromoteIntOp_BUILD_VECTOR(N); break;
+ case ISD::INSERT_VECTOR_ELT:
+ Res = PromoteIntOp_INSERT_VECTOR_ELT(N, OpNo);
+ break;
+
+ case ISD::MEMBARRIER: Res = PromoteIntOp_MEMBARRIER(N); break;
+ }
+
+ // If the result is null, the sub-method took care of registering results etc.
+ if (!Res.Val) return false;
+ // If the result is N, the sub-method updated N in place.
+ if (Res.Val == N) {
+ // Mark N as new and remark N and its operands. This allows us to correctly
+ // revisit N if it needs another step of promotion and allows us to visit
+ // any new operands to N.
+ ReanalyzeNode(N);
+ return true;
+ }
+
+ assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+ "Invalid operand expansion");
+
+ ReplaceValueWith(SDOperand(N, 0), Res);
+ return false;
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_ANY_EXTEND(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_ZERO_EXTEND(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
+ return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType());
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_SIGN_EXTEND(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
+ return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(),
+ Op, DAG.getValueType(N->getOperand(0).getValueType()));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_TRUNCATE(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_FP_EXTEND(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_FP_ROUND(SDNode *N) {
+ SDOperand Op = GetPromotedInteger(N->getOperand(0));
+ return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op,
+ DAG.getIntPtrConstant(0));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_INT_TO_FP(SDNode *N) {
+ SDOperand In = GetPromotedInteger(N->getOperand(0));
+ MVT OpVT = N->getOperand(0).getValueType();
+ if (N->getOpcode() == ISD::UINT_TO_FP)
+ In = DAG.getZeroExtendInReg(In, OpVT);
+ else
+ In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(),
+ In, DAG.getValueType(OpVT));
+
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), In);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_BUILD_PAIR(SDNode *N) {
+ // Since the result type is legal, the operands must promote to it.
+ MVT OVT = N->getOperand(0).getValueType();
+ SDOperand Lo = GetPromotedInteger(N->getOperand(0));
+ SDOperand Hi = GetPromotedInteger(N->getOperand(1));
+ assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?");
+
+ Lo = DAG.getZeroExtendInReg(Lo, OVT);
+ Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi,
+ DAG.getConstant(OVT.getSizeInBits(),
+ TLI.getShiftAmountTy()));
+ return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_SELECT(SDNode *N, unsigned OpNo) {
+ assert(OpNo == 0 && "Only know how to promote condition");
+ SDOperand Cond = GetPromotedInteger(N->getOperand(0)); // Promote condition.
+
+ // The top bits of the promoted condition are not necessarily zero, ensure
+ // that the value is properly zero extended.
+ unsigned BitWidth = Cond.getValueSizeInBits();
+ if (!DAG.MaskedValueIsZero(Cond,
+ APInt::getHighBitsSet(BitWidth, BitWidth-1)))
+ Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
+
+ // The chain (Op#0) and basic block destination (Op#2) are always legal types.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1),
+ N->getOperand(2));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo) {
+ assert(OpNo == 1 && "only know how to promote condition");
+ SDOperand Cond = GetPromotedInteger(N->getOperand(1)); // Promote condition.
+
+ // The top bits of the promoted condition are not necessarily zero, ensure
+ // that the value is properly zero extended.
+ unsigned BitWidth = Cond.getValueSizeInBits();
+ if (!DAG.MaskedValueIsZero(Cond,
+ APInt::getHighBitsSet(BitWidth, BitWidth-1)))
+ Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
+
+ // The chain (Op#0) and basic block destination (Op#2) are always legal types.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond,
+ N->getOperand(2));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo) {
+ assert(OpNo == 2 && "Don't know how to promote this operand");
+
+ SDOperand LHS = N->getOperand(2);
+ SDOperand RHS = N->getOperand(3);
+ PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(1))->get());
+
+ // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always
+ // legal types.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+ N->getOperand(1), LHS, RHS, N->getOperand(4));
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_SETCC(SDNode *N, unsigned OpNo) {
+ assert(OpNo == 0 && "Don't know how to promote this operand");
+
+ SDOperand LHS = N->getOperand(0);
+ SDOperand RHS = N->getOperand(1);
+ PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(2))->get());
+
+ // The CC (#2) is always legal.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2));
+}
+
+/// PromoteSetCCOperands - Promote the operands of a comparison. This code is
+/// shared among BR_CC, SELECT_CC, and SETCC handlers.
+void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
+ ISD::CondCode CCCode) {
+ MVT VT = NewLHS.getValueType();
+
+ // Get the promoted values.
+ NewLHS = GetPromotedInteger(NewLHS);
+ NewRHS = GetPromotedInteger(NewRHS);
+
+ // If this is an FP compare, the operands have already been extended.
+ if (!NewLHS.getValueType().isInteger())
+ return;
+
+ // Otherwise, we have to insert explicit sign or zero extends. Note
+ // that we could insert sign extends for ALL conditions, but zero extend
+ // is cheaper on many machines (an AND instead of two shifts), so prefer
+ // it.
+ switch (CCCode) {
+ default: assert(0 && "Unknown integer comparison!");
+ case ISD::SETEQ:
+ case ISD::SETNE:
+ case ISD::SETUGE:
+ case ISD::SETUGT:
+ case ISD::SETULE:
+ case ISD::SETULT:
+ // ALL of these operations will work if we either sign or zero extend
+ // the operands (including the unsigned comparisons!). Zero extend is
+ // usually a simpler/cheaper operation, so prefer it.
+ NewLHS = DAG.getZeroExtendInReg(NewLHS, VT);
+ NewRHS = DAG.getZeroExtendInReg(NewRHS, VT);
+ return;
+ case ISD::SETGE:
+ case ISD::SETGT:
+ case ISD::SETLT:
+ case ISD::SETLE:
+ NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS,
+ DAG.getValueType(VT));
+ NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS,
+ DAG.getValueType(VT));
+ return;
+ }
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo){
+ // FIXME: Add support for indexed stores.
+ SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
+ int SVOffset = N->getSrcValueOffset();
+ unsigned Alignment = N->getAlignment();
+ bool isVolatile = N->isVolatile();
+
+ SDOperand Val = GetPromotedInteger(N->getValue()); // Get promoted value.
+
+ assert(!N->isTruncatingStore() && "Cannot promote this store operand!");
+
+ // Truncate the value and store the result.
+ return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(),
+ SVOffset, N->getMemoryVT(),
+ isVolatile, Alignment);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_BUILD_VECTOR(SDNode *N) {
+ // The vector type is legal but the element type is not. This implies
+ // that the vector is a power-of-two in length and that the element
+ // type does not have a strange size (eg: it is not i1).
+ MVT VecVT = N->getValueType(0);
+ unsigned NumElts = VecVT.getVectorNumElements();
+ assert(!(NumElts & 1) && "Legal vector of one illegal element?");
+
+ // Build a vector of half the length out of elements of twice the bitwidth.
+ // For example <4 x i16> -> <2 x i32>.
+ MVT OldVT = N->getOperand(0).getValueType();
+ MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
+ assert(OldVT.isSimple() && NewVT.isSimple());
+
+ std::vector<SDOperand> NewElts;
+ NewElts.reserve(NumElts/2);
+
+ for (unsigned i = 0; i < NumElts; i += 2) {
+ // Combine two successive elements into one promoted element.
+ SDOperand Lo = N->getOperand(i);
+ SDOperand Hi = N->getOperand(i+1);
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ NewElts.push_back(JoinIntegers(Lo, Hi));
+ }
+
+ SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
+ MVT::getVectorVT(NewVT, NewElts.size()),
+ &NewElts[0], NewElts.size());
+
+ // Convert the new vector to the old vector type.
+ return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N,
+ unsigned OpNo) {
+ if (OpNo == 1) {
+ // Promote the inserted value. This is valid because the type does not
+ // have to match the vector element type.
+
+ // Check that any extra bits introduced will be truncated away.
+ assert(N->getOperand(1).getValueType().getSizeInBits() >=
+ N->getValueType(0).getVectorElementType().getSizeInBits() &&
+ "Type of inserted value narrower than vector element type!");
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+ GetPromotedInteger(N->getOperand(1)),
+ N->getOperand(2));
+ }
+
+ assert(OpNo == 2 && "Different operand and result vector types?");
+
+ // Promote the index.
+ SDOperand Idx = N->getOperand(2);
+ Idx = DAG.getZeroExtendInReg(GetPromotedInteger(Idx), Idx.getValueType());
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+ N->getOperand(1), Idx);
+}
+
+SDOperand DAGTypeLegalizer::PromoteIntOp_MEMBARRIER(SDNode *N) {
+ SDOperand NewOps[6];
+ NewOps[0] = N->getOperand(0);
+ for (unsigned i = 1; i < array_lengthof(NewOps); ++i) {
+ SDOperand Flag = GetPromotedInteger(N->getOperand(i));
+ NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1);
+ }
+ return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps,
+ array_lengthof(NewOps));
+}
+
+
+//===----------------------------------------------------------------------===//
+// Integer Result Expansion
+//===----------------------------------------------------------------------===//
+
+/// ExpandIntegerResult - This method is called when the specified result of the
+/// specified node is found to need expansion. At this point, the node may also
+/// have invalid operands or may have other results that need promotion, we just
+/// know that (at least) one result needs expansion.
+void DAGTypeLegalizer::ExpandIntegerResult(SDNode *N, unsigned ResNo) {
+ DEBUG(cerr << "Expand integer result: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Lo, Hi;
+ Lo = Hi = SDOperand();
+
+ // See if the target wants to custom expand this node.
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ if (SDNode *P = TLI.ExpandOperationResult(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()) {
+ default:
+#ifndef NDEBUG
+ cerr << "ExpandIntegerResult #" << ResNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0&&"Do not know how to expand the result of this operator!");
+ abort();
+
+ case ISD::UNDEF: ExpandIntRes_UNDEF(N, Lo, Hi); break;
+ case ISD::Constant: ExpandIntRes_Constant(N, Lo, Hi); break;
+ case ISD::BUILD_PAIR: ExpandIntRes_BUILD_PAIR(N, Lo, Hi); break;
+ case ISD::MERGE_VALUES: ExpandIntRes_MERGE_VALUES(N, Lo, Hi); break;
+ case ISD::ANY_EXTEND: ExpandIntRes_ANY_EXTEND(N, Lo, Hi); break;
+ case ISD::ZERO_EXTEND: ExpandIntRes_ZERO_EXTEND(N, Lo, Hi); break;
+ case ISD::SIGN_EXTEND: ExpandIntRes_SIGN_EXTEND(N, Lo, Hi); break;
+ case ISD::AssertZext: ExpandIntRes_AssertZext(N, Lo, Hi); break;
+ case ISD::TRUNCATE: ExpandIntRes_TRUNCATE(N, Lo, Hi); break;
+ case ISD::BIT_CONVERT: ExpandIntRes_BIT_CONVERT(N, Lo, Hi); break;
+ case ISD::SIGN_EXTEND_INREG: ExpandIntRes_SIGN_EXTEND_INREG(N, Lo, Hi); break;
+ case ISD::FP_TO_SINT: ExpandIntRes_FP_TO_SINT(N, Lo, Hi); break;
+ case ISD::FP_TO_UINT: ExpandIntRes_FP_TO_UINT(N, Lo, Hi); break;
+ case ISD::LOAD: ExpandIntRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
+
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR: ExpandIntRes_Logical(N, Lo, Hi); break;
+ case ISD::BSWAP: ExpandIntRes_BSWAP(N, Lo, Hi); break;
+ case ISD::ADD:
+ case ISD::SUB: ExpandIntRes_ADDSUB(N, Lo, Hi); break;
+ case ISD::ADDC:
+ case ISD::SUBC: ExpandIntRes_ADDSUBC(N, Lo, Hi); break;
+ case ISD::ADDE:
+ case ISD::SUBE: ExpandIntRes_ADDSUBE(N, Lo, Hi); break;
+ case ISD::SELECT: ExpandIntRes_SELECT(N, Lo, Hi); break;
+ case ISD::SELECT_CC: ExpandIntRes_SELECT_CC(N, Lo, Hi); break;
+ case ISD::MUL: ExpandIntRes_MUL(N, Lo, Hi); break;
+ case ISD::SDIV: ExpandIntRes_SDIV(N, Lo, Hi); break;
+ case ISD::SREM: ExpandIntRes_SREM(N, Lo, Hi); break;
+ case ISD::UDIV: ExpandIntRes_UDIV(N, Lo, Hi); break;
+ case ISD::UREM: ExpandIntRes_UREM(N, Lo, Hi); break;
+ case ISD::SHL:
+ case ISD::SRA:
+ case ISD::SRL: ExpandIntRes_Shift(N, Lo, Hi); break;
+
+ case ISD::CTLZ: ExpandIntRes_CTLZ(N, Lo, Hi); break;
+ case ISD::CTPOP: ExpandIntRes_CTPOP(N, Lo, Hi); break;
+ case ISD::CTTZ: ExpandIntRes_CTTZ(N, Lo, Hi); break;
+
+ case ISD::EXTRACT_VECTOR_ELT:
+ ExpandIntRes_EXTRACT_VECTOR_ELT(N, Lo, Hi);
+ break;
+ }
+
+ // If Lo/Hi is null, the sub-method took care of registering results etc.
+ if (Lo.Val)
+ SetExpandedInteger(SDOperand(N, ResNo), Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_UNDEF(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ Lo = Hi = DAG.getNode(ISD::UNDEF, NVT);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_Constant(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ unsigned NBitWidth = NVT.getSizeInBits();
+ const APInt &Cst = cast<ConstantSDNode>(N)->getAPIntValue();
+ Lo = DAG.getConstant(APInt(Cst).trunc(NBitWidth), NVT);
+ Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_BUILD_PAIR(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Return the operands.
+ Lo = N->getOperand(0);
+ Hi = N->getOperand(1);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_MERGE_VALUES(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // A MERGE_VALUES node can produce any number of values. We know that the
+ // first illegal one needs to be expanded into Lo/Hi.
+ unsigned i;
+
+ // The string of legal results gets turns into the input operands, which have
+ // the same type.
+ for (i = 0; isTypeLegal(N->getValueType(i)); ++i)
+ ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
+
+ // The first illegal result must be the one that needs to be expanded.
+ GetExpandedInteger(N->getOperand(i), Lo, Hi);
+
+ // Legalize the rest of the results into the input operands whether they are
+ // legal or not.
+ unsigned e = N->getNumValues();
+ for (++i; i != e; ++i)
+ ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
+}
+
+void DAGTypeLegalizer::ExpandIntRes_ANY_EXTEND(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Op = N->getOperand(0);
+ if (Op.getValueType().bitsLE(NVT)) {
+ // The low part is any extension of the input (which degenerates to a copy).
+ Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op);
+ Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined.
+ } else {
+ // For example, extension of an i48 to an i64. The operand type necessarily
+ // promotes to the result type, so will end up being expanded too.
+ assert(getTypeAction(Op.getValueType()) == PromoteInteger &&
+ "Only know how to promote this result!");
+ SDOperand Res = GetPromotedInteger(Op);
+ assert(Res.getValueType() == N->getValueType(0) &&
+ "Operand over promoted?");
+ // Split the promoted operand. This will simplify when it is expanded.
+ SplitInteger(Res, Lo, Hi);
+ }
+}
+
+void DAGTypeLegalizer::ExpandIntRes_ZERO_EXTEND(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Op = N->getOperand(0);
+ if (Op.getValueType().bitsLE(NVT)) {
+ // The low part is zero extension of the input (which degenerates to a copy).
+ Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
+ Hi = DAG.getConstant(0, NVT); // The high part is just a zero.
+ } else {
+ // For example, extension of an i48 to an i64. The operand type necessarily
+ // promotes to the result type, so will end up being expanded too.
+ assert(getTypeAction(Op.getValueType()) == PromoteInteger &&
+ "Only know how to promote this result!");
+ SDOperand Res = GetPromotedInteger(Op);
+ assert(Res.getValueType() == N->getValueType(0) &&
+ "Operand over promoted?");
+ // Split the promoted operand. This will simplify when it is expanded.
+ SplitInteger(Res, Lo, Hi);
+ unsigned ExcessBits =
+ Op.getValueType().getSizeInBits() - NVT.getSizeInBits();
+ Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerVT(ExcessBits));
+ }
+}
+
+void DAGTypeLegalizer::ExpandIntRes_SIGN_EXTEND(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Op = N->getOperand(0);
+ if (Op.getValueType().bitsLE(NVT)) {
+ // The low part is sign extension of the input (which degenerates to a copy).
+ Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
+ // The high part is obtained by SRA'ing all but one of the bits of low part.
+ unsigned LoSize = NVT.getSizeInBits();
+ Hi = DAG.getNode(ISD::SRA, NVT, Lo,
+ DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+ } else {
+ // For example, extension of an i48 to an i64. The operand type necessarily
+ // promotes to the result type, so will end up being expanded too.
+ assert(getTypeAction(Op.getValueType()) == PromoteInteger &&
+ "Only know how to promote this result!");
+ SDOperand Res = GetPromotedInteger(Op);
+ assert(Res.getValueType() == N->getValueType(0) &&
+ "Operand over promoted?");
+ // Split the promoted operand. This will simplify when it is expanded.
+ SplitInteger(Res, Lo, Hi);
+ unsigned ExcessBits =
+ Op.getValueType().getSizeInBits() - NVT.getSizeInBits();
+ Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+ DAG.getValueType(MVT::getIntegerVT(ExcessBits)));
+ }
+}
+
+void DAGTypeLegalizer::ExpandIntRes_AssertZext(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ GetExpandedInteger(N->getOperand(0), Lo, Hi);
+ MVT NVT = Lo.getValueType();
+ MVT EVT = cast<VTSDNode>(N->getOperand(1))->getVT();
+ unsigned NVTBits = NVT.getSizeInBits();
+ unsigned EVTBits = EVT.getSizeInBits();
+
+ if (NVTBits < EVTBits) {
+ Hi = DAG.getNode(ISD::AssertZext, NVT, Hi,
+ DAG.getValueType(MVT::getIntegerVT(EVTBits - NVTBits)));
+ } else {
+ Lo = DAG.getNode(ISD::AssertZext, NVT, Lo, DAG.getValueType(EVT));
+ // The high part must be zero, make it explicit.
+ Hi = DAG.getConstant(0, NVT);
+ }
+}
+
+void DAGTypeLegalizer::ExpandIntRes_TRUNCATE(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ Lo = DAG.getNode(ISD::TRUNCATE, NVT, N->getOperand(0));
+ Hi = DAG.getNode(ISD::SRL, N->getOperand(0).getValueType(), N->getOperand(0),
+ DAG.getConstant(NVT.getSizeInBits(),
+ TLI.getShiftAmountTy()));
+ Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_BIT_CONVERT(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand InOp = N->getOperand(0);
+ MVT InVT = InOp.getValueType();
+
+ // Handle some special cases efficiently.
+ switch (getTypeAction(InVT)) {
+ default:
+ assert(false && "Unknown type action!");
+ case Legal:
+ case PromoteInteger:
+ break;
+ case PromoteFloat:
+ // Convert the integer operand instead.
+ SplitInteger(GetPromotedFloat(InOp), Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
+ return;
+ case ExpandInteger:
+ // Convert the expanded pieces of the input.
+ GetExpandedInteger(InOp, Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
+ return;
+ case ExpandFloat:
+ // Convert the expanded pieces of the input.
+ GetExpandedFloat(InOp, Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
+ return;
+ case Split:
+ // Convert the split parts of the input if it was split in two.
+ GetSplitVector(InOp, Lo, Hi);
+ if (Lo.getValueType() == Hi.getValueType()) {
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
+ return;
+ }
+ break;
+ case Scalarize:
+ // Convert the element instead.
+ SplitInteger(BitConvertToInteger(GetScalarizedVector(InOp)), Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
+ return;
+ }
+
+ // Lower the bit-convert to a store/load from the stack, then expand the load.
+ SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
+ ExpandIntRes_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
+}
+
+void DAGTypeLegalizer::
+ExpandIntRes_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+ GetExpandedInteger(N->getOperand(0), Lo, Hi);
+ MVT EVT = cast<VTSDNode>(N->getOperand(1))->getVT();
+
+ if (EVT.bitsLE(Lo.getValueType())) {
+ // sext_inreg the low part if needed.
+ Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
+ N->getOperand(1));
+
+ // The high part gets the sign extension from the lo-part. This handles
+ // things like sextinreg V:i64 from i8.
+ Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
+ DAG.getConstant(Hi.getValueType().getSizeInBits()-1,
+ TLI.getShiftAmountTy()));
+ } else {
+ // For example, extension of an i48 to an i64. Leave the low part alone,
+ // sext_inreg the high part.
+ unsigned ExcessBits =
+ EVT.getSizeInBits() - Lo.getValueType().getSizeInBits();
+ Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+ DAG.getValueType(MVT::getIntegerVT(ExcessBits)));
+ }
+}
+
+void DAGTypeLegalizer::ExpandIntRes_FP_TO_SINT(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ MVT VT = N->getValueType(0);
+ SDOperand Op = N->getOperand(0);
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i64) {
+ if (Op.getValueType() == MVT::f32)
+ LC = RTLIB::FPTOSINT_F32_I64;
+ else if (Op.getValueType() == MVT::f64)
+ LC = RTLIB::FPTOSINT_F64_I64;
+ else if (Op.getValueType() == MVT::f80)
+ LC = RTLIB::FPTOSINT_F80_I64;
+ else if (Op.getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOSINT_PPCF128_I64;
+ } else if (VT == MVT::i128) {
+ if (Op.getValueType() == MVT::f32)
+ LC = RTLIB::FPTOSINT_F32_I128;
+ else if (Op.getValueType() == MVT::f64)
+ LC = RTLIB::FPTOSINT_F64_I128;
+ else if (Op.getValueType() == MVT::f80)
+ LC = RTLIB::FPTOSINT_F80_I128;
+ else if (Op.getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOSINT_PPCF128_I128;
+ } else {
+ assert(0 && "Unexpected fp-to-sint conversion!");
+ }
+ SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_FP_TO_UINT(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ MVT VT = N->getValueType(0);
+ SDOperand Op = N->getOperand(0);
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (VT == MVT::i64) {
+ if (Op.getValueType() == MVT::f32)
+ LC = RTLIB::FPTOUINT_F32_I64;
+ else if (Op.getValueType() == MVT::f64)
+ LC = RTLIB::FPTOUINT_F64_I64;
+ else if (Op.getValueType() == MVT::f80)
+ LC = RTLIB::FPTOUINT_F80_I64;
+ else if (Op.getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOUINT_PPCF128_I64;
+ } else if (VT == MVT::i128) {
+ if (Op.getValueType() == MVT::f32)
+ LC = RTLIB::FPTOUINT_F32_I128;
+ else if (Op.getValueType() == MVT::f64)
+ LC = RTLIB::FPTOUINT_F64_I128;
+ else if (Op.getValueType() == MVT::f80)
+ LC = RTLIB::FPTOUINT_F80_I128;
+ else if (Op.getValueType() == MVT::ppcf128)
+ LC = RTLIB::FPTOUINT_PPCF128_I128;
+ } else {
+ assert(0 && "Unexpected fp-to-uint conversion!");
+ }
+ SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_LOAD(LoadSDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // FIXME: Add support for indexed loads.
+ MVT VT = N->getValueType(0);
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+ SDOperand Ch = N->getChain(); // Legalize the chain.
+ SDOperand Ptr = N->getBasePtr(); // Legalize the pointer.
+ ISD::LoadExtType ExtType = N->getExtensionType();
+ int SVOffset = N->getSrcValueOffset();
+ unsigned Alignment = N->getAlignment();
+ bool isVolatile = N->isVolatile();
+
+ assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!");
+
+ if (ExtType == ISD::NON_EXTLOAD) {
+ Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+ isVolatile, Alignment);
+ // Increment the pointer to the other half.
+ unsigned IncrementSize = NVT.getSizeInBits()/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
+ isVolatile, MinAlign(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ // Handle endianness of the load.
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ } else if (N->getMemoryVT().bitsLE(NVT)) {
+ MVT EVT = N->getMemoryVT();
+
+ Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT,
+ isVolatile, Alignment);
+
+ // Remember the chain.
+ Ch = Lo.getValue(1);
+
+ if (ExtType == ISD::SEXTLOAD) {
+ // The high part is obtained by SRA'ing all but one of the bits of the
+ // lo part.
+ unsigned LoSize = Lo.getValueType().getSizeInBits();
+ Hi = DAG.getNode(ISD::SRA, NVT, Lo,
+ DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+ } else if (ExtType == ISD::ZEXTLOAD) {
+ // The high part is just a zero.
+ Hi = DAG.getConstant(0, NVT);
+ } else {
+ assert(ExtType == ISD::EXTLOAD && "Unknown extload!");
+ // The high part is undefined.
+ Hi = DAG.getNode(ISD::UNDEF, NVT);
+ }
+ } else if (TLI.isLittleEndian()) {
+ // Little-endian - low bits are at low addresses.
+ Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+ isVolatile, Alignment);
+
+ unsigned ExcessBits =
+ N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits();
+ MVT NEVT = MVT::getIntegerVT(ExcessBits);
+
+ // Increment the pointer to the other half.
+ unsigned IncrementSize = NVT.getSizeInBits()/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize, NEVT,
+ isVolatile, MinAlign(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+ } else {
+ // Big-endian - high bits are at low addresses. Favor aligned loads at
+ // the cost of some bit-fiddling.
+ MVT EVT = N->getMemoryVT();
+ unsigned EBytes = EVT.getStoreSizeInBits()/8;
+ unsigned IncrementSize = NVT.getSizeInBits()/8;
+ unsigned ExcessBits = (EBytes - IncrementSize)*8;
+
+ // Load both the high bits and maybe some of the low bits.
+ Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
+ MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits),
+ isVolatile, Alignment);
+
+ // Increment the pointer to the other half.
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ // Load the rest of the low bits.
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize,
+ MVT::getIntegerVT(ExcessBits),
+ isVolatile, MinAlign(Alignment, IncrementSize));
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ if (ExcessBits < NVT.getSizeInBits()) {
+ // Transfer low bits from the bottom of Hi to the top of Lo.
+ Lo = DAG.getNode(ISD::OR, NVT, Lo,
+ DAG.getNode(ISD::SHL, NVT, Hi,
+ DAG.getConstant(ExcessBits,
+ TLI.getShiftAmountTy())));
+ // Move high bits to the right position in Hi.
+ Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi,
+ DAG.getConstant(NVT.getSizeInBits() - ExcessBits,
+ TLI.getShiftAmountTy()));
+ }
+ }
+
+ // Legalized the chain result - switch anything that used the old chain to
+ // use the new one.
+ ReplaceValueWith(SDOperand(N, 1), Ch);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_Logical(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ SDOperand LL, LH, RL, RH;
+ GetExpandedInteger(N->getOperand(0), LL, LH);
+ GetExpandedInteger(N->getOperand(1), RL, RH);
+ Lo = DAG.getNode(N->getOpcode(), LL.getValueType(), LL, RL);
+ Hi = DAG.getNode(N->getOpcode(), LL.getValueType(), LH, RH);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_BSWAP(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ GetExpandedInteger(N->getOperand(0), Hi, Lo); // Note swapped operands.
+ Lo = DAG.getNode(ISD::BSWAP, Lo.getValueType(), Lo);
+ Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_SELECT(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ SDOperand LL, LH, RL, RH;
+ GetExpandedInteger(N->getOperand(1), LL, LH);
+ GetExpandedInteger(N->getOperand(2), RL, RH);
+ Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL);
+ Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_SELECT_CC(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ SDOperand LL, LH, RL, RH;
+ GetExpandedInteger(N->getOperand(2), LL, LH);
+ GetExpandedInteger(N->getOperand(3), RL, RH);
+ Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0),
+ N->getOperand(1), LL, RL, N->getOperand(4));
+ Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0),
+ N->getOperand(1), LH, RH, N->getOperand(4));
+}
+
+void DAGTypeLegalizer::ExpandIntRes_ADDSUB(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Expand the subcomponents.
+ SDOperand LHSL, LHSH, RHSL, RHSH;
+ GetExpandedInteger(N->getOperand(0), LHSL, LHSH);
+ GetExpandedInteger(N->getOperand(1), RHSL, RHSH);
+ SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+ SDOperand LoOps[2] = { LHSL, RHSL };
+ SDOperand HiOps[3] = { LHSH, RHSH };
+
+ if (N->getOpcode() == ISD::ADD) {
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+ } else {
+ Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
+ }
+}
+
+void DAGTypeLegalizer::ExpandIntRes_ADDSUBC(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Expand the subcomponents.
+ SDOperand LHSL, LHSH, RHSL, RHSH;
+ GetExpandedInteger(N->getOperand(0), LHSL, LHSH);
+ GetExpandedInteger(N->getOperand(1), RHSL, RHSH);
+ SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+ SDOperand LoOps[2] = { LHSL, RHSL };
+ SDOperand HiOps[3] = { LHSH, RHSH };
+
+ if (N->getOpcode() == ISD::ADDC) {
+ Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
+ } else {
+ Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
+ }
+
+ // Legalized the flag result - switch anything that used the old flag to
+ // use the new one.
+ ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1));
+}
+
+void DAGTypeLegalizer::ExpandIntRes_ADDSUBE(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Expand the subcomponents.
+ SDOperand LHSL, LHSH, RHSL, RHSH;
+ GetExpandedInteger(N->getOperand(0), LHSL, LHSH);
+ GetExpandedInteger(N->getOperand(1), RHSL, RHSH);
+ SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
+ SDOperand LoOps[3] = { LHSL, RHSL, N->getOperand(2) };
+ SDOperand HiOps[3] = { LHSH, RHSH };
+
+ Lo = DAG.getNode(N->getOpcode(), VTList, LoOps, 3);
+ HiOps[2] = Lo.getValue(1);
+ Hi = DAG.getNode(N->getOpcode(), VTList, HiOps, 3);
+
+ // Legalized the flag result - switch anything that used the old flag to
+ // use the new one.
+ ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1));
+}
+
+void DAGTypeLegalizer::ExpandIntRes_MUL(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT VT = N->getValueType(0);
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+
+ bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
+ bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
+ bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT);
+ bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT);
+ if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
+ SDOperand LL, LH, RL, RH;
+ GetExpandedInteger(N->getOperand(0), LL, LH);
+ GetExpandedInteger(N->getOperand(1), RL, RH);
+ unsigned OuterBitSize = VT.getSizeInBits();
+ unsigned BitSize = NVT.getSizeInBits();
+ unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
+ unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
+
+ if (DAG.MaskedValueIsZero(N->getOperand(0),
+ APInt::getHighBitsSet(OuterBitSize, LHSSB)) &&
+ DAG.MaskedValueIsZero(N->getOperand(1),
+ APInt::getHighBitsSet(OuterBitSize, RHSSB))) {
+ // The inputs are both zero-extended.
+ if (HasUMUL_LOHI) {
+ // We can emit a umul_lohi.
+ Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
+ Hi = SDOperand(Lo.Val, 1);
+ return;
+ }
+ if (HasMULHU) {
+ // We can emit a mulhu+mul.
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
+ return;
+ }
+ }
+ if (LHSSB > BitSize && RHSSB > BitSize) {
+ // The input values are both sign-extended.
+ if (HasSMUL_LOHI) {
+ // We can emit a smul_lohi.
+ Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
+ Hi = SDOperand(Lo.Val, 1);
+ return;
+ }
+ if (HasMULHS) {
+ // We can emit a mulhs+mul.
+ Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
+ Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
+ return;
+ }
+ }
+ if (HasUMUL_LOHI) {
+ // Lo,Hi = umul LHS, RHS.
+ SDOperand UMulLOHI = DAG.getNode(ISD::UMUL_LOHI,
+ DAG.getVTList(NVT, NVT), LL, RL);
+ Lo = UMulLOHI;
+ Hi = UMulLOHI.getValue(1);
+ RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
+ LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
+ Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
+ return;
+ }
+ }
+
+ // If nothing else, we can make a libcall.
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SplitInteger(MakeLibCall(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/),
+ Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_SDIV(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!");
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true),
+ Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_SREM(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!");
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true),
+ Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_UDIV(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!");
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false),
+ Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_UREM(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!");
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false),
+ Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_Shift(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ MVT VT = N->getValueType(0);
+
+ // If we can emit an efficient shift operation, do so now. Check to see if
+ // the RHS is a constant.
+ if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
+ return ExpandShiftByConstant(N, CN->getValue(), Lo, Hi);
+
+ // If we can determine that the high bit of the shift is zero or one, even if
+ // the low bits are variable, emit this shift in an optimized form.
+ if (ExpandShiftWithKnownAmountBit(N, Lo, Hi))
+ return;
+
+ // If this target supports shift_PARTS, use it. First, map to the _PARTS opc.
+ unsigned PartsOpc;
+ if (N->getOpcode() == ISD::SHL) {
+ PartsOpc = ISD::SHL_PARTS;
+ } else if (N->getOpcode() == ISD::SRL) {
+ PartsOpc = ISD::SRL_PARTS;
+ } else {
+ assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
+ PartsOpc = ISD::SRA_PARTS;
+ }
+
+ // Next check to see if the target supports this SHL_PARTS operation or if it
+ // will custom expand it.
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+ TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT);
+ if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) ||
+ Action == TargetLowering::Custom) {
+ // Expand the subcomponents.
+ SDOperand LHSL, LHSH;
+ GetExpandedInteger(N->getOperand(0), LHSL, LHSH);
+
+ SDOperand Ops[] = { LHSL, LHSH, N->getOperand(1) };
+ MVT VT = LHSL.getValueType();
+ Lo = DAG.getNode(PartsOpc, DAG.getNodeValueTypes(VT, VT), 2, Ops, 3);
+ Hi = Lo.getValue(1);
+ return;
+ }
+
+ // Otherwise, emit a libcall.
+ assert(VT == MVT::i64 && "Unsupported shift!");
+
+ RTLIB::Libcall LC;
+ bool isSigned;
+ if (N->getOpcode() == ISD::SHL) {
+ LC = RTLIB::SHL_I64;
+ isSigned = false; /*sign irrelevant*/
+ } else if (N->getOpcode() == ISD::SRL) {
+ LC = RTLIB::SRL_I64;
+ isSigned = false;
+ } else {
+ assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
+ LC = RTLIB::SRA_I64;
+ isSigned = true;
+ }
+
+ SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
+ SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_CTLZ(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32)
+ GetExpandedInteger(N->getOperand(0), Lo, Hi);
+ MVT NVT = Lo.getValueType();
+
+ SDOperand HiNotZero = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
+ DAG.getConstant(0, NVT), ISD::SETNE);
+
+ SDOperand LoLZ = DAG.getNode(ISD::CTLZ, NVT, Lo);
+ SDOperand HiLZ = DAG.getNode(ISD::CTLZ, NVT, Hi);
+
+ Lo = DAG.getNode(ISD::SELECT, NVT, HiNotZero, HiLZ,
+ DAG.getNode(ISD::ADD, NVT, LoLZ,
+ DAG.getConstant(NVT.getSizeInBits(), NVT)));
+ Hi = DAG.getConstant(0, NVT);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_CTPOP(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo)
+ GetExpandedInteger(N->getOperand(0), Lo, Hi);
+ MVT NVT = Lo.getValueType();
+ Lo = DAG.getNode(ISD::ADD, NVT, DAG.getNode(ISD::CTPOP, NVT, Lo),
+ DAG.getNode(ISD::CTPOP, NVT, Hi));
+ Hi = DAG.getConstant(0, NVT);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_CTTZ(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32)
+ GetExpandedInteger(N->getOperand(0), Lo, Hi);
+ MVT NVT = Lo.getValueType();
+
+ SDOperand LoNotZero = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo,
+ DAG.getConstant(0, NVT), ISD::SETNE);
+
+ SDOperand LoLZ = DAG.getNode(ISD::CTTZ, NVT, Lo);
+ SDOperand HiLZ = DAG.getNode(ISD::CTTZ, NVT, Hi);
+
+ Lo = DAG.getNode(ISD::SELECT, NVT, LoNotZero, LoLZ,
+ DAG.getNode(ISD::ADD, NVT, HiLZ,
+ DAG.getConstant(NVT.getSizeInBits(), NVT)));
+ Hi = DAG.getConstant(0, NVT);
+}
+
+void DAGTypeLegalizer::ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N,
+ SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand OldVec = N->getOperand(0);
+ unsigned OldElts = OldVec.getValueType().getVectorNumElements();
+
+ // Convert to a vector of the expanded element type, for example
+ // <2 x i64> -> <4 x i32>.
+ MVT OldVT = N->getValueType(0);
+ MVT NewVT = TLI.getTypeToTransformTo(OldVT);
+ assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() &&
+ "Do not know how to handle this expansion!");
+
+ SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
+ MVT::getVectorVT(NewVT, 2*OldElts),
+ OldVec);
+
+ // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector.
+ SDOperand Idx = N->getOperand(1);
+
+ // Make sure the type of Idx is big enough to hold the new values.
+ if (Idx.getValueType().bitsLT(TLI.getPointerTy()))
+ Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
+
+ Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx);
+ Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
+
+ Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx,
+ DAG.getConstant(1, Idx.getValueType()));
+ Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+}
+
+/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded,
+/// and the shift amount is a constant 'Amt'. Expand the operation.
+void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Expand the incoming operand to be shifted, so that we have its parts
+ SDOperand InL, InH;
+ GetExpandedInteger(N->getOperand(0), InL, InH);
+
+ MVT NVT = InL.getValueType();
+ unsigned VTBits = N->getValueType(0).getSizeInBits();
+ unsigned NVTBits = NVT.getSizeInBits();
+ MVT ShTy = N->getOperand(1).getValueType();
+
+ if (N->getOpcode() == ISD::SHL) {
+ if (Amt > VTBits) {
+ Lo = Hi = DAG.getConstant(0, NVT);
+ } else if (Amt > NVTBits) {
+ Lo = DAG.getConstant(0, NVT);
+ Hi = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt-NVTBits,ShTy));
+ } else if (Amt == NVTBits) {
+ Lo = DAG.getConstant(0, NVT);
+ Hi = InL;
+ } else {
+ Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy));
+ Hi = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SHL, NVT, InH,
+ DAG.getConstant(Amt, ShTy)),
+ DAG.getNode(ISD::SRL, NVT, InL,
+ DAG.getConstant(NVTBits-Amt, ShTy)));
+ }
+ return;
+ }
+
+ if (N->getOpcode() == ISD::SRL) {
+ if (Amt > VTBits) {
+ Lo = DAG.getConstant(0, NVT);
+ Hi = DAG.getConstant(0, NVT);
+ } else if (Amt > NVTBits) {
+ Lo = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt-NVTBits,ShTy));
+ Hi = DAG.getConstant(0, NVT);
+ } else if (Amt == NVTBits) {
+ Lo = InH;
+ Hi = DAG.getConstant(0, NVT);
+ } else {
+ Lo = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SRL, NVT, InL,
+ DAG.getConstant(Amt, ShTy)),
+ DAG.getNode(ISD::SHL, NVT, InH,
+ DAG.getConstant(NVTBits-Amt, ShTy)));
+ Hi = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt, ShTy));
+ }
+ return;
+ }
+
+ assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
+ if (Amt > VTBits) {
+ Hi = Lo = DAG.getNode(ISD::SRA, NVT, InH,
+ DAG.getConstant(NVTBits-1, ShTy));
+ } else if (Amt > NVTBits) {
+ Lo = DAG.getNode(ISD::SRA, NVT, InH,
+ DAG.getConstant(Amt-NVTBits, ShTy));
+ Hi = DAG.getNode(ISD::SRA, NVT, InH,
+ DAG.getConstant(NVTBits-1, ShTy));
+ } else if (Amt == NVTBits) {
+ Lo = InH;
+ Hi = DAG.getNode(ISD::SRA, NVT, InH,
+ DAG.getConstant(NVTBits-1, ShTy));
+ } else {
+ Lo = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(ISD::SRL, NVT, InL,
+ DAG.getConstant(Amt, ShTy)),
+ DAG.getNode(ISD::SHL, NVT, InH,
+ DAG.getConstant(NVTBits-Amt, ShTy)));
+ Hi = DAG.getNode(ISD::SRA, NVT, InH, DAG.getConstant(Amt, ShTy));
+ }
+}
+
+/// ExpandShiftWithKnownAmountBit - Try to determine whether we can simplify
+/// this shift based on knowledge of the high bit of the shift amount. If we
+/// can tell this, we know that it is >= 32 or < 32, without knowing the actual
+/// shift amount.
+bool DAGTypeLegalizer::
+ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+ SDOperand Amt = N->getOperand(1);
+ MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ MVT ShTy = Amt.getValueType();
+ unsigned ShBits = ShTy.getSizeInBits();
+ unsigned NVTBits = NVT.getSizeInBits();
+ assert(isPowerOf2_32(NVTBits) &&
+ "Expanded integer type size not a power of two!");
+
+ APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits));
+ APInt KnownZero, KnownOne;
+ DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne);
+
+ // If we don't know anything about the high bits, exit.
+ if (((KnownZero|KnownOne) & HighBitMask) == 0)
+ return false;
+
+ // Get the incoming operand to be shifted.
+ SDOperand InL, InH;
+ GetExpandedInteger(N->getOperand(0), InL, InH);
+
+ // If we know that any of the high bits of the shift amount are one, then we
+ // can do this as a couple of simple shifts.
+ if (KnownOne.intersects(HighBitMask)) {
+ // Mask out the high bit, which we know is set.
+ Amt = DAG.getNode(ISD::AND, ShTy, Amt,
+ DAG.getConstant(~HighBitMask, ShTy));
+
+ switch (N->getOpcode()) {
+ default: assert(0 && "Unknown shift");
+ case ISD::SHL:
+ Lo = DAG.getConstant(0, NVT); // Low part is zero.
+ Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part.
+ return true;
+ case ISD::SRL:
+ Hi = DAG.getConstant(0, NVT); // Hi part is zero.
+ Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part.
+ return true;
+ case ISD::SRA:
+ Hi = DAG.getNode(ISD::SRA, NVT, InH, // Sign extend high part.
+ DAG.getConstant(NVTBits-1, ShTy));
+ Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part.
+ return true;
+ }
+ }
+
+ // If we know that all of the high bits of the shift amount are zero, then we
+ // can do this as a couple of simple shifts.
+ if ((KnownZero & HighBitMask) == HighBitMask) {
+ // Compute 32-amt.
+ SDOperand Amt2 = DAG.getNode(ISD::SUB, ShTy,
+ DAG.getConstant(NVTBits, ShTy),
+ Amt);
+ unsigned Op1, Op2;
+ switch (N->getOpcode()) {
+ default: assert(0 && "Unknown shift");
+ case ISD::SHL: Op1 = ISD::SHL; Op2 = ISD::SRL; break;
+ case ISD::SRL:
+ case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break;
+ }
+
+ Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt);
+ Hi = DAG.getNode(ISD::OR, NVT,
+ DAG.getNode(Op1, NVT, InH, Amt),
+ DAG.getNode(Op2, NVT, InL, Amt2));
+ return true;
+ }
+
+ return false;
+}
+
+
+//===----------------------------------------------------------------------===//
+// Integer Operand Expansion
+//===----------------------------------------------------------------------===//
+
+/// ExpandIntegerOperand - This method is called when the specified operand of
+/// the specified node is found to need expansion. At this point, all of the
+/// result types of the node are known to be legal, but other operands of the
+/// node may need promotion or expansion as well as the specified one.
+bool DAGTypeLegalizer::ExpandIntegerOperand(SDNode *N, unsigned OpNo) {
+ DEBUG(cerr << "Expand integer operand: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Res(0, 0);
+
+ if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
+ == TargetLowering::Custom)
+ Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+
+ if (Res.Val == 0) {
+ switch (N->getOpcode()) {
+ default:
+ #ifndef NDEBUG
+ cerr << "ExpandIntegerOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+ #endif
+ assert(0 && "Do not know how to expand this operator's operand!");
+ abort();
+
+ case ISD::TRUNCATE: Res = ExpandIntOp_TRUNCATE(N); break;
+ case ISD::BIT_CONVERT: Res = ExpandIntOp_BIT_CONVERT(N); break;
+
+ case ISD::SINT_TO_FP:
+ Res = ExpandIntOp_SINT_TO_FP(N->getOperand(0), N->getValueType(0));
+ break;
+ case ISD::UINT_TO_FP:
+ Res = ExpandIntOp_UINT_TO_FP(N->getOperand(0), N->getValueType(0));
+ break;
+ case ISD::EXTRACT_ELEMENT: Res = ExpandIntOp_EXTRACT_ELEMENT(N); break;
+
+ case ISD::BR_CC: Res = ExpandIntOp_BR_CC(N); break;
+ case ISD::SETCC: Res = ExpandIntOp_SETCC(N); break;
+
+ case ISD::STORE:
+ Res = ExpandIntOp_STORE(cast<StoreSDNode>(N), OpNo);
+ break;
+
+ case ISD::BUILD_VECTOR: Res = ExpandIntOp_BUILD_VECTOR(N); break;
+ }
+ }
+
+ // If the result is null, the sub-method took care of registering results etc.
+ if (!Res.Val) return false;
+ // If the result is N, the sub-method updated N in place. Check to see if any
+ // operands are new, and if so, mark them.
+ if (Res.Val == N) {
+ // Mark N as new and remark N and its operands. This allows us to correctly
+ // revisit N if it needs another step of expansion and allows us to visit
+ // any new operands to N.
+ ReanalyzeNode(N);
+ return true;
+ }
+
+ assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+ "Invalid operand expansion");
+
+ ReplaceValueWith(SDOperand(N, 0), Res);
+ return false;
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_TRUNCATE(SDNode *N) {
+ SDOperand InL, InH;
+ GetExpandedInteger(N->getOperand(0), InL, InH);
+ // Just truncate the low part of the source.
+ return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_BIT_CONVERT(SDNode *N) {
+ if (N->getValueType(0).isVector()) {
+ // An illegal integer type is being converted to a legal vector type.
+ // Make a two element vector out of the expanded parts and convert that
+ // instead, but only if the new vector type is legal (otherwise there
+ // is no point, and it might create expansion loops). For example, on
+ // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32.
+ MVT OVT = N->getOperand(0).getValueType();
+ MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2);
+
+ if (isTypeLegal(NVT)) {
+ SDOperand Parts[2];
+ GetExpandedInteger(N->getOperand(0), Parts[0], Parts[1]);
+
+ if (TLI.isBigEndian())
+ std::swap(Parts[0], Parts[1]);
+
+ SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2);
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec);
+ }
+ }
+
+ // Otherwise, store to a temporary and load out again as the new type.
+ return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_SINT_TO_FP(SDOperand Source,
+ MVT DestTy) {
+ // We know the destination is legal, but that the input needs to be expanded.
+ MVT SourceVT = Source.getValueType();
+
+ // Check to see if the target has a custom way to lower this. If so, use it.
+ switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) {
+ 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 NV;
+ break; // The target lowered this.
+ }
+
+ RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
+ if (SourceVT == MVT::i64) {
+ if (DestTy == MVT::f32)
+ LC = RTLIB::SINTTOFP_I64_F32;
+ else {
+ assert(DestTy == MVT::f64 && "Unknown fp value type!");
+ LC = RTLIB::SINTTOFP_I64_F64;
+ }
+ } else if (SourceVT == MVT::i128) {
+ if (DestTy == MVT::f32)
+ LC = RTLIB::SINTTOFP_I128_F32;
+ else if (DestTy == MVT::f64)
+ LC = RTLIB::SINTTOFP_I128_F64;
+ else if (DestTy == MVT::f80)
+ LC = RTLIB::SINTTOFP_I128_F80;
+ else {
+ assert(DestTy == MVT::ppcf128 && "Unknown fp value type!");
+ LC = RTLIB::SINTTOFP_I128_PPCF128;
+ }
+ } else {
+ assert(0 && "Unknown int value type!");
+ }
+
+ assert(LC != RTLIB::UNKNOWN_LIBCALL &&
+ "Don't know how to expand this SINT_TO_FP!");
+ return MakeLibCall(LC, DestTy, &Source, 1, true);
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_UINT_TO_FP(SDOperand Source,
+ MVT DestTy) {
+ // We know the destination is legal, but that the input needs to be expanded.
+ assert(getTypeAction(Source.getValueType()) == ExpandInteger &&
+ "This is not an expansion!");
+
+ // 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 = ExpandIntOp_SINT_TO_FP(Source, DestTy);
+
+ // 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;
+ GetExpandedInteger(Source, Lo, Hi);
+
+ SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
+ DAG.getConstant(0, Hi.getValueType()),
+ ISD::SETLT);
+ SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
+ SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
+ SignSet, Four, Zero);
+ uint64_t FF = 0x5f800000ULL;
+ if (TLI.isLittleEndian()) FF <<= 32;
+ Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, 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, NULL, 0);
+ else if (DestTy.bitsGT(MVT::f32))
+ // FIXME: Avoid the extend by construction the right constantpool?
+ FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
+ CPIdx, NULL, 0, MVT::f32);
+ else
+ assert(0 && "Unexpected conversion");
+
+ return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_EXTRACT_ELEMENT(SDNode *N) {
+ SDOperand Lo, Hi;
+ GetExpandedInteger(N->getOperand(0), Lo, Hi);
+ return cast<ConstantSDNode>(N->getOperand(1))->getValue() ? Hi : Lo;
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_BR_CC(SDNode *N) {
+ SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
+ ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
+ ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+
+ // If ExpandSetCCOperands returned a scalar, we need to compare the result
+ // against zero to select between true and false values.
+ if (NewRHS.Val == 0) {
+ NewRHS = DAG.getConstant(0, NewLHS.getValueType());
+ CCCode = ISD::SETNE;
+ }
+
+ // Update N to have the operands specified.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
+ DAG.getCondCode(CCCode), NewLHS, NewRHS,
+ N->getOperand(4));
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_SETCC(SDNode *N) {
+ SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
+ ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
+ ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
+
+ // If ExpandSetCCOperands returned a scalar, use it.
+ if (NewRHS.Val == 0) return NewLHS;
+
+ // Otherwise, update N to have the operands specified.
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS,
+ DAG.getCondCode(CCCode));
+}
+
+/// ExpandSetCCOperands - Expand the operands of a comparison. This code is
+/// shared among BR_CC, SELECT_CC, and SETCC handlers.
+void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
+ ISD::CondCode &CCCode) {
+ SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
+ GetExpandedInteger(NewLHS, LHSLo, LHSHi);
+ GetExpandedInteger(NewRHS, RHSLo, RHSHi);
+
+ MVT VT = NewLHS.getValueType();
+ if (VT == MVT::ppcf128) {
+ // FIXME: This generated code sucks. We want to generate
+ // FCMP crN, hi1, hi2
+ // BNE crN, L:
+ // FCMP crN, lo1, lo2
+ // The following can be improved, but not that much.
+ SDOperand Tmp1, Tmp2, Tmp3;
+ Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ);
+ Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode);
+ Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
+ Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE);
+ Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode);
+ Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
+ NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3);
+ NewRHS = SDOperand(); // LHS is the result, not a compare.
+ return;
+ }
+
+ if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) {
+ if (RHSLo == RHSHi)
+ if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo))
+ if (RHSCST->isAllOnesValue()) {
+ // Equality comparison to -1.
+ NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi);
+ NewRHS = RHSLo;
+ return;
+ }
+
+ NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo);
+ NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi);
+ NewLHS = DAG.getNode(ISD::OR, NewLHS.getValueType(), NewLHS, NewRHS);
+ NewRHS = DAG.getConstant(0, NewLHS.getValueType());
+ return;
+ }
+
+ // If this is a comparison of the sign bit, just look at the top part.
+ // X > -1, x < 0
+ if (ConstantSDNode *CST = dyn_cast<ConstantSDNode>(NewRHS))
+ if ((CCCode == ISD::SETLT && CST->isNullValue()) || // X < 0
+ (CCCode == ISD::SETGT && CST->isAllOnesValue())) { // X > -1
+ NewLHS = LHSHi;
+ NewRHS = RHSHi;
+ return;
+ }
+
+ // FIXME: This generated code sucks.
+ ISD::CondCode LowCC;
+ switch (CCCode) {
+ default: assert(0 && "Unknown integer setcc!");
+ case ISD::SETLT:
+ case ISD::SETULT: LowCC = ISD::SETULT; break;
+ case ISD::SETGT:
+ case ISD::SETUGT: LowCC = ISD::SETUGT; break;
+ case ISD::SETLE:
+ case ISD::SETULE: LowCC = ISD::SETULE; break;
+ case ISD::SETGE:
+ case ISD::SETUGE: LowCC = ISD::SETUGE; break;
+ }
+
+ // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison
+ // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands
+ // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2;
+
+ // NOTE: on targets without efficient SELECT of bools, we can always use
+ // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3)
+ TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, NULL);
+ SDOperand Tmp1, Tmp2;
+ Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC,
+ false, DagCombineInfo);
+ if (!Tmp1.Val)
+ Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC);
+ Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
+ CCCode, false, DagCombineInfo);
+ if (!Tmp2.Val)
+ Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
+ DAG.getCondCode(CCCode));
+
+ ConstantSDNode *Tmp1C = dyn_cast<ConstantSDNode>(Tmp1.Val);
+ ConstantSDNode *Tmp2C = dyn_cast<ConstantSDNode>(Tmp2.Val);
+ if ((Tmp1C && Tmp1C->isNullValue()) ||
+ (Tmp2C && Tmp2C->isNullValue() &&
+ (CCCode == ISD::SETLE || CCCode == ISD::SETGE ||
+ CCCode == ISD::SETUGE || CCCode == ISD::SETULE)) ||
+ (Tmp2C && Tmp2C->getAPIntValue() == 1 &&
+ (CCCode == ISD::SETLT || CCCode == ISD::SETGT ||
+ CCCode == ISD::SETUGT || CCCode == ISD::SETULT))) {
+ // low part is known false, returns high part.
+ // For LE / GE, if high part is known false, ignore the low part.
+ // For LT / GT, if high part is known true, ignore the low part.
+ NewLHS = Tmp2;
+ NewRHS = SDOperand();
+ return;
+ }
+
+ NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
+ ISD::SETEQ, false, DagCombineInfo);
+ if (!NewLHS.Val)
+ NewLHS = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
+ ISD::SETEQ);
+ NewLHS = DAG.getNode(ISD::SELECT, Tmp1.getValueType(),
+ NewLHS, Tmp1, Tmp2);
+ NewRHS = SDOperand();
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo) {
+ // FIXME: Add support for indexed stores.
+ assert(OpNo == 1 && "Can only expand the stored value so far");
+
+ MVT VT = N->getOperand(1).getValueType();
+ MVT NVT = TLI.getTypeToTransformTo(VT);
+ SDOperand Ch = N->getChain();
+ SDOperand Ptr = N->getBasePtr();
+ int SVOffset = N->getSrcValueOffset();
+ unsigned Alignment = N->getAlignment();
+ bool isVolatile = N->isVolatile();
+ SDOperand Lo, Hi;
+
+ assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!");
+
+ if (!N->isTruncatingStore()) {
+ unsigned IncrementSize = 0;
+ GetExpandedInteger(N->getValue(), Lo, Hi);
+ IncrementSize = Hi.getValueType().getSizeInBits()/8;
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
+ Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
+ isVolatile, MinAlign(Alignment, IncrementSize));
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
+ } else if (N->getMemoryVT().bitsLE(NVT)) {
+ GetExpandedInteger(N->getValue(), Lo, Hi);
+ return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
+ N->getMemoryVT(), isVolatile, Alignment);
+ } else if (TLI.isLittleEndian()) {
+ // Little-endian - low bits are at low addresses.
+ GetExpandedInteger(N->getValue(), Lo, Hi);
+
+ Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
+ isVolatile, Alignment);
+
+ unsigned ExcessBits =
+ N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits();
+ MVT NEVT = MVT::getIntegerVT(ExcessBits);
+
+ // Increment the pointer to the other half.
+ unsigned IncrementSize = NVT.getSizeInBits()/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize, NEVT,
+ isVolatile, MinAlign(Alignment, IncrementSize));
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
+ } else {
+ // Big-endian - high bits are at low addresses. Favor aligned stores at
+ // the cost of some bit-fiddling.
+ GetExpandedInteger(N->getValue(), Lo, Hi);
+
+ MVT EVT = N->getMemoryVT();
+ unsigned EBytes = EVT.getStoreSizeInBits()/8;
+ unsigned IncrementSize = NVT.getSizeInBits()/8;
+ unsigned ExcessBits = (EBytes - IncrementSize)*8;
+ MVT HiVT = MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits);
+
+ if (ExcessBits < NVT.getSizeInBits()) {
+ // Transfer high bits from the top of Lo to the bottom of Hi.
+ Hi = DAG.getNode(ISD::SHL, NVT, Hi,
+ DAG.getConstant(NVT.getSizeInBits() - ExcessBits,
+ TLI.getShiftAmountTy()));
+ Hi = DAG.getNode(ISD::OR, NVT, Hi,
+ DAG.getNode(ISD::SRL, NVT, Lo,
+ DAG.getConstant(ExcessBits,
+ TLI.getShiftAmountTy())));
+ }
+
+ // Store both the high bits and maybe some of the low bits.
+ Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
+ SVOffset, HiVT, isVolatile, Alignment);
+
+ // Increment the pointer to the other half.
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ // Store the lowest ExcessBits bits in the second half.
+ Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize,
+ MVT::getIntegerVT(ExcessBits),
+ isVolatile, MinAlign(Alignment, IncrementSize));
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
+ }
+}
+
+SDOperand DAGTypeLegalizer::ExpandIntOp_BUILD_VECTOR(SDNode *N) {
+ // The vector type is legal but the element type needs expansion.
+ MVT VecVT = N->getValueType(0);
+ unsigned NumElts = VecVT.getVectorNumElements();
+ MVT OldVT = N->getOperand(0).getValueType();
+ MVT NewVT = TLI.getTypeToTransformTo(OldVT);
+
+ assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() &&
+ "Do not know how to expand this operand!");
+
+ // Build a vector of twice the length out of the expanded elements.
+ // For example <2 x i64> -> <4 x i32>.
+ std::vector<SDOperand> NewElts;
+ NewElts.reserve(NumElts*2);
+
+ for (unsigned i = 0; i < NumElts; ++i) {
+ SDOperand Lo, Hi;
+ GetExpandedInteger(N->getOperand(i), Lo, Hi);
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ NewElts.push_back(Lo);
+ NewElts.push_back(Hi);
+ }
+
+ SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
+ MVT::getVectorVT(NewVT, NewElts.size()),
+ &NewElts[0], NewElts.size());
+
+ // Convert the new vector to the old vector type.
+ return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
+}
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp?rev=52408&r1=52407&r2=52408&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.cpp Tue Jun 17 09:27:01 2008
@@ -42,7 +42,7 @@
// The root of the dag may dangle to deleted nodes until the type legalizer is
// done. Set it to null to avoid confusion.
DAG.setRoot(SDOperand());
-
+
// Walk all nodes in the graph, assigning them a NodeID of 'ReadyToProcess'
// (and remembering them) if they are leaves and assigning 'NewNode' if
// non-leaves.
@@ -55,14 +55,14 @@
I->setNodeId(NewNode);
}
}
-
+
// Now that we have a set of nodes to process, handle them all.
while (!Worklist.empty()) {
SDNode *N = Worklist.back();
Worklist.pop_back();
assert(N->getNodeId() == ReadyToProcess &&
"Node should be ready if on worklist!");
-
+
// Scan the values produced by the node, checking to see if any result
// types are illegal.
unsigned i = 0;
@@ -74,14 +74,17 @@
assert(false && "Unknown action!");
case Legal:
break;
- case Promote:
- PromoteResult(N, i);
+ case PromoteInteger:
+ PromoteIntegerResult(N, i);
goto NodeDone;
- case Expand:
- ExpandResult(N, i);
+ case ExpandInteger:
+ ExpandIntegerResult(N, i);
goto NodeDone;
- case FloatToInt:
- FloatToIntResult(N, i);
+ case PromoteFloat:
+ PromoteFloatResult(N, i);
+ goto NodeDone;
+ case ExpandFloat:
+ ExpandFloatResult(N, i);
goto NodeDone;
case Scalarize:
ScalarizeResult(N, i);
@@ -104,14 +107,17 @@
assert(false && "Unknown action!");
case Legal:
continue;
- case Promote:
- NeedsRevisit = PromoteOperand(N, i);
+ case PromoteInteger:
+ NeedsRevisit = PromoteIntegerOperand(N, i);
+ break;
+ case ExpandInteger:
+ NeedsRevisit = ExpandIntegerOperand(N, i);
break;
- case Expand:
- NeedsRevisit = ExpandOperand(N, i);
+ case PromoteFloat:
+ NeedsRevisit = PromoteFloatOperand(N, i);
break;
- case FloatToInt:
- NeedsRevisit = FloatToIntOperand(N, i);
+ case ExpandFloat:
+ NeedsRevisit = ExpandFloatOperand(N, i);
break;
case Scalarize:
NeedsRevisit = ScalarizeOperand(N, i);
@@ -126,7 +132,7 @@
// If the node needs revisiting, don't add all users to the worklist etc.
if (NeedsRevisit)
continue;
-
+
if (i == NumOperands)
DEBUG(cerr << "Legally typed node: "; N->dump(&DAG); cerr << "\n");
}
@@ -135,37 +141,37 @@
// If we reach here, the node was processed, potentially creating new nodes.
// Mark it as processed and add its users to the worklist as appropriate.
N->setNodeId(Processed);
-
+
for (SDNode::use_iterator UI = N->use_begin(), E = N->use_end();
UI != E; ++UI) {
SDNode *User = UI->getUser();
int NodeID = User->getNodeId();
assert(NodeID != ReadyToProcess && NodeID != Processed &&
"Invalid node id for user of unprocessed node!");
-
+
// This node has two options: it can either be a new node or its Node ID
// may be a count of the number of operands it has that are not ready.
if (NodeID > 0) {
User->setNodeId(NodeID-1);
-
+
// If this was the last use it was waiting on, add it to the ready list.
if (NodeID-1 == ReadyToProcess)
Worklist.push_back(User);
continue;
}
-
+
// Otherwise, this node is new: this is the first operand of it that
// became ready. Its new NodeID is the number of operands it has minus 1
// (as this node is now processed).
assert(NodeID == NewNode && "Unknown node ID!");
User->setNodeId(User->getNumOperands()-1);
-
+
// If the node only has a single operand, it is now ready.
if (User->getNumOperands() == 1)
Worklist.push_back(User);
}
}
-
+
// If the root changed (e.g. it was a dead load, update the root).
DAG.setRoot(Dummy.getValue());
@@ -315,8 +321,8 @@
NodeUpdateListener NUL(*this);
DAG.ReplaceAllUsesOfValueWith(From, To, &NUL);
- // The old node may still be present in a map like ExpandedNodes or
- // PromotedNodes. Inform maps about the replacement.
+ // The old node may still be present in a map like ExpandedIntegers or
+ // PromotedIntegers. Inform maps about the replacement.
NoteReplacement(From, To);
}
@@ -336,8 +342,8 @@
NodeUpdateListener NUL(*this);
DAG.ReplaceAllUsesWith(From, To, &NUL);
- // The old node may still be present in a map like ExpandedNodes or
- // PromotedNodes. Inform maps about the replacement.
+ // The old node may still be present in a map like ExpandedIntegers or
+ // PromotedIntegers. Inform maps about the replacement.
for (unsigned i = 0, e = From->getNumValues(); i != e; ++i) {
assert(From->getValueType(i) == To->getValueType(i) &&
"Node results don't match");
@@ -380,29 +386,38 @@
I->second = Replacement;
}
- for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedNodes.begin(),
- E = PromotedNodes.end(); I != E; ++I) {
+ for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedIntegers.begin(),
+ E = PromotedIntegers.end(); I != E; ++I) {
assert(I->first != N);
if (I->second == N)
I->second = Replacement;
}
- for (DenseMap<SDOperand, SDOperand>::iterator I = FloatToIntedNodes.begin(),
- E = FloatToIntedNodes.end(); I != E; ++I) {
+ for (DenseMap<SDOperand, SDOperand>::iterator I = PromotedFloats.begin(),
+ E = PromotedFloats.end(); I != E; ++I) {
assert(I->first != N);
if (I->second == N)
I->second = Replacement;
}
- for (DenseMap<SDOperand, SDOperand>::iterator I = ScalarizedNodes.begin(),
- E = ScalarizedNodes.end(); I != E; ++I) {
+ for (DenseMap<SDOperand, SDOperand>::iterator I = ScalarizedVectors.begin(),
+ E = ScalarizedVectors.end(); I != E; ++I) {
assert(I->first != N);
if (I->second == N)
I->second = Replacement;
}
for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
- I = ExpandedNodes.begin(), E = ExpandedNodes.end(); I != E; ++I) {
+ I = ExpandedIntegers.begin(), E = ExpandedIntegers.end(); I != E; ++I){
+ assert(I->first != N);
+ if (I->second.first == N)
+ I->second.first = Replacement;
+ if (I->second.second == N)
+ I->second.second = Replacement;
+ }
+
+ for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
+ I = ExpandedFloats.begin(), E = ExpandedFloats.end(); I != E; ++I) {
assert(I->first != N);
if (I->second.first == N)
I->second.first = Replacement;
@@ -411,7 +426,7 @@
}
for (DenseMap<SDOperand, std::pair<SDOperand, SDOperand> >::iterator
- I = SplitNodes.begin(), E = SplitNodes.end(); I != E; ++I) {
+ I = SplitVectors.begin(), E = SplitVectors.end(); I != E; ++I) {
assert(I->first != N);
if (I->second.first == N)
I->second.first = Replacement;
@@ -422,36 +437,62 @@
}
-void DAGTypeLegalizer::SetPromotedOp(SDOperand Op, SDOperand Result) {
+void DAGTypeLegalizer::SetPromotedInteger(SDOperand Op, SDOperand Result) {
ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
- SDOperand &OpEntry = PromotedNodes[Op];
+ SDOperand &OpEntry = PromotedIntegers[Op];
assert(OpEntry.Val == 0 && "Node is already promoted!");
OpEntry = Result;
}
-void DAGTypeLegalizer::SetIntegerOp(SDOperand Op, SDOperand Result) {
+void DAGTypeLegalizer::SetPromotedFloat(SDOperand Op, SDOperand Result) {
ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
- SDOperand &OpEntry = FloatToIntedNodes[Op];
+ SDOperand &OpEntry = PromotedFloats[Op];
assert(OpEntry.Val == 0 && "Node is already converted to integer!");
OpEntry = Result;
}
-void DAGTypeLegalizer::SetScalarizedOp(SDOperand Op, SDOperand Result) {
+void DAGTypeLegalizer::SetScalarizedVector(SDOperand Op, SDOperand Result) {
ExpungeNode(Result);
AnalyzeNewNode(Result.Val);
- SDOperand &OpEntry = ScalarizedNodes[Op];
+ SDOperand &OpEntry = ScalarizedVectors[Op];
assert(OpEntry.Val == 0 && "Node is already scalarized!");
OpEntry = Result;
}
-void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo,
- SDOperand &Hi) {
- std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
+void DAGTypeLegalizer::GetExpandedInteger(SDOperand Op, SDOperand &Lo,
+ SDOperand &Hi) {
+ std::pair<SDOperand, SDOperand> &Entry = ExpandedIntegers[Op];
+ RemapNode(Entry.first);
+ RemapNode(Entry.second);
+ assert(Entry.first.Val && "Operand isn't expanded");
+ Lo = Entry.first;
+ Hi = Entry.second;
+}
+
+void DAGTypeLegalizer::SetExpandedInteger(SDOperand Op, SDOperand Lo,
+ SDOperand Hi) {
+ ExpungeNode(Lo);
+ ExpungeNode(Hi);
+
+ // Lo/Hi may have been newly allocated, if so, add nodeid's as relevant.
+ AnalyzeNewNode(Lo.Val);
+ AnalyzeNewNode(Hi.Val);
+
+ // Remember that this is the result of the node.
+ std::pair<SDOperand, SDOperand> &Entry = ExpandedIntegers[Op];
+ assert(Entry.first.Val == 0 && "Node already expanded");
+ Entry.first = Lo;
+ Entry.second = Hi;
+}
+
+void DAGTypeLegalizer::GetExpandedFloat(SDOperand Op, SDOperand &Lo,
+ SDOperand &Hi) {
+ std::pair<SDOperand, SDOperand> &Entry = ExpandedFloats[Op];
RemapNode(Entry.first);
RemapNode(Entry.second);
assert(Entry.first.Val && "Operand isn't expanded");
@@ -459,7 +500,8 @@
Hi = Entry.second;
}
-void DAGTypeLegalizer::SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
+void DAGTypeLegalizer::SetExpandedFloat(SDOperand Op, SDOperand Lo,
+ SDOperand Hi) {
ExpungeNode(Lo);
ExpungeNode(Hi);
@@ -468,14 +510,15 @@
AnalyzeNewNode(Hi.Val);
// Remember that this is the result of the node.
- std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
+ std::pair<SDOperand, SDOperand> &Entry = ExpandedFloats[Op];
assert(Entry.first.Val == 0 && "Node already expanded");
Entry.first = Lo;
Entry.second = Hi;
}
-void DAGTypeLegalizer::GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
- std::pair<SDOperand, SDOperand> &Entry = SplitNodes[Op];
+void DAGTypeLegalizer::GetSplitVector(SDOperand Op, SDOperand &Lo,
+ SDOperand &Hi) {
+ std::pair<SDOperand, SDOperand> &Entry = SplitVectors[Op];
RemapNode(Entry.first);
RemapNode(Entry.second);
assert(Entry.first.Val && "Operand isn't split");
@@ -483,7 +526,8 @@
Hi = Entry.second;
}
-void DAGTypeLegalizer::SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi) {
+void DAGTypeLegalizer::SetSplitVector(SDOperand Op, SDOperand Lo,
+ SDOperand Hi) {
ExpungeNode(Lo);
ExpungeNode(Hi);
@@ -492,7 +536,7 @@
AnalyzeNewNode(Hi.Val);
// Remember that this is the result of the node.
- std::pair<SDOperand, SDOperand> &Entry = SplitNodes[Op];
+ std::pair<SDOperand, SDOperand> &Entry = SplitVectors[Op];
assert(Entry.first.Val == 0 && "Node already split");
Entry.first = Lo;
Entry.second = Hi;
@@ -505,11 +549,11 @@
return DAG.getNode(ISD::BIT_CONVERT, MVT::getIntegerVT(BitWidth), Op);
}
-SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op,
+SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op,
MVT DestVT) {
// Create the stack frame object.
SDOperand FIPtr = DAG.CreateStackTemporary(DestVT);
-
+
// Emit a store to the stack slot.
SDOperand Store = DAG.getStore(DAG.getEntryNode(), Op, FIPtr, NULL, 0);
// Result is a load from the stack slot.
@@ -605,6 +649,6 @@
/// the graph.
void SelectionDAG::LegalizeTypes() {
if (ViewLegalizeTypesDAGs) viewGraph();
-
+
DAGTypeLegalizer(*this).run();
}
Modified: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h?rev=52408&r1=52407&r2=52408&view=diff
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypes.h Tue Jun 17 09:27:01 2008
@@ -47,31 +47,32 @@
/// ReadyToProcess - All operands have been processed, so this node is ready
/// to be handled.
ReadyToProcess = 0,
-
+
/// NewNode - This is a new node that was created in the process of
/// legalizing some other node.
NewNode = -1,
-
+
/// Processed - This is a node that has already been processed.
Processed = -2
-
+
// 1+ - This is a node which has this many unlegalized operands.
};
private:
enum LegalizeAction {
- Legal, // The target natively supports this type.
- Promote, // This type should be executed in a larger type.
- Expand, // This type should be split into two types of half the size.
- FloatToInt, // Convert a floating point type to an integer of the same size.
- Scalarize, // Replace this one-element vector type with its element type.
- Split // This vector type should be split into smaller vectors.
+ Legal, // The target natively supports this type.
+ PromoteInteger, // Replace this integer type with a larger one.
+ ExpandInteger, // Split this integer type into two of half the size.
+ PromoteFloat, // Convert this float type to a same size integer type.
+ ExpandFloat, // Split this float type into two of half the size.
+ Scalarize, // Replace this one-element vector type with its element type.
+ Split // This vector type should be split into smaller vectors.
};
/// ValueTypeActions - This is a bitvector that contains two bits for each
/// simple value type, where the two bits correspond to the LegalizeAction
/// enum from TargetLowering. This can be queried with "getTypeAction(VT)".
TargetLowering::ValueTypeActionImpl ValueTypeActions;
-
+
/// getTypeAction - Return how we should legalize values of this type, either
/// it is already legal, or we need to promote it to a larger integer type, or
/// we need to expand it into multiple registers of a smaller integer type, or
@@ -84,16 +85,19 @@
case TargetLowering::Legal:
return Legal;
case TargetLowering::Promote:
- return Promote;
+ return PromoteInteger;
case TargetLowering::Expand:
// Expand can mean
// 1) split scalar in half, 2) convert a float to an integer,
// 3) scalarize a single-element vector, 4) split a vector in two.
if (!VT.isVector()) {
- if (VT.getSizeInBits() == TLI.getTypeToTransformTo(VT).getSizeInBits())
- return FloatToInt;
+ if (VT.isInteger())
+ return ExpandInteger;
+ else if (VT.getSizeInBits() ==
+ TLI.getTypeToTransformTo(VT).getSizeInBits())
+ return PromoteFloat;
else
- return Expand;
+ return ExpandFloat;
} else if (VT.getVectorNumElements() == 1) {
return Scalarize;
} else {
@@ -107,26 +111,30 @@
return ValueTypeActions.getTypeAction(VT) == TargetLowering::Legal;
}
- /// PromotedNodes - For nodes that are below legal width, this map indicates
- /// what promoted value to use.
- DenseMap<SDOperand, SDOperand> PromotedNodes;
-
- /// ExpandedNodes - For nodes that need to be expanded this map indicates
- /// which operands are the expanded version of the input.
- DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedNodes;
+ /// PromotedIntegers - For integer nodes that are below legal width, this map
+ /// indicates what promoted value to use.
+ DenseMap<SDOperand, SDOperand> PromotedIntegers;
+
+ /// ExpandedIntegers - For integer nodes that need to be expanded this map
+ /// indicates which operands are the expanded version of the input.
+ DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedIntegers;
- /// FloatToIntedNodes - For floating point nodes converted to integers of
+ /// PromotedFloats - For floating point nodes converted to integers of
/// the same size, this map indicates the converted value to use.
- DenseMap<SDOperand, SDOperand> FloatToIntedNodes;
+ DenseMap<SDOperand, SDOperand> PromotedFloats;
+
+ /// ExpandedFloats - For float nodes that need to be expanded this map
+ /// indicates which operands are the expanded version of the input.
+ DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > ExpandedFloats;
- /// ScalarizedNodes - For nodes that are <1 x ty>, this map indicates the
+ /// ScalarizedVectors - For nodes that are <1 x ty>, this map indicates the
/// scalar value of type 'ty' to use.
- DenseMap<SDOperand, SDOperand> ScalarizedNodes;
+ DenseMap<SDOperand, SDOperand> ScalarizedVectors;
- /// SplitNodes - For nodes that need to be split this map indicates
+ /// SplitVectors - For nodes that need to be split this map indicates
/// which operands are the expanded version of the input.
- DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > SplitNodes;
-
+ DenseMap<SDOperand, std::pair<SDOperand, SDOperand> > SplitVectors;
+
/// ReplacedNodes - For nodes that have been replaced with another,
/// indicates the replacement node to use.
DenseMap<SDOperand, SDOperand> ReplacedNodes;
@@ -135,17 +143,17 @@
/// pushed onto this worklist, all operands of a node must have already been
/// processed.
SmallVector<SDNode*, 128> Worklist;
-
+
public:
explicit DAGTypeLegalizer(SelectionDAG &dag)
: TLI(dag.getTargetLoweringInfo()), DAG(dag),
ValueTypeActions(TLI.getValueTypeActions()) {
assert(MVT::LAST_VALUETYPE <= 32 &&
"Too many value types for ValueTypeActions to hold!");
- }
-
+ }
+
void run();
-
+
/// ReanalyzeNode - Recompute the NodeID and correct processed operands
/// for the specified node, adding it to the worklist if ready.
void ReanalyzeNode(SDNode *N) {
@@ -183,174 +191,186 @@
SDOperand Index);
//===--------------------------------------------------------------------===//
- // Promotion Support: LegalizeTypesPromote.cpp
+ // Integer Promotion Support: LegalizeIntegerTypes.cpp
//===--------------------------------------------------------------------===//
-
- SDOperand GetPromotedOp(SDOperand Op) {
- SDOperand &PromotedOp = PromotedNodes[Op];
+
+ SDOperand GetPromotedInteger(SDOperand Op) {
+ SDOperand &PromotedOp = PromotedIntegers[Op];
RemapNode(PromotedOp);
assert(PromotedOp.Val && "Operand wasn't promoted?");
return PromotedOp;
}
- void SetPromotedOp(SDOperand Op, SDOperand Result);
-
- /// GetPromotedZExtOp - Get a promoted operand and zero extend it to the final
- /// size.
- SDOperand GetPromotedZExtOp(SDOperand Op) {
+ void SetPromotedInteger(SDOperand Op, SDOperand Result);
+
+ /// ZExtPromotedInteger - Get a promoted operand and zero extend it to the
+ /// final size.
+ SDOperand ZExtPromotedInteger(SDOperand Op) {
MVT OldVT = Op.getValueType();
- Op = GetPromotedOp(Op);
+ Op = GetPromotedInteger(Op);
return DAG.getZeroExtendInReg(Op, OldVT);
- }
-
- // Result Promotion.
- void PromoteResult(SDNode *N, unsigned ResNo);
- SDOperand PromoteResult_BIT_CONVERT(SDNode *N);
- SDOperand PromoteResult_BUILD_PAIR(SDNode *N);
- SDOperand PromoteResult_Constant(SDNode *N);
- SDOperand PromoteResult_CTLZ(SDNode *N);
- SDOperand PromoteResult_CTPOP(SDNode *N);
- SDOperand PromoteResult_CTTZ(SDNode *N);
- SDOperand PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N);
- SDOperand PromoteResult_FP_ROUND(SDNode *N);
- SDOperand PromoteResult_FP_TO_XINT(SDNode *N);
- SDOperand PromoteResult_INT_EXTEND(SDNode *N);
- SDOperand PromoteResult_LOAD(LoadSDNode *N);
- SDOperand PromoteResult_SDIV(SDNode *N);
- SDOperand PromoteResult_SELECT (SDNode *N);
- SDOperand PromoteResult_SELECT_CC(SDNode *N);
- SDOperand PromoteResult_SETCC(SDNode *N);
- SDOperand PromoteResult_SHL(SDNode *N);
- SDOperand PromoteResult_SimpleIntBinOp(SDNode *N);
- SDOperand PromoteResult_SRA(SDNode *N);
- SDOperand PromoteResult_SRL(SDNode *N);
- SDOperand PromoteResult_TRUNCATE(SDNode *N);
- SDOperand PromoteResult_UDIV(SDNode *N);
- SDOperand PromoteResult_UNDEF(SDNode *N);
-
- // Operand Promotion.
- bool PromoteOperand(SDNode *N, unsigned OperandNo);
- SDOperand PromoteOperand_ANY_EXTEND(SDNode *N);
- SDOperand PromoteOperand_BUILD_PAIR(SDNode *N);
- SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_BUILD_VECTOR(SDNode *N);
- SDOperand PromoteOperand_FP_EXTEND(SDNode *N);
- SDOperand PromoteOperand_FP_ROUND(SDNode *N);
- SDOperand PromoteOperand_INT_TO_FP(SDNode *N);
- SDOperand PromoteOperand_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_MEMBARRIER(SDNode *N);
- SDOperand PromoteOperand_RET(SDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_SETCC(SDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_SIGN_EXTEND(SDNode *N);
- SDOperand PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo);
- SDOperand PromoteOperand_TRUNCATE(SDNode *N);
- SDOperand PromoteOperand_ZERO_EXTEND(SDNode *N);
+ }
+
+ // Integer Result Promotion.
+ void PromoteIntegerResult(SDNode *N, unsigned ResNo);
+ SDOperand PromoteIntRes_BIT_CONVERT(SDNode *N);
+ SDOperand PromoteIntRes_BUILD_PAIR(SDNode *N);
+ SDOperand PromoteIntRes_Constant(SDNode *N);
+ SDOperand PromoteIntRes_CTLZ(SDNode *N);
+ SDOperand PromoteIntRes_CTPOP(SDNode *N);
+ SDOperand PromoteIntRes_CTTZ(SDNode *N);
+ SDOperand PromoteIntRes_EXTRACT_VECTOR_ELT(SDNode *N);
+ SDOperand PromoteIntRes_FP_ROUND(SDNode *N);
+ SDOperand PromoteIntRes_FP_TO_XINT(SDNode *N);
+ SDOperand PromoteIntRes_INT_EXTEND(SDNode *N);
+ SDOperand PromoteIntRes_LOAD(LoadSDNode *N);
+ SDOperand PromoteIntRes_SDIV(SDNode *N);
+ SDOperand PromoteIntRes_SELECT (SDNode *N);
+ SDOperand PromoteIntRes_SELECT_CC(SDNode *N);
+ SDOperand PromoteIntRes_SETCC(SDNode *N);
+ SDOperand PromoteIntRes_SHL(SDNode *N);
+ SDOperand PromoteIntRes_SimpleIntBinOp(SDNode *N);
+ SDOperand PromoteIntRes_SRA(SDNode *N);
+ SDOperand PromoteIntRes_SRL(SDNode *N);
+ SDOperand PromoteIntRes_TRUNCATE(SDNode *N);
+ SDOperand PromoteIntRes_UDIV(SDNode *N);
+ SDOperand PromoteIntRes_UNDEF(SDNode *N);
+
+ // Integer Operand Promotion.
+ bool PromoteIntegerOperand(SDNode *N, unsigned OperandNo);
+ SDOperand PromoteIntOp_ANY_EXTEND(SDNode *N);
+ SDOperand PromoteIntOp_BUILD_PAIR(SDNode *N);
+ SDOperand PromoteIntOp_BR_CC(SDNode *N, unsigned OpNo);
+ SDOperand PromoteIntOp_BRCOND(SDNode *N, unsigned OpNo);
+ SDOperand PromoteIntOp_BUILD_VECTOR(SDNode *N);
+ SDOperand PromoteIntOp_FP_EXTEND(SDNode *N);
+ SDOperand PromoteIntOp_FP_ROUND(SDNode *N);
+ SDOperand PromoteIntOp_INT_TO_FP(SDNode *N);
+ SDOperand PromoteIntOp_INSERT_VECTOR_ELT(SDNode *N, unsigned OpNo);
+ SDOperand PromoteIntOp_MEMBARRIER(SDNode *N);
+ SDOperand PromoteIntOp_SELECT(SDNode *N, unsigned OpNo);
+ SDOperand PromoteIntOp_SETCC(SDNode *N, unsigned OpNo);
+ SDOperand PromoteIntOp_SIGN_EXTEND(SDNode *N);
+ SDOperand PromoteIntOp_STORE(StoreSDNode *N, unsigned OpNo);
+ SDOperand PromoteIntOp_TRUNCATE(SDNode *N);
+ SDOperand PromoteIntOp_ZERO_EXTEND(SDNode *N);
void PromoteSetCCOperands(SDOperand &LHS,SDOperand &RHS, ISD::CondCode Code);
//===--------------------------------------------------------------------===//
- // Expansion Support: LegalizeTypesExpand.cpp
+ // Integer Expansion Support: LegalizeIntegerTypes.cpp
//===--------------------------------------------------------------------===//
-
- void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
- void SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi);
-
- // Result Expansion.
- void ExpandResult(SDNode *N, unsigned ResNo);
- void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_MERGE_VALUES(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
-
- void ExpandResult_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
- void ExpandResult_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi);
-
- void ExpandShiftByConstant(SDNode *N, unsigned Amt,
+
+ void GetExpandedInteger(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+ void SetExpandedInteger(SDOperand Op, SDOperand Lo, SDOperand Hi);
+
+ // Integer Result Expansion.
+ void ExpandIntegerResult(SDNode *N, unsigned ResNo);
+ void ExpandIntRes_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_AssertZext (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_BIT_CONVERT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_BUILD_PAIR (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_Constant (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_CTLZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_CTPOP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_CTTZ (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_EXTRACT_VECTOR_ELT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_LOAD (LoadSDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_MERGE_VALUES (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_SIGN_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_SIGN_EXTEND_INREG (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_TRUNCATE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_UNDEF (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_ZERO_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_FP_TO_SINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_FP_TO_UINT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+
+ void ExpandIntRes_Logical (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_BSWAP (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_ADDSUB (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_ADDSUBC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_ADDSUBE (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_SELECT (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_SELECT_CC (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_MUL (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_SDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_SREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_UDIV (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_UREM (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandIntRes_Shift (SDNode *N, SDOperand &Lo, SDOperand &Hi);
+
+ void ExpandShiftByConstant(SDNode *N, unsigned Amt,
SDOperand &Lo, SDOperand &Hi);
bool ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi);
- // Operand Expansion.
- bool ExpandOperand(SDNode *N, unsigned OperandNo);
- SDOperand ExpandOperand_BIT_CONVERT(SDNode *N);
- SDOperand ExpandOperand_BR_CC(SDNode *N);
- SDOperand ExpandOperand_BUILD_VECTOR(SDNode *N);
- SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N);
- SDOperand ExpandOperand_SETCC(SDNode *N);
- SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT DestTy);
- SDOperand ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo);
- SDOperand ExpandOperand_TRUNCATE(SDNode *N);
- SDOperand ExpandOperand_UINT_TO_FP(SDOperand Source, MVT DestTy);
+ // Integer Operand Expansion.
+ bool ExpandIntegerOperand(SDNode *N, unsigned OperandNo);
+ SDOperand ExpandIntOp_BIT_CONVERT(SDNode *N);
+ SDOperand ExpandIntOp_BR_CC(SDNode *N);
+ SDOperand ExpandIntOp_BUILD_VECTOR(SDNode *N);
+ SDOperand ExpandIntOp_EXTRACT_ELEMENT(SDNode *N);
+ SDOperand ExpandIntOp_SETCC(SDNode *N);
+ SDOperand ExpandIntOp_SINT_TO_FP(SDOperand Source, MVT DestTy);
+ SDOperand ExpandIntOp_STORE(StoreSDNode *N, unsigned OpNo);
+ SDOperand ExpandIntOp_TRUNCATE(SDNode *N);
+ SDOperand ExpandIntOp_UINT_TO_FP(SDOperand Source, MVT DestTy);
void ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
ISD::CondCode &CCCode);
-
+
//===--------------------------------------------------------------------===//
- // Float to Integer Conversion Support: LegalizeTypesFloatToInt.cpp
+ // Float to Integer Conversion Support: LegalizeFloatTypes.cpp
//===--------------------------------------------------------------------===//
- SDOperand GetIntegerOp(SDOperand Op) {
- SDOperand &IntegerOp = FloatToIntedNodes[Op];
- RemapNode(IntegerOp);
- assert(IntegerOp.Val && "Operand wasn't converted to integer?");
- return IntegerOp;
+ SDOperand GetPromotedFloat(SDOperand Op) {
+ SDOperand &PromotedOp = PromotedFloats[Op];
+ RemapNode(PromotedOp);
+ assert(PromotedOp.Val && "Operand wasn't converted to integer?");
+ return PromotedOp;
}
- void SetIntegerOp(SDOperand Op, SDOperand Result);
+ void SetPromotedFloat(SDOperand Op, SDOperand Result);
// Result Float to Integer Conversion.
- void FloatToIntResult(SDNode *N, unsigned OpNo);
- SDOperand FloatToIntRes_BIT_CONVERT(SDNode *N);
- SDOperand FloatToIntRes_BUILD_PAIR(SDNode *N);
- SDOperand FloatToIntRes_ConstantFP(ConstantFPSDNode *N);
- SDOperand FloatToIntRes_FADD(SDNode *N);
- SDOperand FloatToIntRes_FCOPYSIGN(SDNode *N);
- SDOperand FloatToIntRes_FMUL(SDNode *N);
- SDOperand FloatToIntRes_FSUB(SDNode *N);
- SDOperand FloatToIntRes_LOAD(SDNode *N);
- SDOperand FloatToIntRes_XINT_TO_FP(SDNode *N);
+ void PromoteFloatResult(SDNode *N, unsigned OpNo);
+ SDOperand PromoteFloatRes_BIT_CONVERT(SDNode *N);
+ SDOperand PromoteFloatRes_BUILD_PAIR(SDNode *N);
+ SDOperand PromoteFloatRes_ConstantFP(ConstantFPSDNode *N);
+ SDOperand PromoteFloatRes_FADD(SDNode *N);
+ SDOperand PromoteFloatRes_FCOPYSIGN(SDNode *N);
+ SDOperand PromoteFloatRes_FMUL(SDNode *N);
+ SDOperand PromoteFloatRes_FSUB(SDNode *N);
+ SDOperand PromoteFloatRes_LOAD(SDNode *N);
+ SDOperand PromoteFloatRes_XINT_TO_FP(SDNode *N);
// Operand Float to Integer Conversion.
- bool FloatToIntOperand(SDNode *N, unsigned OpNo);
- SDOperand FloatToIntOp_BIT_CONVERT(SDNode *N);
+ bool PromoteFloatOperand(SDNode *N, unsigned OpNo);
+ SDOperand PromoteFloatOp_BIT_CONVERT(SDNode *N);
+
+ //===--------------------------------------------------------------------===//
+ // Float Expansion Support: LegalizeFloatTypes.cpp
+ //===--------------------------------------------------------------------===//
+
+ void GetExpandedFloat(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+ void SetExpandedFloat(SDOperand Op, SDOperand Lo, SDOperand Hi);
+
+ // Float Result Expansion.
+ void ExpandFloatResult(SDNode *N, unsigned ResNo);
+
+ // Float Operand Expansion.
+ bool ExpandFloatOperand(SDNode *N, unsigned OperandNo);
//===--------------------------------------------------------------------===//
- // Scalarization Support: LegalizeTypesScalarize.cpp
+ // Scalarization Support: LegalizeVectorTypes.cpp
//===--------------------------------------------------------------------===//
-
- SDOperand GetScalarizedOp(SDOperand Op) {
- SDOperand &ScalarOp = ScalarizedNodes[Op];
- RemapNode(ScalarOp);
- assert(ScalarOp.Val && "Operand wasn't scalarized?");
- return ScalarOp;
+
+ SDOperand GetScalarizedVector(SDOperand Op) {
+ SDOperand &ScalarizedOp = ScalarizedVectors[Op];
+ RemapNode(ScalarizedOp);
+ assert(ScalarizedOp.Val && "Operand wasn't scalarized?");
+ return ScalarizedOp;
}
- void SetScalarizedOp(SDOperand Op, SDOperand Result);
-
- // Result Vector Scalarization: <1 x ty> -> ty.
+ void SetScalarizedVector(SDOperand Op, SDOperand Result);
+
+ // Vector Result Scalarization: <1 x ty> -> ty.
void ScalarizeResult(SDNode *N, unsigned OpNo);
SDOperand ScalarizeRes_BinOp(SDNode *N);
SDOperand ScalarizeRes_UnaryOp(SDNode *N);
@@ -363,20 +383,20 @@
SDOperand ScalarizeRes_UNDEF(SDNode *N);
SDOperand ScalarizeRes_VECTOR_SHUFFLE(SDNode *N);
- // Operand Vector Scalarization: <1 x ty> -> ty.
+ // Vector Operand Scalarization: <1 x ty> -> ty.
bool ScalarizeOperand(SDNode *N, unsigned OpNo);
SDOperand ScalarizeOp_BIT_CONVERT(SDNode *N);
SDOperand ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N);
SDOperand ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo);
//===--------------------------------------------------------------------===//
- // Vector Splitting Support: LegalizeTypesSplit.cpp
+ // Vector Splitting Support: LegalizeVectorTypes.cpp
//===--------------------------------------------------------------------===//
-
- void GetSplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
- void SetSplitOp(SDOperand Op, SDOperand Lo, SDOperand Hi);
-
- // Result Vector Splitting: <128 x ty> -> 2 x <64 x ty>.
+
+ void GetSplitVector(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+ void SetSplitVector(SDOperand Op, SDOperand Lo, SDOperand Hi);
+
+ // Vector Result Splitting: <128 x ty> -> 2 x <64 x ty>.
void SplitResult(SDNode *N, unsigned OpNo);
void SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi);
@@ -392,8 +412,8 @@
void SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
-
- // Operand Vector Splitting: <128 x ty> -> 2 x <64 x ty>.
+
+ // Vector Operand Splitting: <128 x ty> -> 2 x <64 x ty>.
bool SplitOperand(SDNode *N, unsigned OpNo);
SDOperand SplitOp_BIT_CONVERT(SDNode *N);
Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp?rev=52407&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesExpand.cpp (removed)
@@ -1,1465 +0,0 @@
-//===-- LegalizeTypesExpand.cpp - Expansion for LegalizeTypes -------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements expansion support for LegalizeTypes. Expansion is the
-// act of changing a computation in an invalid type to be a computation in
-// multiple registers of a smaller type. For example, implementing i64
-// arithmetic in two i32 registers (as is often needed on 32-bit targets, for
-// example).
-//
-//===----------------------------------------------------------------------===//
-
-#include "LegalizeTypes.h"
-#include "llvm/Constants.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Result Expansion
-//===----------------------------------------------------------------------===//
-
-/// ExpandResult - This method is called when the specified result of the
-/// specified node is found to need expansion. At this point, the node may also
-/// have invalid operands or may have other results that need promotion, we just
-/// know that (at least) one result needs expansion.
-void DAGTypeLegalizer::ExpandResult(SDNode *N, unsigned ResNo) {
- DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n");
- SDOperand Lo, Hi;
- Lo = Hi = SDOperand();
-
- // See if the target wants to custom expand this node.
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom) {
- // If the target wants to, allow it to lower this itself.
- if (SDNode *P = TLI.ExpandOperationResult(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()) {
- default:
-#ifndef NDEBUG
- cerr << "ExpandResult #" << ResNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to expand the result of this operator!");
- abort();
-
- case ISD::UNDEF: ExpandResult_UNDEF(N, Lo, Hi); break;
- case ISD::Constant: ExpandResult_Constant(N, Lo, Hi); break;
- case ISD::BUILD_PAIR: ExpandResult_BUILD_PAIR(N, Lo, Hi); break;
- case ISD::MERGE_VALUES: ExpandResult_MERGE_VALUES(N, Lo, Hi); break;
- case ISD::ANY_EXTEND: ExpandResult_ANY_EXTEND(N, Lo, Hi); break;
- case ISD::ZERO_EXTEND: ExpandResult_ZERO_EXTEND(N, Lo, Hi); break;
- case ISD::SIGN_EXTEND: ExpandResult_SIGN_EXTEND(N, Lo, Hi); break;
- case ISD::AssertZext: ExpandResult_AssertZext(N, Lo, Hi); break;
- case ISD::TRUNCATE: ExpandResult_TRUNCATE(N, Lo, Hi); break;
- case ISD::BIT_CONVERT: ExpandResult_BIT_CONVERT(N, Lo, Hi); break;
- case ISD::SIGN_EXTEND_INREG: ExpandResult_SIGN_EXTEND_INREG(N, Lo, Hi); break;
- case ISD::FP_TO_SINT: ExpandResult_FP_TO_SINT(N, Lo, Hi); break;
- case ISD::FP_TO_UINT: ExpandResult_FP_TO_UINT(N, Lo, Hi); break;
- case ISD::LOAD: ExpandResult_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
-
- case ISD::AND:
- case ISD::OR:
- case ISD::XOR: ExpandResult_Logical(N, Lo, Hi); break;
- case ISD::BSWAP: ExpandResult_BSWAP(N, Lo, Hi); break;
- case ISD::ADD:
- case ISD::SUB: ExpandResult_ADDSUB(N, Lo, Hi); break;
- case ISD::ADDC:
- case ISD::SUBC: ExpandResult_ADDSUBC(N, Lo, Hi); break;
- case ISD::ADDE:
- case ISD::SUBE: ExpandResult_ADDSUBE(N, Lo, Hi); break;
- case ISD::SELECT: ExpandResult_SELECT(N, Lo, Hi); break;
- case ISD::SELECT_CC: ExpandResult_SELECT_CC(N, Lo, Hi); break;
- case ISD::MUL: ExpandResult_MUL(N, Lo, Hi); break;
- case ISD::SDIV: ExpandResult_SDIV(N, Lo, Hi); break;
- case ISD::SREM: ExpandResult_SREM(N, Lo, Hi); break;
- case ISD::UDIV: ExpandResult_UDIV(N, Lo, Hi); break;
- case ISD::UREM: ExpandResult_UREM(N, Lo, Hi); break;
- case ISD::SHL:
- case ISD::SRA:
- case ISD::SRL: ExpandResult_Shift(N, Lo, Hi); break;
-
- case ISD::CTLZ: ExpandResult_CTLZ(N, Lo, Hi); break;
- case ISD::CTPOP: ExpandResult_CTPOP(N, Lo, Hi); break;
- case ISD::CTTZ: ExpandResult_CTTZ(N, Lo, Hi); break;
-
- case ISD::EXTRACT_VECTOR_ELT:
- ExpandResult_EXTRACT_VECTOR_ELT(N, Lo, Hi);
- break;
- }
-
- // If Lo/Hi is null, the sub-method took care of registering results etc.
- if (Lo.Val)
- SetExpandedOp(SDOperand(N, ResNo), Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_UNDEF(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- Lo = Hi = DAG.getNode(ISD::UNDEF, NVT);
-}
-
-void DAGTypeLegalizer::ExpandResult_Constant(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- unsigned NBitWidth = NVT.getSizeInBits();
- const APInt &Cst = cast<ConstantSDNode>(N)->getAPIntValue();
- Lo = DAG.getConstant(APInt(Cst).trunc(NBitWidth), NVT);
- Hi = DAG.getConstant(Cst.lshr(NBitWidth).trunc(NBitWidth), NVT);
-}
-
-void DAGTypeLegalizer::ExpandResult_BUILD_PAIR(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // Return the operands.
- Lo = N->getOperand(0);
- Hi = N->getOperand(1);
-}
-
-void DAGTypeLegalizer::ExpandResult_MERGE_VALUES(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // A MERGE_VALUES node can produce any number of values. We know that the
- // first illegal one needs to be expanded into Lo/Hi.
- unsigned i;
-
- // The string of legal results gets turns into the input operands, which have
- // the same type.
- for (i = 0; isTypeLegal(N->getValueType(i)); ++i)
- ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
-
- // The first illegal result must be the one that needs to be expanded.
- GetExpandedOp(N->getOperand(i), Lo, Hi);
-
- // Legalize the rest of the results into the input operands whether they are
- // legal or not.
- unsigned e = N->getNumValues();
- for (++i; i != e; ++i)
- ReplaceValueWith(SDOperand(N, i), SDOperand(N->getOperand(i)));
-}
-
-void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand Op = N->getOperand(0);
- if (Op.getValueType().bitsLE(NVT)) {
- // The low part is any extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, Op);
- Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined.
- } else {
- // For example, extension of an i48 to an i64. The operand type necessarily
- // promotes to the result type, so will end up being expanded too.
- assert(getTypeAction(Op.getValueType()) == Promote &&
- "Only know how to promote this result!");
- SDOperand Res = GetPromotedOp(Op);
- assert(Res.getValueType() == N->getValueType(0) &&
- "Operand over promoted?");
- // Split the promoted operand. This will simplify when it is expanded.
- SplitInteger(Res, Lo, Hi);
- }
-}
-
-void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand Op = N->getOperand(0);
- if (Op.getValueType().bitsLE(NVT)) {
- // The low part is zero extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::ZERO_EXTEND, NVT, N->getOperand(0));
- Hi = DAG.getConstant(0, NVT); // The high part is just a zero.
- } else {
- // For example, extension of an i48 to an i64. The operand type necessarily
- // promotes to the result type, so will end up being expanded too.
- assert(getTypeAction(Op.getValueType()) == Promote &&
- "Only know how to promote this result!");
- SDOperand Res = GetPromotedOp(Op);
- assert(Res.getValueType() == N->getValueType(0) &&
- "Operand over promoted?");
- // Split the promoted operand. This will simplify when it is expanded.
- SplitInteger(Res, Lo, Hi);
- unsigned ExcessBits =
- Op.getValueType().getSizeInBits() - NVT.getSizeInBits();
- Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerVT(ExcessBits));
- }
-}
-
-void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand Op = N->getOperand(0);
- if (Op.getValueType().bitsLE(NVT)) {
- // The low part is sign extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
- // The high part is obtained by SRA'ing all but one of the bits of low part.
- unsigned LoSize = NVT.getSizeInBits();
- Hi = DAG.getNode(ISD::SRA, NVT, Lo,
- DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
- } else {
- // For example, extension of an i48 to an i64. The operand type necessarily
- // promotes to the result type, so will end up being expanded too.
- assert(getTypeAction(Op.getValueType()) == Promote &&
- "Only know how to promote this result!");
- SDOperand Res = GetPromotedOp(Op);
- assert(Res.getValueType() == N->getValueType(0) &&
- "Operand over promoted?");
- // Split the promoted operand. This will simplify when it is expanded.
- SplitInteger(Res, Lo, Hi);
- unsigned ExcessBits =
- Op.getValueType().getSizeInBits() - NVT.getSizeInBits();
- Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
- DAG.getValueType(MVT::getIntegerVT(ExcessBits)));
- }
-}
-
-void DAGTypeLegalizer::ExpandResult_AssertZext(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- MVT NVT = Lo.getValueType();
- MVT EVT = cast<VTSDNode>(N->getOperand(1))->getVT();
- unsigned NVTBits = NVT.getSizeInBits();
- unsigned EVTBits = EVT.getSizeInBits();
-
- if (NVTBits < EVTBits) {
- Hi = DAG.getNode(ISD::AssertZext, NVT, Hi,
- DAG.getValueType(MVT::getIntegerVT(EVTBits - NVTBits)));
- } else {
- Lo = DAG.getNode(ISD::AssertZext, NVT, Lo, DAG.getValueType(EVT));
- // The high part must be zero, make it explicit.
- Hi = DAG.getConstant(0, NVT);
- }
-}
-
-void DAGTypeLegalizer::ExpandResult_TRUNCATE(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- Lo = DAG.getNode(ISD::TRUNCATE, NVT, N->getOperand(0));
- Hi = DAG.getNode(ISD::SRL, N->getOperand(0).getValueType(), N->getOperand(0),
- DAG.getConstant(NVT.getSizeInBits(),
- TLI.getShiftAmountTy()));
- Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand InOp = N->getOperand(0);
- MVT InVT = InOp.getValueType();
-
- // Handle some special cases efficiently.
- switch (getTypeAction(InVT)) {
- default:
- assert(false && "Unknown type action!");
- case Legal:
- case Promote:
- break;
- case Expand:
- // Convert the expanded pieces of the input.
- GetExpandedOp(InOp, Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
- return;
- case FloatToInt:
- // Convert the integer operand instead.
- SplitInteger(GetIntegerOp(InOp), Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
- return;
- case Split:
- // Convert the split parts of the input if it was split in two.
- GetSplitOp(InOp, Lo, Hi);
- if (Lo.getValueType() == Hi.getValueType()) {
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
- return;
- }
- break;
- case Scalarize:
- // Convert the element instead.
- SplitInteger(BitConvertToInteger(GetScalarizedOp(InOp)), Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, NVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, NVT, Hi);
- return;
- }
-
- // Lower the bit-convert to a store/load from the stack, then expand the load.
- SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
- ExpandResult_LOAD(cast<LoadSDNode>(Op.Val), Lo, Hi);
-}
-
-void DAGTypeLegalizer::
-ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- MVT EVT = cast<VTSDNode>(N->getOperand(1))->getVT();
-
- if (EVT.bitsLE(Lo.getValueType())) {
- // sext_inreg the low part if needed.
- Lo = DAG.getNode(ISD::SIGN_EXTEND_INREG, Lo.getValueType(), Lo,
- N->getOperand(1));
-
- // The high part gets the sign extension from the lo-part. This handles
- // things like sextinreg V:i64 from i8.
- Hi = DAG.getNode(ISD::SRA, Hi.getValueType(), Lo,
- DAG.getConstant(Hi.getValueType().getSizeInBits()-1,
- TLI.getShiftAmountTy()));
- } else {
- // For example, extension of an i48 to an i64. Leave the low part alone,
- // sext_inreg the high part.
- unsigned ExcessBits =
- EVT.getSizeInBits() - Lo.getValueType().getSizeInBits();
- Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
- DAG.getValueType(MVT::getIntegerVT(ExcessBits)));
- }
-}
-
-void DAGTypeLegalizer::ExpandResult_FP_TO_SINT(SDNode *N, SDOperand &Lo,
- SDOperand &Hi) {
- MVT VT = N->getValueType(0);
- SDOperand Op = N->getOperand(0);
- RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (VT == MVT::i64) {
- if (Op.getValueType() == MVT::f32)
- LC = RTLIB::FPTOSINT_F32_I64;
- else if (Op.getValueType() == MVT::f64)
- LC = RTLIB::FPTOSINT_F64_I64;
- else if (Op.getValueType() == MVT::f80)
- LC = RTLIB::FPTOSINT_F80_I64;
- else if (Op.getValueType() == MVT::ppcf128)
- LC = RTLIB::FPTOSINT_PPCF128_I64;
- } else if (VT == MVT::i128) {
- if (Op.getValueType() == MVT::f32)
- LC = RTLIB::FPTOSINT_F32_I128;
- else if (Op.getValueType() == MVT::f64)
- LC = RTLIB::FPTOSINT_F64_I128;
- else if (Op.getValueType() == MVT::f80)
- LC = RTLIB::FPTOSINT_F80_I128;
- else if (Op.getValueType() == MVT::ppcf128)
- LC = RTLIB::FPTOSINT_PPCF128_I128;
- } else {
- assert(0 && "Unexpected fp-to-sint conversion!");
- }
- SplitInteger(MakeLibCall(LC, VT, &Op, 1, true/*sign irrelevant*/), Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_FP_TO_UINT(SDNode *N, SDOperand &Lo,
- SDOperand &Hi) {
- MVT VT = N->getValueType(0);
- SDOperand Op = N->getOperand(0);
- RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (VT == MVT::i64) {
- if (Op.getValueType() == MVT::f32)
- LC = RTLIB::FPTOUINT_F32_I64;
- else if (Op.getValueType() == MVT::f64)
- LC = RTLIB::FPTOUINT_F64_I64;
- else if (Op.getValueType() == MVT::f80)
- LC = RTLIB::FPTOUINT_F80_I64;
- else if (Op.getValueType() == MVT::ppcf128)
- LC = RTLIB::FPTOUINT_PPCF128_I64;
- } else if (VT == MVT::i128) {
- if (Op.getValueType() == MVT::f32)
- LC = RTLIB::FPTOUINT_F32_I128;
- else if (Op.getValueType() == MVT::f64)
- LC = RTLIB::FPTOUINT_F64_I128;
- else if (Op.getValueType() == MVT::f80)
- LC = RTLIB::FPTOUINT_F80_I128;
- else if (Op.getValueType() == MVT::ppcf128)
- LC = RTLIB::FPTOUINT_PPCF128_I128;
- } else {
- assert(0 && "Unexpected fp-to-uint conversion!");
- }
- SplitInteger(MakeLibCall(LC, VT, &Op, 1, false/*sign irrelevant*/), Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // FIXME: Add support for indexed loads.
- MVT VT = N->getValueType(0);
- MVT NVT = TLI.getTypeToTransformTo(VT);
- SDOperand Ch = N->getChain(); // Legalize the chain.
- SDOperand Ptr = N->getBasePtr(); // Legalize the pointer.
- ISD::LoadExtType ExtType = N->getExtensionType();
- int SVOffset = N->getSrcValueOffset();
- unsigned Alignment = N->getAlignment();
- bool isVolatile = N->isVolatile();
-
- assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!");
-
- if (ExtType == ISD::NON_EXTLOAD) {
- Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
- isVolatile, Alignment);
- // Increment the pointer to the other half.
- unsigned IncrementSize = NVT.getSizeInBits()/8;
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
- isVolatile, MinAlign(Alignment, IncrementSize));
-
- // Build a factor node to remember that this load is independent of the
- // other one.
- Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
- Hi.getValue(1));
-
- // Handle endianness of the load.
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- } else if (N->getMemoryVT().bitsLE(NVT)) {
- MVT EVT = N->getMemoryVT();
-
- Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset, EVT,
- isVolatile, Alignment);
-
- // Remember the chain.
- Ch = Lo.getValue(1);
-
- if (ExtType == ISD::SEXTLOAD) {
- // The high part is obtained by SRA'ing all but one of the bits of the
- // lo part.
- unsigned LoSize = Lo.getValueType().getSizeInBits();
- Hi = DAG.getNode(ISD::SRA, NVT, Lo,
- DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
- } else if (ExtType == ISD::ZEXTLOAD) {
- // The high part is just a zero.
- Hi = DAG.getConstant(0, NVT);
- } else {
- assert(ExtType == ISD::EXTLOAD && "Unknown extload!");
- // The high part is undefined.
- Hi = DAG.getNode(ISD::UNDEF, NVT);
- }
- } else if (TLI.isLittleEndian()) {
- // Little-endian - low bits are at low addresses.
- Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
- isVolatile, Alignment);
-
- unsigned ExcessBits =
- N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits();
- MVT NEVT = MVT::getIntegerVT(ExcessBits);
-
- // Increment the pointer to the other half.
- unsigned IncrementSize = NVT.getSizeInBits()/8;
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
- SVOffset+IncrementSize, NEVT,
- isVolatile, MinAlign(Alignment, IncrementSize));
-
- // Build a factor node to remember that this load is independent of the
- // other one.
- Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
- Hi.getValue(1));
- } else {
- // Big-endian - high bits are at low addresses. Favor aligned loads at
- // the cost of some bit-fiddling.
- MVT EVT = N->getMemoryVT();
- unsigned EBytes = EVT.getStoreSizeInBits()/8;
- unsigned IncrementSize = NVT.getSizeInBits()/8;
- unsigned ExcessBits = (EBytes - IncrementSize)*8;
-
- // Load both the high bits and maybe some of the low bits.
- Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
- MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits),
- isVolatile, Alignment);
-
- // Increment the pointer to the other half.
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- // Load the rest of the low bits.
- Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
- SVOffset+IncrementSize,
- MVT::getIntegerVT(ExcessBits),
- isVolatile, MinAlign(Alignment, IncrementSize));
-
- // Build a factor node to remember that this load is independent of the
- // other one.
- Ch = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
- Hi.getValue(1));
-
- if (ExcessBits < NVT.getSizeInBits()) {
- // Transfer low bits from the bottom of Hi to the top of Lo.
- Lo = DAG.getNode(ISD::OR, NVT, Lo,
- DAG.getNode(ISD::SHL, NVT, Hi,
- DAG.getConstant(ExcessBits,
- TLI.getShiftAmountTy())));
- // Move high bits to the right position in Hi.
- Hi = DAG.getNode(ExtType == ISD::SEXTLOAD ? ISD::SRA : ISD::SRL, NVT, Hi,
- DAG.getConstant(NVT.getSizeInBits() - ExcessBits,
- TLI.getShiftAmountTy()));
- }
- }
-
- // Legalized the chain result - switch anything that used the old chain to
- // use the new one.
- ReplaceValueWith(SDOperand(N, 1), Ch);
-}
-
-void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- SDOperand LL, LH, RL, RH;
- GetExpandedOp(N->getOperand(0), LL, LH);
- GetExpandedOp(N->getOperand(1), RL, RH);
- Lo = DAG.getNode(N->getOpcode(), LL.getValueType(), LL, RL);
- Hi = DAG.getNode(N->getOpcode(), LL.getValueType(), LH, RH);
-}
-
-void DAGTypeLegalizer::ExpandResult_BSWAP(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- GetExpandedOp(N->getOperand(0), Hi, Lo); // Note swapped operands.
- Lo = DAG.getNode(ISD::BSWAP, Lo.getValueType(), Lo);
- Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_SELECT(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- SDOperand LL, LH, RL, RH;
- GetExpandedOp(N->getOperand(1), LL, LH);
- GetExpandedOp(N->getOperand(2), RL, RH);
- Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LL, RL);
- Hi = DAG.getNode(ISD::SELECT, LL.getValueType(), N->getOperand(0), LH, RH);
-}
-
-void DAGTypeLegalizer::ExpandResult_SELECT_CC(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- SDOperand LL, LH, RL, RH;
- GetExpandedOp(N->getOperand(2), LL, LH);
- GetExpandedOp(N->getOperand(3), RL, RH);
- Lo = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0),
- N->getOperand(1), LL, RL, N->getOperand(4));
- Hi = DAG.getNode(ISD::SELECT_CC, LL.getValueType(), N->getOperand(0),
- N->getOperand(1), LH, RH, N->getOperand(4));
-}
-
-void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // Expand the subcomponents.
- SDOperand LHSL, LHSH, RHSL, RHSH;
- GetExpandedOp(N->getOperand(0), LHSL, LHSH);
- GetExpandedOp(N->getOperand(1), RHSL, RHSH);
- SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
- SDOperand LoOps[2] = { LHSL, RHSL };
- SDOperand HiOps[3] = { LHSH, RHSH };
-
- if (N->getOpcode() == ISD::ADD) {
- Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
- } else {
- Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
- }
-}
-
-void DAGTypeLegalizer::ExpandResult_ADDSUBC(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // Expand the subcomponents.
- SDOperand LHSL, LHSH, RHSL, RHSH;
- GetExpandedOp(N->getOperand(0), LHSL, LHSH);
- GetExpandedOp(N->getOperand(1), RHSL, RHSH);
- SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
- SDOperand LoOps[2] = { LHSL, RHSL };
- SDOperand HiOps[3] = { LHSH, RHSH };
-
- if (N->getOpcode() == ISD::ADDC) {
- Lo = DAG.getNode(ISD::ADDC, VTList, LoOps, 2);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::ADDE, VTList, HiOps, 3);
- } else {
- Lo = DAG.getNode(ISD::SUBC, VTList, LoOps, 2);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(ISD::SUBE, VTList, HiOps, 3);
- }
-
- // Legalized the flag result - switch anything that used the old flag to
- // use the new one.
- ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1));
-}
-
-void DAGTypeLegalizer::ExpandResult_ADDSUBE(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // Expand the subcomponents.
- SDOperand LHSL, LHSH, RHSL, RHSH;
- GetExpandedOp(N->getOperand(0), LHSL, LHSH);
- GetExpandedOp(N->getOperand(1), RHSL, RHSH);
- SDVTList VTList = DAG.getVTList(LHSL.getValueType(), MVT::Flag);
- SDOperand LoOps[3] = { LHSL, RHSL, N->getOperand(2) };
- SDOperand HiOps[3] = { LHSH, RHSH };
-
- Lo = DAG.getNode(N->getOpcode(), VTList, LoOps, 3);
- HiOps[2] = Lo.getValue(1);
- Hi = DAG.getNode(N->getOpcode(), VTList, HiOps, 3);
-
- // Legalized the flag result - switch anything that used the old flag to
- // use the new one.
- ReplaceValueWith(SDOperand(N, 1), Hi.getValue(1));
-}
-
-void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT VT = N->getValueType(0);
- MVT NVT = TLI.getTypeToTransformTo(VT);
-
- bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
- bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
- bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT);
- bool HasUMUL_LOHI = TLI.isOperationLegal(ISD::UMUL_LOHI, NVT);
- if (HasMULHU || HasMULHS || HasUMUL_LOHI || HasSMUL_LOHI) {
- SDOperand LL, LH, RL, RH;
- GetExpandedOp(N->getOperand(0), LL, LH);
- GetExpandedOp(N->getOperand(1), RL, RH);
- unsigned OuterBitSize = VT.getSizeInBits();
- unsigned BitSize = NVT.getSizeInBits();
- unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
- unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
-
- if (DAG.MaskedValueIsZero(N->getOperand(0),
- APInt::getHighBitsSet(OuterBitSize, LHSSB)) &&
- DAG.MaskedValueIsZero(N->getOperand(1),
- APInt::getHighBitsSet(OuterBitSize, RHSSB))) {
- // The inputs are both zero-extended.
- if (HasUMUL_LOHI) {
- // We can emit a umul_lohi.
- Lo = DAG.getNode(ISD::UMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
- Hi = SDOperand(Lo.Val, 1);
- return;
- }
- if (HasMULHU) {
- // We can emit a mulhu+mul.
- Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
- Hi = DAG.getNode(ISD::MULHU, NVT, LL, RL);
- return;
- }
- }
- if (LHSSB > BitSize && RHSSB > BitSize) {
- // The input values are both sign-extended.
- if (HasSMUL_LOHI) {
- // We can emit a smul_lohi.
- Lo = DAG.getNode(ISD::SMUL_LOHI, DAG.getVTList(NVT, NVT), LL, RL);
- Hi = SDOperand(Lo.Val, 1);
- return;
- }
- if (HasMULHS) {
- // We can emit a mulhs+mul.
- Lo = DAG.getNode(ISD::MUL, NVT, LL, RL);
- Hi = DAG.getNode(ISD::MULHS, NVT, LL, RL);
- return;
- }
- }
- if (HasUMUL_LOHI) {
- // Lo,Hi = umul LHS, RHS.
- SDOperand UMulLOHI = DAG.getNode(ISD::UMUL_LOHI,
- DAG.getVTList(NVT, NVT), LL, RL);
- Lo = UMulLOHI;
- Hi = UMulLOHI.getValue(1);
- RH = DAG.getNode(ISD::MUL, NVT, LL, RH);
- LH = DAG.getNode(ISD::MUL, NVT, LH, RL);
- Hi = DAG.getNode(ISD::ADD, NVT, Hi, RH);
- Hi = DAG.getNode(ISD::ADD, NVT, Hi, LH);
- return;
- }
- }
-
- // If nothing else, we can make a libcall.
- SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::MUL_I64, VT, Ops, 2, true/*sign irrelevant*/),
- Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_SDIV(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported sdiv!");
- SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::SDIV_I64, N->getValueType(0), Ops, 2, true),
- Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_SREM(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported srem!");
- SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::SREM_I64, N->getValueType(0), Ops, 2, true),
- Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_UDIV(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported udiv!");
- SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::UDIV_I64, N->getValueType(0), Ops, 2, false),
- Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_UREM(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- assert(N->getValueType(0) == MVT::i64 && "Unsupported urem!");
- SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(RTLIB::UREM_I64, N->getValueType(0), Ops, 2, false),
- Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_Shift(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- MVT VT = N->getValueType(0);
-
- // If we can emit an efficient shift operation, do so now. Check to see if
- // the RHS is a constant.
- if (ConstantSDNode *CN = dyn_cast<ConstantSDNode>(N->getOperand(1)))
- return ExpandShiftByConstant(N, CN->getValue(), Lo, Hi);
-
- // If we can determine that the high bit of the shift is zero or one, even if
- // the low bits are variable, emit this shift in an optimized form.
- if (ExpandShiftWithKnownAmountBit(N, Lo, Hi))
- return;
-
- // If this target supports shift_PARTS, use it. First, map to the _PARTS opc.
- unsigned PartsOpc;
- if (N->getOpcode() == ISD::SHL) {
- PartsOpc = ISD::SHL_PARTS;
- } else if (N->getOpcode() == ISD::SRL) {
- PartsOpc = ISD::SRL_PARTS;
- } else {
- assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
- PartsOpc = ISD::SRA_PARTS;
- }
-
- // Next check to see if the target supports this SHL_PARTS operation or if it
- // will custom expand it.
- MVT NVT = TLI.getTypeToTransformTo(VT);
- TargetLowering::LegalizeAction Action = TLI.getOperationAction(PartsOpc, NVT);
- if ((Action == TargetLowering::Legal && TLI.isTypeLegal(NVT)) ||
- Action == TargetLowering::Custom) {
- // Expand the subcomponents.
- SDOperand LHSL, LHSH;
- GetExpandedOp(N->getOperand(0), LHSL, LHSH);
-
- SDOperand Ops[] = { LHSL, LHSH, N->getOperand(1) };
- MVT VT = LHSL.getValueType();
- Lo = DAG.getNode(PartsOpc, DAG.getNodeValueTypes(VT, VT), 2, Ops, 3);
- Hi = Lo.getValue(1);
- return;
- }
-
- // Otherwise, emit a libcall.
- assert(VT == MVT::i64 && "Unsupported shift!");
-
- RTLIB::Libcall LC;
- bool isSigned;
- if (N->getOpcode() == ISD::SHL) {
- LC = RTLIB::SHL_I64;
- isSigned = false; /*sign irrelevant*/
- } else if (N->getOpcode() == ISD::SRL) {
- LC = RTLIB::SRL_I64;
- isSigned = false;
- } else {
- assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
- LC = RTLIB::SRA_I64;
- isSigned = true;
- }
-
- SDOperand Ops[2] = { N->getOperand(0), N->getOperand(1) };
- SplitInteger(MakeLibCall(LC, VT, Ops, 2, isSigned), Lo, Hi);
-}
-
-void DAGTypeLegalizer::ExpandResult_CTLZ(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // ctlz (HiLo) -> Hi != 0 ? ctlz(Hi) : (ctlz(Lo)+32)
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- MVT NVT = Lo.getValueType();
-
- SDOperand HiNotZero = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
- DAG.getConstant(0, NVT), ISD::SETNE);
-
- SDOperand LoLZ = DAG.getNode(ISD::CTLZ, NVT, Lo);
- SDOperand HiLZ = DAG.getNode(ISD::CTLZ, NVT, Hi);
-
- Lo = DAG.getNode(ISD::SELECT, NVT, HiNotZero, HiLZ,
- DAG.getNode(ISD::ADD, NVT, LoLZ,
- DAG.getConstant(NVT.getSizeInBits(), NVT)));
- Hi = DAG.getConstant(0, NVT);
-}
-
-void DAGTypeLegalizer::ExpandResult_CTPOP(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // ctpop(HiLo) -> ctpop(Hi)+ctpop(Lo)
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- MVT NVT = Lo.getValueType();
- Lo = DAG.getNode(ISD::ADD, NVT, DAG.getNode(ISD::CTPOP, NVT, Lo),
- DAG.getNode(ISD::CTPOP, NVT, Hi));
- Hi = DAG.getConstant(0, NVT);
-}
-
-void DAGTypeLegalizer::ExpandResult_CTTZ(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // cttz (HiLo) -> Lo != 0 ? cttz(Lo) : (cttz(Hi)+32)
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- MVT NVT = Lo.getValueType();
-
- SDOperand LoNotZero = DAG.getSetCC(TLI.getSetCCResultType(Lo), Lo,
- DAG.getConstant(0, NVT), ISD::SETNE);
-
- SDOperand LoLZ = DAG.getNode(ISD::CTTZ, NVT, Lo);
- SDOperand HiLZ = DAG.getNode(ISD::CTTZ, NVT, Hi);
-
- Lo = DAG.getNode(ISD::SELECT, NVT, LoNotZero, LoLZ,
- DAG.getNode(ISD::ADD, NVT, HiLZ,
- DAG.getConstant(NVT.getSizeInBits(), NVT)));
- Hi = DAG.getConstant(0, NVT);
-}
-
-void DAGTypeLegalizer::ExpandResult_EXTRACT_VECTOR_ELT(SDNode *N,
- SDOperand &Lo,
- SDOperand &Hi) {
- SDOperand OldVec = N->getOperand(0);
- unsigned OldElts = OldVec.getValueType().getVectorNumElements();
-
- // Convert to a vector of the expanded element type, for example
- // <2 x i64> -> <4 x i32>.
- MVT OldVT = N->getValueType(0);
- MVT NewVT = TLI.getTypeToTransformTo(OldVT);
- assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() &&
- "Do not know how to handle this expansion!");
-
- SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
- MVT::getVectorVT(NewVT, 2*OldElts),
- OldVec);
-
- // Extract the elements at 2 * Idx and 2 * Idx + 1 from the new vector.
- SDOperand Idx = N->getOperand(1);
-
- // Make sure the type of Idx is big enough to hold the new values.
- if (Idx.getValueType().bitsLT(TLI.getPointerTy()))
- Idx = DAG.getNode(ISD::ZERO_EXTEND, TLI.getPointerTy(), Idx);
-
- Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx, Idx);
- Lo = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
-
- Idx = DAG.getNode(ISD::ADD, Idx.getValueType(), Idx,
- DAG.getConstant(1, Idx.getValueType()));
- Hi = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, Idx);
-
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
-}
-
-/// ExpandShiftByConstant - N is a shift by a value that needs to be expanded,
-/// and the shift amount is a constant 'Amt'. Expand the operation.
-void DAGTypeLegalizer::ExpandShiftByConstant(SDNode *N, unsigned Amt,
- SDOperand &Lo, SDOperand &Hi) {
- // Expand the incoming operand to be shifted, so that we have its parts
- SDOperand InL, InH;
- GetExpandedOp(N->getOperand(0), InL, InH);
-
- MVT NVT = InL.getValueType();
- unsigned VTBits = N->getValueType(0).getSizeInBits();
- unsigned NVTBits = NVT.getSizeInBits();
- MVT ShTy = N->getOperand(1).getValueType();
-
- if (N->getOpcode() == ISD::SHL) {
- if (Amt > VTBits) {
- Lo = Hi = DAG.getConstant(0, NVT);
- } else if (Amt > NVTBits) {
- Lo = DAG.getConstant(0, NVT);
- Hi = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt-NVTBits,ShTy));
- } else if (Amt == NVTBits) {
- Lo = DAG.getConstant(0, NVT);
- Hi = InL;
- } else {
- Lo = DAG.getNode(ISD::SHL, NVT, InL, DAG.getConstant(Amt, ShTy));
- Hi = DAG.getNode(ISD::OR, NVT,
- DAG.getNode(ISD::SHL, NVT, InH,
- DAG.getConstant(Amt, ShTy)),
- DAG.getNode(ISD::SRL, NVT, InL,
- DAG.getConstant(NVTBits-Amt, ShTy)));
- }
- return;
- }
-
- if (N->getOpcode() == ISD::SRL) {
- if (Amt > VTBits) {
- Lo = DAG.getConstant(0, NVT);
- Hi = DAG.getConstant(0, NVT);
- } else if (Amt > NVTBits) {
- Lo = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt-NVTBits,ShTy));
- Hi = DAG.getConstant(0, NVT);
- } else if (Amt == NVTBits) {
- Lo = InH;
- Hi = DAG.getConstant(0, NVT);
- } else {
- Lo = DAG.getNode(ISD::OR, NVT,
- DAG.getNode(ISD::SRL, NVT, InL,
- DAG.getConstant(Amt, ShTy)),
- DAG.getNode(ISD::SHL, NVT, InH,
- DAG.getConstant(NVTBits-Amt, ShTy)));
- Hi = DAG.getNode(ISD::SRL, NVT, InH, DAG.getConstant(Amt, ShTy));
- }
- return;
- }
-
- assert(N->getOpcode() == ISD::SRA && "Unknown shift!");
- if (Amt > VTBits) {
- Hi = Lo = DAG.getNode(ISD::SRA, NVT, InH,
- DAG.getConstant(NVTBits-1, ShTy));
- } else if (Amt > NVTBits) {
- Lo = DAG.getNode(ISD::SRA, NVT, InH,
- DAG.getConstant(Amt-NVTBits, ShTy));
- Hi = DAG.getNode(ISD::SRA, NVT, InH,
- DAG.getConstant(NVTBits-1, ShTy));
- } else if (Amt == NVTBits) {
- Lo = InH;
- Hi = DAG.getNode(ISD::SRA, NVT, InH,
- DAG.getConstant(NVTBits-1, ShTy));
- } else {
- Lo = DAG.getNode(ISD::OR, NVT,
- DAG.getNode(ISD::SRL, NVT, InL,
- DAG.getConstant(Amt, ShTy)),
- DAG.getNode(ISD::SHL, NVT, InH,
- DAG.getConstant(NVTBits-Amt, ShTy)));
- Hi = DAG.getNode(ISD::SRA, NVT, InH, DAG.getConstant(Amt, ShTy));
- }
-}
-
-/// ExpandShiftWithKnownAmountBit - Try to determine whether we can simplify
-/// this shift based on knowledge of the high bit of the shift amount. If we
-/// can tell this, we know that it is >= 32 or < 32, without knowing the actual
-/// shift amount.
-bool DAGTypeLegalizer::
-ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
- SDOperand Amt = N->getOperand(1);
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- MVT ShTy = Amt.getValueType();
- unsigned ShBits = ShTy.getSizeInBits();
- unsigned NVTBits = NVT.getSizeInBits();
- assert(isPowerOf2_32(NVTBits) &&
- "Expanded integer type size not a power of two!");
-
- APInt HighBitMask = APInt::getHighBitsSet(ShBits, ShBits - Log2_32(NVTBits));
- APInt KnownZero, KnownOne;
- DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne);
-
- // If we don't know anything about the high bits, exit.
- if (((KnownZero|KnownOne) & HighBitMask) == 0)
- return false;
-
- // Get the incoming operand to be shifted.
- SDOperand InL, InH;
- GetExpandedOp(N->getOperand(0), InL, InH);
-
- // If we know that any of the high bits of the shift amount are one, then we
- // can do this as a couple of simple shifts.
- if (KnownOne.intersects(HighBitMask)) {
- // Mask out the high bit, which we know is set.
- Amt = DAG.getNode(ISD::AND, ShTy, Amt,
- DAG.getConstant(~HighBitMask, ShTy));
-
- switch (N->getOpcode()) {
- default: assert(0 && "Unknown shift");
- case ISD::SHL:
- Lo = DAG.getConstant(0, NVT); // Low part is zero.
- Hi = DAG.getNode(ISD::SHL, NVT, InL, Amt); // High part from Lo part.
- return true;
- case ISD::SRL:
- Hi = DAG.getConstant(0, NVT); // Hi part is zero.
- Lo = DAG.getNode(ISD::SRL, NVT, InH, Amt); // Lo part from Hi part.
- return true;
- case ISD::SRA:
- Hi = DAG.getNode(ISD::SRA, NVT, InH, // Sign extend high part.
- DAG.getConstant(NVTBits-1, ShTy));
- Lo = DAG.getNode(ISD::SRA, NVT, InH, Amt); // Lo part from Hi part.
- return true;
- }
- }
-
- // If we know that all of the high bits of the shift amount are zero, then we
- // can do this as a couple of simple shifts.
- if ((KnownZero & HighBitMask) == HighBitMask) {
- // Compute 32-amt.
- SDOperand Amt2 = DAG.getNode(ISD::SUB, ShTy,
- DAG.getConstant(NVTBits, ShTy),
- Amt);
- unsigned Op1, Op2;
- switch (N->getOpcode()) {
- default: assert(0 && "Unknown shift");
- case ISD::SHL: Op1 = ISD::SHL; Op2 = ISD::SRL; break;
- case ISD::SRL:
- case ISD::SRA: Op1 = ISD::SRL; Op2 = ISD::SHL; break;
- }
-
- Lo = DAG.getNode(N->getOpcode(), NVT, InL, Amt);
- Hi = DAG.getNode(ISD::OR, NVT,
- DAG.getNode(Op1, NVT, InH, Amt),
- DAG.getNode(Op2, NVT, InL, Amt2));
- return true;
- }
-
- return false;
-}
-
-
-//===----------------------------------------------------------------------===//
-// Operand Expansion
-//===----------------------------------------------------------------------===//
-
-/// ExpandOperand - This method is called when the specified operand of the
-/// specified node is found to need expansion. At this point, all of the result
-/// types of the node are known to be legal, but other operands of the node may
-/// need promotion or expansion as well as the specified one.
-bool DAGTypeLegalizer::ExpandOperand(SDNode *N, unsigned OpNo) {
- DEBUG(cerr << "Expand node operand: "; N->dump(&DAG); cerr << "\n");
- SDOperand Res(0, 0);
-
- if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
- == TargetLowering::Custom)
- Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
-
- if (Res.Val == 0) {
- switch (N->getOpcode()) {
- default:
- #ifndef NDEBUG
- cerr << "ExpandOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
- #endif
- assert(0 && "Do not know how to expand this operator's operand!");
- abort();
-
- case ISD::TRUNCATE: Res = ExpandOperand_TRUNCATE(N); break;
- case ISD::BIT_CONVERT: Res = ExpandOperand_BIT_CONVERT(N); break;
-
- case ISD::SINT_TO_FP:
- Res = ExpandOperand_SINT_TO_FP(N->getOperand(0), N->getValueType(0));
- break;
- case ISD::UINT_TO_FP:
- Res = ExpandOperand_UINT_TO_FP(N->getOperand(0), N->getValueType(0));
- break;
- case ISD::EXTRACT_ELEMENT: Res = ExpandOperand_EXTRACT_ELEMENT(N); break;
-
- case ISD::BR_CC: Res = ExpandOperand_BR_CC(N); break;
- case ISD::SETCC: Res = ExpandOperand_SETCC(N); break;
-
- case ISD::STORE:
- Res = ExpandOperand_STORE(cast<StoreSDNode>(N), OpNo);
- break;
-
- case ISD::BUILD_VECTOR: Res = ExpandOperand_BUILD_VECTOR(N); break;
- }
- }
-
- // If the result is null, the sub-method took care of registering results etc.
- if (!Res.Val) return false;
- // If the result is N, the sub-method updated N in place. Check to see if any
- // operands are new, and if so, mark them.
- if (Res.Val == N) {
- // Mark N as new and remark N and its operands. This allows us to correctly
- // revisit N if it needs another step of promotion and allows us to visit
- // any new operands to N.
- ReanalyzeNode(N);
- return true;
- }
-
- assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
- "Invalid operand expansion");
-
- ReplaceValueWith(SDOperand(N, 0), Res);
- return false;
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_TRUNCATE(SDNode *N) {
- SDOperand InL, InH;
- GetExpandedOp(N->getOperand(0), InL, InH);
- // Just truncate the low part of the source.
- return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) {
- if (N->getValueType(0).isVector()) {
- // An illegal integer type is being converted to a legal vector type.
- // Make a two element vector out of the expanded parts and convert that
- // instead, but only if the new vector type is legal (otherwise there
- // is no point, and it might create expansion loops). For example, on
- // x86 this turns v1i64 = BIT_CONVERT i64 into v1i64 = BIT_CONVERT v2i32.
- MVT OVT = N->getOperand(0).getValueType();
- MVT NVT = MVT::getVectorVT(TLI.getTypeToTransformTo(OVT), 2);
-
- if (isTypeLegal(NVT)) {
- SDOperand Parts[2];
- GetExpandedOp(N->getOperand(0), Parts[0], Parts[1]);
-
- if (TLI.isBigEndian())
- std::swap(Parts[0], Parts[1]);
-
- SDOperand Vec = DAG.getNode(ISD::BUILD_VECTOR, NVT, Parts, 2);
- return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Vec);
- }
- }
-
- // Otherwise, store to a temporary and load out again as the new type.
- return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source,
- MVT DestTy) {
- // We know the destination is legal, but that the input needs to be expanded.
- MVT SourceVT = Source.getValueType();
-
- // Check to see if the target has a custom way to lower this. If so, use it.
- switch (TLI.getOperationAction(ISD::SINT_TO_FP, SourceVT)) {
- 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 NV;
- break; // The target lowered this.
- }
-
- RTLIB::Libcall LC = RTLIB::UNKNOWN_LIBCALL;
- if (SourceVT == MVT::i64) {
- if (DestTy == MVT::f32)
- LC = RTLIB::SINTTOFP_I64_F32;
- else {
- assert(DestTy == MVT::f64 && "Unknown fp value type!");
- LC = RTLIB::SINTTOFP_I64_F64;
- }
- } else if (SourceVT == MVT::i128) {
- if (DestTy == MVT::f32)
- LC = RTLIB::SINTTOFP_I128_F32;
- else if (DestTy == MVT::f64)
- LC = RTLIB::SINTTOFP_I128_F64;
- else if (DestTy == MVT::f80)
- LC = RTLIB::SINTTOFP_I128_F80;
- else {
- assert(DestTy == MVT::ppcf128 && "Unknown fp value type!");
- LC = RTLIB::SINTTOFP_I128_PPCF128;
- }
- } else {
- assert(0 && "Unknown int value type!");
- }
-
- assert(LC != RTLIB::UNKNOWN_LIBCALL &&
- "Don't know how to expand this SINT_TO_FP!");
- return MakeLibCall(LC, DestTy, &Source, 1, true);
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source,
- MVT DestTy) {
- // We know the destination is legal, but that the input needs to be expanded.
- assert(getTypeAction(Source.getValueType()) == Expand &&
- "This is not an expansion!");
-
- // 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 = ExpandOperand_SINT_TO_FP(Source, DestTy);
-
- // 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;
- GetExpandedOp(Source, Lo, Hi);
-
- SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Hi), Hi,
- DAG.getConstant(0, Hi.getValueType()),
- ISD::SETLT);
- SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.getIntPtrConstant(4);
- SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
- SignSet, Four, Zero);
- uint64_t FF = 0x5f800000ULL;
- if (TLI.isLittleEndian()) FF <<= 32;
- Constant *FudgeFactor = ConstantInt::get((Type*)Type::Int64Ty, 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, NULL, 0);
- else if (DestTy.bitsGT(MVT::f32))
- // FIXME: Avoid the extend by construction the right constantpool?
- FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestTy, DAG.getEntryNode(),
- CPIdx, NULL, 0, MVT::f32);
- else
- assert(0 && "Unexpected conversion");
-
- return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_EXTRACT_ELEMENT(SDNode *N) {
- SDOperand Lo, Hi;
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- return cast<ConstantSDNode>(N->getOperand(1))->getValue() ? Hi : Lo;
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_BR_CC(SDNode *N) {
- SDOperand NewLHS = N->getOperand(2), NewRHS = N->getOperand(3);
- ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(1))->get();
- ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
-
- // If ExpandSetCCOperands returned a scalar, we need to compare the result
- // against zero to select between true and false values.
- if (NewRHS.Val == 0) {
- NewRHS = DAG.getConstant(0, NewLHS.getValueType());
- CCCode = ISD::SETNE;
- }
-
- // Update N to have the operands specified.
- return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
- DAG.getCondCode(CCCode), NewLHS, NewRHS,
- N->getOperand(4));
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_SETCC(SDNode *N) {
- SDOperand NewLHS = N->getOperand(0), NewRHS = N->getOperand(1);
- ISD::CondCode CCCode = cast<CondCodeSDNode>(N->getOperand(2))->get();
- ExpandSetCCOperands(NewLHS, NewRHS, CCCode);
-
- // If ExpandSetCCOperands returned a scalar, use it.
- if (NewRHS.Val == 0) return NewLHS;
-
- // Otherwise, update N to have the operands specified.
- return DAG.UpdateNodeOperands(SDOperand(N, 0), NewLHS, NewRHS,
- DAG.getCondCode(CCCode));
-}
-
-/// ExpandSetCCOperands - Expand the operands of a comparison. This code is
-/// shared among BR_CC, SELECT_CC, and SETCC handlers.
-void DAGTypeLegalizer::ExpandSetCCOperands(SDOperand &NewLHS, SDOperand &NewRHS,
- ISD::CondCode &CCCode) {
- SDOperand LHSLo, LHSHi, RHSLo, RHSHi;
- GetExpandedOp(NewLHS, LHSLo, LHSHi);
- GetExpandedOp(NewRHS, RHSLo, RHSHi);
-
- MVT VT = NewLHS.getValueType();
- if (VT == MVT::ppcf128) {
- // FIXME: This generated code sucks. We want to generate
- // FCMP crN, hi1, hi2
- // BNE crN, L:
- // FCMP crN, lo1, lo2
- // The following can be improved, but not that much.
- SDOperand Tmp1, Tmp2, Tmp3;
- Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETEQ);
- Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, CCCode);
- Tmp3 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
- Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, ISD::SETNE);
- Tmp2 = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi, CCCode);
- Tmp1 = DAG.getNode(ISD::AND, Tmp1.getValueType(), Tmp1, Tmp2);
- NewLHS = DAG.getNode(ISD::OR, Tmp1.getValueType(), Tmp1, Tmp3);
- NewRHS = SDOperand(); // LHS is the result, not a compare.
- return;
- }
-
- if (CCCode == ISD::SETEQ || CCCode == ISD::SETNE) {
- if (RHSLo == RHSHi)
- if (ConstantSDNode *RHSCST = dyn_cast<ConstantSDNode>(RHSLo))
- if (RHSCST->isAllOnesValue()) {
- // Equality comparison to -1.
- NewLHS = DAG.getNode(ISD::AND, LHSLo.getValueType(), LHSLo, LHSHi);
- NewRHS = RHSLo;
- return;
- }
-
- NewLHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSLo, RHSLo);
- NewRHS = DAG.getNode(ISD::XOR, LHSLo.getValueType(), LHSHi, RHSHi);
- NewLHS = DAG.getNode(ISD::OR, NewLHS.getValueType(), NewLHS, NewRHS);
- NewRHS = DAG.getConstant(0, NewLHS.getValueType());
- return;
- }
-
- // If this is a comparison of the sign bit, just look at the top part.
- // X > -1, x < 0
- if (ConstantSDNode *CST = dyn_cast<ConstantSDNode>(NewRHS))
- if ((CCCode == ISD::SETLT && CST->isNullValue()) || // X < 0
- (CCCode == ISD::SETGT && CST->isAllOnesValue())) { // X > -1
- NewLHS = LHSHi;
- NewRHS = RHSHi;
- return;
- }
-
- // FIXME: This generated code sucks.
- ISD::CondCode LowCC;
- switch (CCCode) {
- default: assert(0 && "Unknown integer setcc!");
- case ISD::SETLT:
- case ISD::SETULT: LowCC = ISD::SETULT; break;
- case ISD::SETGT:
- case ISD::SETUGT: LowCC = ISD::SETUGT; break;
- case ISD::SETLE:
- case ISD::SETULE: LowCC = ISD::SETULE; break;
- case ISD::SETGE:
- case ISD::SETUGE: LowCC = ISD::SETUGE; break;
- }
-
- // Tmp1 = lo(op1) < lo(op2) // Always unsigned comparison
- // Tmp2 = hi(op1) < hi(op2) // Signedness depends on operands
- // dest = hi(op1) == hi(op2) ? Tmp1 : Tmp2;
-
- // NOTE: on targets without efficient SELECT of bools, we can always use
- // this identity: (B1 ? B2 : B3) --> (B1 & B2)|(!B1&B3)
- TargetLowering::DAGCombinerInfo DagCombineInfo(DAG, false, true, NULL);
- SDOperand Tmp1, Tmp2;
- Tmp1 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC,
- false, DagCombineInfo);
- if (!Tmp1.Val)
- Tmp1 = DAG.getSetCC(TLI.getSetCCResultType(LHSLo), LHSLo, RHSLo, LowCC);
- Tmp2 = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
- CCCode, false, DagCombineInfo);
- if (!Tmp2.Val)
- Tmp2 = DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
- DAG.getCondCode(CCCode));
-
- ConstantSDNode *Tmp1C = dyn_cast<ConstantSDNode>(Tmp1.Val);
- ConstantSDNode *Tmp2C = dyn_cast<ConstantSDNode>(Tmp2.Val);
- if ((Tmp1C && Tmp1C->isNullValue()) ||
- (Tmp2C && Tmp2C->isNullValue() &&
- (CCCode == ISD::SETLE || CCCode == ISD::SETGE ||
- CCCode == ISD::SETUGE || CCCode == ISD::SETULE)) ||
- (Tmp2C && Tmp2C->getAPIntValue() == 1 &&
- (CCCode == ISD::SETLT || CCCode == ISD::SETGT ||
- CCCode == ISD::SETUGT || CCCode == ISD::SETULT))) {
- // low part is known false, returns high part.
- // For LE / GE, if high part is known false, ignore the low part.
- // For LT / GT, if high part is known true, ignore the low part.
- NewLHS = Tmp2;
- NewRHS = SDOperand();
- return;
- }
-
- NewLHS = TLI.SimplifySetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
- ISD::SETEQ, false, DagCombineInfo);
- if (!NewLHS.Val)
- NewLHS = DAG.getSetCC(TLI.getSetCCResultType(LHSHi), LHSHi, RHSHi,
- ISD::SETEQ);
- NewLHS = DAG.getNode(ISD::SELECT, Tmp1.getValueType(),
- NewLHS, Tmp1, Tmp2);
- NewRHS = SDOperand();
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) {
- // FIXME: Add support for indexed stores.
- assert(OpNo == 1 && "Can only expand the stored value so far");
-
- MVT VT = N->getOperand(1).getValueType();
- MVT NVT = TLI.getTypeToTransformTo(VT);
- SDOperand Ch = N->getChain();
- SDOperand Ptr = N->getBasePtr();
- int SVOffset = N->getSrcValueOffset();
- unsigned Alignment = N->getAlignment();
- bool isVolatile = N->isVolatile();
- SDOperand Lo, Hi;
-
- assert(!(NVT.getSizeInBits() & 7) && "Expanded type not byte sized!");
-
- if (!N->isTruncatingStore()) {
- unsigned IncrementSize = 0;
- GetExpandedOp(N->getValue(), Lo, Hi);
- IncrementSize = Hi.getValueType().getSizeInBits()/8;
-
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
-
- Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(),
- SVOffset, isVolatile, Alignment);
-
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
- Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
- isVolatile, MinAlign(Alignment, IncrementSize));
- return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
- } else if (N->getMemoryVT().bitsLE(NVT)) {
- GetExpandedOp(N->getValue(), Lo, Hi);
- return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
- N->getMemoryVT(), isVolatile, Alignment);
- } else if (TLI.isLittleEndian()) {
- // Little-endian - low bits are at low addresses.
- GetExpandedOp(N->getValue(), Lo, Hi);
-
- Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
- isVolatile, Alignment);
-
- unsigned ExcessBits =
- N->getMemoryVT().getSizeInBits() - NVT.getSizeInBits();
- MVT NEVT = MVT::getIntegerVT(ExcessBits);
-
- // Increment the pointer to the other half.
- unsigned IncrementSize = NVT.getSizeInBits()/8;
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
- SVOffset+IncrementSize, NEVT,
- isVolatile, MinAlign(Alignment, IncrementSize));
- return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
- } else {
- // Big-endian - high bits are at low addresses. Favor aligned stores at
- // the cost of some bit-fiddling.
- GetExpandedOp(N->getValue(), Lo, Hi);
-
- MVT EVT = N->getMemoryVT();
- unsigned EBytes = EVT.getStoreSizeInBits()/8;
- unsigned IncrementSize = NVT.getSizeInBits()/8;
- unsigned ExcessBits = (EBytes - IncrementSize)*8;
- MVT HiVT = MVT::getIntegerVT(EVT.getSizeInBits() - ExcessBits);
-
- if (ExcessBits < NVT.getSizeInBits()) {
- // Transfer high bits from the top of Lo to the bottom of Hi.
- Hi = DAG.getNode(ISD::SHL, NVT, Hi,
- DAG.getConstant(NVT.getSizeInBits() - ExcessBits,
- TLI.getShiftAmountTy()));
- Hi = DAG.getNode(ISD::OR, NVT, Hi,
- DAG.getNode(ISD::SRL, NVT, Lo,
- DAG.getConstant(ExcessBits,
- TLI.getShiftAmountTy())));
- }
-
- // Store both the high bits and maybe some of the low bits.
- Hi = DAG.getTruncStore(Ch, Hi, Ptr, N->getSrcValue(),
- SVOffset, HiVT, isVolatile, Alignment);
-
- // Increment the pointer to the other half.
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- // Store the lowest ExcessBits bits in the second half.
- Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(),
- SVOffset+IncrementSize,
- MVT::getIntegerVT(ExcessBits),
- isVolatile, MinAlign(Alignment, IncrementSize));
- return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
- }
-}
-
-SDOperand DAGTypeLegalizer::ExpandOperand_BUILD_VECTOR(SDNode *N) {
- // The vector type is legal but the element type needs expansion.
- MVT VecVT = N->getValueType(0);
- unsigned NumElts = VecVT.getVectorNumElements();
- MVT OldVT = N->getOperand(0).getValueType();
- MVT NewVT = TLI.getTypeToTransformTo(OldVT);
-
- assert(OldVT.getSizeInBits() == 2 * NewVT.getSizeInBits() &&
- "Do not know how to expand this operand!");
-
- // Build a vector of twice the length out of the expanded elements.
- // For example <2 x i64> -> <4 x i32>.
- std::vector<SDOperand> NewElts;
- NewElts.reserve(NumElts*2);
-
- for (unsigned i = 0; i < NumElts; ++i) {
- SDOperand Lo, Hi;
- GetExpandedOp(N->getOperand(i), Lo, Hi);
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- NewElts.push_back(Lo);
- NewElts.push_back(Hi);
- }
-
- SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
- MVT::getVectorVT(NewVT, NewElts.size()),
- &NewElts[0], NewElts.size());
-
- // Convert the new vector to the old vector type.
- return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
-}
Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp?rev=52407&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesFloatToInt.cpp (removed)
@@ -1,357 +0,0 @@
-//===-- LegalizeTypesFloatToInt.cpp - LegalizeTypes float to int support --===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements float to integer conversion for LegalizeTypes. This
-// is the act of turning a computation in an invalid floating point type into
-// a computation in an integer type of the same size. For example, turning
-// f32 arithmetic into operations using i32. Also known as "soft float".
-// The result is equivalent to bitcasting the float value to the integer type.
-//
-//===----------------------------------------------------------------------===//
-
-#include "llvm/CodeGen/PseudoSourceValue.h"
-#include "llvm/DerivedTypes.h"
-#include "LegalizeTypes.h"
-using namespace llvm;
-
-/// GetFPLibCall - Return the right libcall for the given floating point type.
-static RTLIB::Libcall GetFPLibCall(MVT VT,
- RTLIB::Libcall Call_F32,
- RTLIB::Libcall Call_F64,
- RTLIB::Libcall Call_F80,
- RTLIB::Libcall Call_PPCF128) {
- return
- VT == MVT::f32 ? Call_F32 :
- VT == MVT::f64 ? Call_F64 :
- VT == MVT::f80 ? Call_F80 :
- VT == MVT::ppcf128 ? Call_PPCF128 :
- RTLIB::UNKNOWN_LIBCALL;
-}
-
-//===----------------------------------------------------------------------===//
-// Result Float to Integer Conversion.
-//===----------------------------------------------------------------------===//
-
-void DAGTypeLegalizer::FloatToIntResult(SDNode *N, unsigned ResNo) {
- DEBUG(cerr << "FloatToInt node result " << ResNo << ": "; N->dump(&DAG);
- cerr << "\n");
- SDOperand R = SDOperand();
-
- // FIXME: Custom lowering for float-to-int?
-#if 0
- // See if the target wants to custom convert this node to an integer.
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom) {
- // If the target wants to, allow it to lower this itself.
- if (SDNode *P = TLI.FloatToIntOperationResult(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;
- }
- }
-#endif
-
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "FloatToIntResult #" << ResNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to convert the result of this operator!");
- abort();
-
- case ISD::BIT_CONVERT: R = FloatToIntRes_BIT_CONVERT(N); break;
- case ISD::BUILD_PAIR: R = FloatToIntRes_BUILD_PAIR(N); break;
- case ISD::ConstantFP:
- R = FloatToIntRes_ConstantFP(cast<ConstantFPSDNode>(N));
- break;
- case ISD::FCOPYSIGN: R = FloatToIntRes_FCOPYSIGN(N); break;
- case ISD::LOAD: R = FloatToIntRes_LOAD(N); break;
- case ISD::SINT_TO_FP:
- case ISD::UINT_TO_FP: R = FloatToIntRes_XINT_TO_FP(N); break;
-
- case ISD::FADD: R = FloatToIntRes_FADD(N); break;
- case ISD::FMUL: R = FloatToIntRes_FMUL(N); break;
- case ISD::FSUB: R = FloatToIntRes_FSUB(N); break;
- }
-
- // If R is null, the sub-method took care of registering the result.
- if (R.Val)
- SetIntegerOp(SDOperand(N, ResNo), R);
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_BIT_CONVERT(SDNode *N) {
- return BitConvertToInteger(N->getOperand(0));
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_BUILD_PAIR(SDNode *N) {
- // Convert the inputs to integers, and build a new pair out of them.
- return DAG.getNode(ISD::BUILD_PAIR,
- TLI.getTypeToTransformTo(N->getValueType(0)),
- BitConvertToInteger(N->getOperand(0)),
- BitConvertToInteger(N->getOperand(1)));
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_ConstantFP(ConstantFPSDNode *N) {
- return DAG.getConstant(N->getValueAPF().convertToAPInt(),
- TLI.getTypeToTransformTo(N->getValueType(0)));
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_FADD(SDNode *N) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)),
- GetIntegerOp(N->getOperand(1)) };
- return MakeLibCall(GetFPLibCall(N->getValueType(0),
- RTLIB::ADD_F32,
- RTLIB::ADD_F64,
- RTLIB::ADD_F80,
- RTLIB::ADD_PPCF128),
- NVT, Ops, 2, false/*sign irrelevant*/);
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_FCOPYSIGN(SDNode *N) {
- SDOperand LHS = GetIntegerOp(N->getOperand(0));
- SDOperand RHS = BitConvertToInteger(N->getOperand(1));
-
- MVT LVT = LHS.getValueType();
- MVT RVT = RHS.getValueType();
-
- unsigned LSize = LVT.getSizeInBits();
- unsigned RSize = RVT.getSizeInBits();
-
- // First get the sign bit of second operand.
- SDOperand SignBit = DAG.getNode(ISD::SHL, RVT, DAG.getConstant(1, RVT),
- DAG.getConstant(RSize - 1,
- TLI.getShiftAmountTy()));
- SignBit = DAG.getNode(ISD::AND, RVT, RHS, SignBit);
-
- // Shift right or sign-extend it if the two operands have different types.
- int SizeDiff = RVT.getSizeInBits() - LVT.getSizeInBits();
- if (SizeDiff > 0) {
- SignBit = DAG.getNode(ISD::SRL, RVT, SignBit,
- DAG.getConstant(SizeDiff, TLI.getShiftAmountTy()));
- SignBit = DAG.getNode(ISD::TRUNCATE, LVT, SignBit);
- } else if (SizeDiff < 0) {
- SignBit = DAG.getNode(ISD::ANY_EXTEND, LVT, SignBit);
- SignBit = DAG.getNode(ISD::SHL, LVT, SignBit,
- DAG.getConstant(-SizeDiff, TLI.getShiftAmountTy()));
- }
-
- // Clear the sign bit of the first operand.
- SDOperand Mask = DAG.getNode(ISD::SHL, LVT, DAG.getConstant(1, LVT),
- DAG.getConstant(LSize - 1,
- TLI.getShiftAmountTy()));
- Mask = DAG.getNode(ISD::SUB, LVT, Mask, DAG.getConstant(1, LVT));
- LHS = DAG.getNode(ISD::AND, LVT, LHS, Mask);
-
- // Or the value with the sign bit.
- return DAG.getNode(ISD::OR, LVT, LHS, SignBit);
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_FMUL(SDNode *N) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)),
- GetIntegerOp(N->getOperand(1)) };
- return MakeLibCall(GetFPLibCall(N->getValueType(0),
- RTLIB::MUL_F32,
- RTLIB::MUL_F64,
- RTLIB::MUL_F80,
- RTLIB::MUL_PPCF128),
- NVT, Ops, 2, false/*sign irrelevant*/);
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_FSUB(SDNode *N) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- SDOperand Ops[2] = { GetIntegerOp(N->getOperand(0)),
- GetIntegerOp(N->getOperand(1)) };
- return MakeLibCall(GetFPLibCall(N->getValueType(0),
- RTLIB::SUB_F32,
- RTLIB::SUB_F64,
- RTLIB::SUB_F80,
- RTLIB::SUB_PPCF128),
- NVT, Ops, 2, false/*sign irrelevant*/);
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_LOAD(SDNode *N) {
- LoadSDNode *L = cast<LoadSDNode>(N);
- MVT VT = N->getValueType(0);
- MVT NVT = TLI.getTypeToTransformTo(VT);
-
- if (L->getExtensionType() == ISD::NON_EXTLOAD)
- return DAG.getLoad(L->getAddressingMode(), L->getExtensionType(),
- NVT, L->getChain(), L->getBasePtr(), L->getOffset(),
- L->getSrcValue(), L->getSrcValueOffset(), NVT,
- L->isVolatile(), L->getAlignment());
-
- // Do a non-extending load followed by FP_EXTEND.
- SDOperand NL = DAG.getLoad(L->getAddressingMode(), ISD::NON_EXTLOAD,
- L->getMemoryVT(), L->getChain(),
- L->getBasePtr(), L->getOffset(),
- L->getSrcValue(), L->getSrcValueOffset(),
- L->getMemoryVT(),
- L->isVolatile(), L->getAlignment());
- return BitConvertToInteger(DAG.getNode(ISD::FP_EXTEND, VT, NL));
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntRes_XINT_TO_FP(SDNode *N) {
- bool isSigned = N->getOpcode() == ISD::SINT_TO_FP;
- MVT DestVT = N->getValueType(0);
- SDOperand Op = N->getOperand(0);
-
- if (Op.getValueType() == MVT::i32) {
- // simple 32-bit [signed|unsigned] integer to float/double expansion
-
- // Get the stack frame index of a 8 byte buffer.
- SDOperand StackSlot = DAG.CreateStackTemporary(MVT::f64);
-
- // word offset constant for Hi/Lo address computation
- SDOperand Offset =
- DAG.getConstant(MVT(MVT::i32).getSizeInBits() / 8,
- TLI.getPointerTy());
- // set up Hi and Lo (into buffer) address based on endian
- SDOperand Hi = StackSlot;
- SDOperand Lo = DAG.getNode(ISD::ADD, TLI.getPointerTy(), StackSlot, Offset);
- if (TLI.isLittleEndian())
- std::swap(Hi, Lo);
-
- // if signed map to unsigned space
- SDOperand OpMapped;
- if (isSigned) {
- // constant used to invert sign bit (signed to unsigned mapping)
- SDOperand SignBit = DAG.getConstant(0x80000000u, MVT::i32);
- OpMapped = DAG.getNode(ISD::XOR, MVT::i32, Op, SignBit);
- } else {
- OpMapped = Op;
- }
- // store the lo of the constructed double - based on integer input
- SDOperand Store1 = DAG.getStore(DAG.getEntryNode(),
- OpMapped, Lo, NULL, 0);
- // 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.getStore(Store1, InitialHi, Hi, NULL, 0);
- // load the constructed double
- SDOperand Load = DAG.getLoad(MVT::f64, Store2, StackSlot, NULL, 0);
- // 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 (DestVT.bitsLT(MVT::f64)) {
- Result = DAG.getNode(ISD::FP_ROUND, DestVT, Sub,
- DAG.getIntPtrConstant(0));
- } else if (DestVT.bitsGT(MVT::f64)) {
- Result = DAG.getNode(ISD::FP_EXTEND, DestVT, Sub);
- }
- return BitConvertToInteger(Result);
- }
- assert(!isSigned && "Legalize cannot Expand SINT_TO_FP for i64 yet");
- SDOperand Tmp1 = DAG.getNode(ISD::SINT_TO_FP, DestVT, Op);
-
- SDOperand SignSet = DAG.getSetCC(TLI.getSetCCResultType(Op), Op,
- DAG.getConstant(0, Op.getValueType()),
- ISD::SETLT);
- SDOperand Zero = DAG.getIntPtrConstant(0), Four = DAG.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 (Op.getValueType().getSimpleVT()) {
- 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 = ConstantInt::get(Type::Int64Ty, 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,
- PseudoSourceValue::getConstantPool(), 0);
- else {
- FudgeInReg = DAG.getExtLoad(ISD::EXTLOAD, DestVT,
- DAG.getEntryNode(), CPIdx,
- PseudoSourceValue::getConstantPool(), 0,
- MVT::f32);
- }
-
- return BitConvertToInteger(DAG.getNode(ISD::FADD, DestVT, Tmp1, FudgeInReg));
-}
-
-
-//===----------------------------------------------------------------------===//
-// Operand Float to Integer Conversion..
-//===----------------------------------------------------------------------===//
-
-bool DAGTypeLegalizer::FloatToIntOperand(SDNode *N, unsigned OpNo) {
- DEBUG(cerr << "FloatToInt node operand " << OpNo << ": "; N->dump(&DAG);
- cerr << "\n");
- SDOperand Res(0, 0);
-
- // FIXME: Custom lowering for float-to-int?
-#if 0
- if (TLI.getOperationAction(N->getOpcode(), N->getOperand(OpNo).getValueType())
- == TargetLowering::Custom)
- Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
-#endif
-
- if (Res.Val == 0) {
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "FloatToIntOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to convert this operator's operand!");
- abort();
-
- case ISD::BIT_CONVERT: Res = FloatToIntOp_BIT_CONVERT(N); break;
- }
- }
-
- // If the result is null, the sub-method took care of registering results etc.
- if (!Res.Val) return false;
-
- // If the result is N, the sub-method updated N in place. Check to see if any
- // operands are new, and if so, mark them.
- if (Res.Val == N) {
- // Mark N as new and remark N and its operands. This allows us to correctly
- // revisit N if it needs another step of promotion and allows us to visit
- // any new operands to N.
- ReanalyzeNode(N);
- return true;
- }
-
- assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
- "Invalid operand expansion");
-
- ReplaceValueWith(SDOperand(N, 0), Res);
- return false;
-}
-
-SDOperand DAGTypeLegalizer::FloatToIntOp_BIT_CONVERT(SDNode *N) {
- return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
- GetIntegerOp(N->getOperand(0)));
-}
Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp?rev=52407&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesPromote.cpp (removed)
@@ -1,748 +0,0 @@
-//===-- LegalizeTypesPromote.cpp - Promotion for LegalizeTypes ------------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements promotion support for LegalizeTypes. Promotion is the
-// act of changing a computation in an invalid type to be a computation in a
-// larger type. For example, implementing i8 arithmetic in an i32 register (as
-// is often needed on powerpc for example).
-//
-//===----------------------------------------------------------------------===//
-
-#include "LegalizeTypes.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Result Promotion
-//===----------------------------------------------------------------------===//
-
-/// PromoteResult - This method is called when a result of a node is found to be
-/// in need of promotion to a larger type. At this point, the node may also
-/// have invalid operands or may have other results that need expansion, we just
-/// know that (at least) one result needs promotion.
-void DAGTypeLegalizer::PromoteResult(SDNode *N, unsigned ResNo) {
- DEBUG(cerr << "Promote node result: "; N->dump(&DAG); cerr << "\n");
- SDOperand Result = SDOperand();
-
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "PromoteResult #" << ResNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to promote this operator!");
- abort();
- case ISD::UNDEF: Result = PromoteResult_UNDEF(N); break;
- case ISD::Constant: Result = PromoteResult_Constant(N); break;
-
- case ISD::TRUNCATE: Result = PromoteResult_TRUNCATE(N); break;
- case ISD::SIGN_EXTEND:
- case ISD::ZERO_EXTEND:
- case ISD::ANY_EXTEND: Result = PromoteResult_INT_EXTEND(N); break;
- case ISD::FP_ROUND: Result = PromoteResult_FP_ROUND(N); break;
- case ISD::FP_TO_SINT:
- case ISD::FP_TO_UINT: Result = PromoteResult_FP_TO_XINT(N); break;
- case ISD::SETCC: Result = PromoteResult_SETCC(N); break;
- case ISD::LOAD: Result = PromoteResult_LOAD(cast<LoadSDNode>(N)); break;
- case ISD::BUILD_PAIR: Result = PromoteResult_BUILD_PAIR(N); break;
- case ISD::BIT_CONVERT: Result = PromoteResult_BIT_CONVERT(N); break;
-
- case ISD::AND:
- case ISD::OR:
- case ISD::XOR:
- case ISD::ADD:
- case ISD::SUB:
- case ISD::MUL: Result = PromoteResult_SimpleIntBinOp(N); break;
-
- case ISD::SDIV:
- case ISD::SREM: Result = PromoteResult_SDIV(N); break;
-
- case ISD::UDIV:
- case ISD::UREM: Result = PromoteResult_UDIV(N); break;
-
- case ISD::SHL: Result = PromoteResult_SHL(N); break;
- case ISD::SRA: Result = PromoteResult_SRA(N); break;
- case ISD::SRL: Result = PromoteResult_SRL(N); break;
-
- case ISD::SELECT: Result = PromoteResult_SELECT(N); break;
- case ISD::SELECT_CC: Result = PromoteResult_SELECT_CC(N); break;
-
- case ISD::CTLZ: Result = PromoteResult_CTLZ(N); break;
- case ISD::CTPOP: Result = PromoteResult_CTPOP(N); break;
- case ISD::CTTZ: Result = PromoteResult_CTTZ(N); break;
-
- case ISD::EXTRACT_VECTOR_ELT:
- Result = PromoteResult_EXTRACT_VECTOR_ELT(N);
- break;
- }
-
- // If Result is null, the sub-method took care of registering the result.
- if (Result.Val)
- SetPromotedOp(SDOperand(N, ResNo), Result);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_UNDEF(SDNode *N) {
- return DAG.getNode(ISD::UNDEF, TLI.getTypeToTransformTo(N->getValueType(0)));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_Constant(SDNode *N) {
- MVT VT = N->getValueType(0);
- // Zero extend things like i1, sign extend everything else. It shouldn't
- // matter in theory which one we pick, but this tends to give better code?
- unsigned Opc = VT.isByteSized() ? ISD::SIGN_EXTEND : ISD::ZERO_EXTEND;
- SDOperand Result = DAG.getNode(Opc, TLI.getTypeToTransformTo(VT),
- SDOperand(N, 0));
- assert(isa<ConstantSDNode>(Result) && "Didn't constant fold ext?");
- return Result;
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) {
- SDOperand Res;
-
- switch (getTypeAction(N->getOperand(0).getValueType())) {
- default: assert(0 && "Unknown type action!");
- case Legal:
- case Expand:
- Res = N->getOperand(0);
- break;
- case Promote:
- Res = GetPromotedOp(N->getOperand(0));
- break;
- }
-
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- assert(Res.getValueType().getSizeInBits() >= NVT.getSizeInBits() &&
- "Truncation doesn't make sense!");
- if (Res.getValueType() == NVT)
- return Res;
-
- // Truncate to NVT instead of VT
- return DAG.getNode(ISD::TRUNCATE, NVT, Res);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_INT_EXTEND(SDNode *N) {
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-
- if (getTypeAction(N->getOperand(0).getValueType()) == Promote) {
- SDOperand Res = GetPromotedOp(N->getOperand(0));
- assert(Res.getValueType().getSizeInBits() <= NVT.getSizeInBits() &&
- "Extension doesn't make sense!");
-
- // If the result and operand types are the same after promotion, simplify
- // to an in-register extension.
- if (NVT == Res.getValueType()) {
- // The high bits are not guaranteed to be anything. Insert an extend.
- if (N->getOpcode() == ISD::SIGN_EXTEND)
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res,
- DAG.getValueType(N->getOperand(0).getValueType()));
- if (N->getOpcode() == ISD::ZERO_EXTEND)
- return DAG.getZeroExtendInReg(Res, N->getOperand(0).getValueType());
- assert(N->getOpcode() == ISD::ANY_EXTEND && "Unknown integer extension!");
- return Res;
- }
- }
-
- // Otherwise, just extend the original operand all the way to the larger type.
- return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_FP_ROUND(SDNode *N) {
- // NOTE: Assumes input is legal.
- if (N->getConstantOperandVal(1) == 0)
- return DAG.getNode(ISD::FP_ROUND_INREG, N->getOperand(0).getValueType(),
- N->getOperand(0), DAG.getValueType(N->getValueType(0)));
- // If the precision discard isn't needed, just return the operand unrounded.
- return N->getOperand(0);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_FP_TO_XINT(SDNode *N) {
- SDOperand Op = N->getOperand(0);
- // If the operand needed to be promoted, do so now.
- if (getTypeAction(Op.getValueType()) == Promote)
- // The input result is prerounded, so we don't have to do anything special.
- Op = GetPromotedOp(Op);
-
- unsigned NewOpc = N->getOpcode();
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
-
- // If we're promoting a UINT to a larger size, check to see if the new node
- // will be legal. If it isn't, check to see if FP_TO_SINT is legal, since
- // we can use that instead. This allows us to generate better code for
- // FP_TO_UINT for small destination sizes on targets where FP_TO_UINT is not
- // legal, such as PowerPC.
- if (N->getOpcode() == ISD::FP_TO_UINT) {
- if (!TLI.isOperationLegal(ISD::FP_TO_UINT, NVT) &&
- (TLI.isOperationLegal(ISD::FP_TO_SINT, NVT) ||
- TLI.getOperationAction(ISD::FP_TO_SINT, NVT)==TargetLowering::Custom))
- NewOpc = ISD::FP_TO_SINT;
- }
-
- return DAG.getNode(NewOpc, NVT, Op);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) {
- assert(isTypeLegal(TLI.getSetCCResultType(N->getOperand(0)))
- && "SetCC type is not legal??");
- return DAG.getNode(ISD::SETCC, TLI.getSetCCResultType(N->getOperand(0)),
- N->getOperand(0), N->getOperand(1), N->getOperand(2));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_LOAD(LoadSDNode *N) {
- // FIXME: Add support for indexed loads.
- MVT NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- ISD::LoadExtType ExtType =
- ISD::isNON_EXTLoad(N) ? ISD::EXTLOAD : N->getExtensionType();
- SDOperand Res = DAG.getExtLoad(ExtType, NVT, N->getChain(), N->getBasePtr(),
- N->getSrcValue(), N->getSrcValueOffset(),
- N->getMemoryVT(), N->isVolatile(),
- N->getAlignment());
-
- // Legalized the chain result - switch anything that used the old chain to
- // use the new one.
- ReplaceValueWith(SDOperand(N, 1), Res.getValue(1));
- return Res;
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_BUILD_PAIR(SDNode *N) {
- // The pair element type may be legal, or may not promote to the same type as
- // the result, for example i14 = BUILD_PAIR (i7, i7). Handle all cases.
- return DAG.getNode(ISD::ANY_EXTEND,
- TLI.getTypeToTransformTo(N->getValueType(0)),
- JoinIntegers(N->getOperand(0), N->getOperand(1)));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_BIT_CONVERT(SDNode *N) {
- SDOperand InOp = N->getOperand(0);
- MVT InVT = InOp.getValueType();
- MVT NInVT = TLI.getTypeToTransformTo(InVT);
- MVT OutVT = TLI.getTypeToTransformTo(N->getValueType(0));
-
- switch (getTypeAction(InVT)) {
- default:
- assert(false && "Unknown type action!");
- break;
- case Legal:
- break;
- case Promote:
- if (OutVT.getSizeInBits() == NInVT.getSizeInBits())
- // The input promotes to the same size. Convert the promoted value.
- return DAG.getNode(ISD::BIT_CONVERT, OutVT, GetPromotedOp(InOp));
- break;
- case Expand:
- break;
- case FloatToInt:
- // Promote the integer operand by hand.
- return DAG.getNode(ISD::ANY_EXTEND, OutVT, GetIntegerOp(InOp));
- case Scalarize:
- // Convert the element to an integer and promote it by hand.
- return DAG.getNode(ISD::ANY_EXTEND, OutVT,
- BitConvertToInteger(GetScalarizedOp(InOp)));
- case Split:
- // For example, i32 = BIT_CONVERT v2i16 on alpha. Convert the split
- // pieces of the input into integers and reassemble in the final type.
- SDOperand Lo, Hi;
- GetSplitOp(N->getOperand(0), Lo, Hi);
- Lo = BitConvertToInteger(Lo);
- Hi = BitConvertToInteger(Hi);
-
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
-
- InOp = DAG.getNode(ISD::ANY_EXTEND,
- MVT::getIntegerVT(OutVT.getSizeInBits()),
- JoinIntegers(Lo, Hi));
- return DAG.getNode(ISD::BIT_CONVERT, OutVT, InOp);
- }
-
- // Otherwise, lower the bit-convert to a store/load from the stack, then
- // promote the load.
- SDOperand Op = CreateStackStoreLoad(InOp, N->getValueType(0));
- return PromoteResult_LOAD(cast<LoadSDNode>(Op.Val));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SimpleIntBinOp(SDNode *N) {
- // The input may have strange things in the top bits of the registers, but
- // these operations don't care. They may have weird bits going out, but
- // that too is okay if they are integer operations.
- SDOperand LHS = GetPromotedOp(N->getOperand(0));
- SDOperand RHS = GetPromotedOp(N->getOperand(1));
- return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SDIV(SDNode *N) {
- // Sign extend the input.
- SDOperand LHS = GetPromotedOp(N->getOperand(0));
- SDOperand RHS = GetPromotedOp(N->getOperand(1));
- MVT VT = N->getValueType(0);
- LHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, LHS.getValueType(), LHS,
- DAG.getValueType(VT));
- RHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, RHS.getValueType(), RHS,
- DAG.getValueType(VT));
-
- return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_UDIV(SDNode *N) {
- // Zero extend the input.
- SDOperand LHS = GetPromotedOp(N->getOperand(0));
- SDOperand RHS = GetPromotedOp(N->getOperand(1));
- MVT VT = N->getValueType(0);
- LHS = DAG.getZeroExtendInReg(LHS, VT);
- RHS = DAG.getZeroExtendInReg(RHS, VT);
-
- return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SHL(SDNode *N) {
- return DAG.getNode(ISD::SHL, TLI.getTypeToTransformTo(N->getValueType(0)),
- GetPromotedOp(N->getOperand(0)), N->getOperand(1));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SRA(SDNode *N) {
- // The input value must be properly sign extended.
- MVT VT = N->getValueType(0);
- MVT NVT = TLI.getTypeToTransformTo(VT);
- SDOperand Res = GetPromotedOp(N->getOperand(0));
- Res = DAG.getNode(ISD::SIGN_EXTEND_INREG, NVT, Res, DAG.getValueType(VT));
- return DAG.getNode(ISD::SRA, NVT, Res, N->getOperand(1));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SRL(SDNode *N) {
- // The input value must be properly zero extended.
- MVT VT = N->getValueType(0);
- MVT NVT = TLI.getTypeToTransformTo(VT);
- SDOperand Res = GetPromotedZExtOp(N->getOperand(0));
- return DAG.getNode(ISD::SRL, NVT, Res, N->getOperand(1));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SELECT(SDNode *N) {
- SDOperand LHS = GetPromotedOp(N->getOperand(1));
- SDOperand RHS = GetPromotedOp(N->getOperand(2));
- return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0),LHS,RHS);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_SELECT_CC(SDNode *N) {
- SDOperand LHS = GetPromotedOp(N->getOperand(2));
- SDOperand RHS = GetPromotedOp(N->getOperand(3));
- return DAG.getNode(ISD::SELECT_CC, LHS.getValueType(), N->getOperand(0),
- N->getOperand(1), LHS, RHS, N->getOperand(4));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_CTLZ(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- MVT OVT = N->getValueType(0);
- MVT NVT = Op.getValueType();
- // Zero extend to the promoted type and do the count there.
- Op = DAG.getNode(ISD::CTLZ, NVT, DAG.getZeroExtendInReg(Op, OVT));
- // Subtract off the extra leading bits in the bigger type.
- return DAG.getNode(ISD::SUB, NVT, Op,
- DAG.getConstant(NVT.getSizeInBits() -
- OVT.getSizeInBits(), NVT));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_CTPOP(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- MVT OVT = N->getValueType(0);
- MVT NVT = Op.getValueType();
- // Zero extend to the promoted type and do the count there.
- return DAG.getNode(ISD::CTPOP, NVT, DAG.getZeroExtendInReg(Op, OVT));
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_CTTZ(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- MVT OVT = N->getValueType(0);
- MVT NVT = Op.getValueType();
- // The count is the same in the promoted type except if the original
- // value was zero. This can be handled by setting the bit just off
- // the top of the original type.
- Op = DAG.getNode(ISD::OR, NVT, Op,
- // FIXME: Do this using an APINT constant.
- DAG.getConstant(1UL << OVT.getSizeInBits(), NVT));
- return DAG.getNode(ISD::CTTZ, NVT, Op);
-}
-
-SDOperand DAGTypeLegalizer::PromoteResult_EXTRACT_VECTOR_ELT(SDNode *N) {
- MVT OldVT = N->getValueType(0);
- SDOperand OldVec = N->getOperand(0);
- unsigned OldElts = OldVec.getValueType().getVectorNumElements();
-
- if (OldElts == 1) {
- assert(!isTypeLegal(OldVec.getValueType()) &&
- "Legal one-element vector of a type needing promotion!");
- // It is tempting to follow GetScalarizedOp by a call to GetPromotedOp,
- // but this would be wrong because the scalarized value may not yet have
- // been processed.
- return DAG.getNode(ISD::ANY_EXTEND, TLI.getTypeToTransformTo(OldVT),
- GetScalarizedOp(OldVec));
- }
-
- // Convert to a vector half as long with an element type of twice the width,
- // for example <4 x i16> -> <2 x i32>.
- assert(!(OldElts & 1) && "Odd length vectors not supported!");
- MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
- assert(OldVT.isSimple() && NewVT.isSimple());
-
- SDOperand NewVec = DAG.getNode(ISD::BIT_CONVERT,
- MVT::getVectorVT(NewVT, OldElts / 2),
- OldVec);
-
- // Extract the element at OldIdx / 2 from the new vector.
- SDOperand OldIdx = N->getOperand(1);
- SDOperand NewIdx = DAG.getNode(ISD::SRL, OldIdx.getValueType(), OldIdx,
- DAG.getConstant(1, TLI.getShiftAmountTy()));
- SDOperand Elt = DAG.getNode(ISD::EXTRACT_VECTOR_ELT, NewVT, NewVec, NewIdx);
-
- // Select the appropriate half of the element: Lo if OldIdx was even,
- // Hi if it was odd.
- SDOperand Lo = Elt;
- SDOperand Hi = DAG.getNode(ISD::SRL, NewVT, Elt,
- DAG.getConstant(OldVT.getSizeInBits(),
- TLI.getShiftAmountTy()));
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
-
- SDOperand Odd = DAG.getNode(ISD::AND, OldIdx.getValueType(), OldIdx,
- DAG.getConstant(1, TLI.getShiftAmountTy()));
- return DAG.getNode(ISD::SELECT, NewVT, Odd, Hi, Lo);
-}
-
-//===----------------------------------------------------------------------===//
-// Operand Promotion
-//===----------------------------------------------------------------------===//
-
-/// PromoteOperand - This method is called when the specified operand of the
-/// specified node is found to need promotion. At this point, all of the result
-/// types of the node are known to be legal, but other operands of the node may
-/// need promotion or expansion as well as the specified one.
-bool DAGTypeLegalizer::PromoteOperand(SDNode *N, unsigned OpNo) {
- DEBUG(cerr << "Promote node operand: "; N->dump(&DAG); cerr << "\n");
- SDOperand Res;
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "PromoteOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to promote this operator's operand!");
- abort();
-
- case ISD::ANY_EXTEND: Res = PromoteOperand_ANY_EXTEND(N); break;
- case ISD::ZERO_EXTEND: Res = PromoteOperand_ZERO_EXTEND(N); break;
- case ISD::SIGN_EXTEND: Res = PromoteOperand_SIGN_EXTEND(N); break;
- case ISD::TRUNCATE: Res = PromoteOperand_TRUNCATE(N); break;
- case ISD::FP_EXTEND: Res = PromoteOperand_FP_EXTEND(N); break;
- case ISD::FP_ROUND: Res = PromoteOperand_FP_ROUND(N); break;
- case ISD::SINT_TO_FP:
- case ISD::UINT_TO_FP: Res = PromoteOperand_INT_TO_FP(N); break;
- case ISD::BUILD_PAIR: Res = PromoteOperand_BUILD_PAIR(N); break;
-
- case ISD::SELECT: Res = PromoteOperand_SELECT(N, OpNo); break;
- case ISD::BRCOND: Res = PromoteOperand_BRCOND(N, OpNo); break;
- case ISD::BR_CC: Res = PromoteOperand_BR_CC(N, OpNo); break;
- case ISD::SETCC: Res = PromoteOperand_SETCC(N, OpNo); break;
-
- case ISD::STORE: Res = PromoteOperand_STORE(cast<StoreSDNode>(N),
- OpNo); break;
-
- case ISD::BUILD_VECTOR: Res = PromoteOperand_BUILD_VECTOR(N); break;
- case ISD::INSERT_VECTOR_ELT:
- Res = PromoteOperand_INSERT_VECTOR_ELT(N, OpNo);
- break;
-
- case ISD::RET: Res = PromoteOperand_RET(N, OpNo); break;
-
- case ISD::MEMBARRIER: Res = PromoteOperand_MEMBARRIER(N); break;
- }
-
- // If the result is null, the sub-method took care of registering results etc.
- if (!Res.Val) return false;
- // If the result is N, the sub-method updated N in place.
- if (Res.Val == N) {
- // Mark N as new and remark N and its operands. This allows us to correctly
- // revisit N if it needs another step of promotion and allows us to visit
- // any new operands to N.
- ReanalyzeNode(N);
- return true;
- }
-
- assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
- "Invalid operand expansion");
-
- ReplaceValueWith(SDOperand(N, 0), Res);
- return false;
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_ANY_EXTEND(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- return DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_ZERO_EXTEND(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
- return DAG.getZeroExtendInReg(Op, N->getOperand(0).getValueType());
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_SIGN_EXTEND(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- Op = DAG.getNode(ISD::ANY_EXTEND, N->getValueType(0), Op);
- return DAG.getNode(ISD::SIGN_EXTEND_INREG, Op.getValueType(),
- Op, DAG.getValueType(N->getOperand(0).getValueType()));
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_TRUNCATE(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), Op);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_FP_EXTEND(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- return DAG.getNode(ISD::FP_EXTEND, N->getValueType(0), Op);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_FP_ROUND(SDNode *N) {
- SDOperand Op = GetPromotedOp(N->getOperand(0));
- return DAG.getNode(ISD::FP_ROUND, N->getValueType(0), Op,
- DAG.getIntPtrConstant(0));
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) {
- SDOperand In = GetPromotedOp(N->getOperand(0));
- MVT OpVT = N->getOperand(0).getValueType();
- if (N->getOpcode() == ISD::UINT_TO_FP)
- In = DAG.getZeroExtendInReg(In, OpVT);
- else
- In = DAG.getNode(ISD::SIGN_EXTEND_INREG, In.getValueType(),
- In, DAG.getValueType(OpVT));
-
- return DAG.UpdateNodeOperands(SDOperand(N, 0), In);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_PAIR(SDNode *N) {
- // Since the result type is legal, the operands must promote to it.
- MVT OVT = N->getOperand(0).getValueType();
- SDOperand Lo = GetPromotedOp(N->getOperand(0));
- SDOperand Hi = GetPromotedOp(N->getOperand(1));
- assert(Lo.getValueType() == N->getValueType(0) && "Operand over promoted?");
-
- Lo = DAG.getZeroExtendInReg(Lo, OVT);
- Hi = DAG.getNode(ISD::SHL, N->getValueType(0), Hi,
- DAG.getConstant(OVT.getSizeInBits(),
- TLI.getShiftAmountTy()));
- return DAG.getNode(ISD::OR, N->getValueType(0), Lo, Hi);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_SELECT(SDNode *N, unsigned OpNo) {
- assert(OpNo == 0 && "Only know how to promote condition");
- SDOperand Cond = GetPromotedOp(N->getOperand(0)); // Promote the condition.
-
- // The top bits of the promoted condition are not necessarily zero, ensure
- // that the value is properly zero extended.
- unsigned BitWidth = Cond.getValueSizeInBits();
- if (!DAG.MaskedValueIsZero(Cond,
- APInt::getHighBitsSet(BitWidth, BitWidth-1)))
- Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
-
- // The chain (Op#0) and basic block destination (Op#2) are always legal types.
- return DAG.UpdateNodeOperands(SDOperand(N, 0), Cond, N->getOperand(1),
- N->getOperand(2));
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_BRCOND(SDNode *N, unsigned OpNo) {
- assert(OpNo == 1 && "only know how to promote condition");
- SDOperand Cond = GetPromotedOp(N->getOperand(1)); // Promote the condition.
-
- // The top bits of the promoted condition are not necessarily zero, ensure
- // that the value is properly zero extended.
- unsigned BitWidth = Cond.getValueSizeInBits();
- if (!DAG.MaskedValueIsZero(Cond,
- APInt::getHighBitsSet(BitWidth, BitWidth-1)))
- Cond = DAG.getZeroExtendInReg(Cond, MVT::i1);
-
- // The chain (Op#0) and basic block destination (Op#2) are always legal types.
- return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0), Cond,
- N->getOperand(2));
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_BR_CC(SDNode *N, unsigned OpNo) {
- assert(OpNo == 2 && "Don't know how to promote this operand");
-
- SDOperand LHS = N->getOperand(2);
- SDOperand RHS = N->getOperand(3);
- PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(1))->get());
-
- // The chain (Op#0), CC (#1) and basic block destination (Op#4) are always
- // legal types.
- return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
- N->getOperand(1), LHS, RHS, N->getOperand(4));
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_SETCC(SDNode *N, unsigned OpNo) {
- assert(OpNo == 0 && "Don't know how to promote this operand");
-
- SDOperand LHS = N->getOperand(0);
- SDOperand RHS = N->getOperand(1);
- PromoteSetCCOperands(LHS, RHS, cast<CondCodeSDNode>(N->getOperand(2))->get());
-
- // The CC (#2) is always legal.
- return DAG.UpdateNodeOperands(SDOperand(N, 0), LHS, RHS, N->getOperand(2));
-}
-
-/// PromoteSetCCOperands - Promote the operands of a comparison. This code is
-/// shared among BR_CC, SELECT_CC, and SETCC handlers.
-void DAGTypeLegalizer::PromoteSetCCOperands(SDOperand &NewLHS,SDOperand &NewRHS,
- ISD::CondCode CCCode) {
- MVT VT = NewLHS.getValueType();
-
- // Get the promoted values.
- NewLHS = GetPromotedOp(NewLHS);
- NewRHS = GetPromotedOp(NewRHS);
-
- // If this is an FP compare, the operands have already been extended.
- if (!NewLHS.getValueType().isInteger())
- return;
-
- // Otherwise, we have to insert explicit sign or zero extends. Note
- // that we could insert sign extends for ALL conditions, but zero extend
- // is cheaper on many machines (an AND instead of two shifts), so prefer
- // it.
- switch (CCCode) {
- default: assert(0 && "Unknown integer comparison!");
- case ISD::SETEQ:
- case ISD::SETNE:
- case ISD::SETUGE:
- case ISD::SETUGT:
- case ISD::SETULE:
- case ISD::SETULT:
- // ALL of these operations will work if we either sign or zero extend
- // the operands (including the unsigned comparisons!). Zero extend is
- // usually a simpler/cheaper operation, so prefer it.
- NewLHS = DAG.getZeroExtendInReg(NewLHS, VT);
- NewRHS = DAG.getZeroExtendInReg(NewRHS, VT);
- return;
- case ISD::SETGE:
- case ISD::SETGT:
- case ISD::SETLT:
- case ISD::SETLE:
- NewLHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewLHS.getValueType(), NewLHS,
- DAG.getValueType(VT));
- NewRHS = DAG.getNode(ISD::SIGN_EXTEND_INREG, NewRHS.getValueType(), NewRHS,
- DAG.getValueType(VT));
- return;
- }
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){
- // FIXME: Add support for indexed stores.
- SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
- int SVOffset = N->getSrcValueOffset();
- unsigned Alignment = N->getAlignment();
- bool isVolatile = N->isVolatile();
-
- SDOperand Val = GetPromotedOp(N->getValue()); // Get promoted value.
-
- assert(!N->isTruncatingStore() && "Cannot promote this store operand!");
-
- // Truncate the value and store the result.
- return DAG.getTruncStore(Ch, Val, Ptr, N->getSrcValue(),
- SVOffset, N->getMemoryVT(),
- isVolatile, Alignment);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_BUILD_VECTOR(SDNode *N) {
- // The vector type is legal but the element type is not. This implies
- // that the vector is a power-of-two in length and that the element
- // type does not have a strange size (eg: it is not i1).
- MVT VecVT = N->getValueType(0);
- unsigned NumElts = VecVT.getVectorNumElements();
- assert(!(NumElts & 1) && "Legal vector of one illegal element?");
-
- // Build a vector of half the length out of elements of twice the bitwidth.
- // For example <4 x i16> -> <2 x i32>.
- MVT OldVT = N->getOperand(0).getValueType();
- MVT NewVT = MVT::getIntegerVT(2 * OldVT.getSizeInBits());
- assert(OldVT.isSimple() && NewVT.isSimple());
-
- std::vector<SDOperand> NewElts;
- NewElts.reserve(NumElts/2);
-
- for (unsigned i = 0; i < NumElts; i += 2) {
- // Combine two successive elements into one promoted element.
- SDOperand Lo = N->getOperand(i);
- SDOperand Hi = N->getOperand(i+1);
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- NewElts.push_back(JoinIntegers(Lo, Hi));
- }
-
- SDOperand NewVec = DAG.getNode(ISD::BUILD_VECTOR,
- MVT::getVectorVT(NewVT, NewElts.size()),
- &NewElts[0], NewElts.size());
-
- // Convert the new vector to the old vector type.
- return DAG.getNode(ISD::BIT_CONVERT, VecVT, NewVec);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_INSERT_VECTOR_ELT(SDNode *N,
- unsigned OpNo) {
- if (OpNo == 1) {
- // Promote the inserted value. This is valid because the type does not
- // have to match the vector element type.
-
- // Check that any extra bits introduced will be truncated away.
- assert(N->getOperand(1).getValueType().getSizeInBits() >=
- N->getValueType(0).getVectorElementType().getSizeInBits() &&
- "Type of inserted value narrower than vector element type!");
- return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
- GetPromotedOp(N->getOperand(1)),
- N->getOperand(2));
- }
-
- assert(OpNo == 2 && "Different operand and result vector types?");
-
- // Promote the index.
- SDOperand Idx = N->getOperand(2);
- Idx = DAG.getZeroExtendInReg(GetPromotedOp(Idx), Idx.getValueType());
- return DAG.UpdateNodeOperands(SDOperand(N, 0), N->getOperand(0),
- N->getOperand(1), Idx);
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_RET(SDNode *N, unsigned OpNo) {
- assert(!(OpNo & 1) && "Return values should be legally typed!");
- assert((N->getNumOperands() & 1) && "Wrong number of operands!");
-
- // It's a flag. Promote all the flags in one hit, as an optimization.
- SmallVector<SDOperand, 8> NewValues(N->getNumOperands());
- NewValues[0] = N->getOperand(0); // The chain
- for (unsigned i = 1, e = N->getNumOperands(); i < e; i += 2) {
- // The return value.
- NewValues[i] = N->getOperand(i);
-
- // The flag.
- SDOperand Flag = N->getOperand(i + 1);
- if (getTypeAction(Flag.getValueType()) == Promote)
- // The promoted value may have rubbish in the new bits, but that
- // doesn't matter because those bits aren't queried anyway.
- Flag = GetPromotedOp(Flag);
- NewValues[i + 1] = Flag;
- }
-
- return DAG.UpdateNodeOperands(SDOperand (N, 0),
- &NewValues[0], NewValues.size());
-}
-
-SDOperand DAGTypeLegalizer::PromoteOperand_MEMBARRIER(SDNode *N) {
- SDOperand NewOps[6];
- NewOps[0] = N->getOperand(0);
- for (unsigned i = 1; i < array_lengthof(NewOps); ++i) {
- SDOperand Flag = GetPromotedOp(N->getOperand(i));
- NewOps[i] = DAG.getZeroExtendInReg(Flag, MVT::i1);
- }
- return DAG.UpdateNodeOperands(SDOperand (N, 0), NewOps,
- array_lengthof(NewOps));
-}
Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp?rev=52407&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesScalarize.cpp (removed)
@@ -1,233 +0,0 @@
-//===-- LegalizeTypesScalarize.cpp - Scalarization for LegalizeTypes ------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements scalarization support for LegalizeTypes. Scalarization
-// is the act of changing a computation in an invalid single-element vector type
-// to be a computation in its scalar element type. For example, implementing
-// <1 x f32> arithmetic in a scalar f32 register. This is needed as a base case
-// when scalarizing vector arithmetic like <4 x f32>, which eventually
-// decomposes to scalars if the target doesn't support v4f32 or v2f32 types.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LegalizeTypes.h"
-using namespace llvm;
-
-//===----------------------------------------------------------------------===//
-// Result Vector Scalarization: <1 x ty> -> ty.
-//===----------------------------------------------------------------------===//
-
-void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) {
- DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG);
- cerr << "\n");
- SDOperand R = SDOperand();
-
- // FIXME: Custom lowering for scalarization?
-#if 0
- // See if the target wants to custom expand this node.
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom) {
- // If the target wants to, allow it to lower this itself.
- if (SDNode *P = TLI.ExpandOperationResult(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;
- }
- }
-#endif
-
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "ScalarizeResult #" << ResNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to scalarize the result of this operator!");
- abort();
-
- case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break;
- case ISD::LOAD: R = ScalarizeRes_LOAD(cast<LoadSDNode>(N)); break;
- case ISD::ADD:
- case ISD::FADD:
- case ISD::SUB:
- case ISD::FSUB:
- case ISD::MUL:
- case ISD::FMUL:
- case ISD::SDIV:
- case ISD::UDIV:
- case ISD::FDIV:
- case ISD::SREM:
- case ISD::UREM:
- case ISD::FREM:
- case ISD::FPOW:
- case ISD::AND:
- case ISD::OR:
- case ISD::XOR: R = ScalarizeRes_BinOp(N); break;
- case ISD::FNEG:
- case ISD::FABS:
- case ISD::FSQRT:
- case ISD::FSIN:
- case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break;
- case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break;
- case ISD::BUILD_VECTOR: R = N->getOperand(0); break;
- case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break;
- case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break;
- case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break;
- case ISD::SELECT: R = ScalarizeRes_SELECT(N); break;
- }
-
- // If R is null, the sub-method took care of registering the result.
- if (R.Val)
- SetScalarizedOp(SDOperand(N, ResNo), R);
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) {
- return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType());
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) {
- // FIXME: Add support for indexed loads.
- SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(),
- N->getChain(), N->getBasePtr(),
- N->getSrcValue(), N->getSrcValueOffset(),
- N->isVolatile(), N->getAlignment());
-
- // Legalized the chain result - switch anything that used the old chain to
- // use the new one.
- ReplaceValueWith(SDOperand(N, 1), Result.getValue(1));
- return Result;
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) {
- SDOperand LHS = GetScalarizedOp(N->getOperand(0));
- SDOperand RHS = GetScalarizedOp(N->getOperand(1));
- return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
- SDOperand Op = GetScalarizedOp(N->getOperand(0));
- return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) {
- SDOperand Op = GetScalarizedOp(N->getOperand(0));
- return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1));
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) {
- // The value to insert may have a wider type than the vector element type,
- // so be sure to truncate it to the element type if necessary.
- SDOperand Op = N->getOperand(1);
- MVT EltVT = N->getValueType(0).getVectorElementType();
- if (Op.getValueType().bitsGT(EltVT))
- Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op);
- assert(Op.getValueType() == EltVT && "Invalid type for inserted value!");
- return Op;
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
- // Figure out if the scalar is the LHS or RHS and return it.
- SDOperand EltNum = N->getOperand(2).getOperand(0);
- unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
- return GetScalarizedOp(N->getOperand(Op));
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
- MVT NewVT = N->getValueType(0).getVectorElementType();
- return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
-}
-
-SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
- SDOperand LHS = GetScalarizedOp(N->getOperand(1));
- return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
- GetScalarizedOp(N->getOperand(2)));
-}
-
-
-//===----------------------------------------------------------------------===//
-// Operand Vector Scalarization <1 x ty> -> ty.
-//===----------------------------------------------------------------------===//
-
-bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
- DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
- cerr << "\n");
- SDOperand Res(0, 0);
-
- // FIXME: Should we support custom lowering for scalarization?
-#if 0
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom)
- Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
-#endif
-
- if (Res.Val == 0) {
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "ScalarizeOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to scalarize this operator's operand!");
- abort();
-
- case ISD::BIT_CONVERT:
- Res = ScalarizeOp_BIT_CONVERT(N); break;
-
- case ISD::EXTRACT_VECTOR_ELT:
- Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
-
- case ISD::STORE:
- Res = ScalarizeOp_STORE(cast<StoreSDNode>(N), OpNo); break;
- }
- }
-
- // If the result is null, the sub-method took care of registering results etc.
- if (!Res.Val) return false;
-
- // If the result is N, the sub-method updated N in place. Check to see if any
- // operands are new, and if so, mark them.
- if (Res.Val == N) {
- // Mark N as new and remark N and its operands. This allows us to correctly
- // revisit N if it needs another step of promotion and allows us to visit
- // any new operands to N.
- ReanalyzeNode(N);
- return true;
- }
-
- assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
- "Invalid operand expansion");
-
- ReplaceValueWith(SDOperand(N, 0), Res);
- return false;
-}
-
-/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
-/// to be scalarized, it must be <1 x ty>. Convert the element instead.
-SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
- SDOperand Elt = GetScalarizedOp(N->getOperand(0));
- return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
-}
-
-/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
-/// scalarized, it must be <1 x ty>, so just return the element, ignoring the
-/// index.
-SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) {
- return GetScalarizedOp(N->getOperand(0));
-}
-
-/// ScalarizeOp_STORE - If the value to store is a vector that needs to be
-/// scalarized, it must be <1 x ty>. Just store the element.
-SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) {
- // FIXME: Add support for indexed stores.
- assert(OpNo == 1 && "Do not know how to scalarize this operand!");
- return DAG.getStore(N->getChain(), GetScalarizedOp(N->getOperand(1)),
- N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
- N->isVolatile(), N->getAlignment());
-}
Removed: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp?rev=52407&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp (original)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeTypesSplit.cpp (removed)
@@ -1,582 +0,0 @@
-//===-- LegalizeTypesSplit.cpp - Vector Splitting for LegalizeTypes -------===//
-//
-// The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This file implements vector splitting support for LegalizeTypes. Vector
-// splitting is the act of changing a computation in an invalid vector type to
-// be a computation in multiple vectors of a smaller type. For example,
-// implementing <128 x f32> operations in terms of two <64 x f32> operations.
-//
-//===----------------------------------------------------------------------===//
-
-#include "LegalizeTypes.h"
-using namespace llvm;
-
-/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector
-/// type that needs to be split. This handles non-power of two vectors.
-static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) {
- MVT NewEltVT = InVT.getVectorElementType();
- unsigned NumElements = InVT.getVectorNumElements();
- if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector.
- NumElements >>= 1;
- Lo = Hi = MVT::getVectorVT(NewEltVT, NumElements);
- } else { // Non-power-of-two vectors.
- unsigned NewNumElts_Lo = 1 << Log2_32(NumElements);
- unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo;
- Lo = MVT::getVectorVT(NewEltVT, NewNumElts_Lo);
- Hi = MVT::getVectorVT(NewEltVT, NewNumElts_Hi);
- }
-}
-
-
-//===----------------------------------------------------------------------===//
-// Result Vector Splitting
-//===----------------------------------------------------------------------===//
-
-/// SplitResult - This method is called when the specified result of the
-/// specified node is found to need vector splitting. At this point, the node
-/// may also have invalid operands or may have other results that need
-/// legalization, we just know that (at least) one result needs vector
-/// splitting.
-void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) {
- DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n");
- SDOperand Lo, Hi;
-
-#if 0
- // See if the target wants to custom expand this node.
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom) {
- // If the target wants to, allow it to lower this itself.
- if (SDNode *P = TLI.ExpandOperationResult(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;
- }
- }
-#endif
-
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "SplitResult #" << ResNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to split the result of this operator!");
- abort();
-
- case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
- case ISD::LOAD: SplitRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
- case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break;
- case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
- case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break;
- case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break;
- case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break;
- case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break;
- case ISD::CTTZ:
- case ISD::CTLZ:
- case ISD::CTPOP:
- case ISD::FNEG:
- case ISD::FABS:
- case ISD::FSQRT:
- case ISD::FSIN:
- case ISD::FCOS:
- case ISD::FP_TO_SINT:
- case ISD::FP_TO_UINT:
- case ISD::SINT_TO_FP:
- case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break;
- case ISD::ADD:
- case ISD::SUB:
- case ISD::MUL:
- case ISD::FADD:
- case ISD::FSUB:
- case ISD::FMUL:
- case ISD::SDIV:
- case ISD::UDIV:
- case ISD::FDIV:
- case ISD::FPOW:
- case ISD::AND:
- case ISD::OR:
- case ISD::XOR:
- case ISD::UREM:
- case ISD::SREM:
- case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break;
- case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break;
- case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break;
- }
-
- // If Lo/Hi is null, the sub-method took care of registering results etc.
- if (Lo.Val)
- SetSplitOp(SDOperand(N, ResNo), Lo, Hi);
-}
-
-void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
- MVT LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
-
- Lo = DAG.getNode(ISD::UNDEF, LoVT);
- Hi = DAG.getNode(ISD::UNDEF, HiVT);
-}
-
-void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD,
- SDOperand &Lo, SDOperand &Hi) {
- // FIXME: Add support for indexed loads.
- MVT LoVT, HiVT;
- GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT);
-
- SDOperand Ch = LD->getChain();
- SDOperand Ptr = LD->getBasePtr();
- const Value *SV = LD->getSrcValue();
- int SVOffset = LD->getSrcValueOffset();
- unsigned Alignment = LD->getAlignment();
- bool isVolatile = LD->isVolatile();
-
- Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
- unsigned IncrementSize = LoVT.getSizeInBits()/8;
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
- SVOffset += IncrementSize;
- Alignment = MinAlign(Alignment, IncrementSize);
- Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
-
- // Build a factor node to remember that this load is independent of the
- // other one.
- SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
- Hi.getValue(1));
-
- // Legalized the chain result - switch anything that used the old chain to
- // use the new one.
- ReplaceValueWith(SDOperand(LD, 1), TF);
-}
-
-void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo,
- SDOperand &Hi) {
- Lo = N->getOperand(0);
- Hi = N->getOperand(1);
-}
-
-void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo,
- SDOperand &Hi) {
- SDOperand Vec = N->getOperand(0);
- SDOperand Elt = N->getOperand(1);
- SDOperand Idx = N->getOperand(2);
- GetSplitOp(Vec, Lo, Hi);
-
- if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
- unsigned IdxVal = CIdx->getValue();
- unsigned LoNumElts = Lo.getValueType().getVectorNumElements();
- if (IdxVal < LoNumElts)
- Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, Lo.getValueType(), Lo, Elt, Idx);
- else
- Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, Elt,
- DAG.getIntPtrConstant(IdxVal - LoNumElts));
- return;
- }
-
- // Spill the vector to the stack.
- MVT VecVT = Vec.getValueType();
- SDOperand StackPtr = DAG.CreateStackTemporary(VecVT);
- SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
-
- // Store the new element.
- SDOperand EltPtr = GetVectorElementPointer(StackPtr,
- VecVT.getVectorElementType(), Idx);
- Store = DAG.getStore(Store, Elt, EltPtr, NULL, 0);
-
- // Reload the vector from the stack.
- SDOperand Load = DAG.getLoad(VecVT, Store, StackPtr, NULL, 0);
-
- // Split it.
- SplitRes_LOAD(cast<LoadSDNode>(Load.Val), Lo, Hi);
-}
-
-void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // Build the low part.
- SDOperand Mask = N->getOperand(2);
- SmallVector<SDOperand, 16> Ops;
- MVT LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
- MVT EltVT = LoVT.getVectorElementType();
- unsigned LoNumElts = LoVT.getVectorNumElements();
- unsigned NumElements = Mask.getNumOperands();
-
- // Insert all of the elements from the input that are needed. We use
- // buildvector of extractelement here because the input vectors will have
- // to be legalized, so this makes the code simpler.
- for (unsigned i = 0; i != LoNumElts; ++i) {
- unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
- SDOperand InVec = N->getOperand(0);
- if (Idx >= NumElements) {
- InVec = N->getOperand(1);
- Idx -= NumElements;
- }
- Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec,
- DAG.getIntPtrConstant(Idx)));
- }
- Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size());
- Ops.clear();
-
- for (unsigned i = LoNumElts; i != NumElements; ++i) {
- unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
- SDOperand InVec = N->getOperand(0);
- if (Idx >= NumElements) {
- InVec = N->getOperand(1);
- Idx -= NumElements;
- }
- Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec,
- DAG.getIntPtrConstant(Idx)));
- }
- Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size());
-}
-
-void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo,
- SDOperand &Hi) {
- MVT LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
- unsigned LoNumElts = LoVT.getVectorNumElements();
- SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
- Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size());
-
- SmallVector<SDOperand, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
- Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size());
-}
-
-void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // FIXME: Handle non-power-of-two vectors?
- unsigned NumSubvectors = N->getNumOperands() / 2;
- if (NumSubvectors == 1) {
- Lo = N->getOperand(0);
- Hi = N->getOperand(1);
- return;
- }
-
- MVT LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
-
- SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
- Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size());
-
- SmallVector<SDOperand, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
- Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size());
-}
-
-void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
- SDOperand &Lo, SDOperand &Hi) {
- // We know the result is a vector. The input may be either a vector or a
- // scalar value.
- MVT LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
-
- SDOperand InOp = N->getOperand(0);
- MVT InVT = InOp.getValueType();
-
- // Handle some special cases efficiently.
- switch (getTypeAction(InVT)) {
- default:
- assert(false && "Unknown type action!");
- case Legal:
- case FloatToInt:
- case Promote:
- case Scalarize:
- break;
- case Expand:
- // A scalar to vector conversion, where the scalar needs expansion.
- // If the vector is being split in two then we can just convert the
- // expanded pieces.
- if (LoVT == HiVT) {
- GetExpandedOp(InOp, Lo, Hi);
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
- return;
- }
- break;
- case Split:
- // If the input is a vector that needs to be split, convert each split
- // piece of the input now.
- GetSplitOp(InOp, Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
- return;
- }
-
- // In the general case, convert the input to an integer and split it by hand.
- MVT LoIntVT = MVT::getIntegerVT(LoVT.getSizeInBits());
- MVT HiIntVT = MVT::getIntegerVT(HiVT.getSizeInBits());
- if (TLI.isBigEndian())
- std::swap(LoIntVT, HiIntVT);
-
- SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
-
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
- Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
- Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
-}
-
-void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
- SDOperand LHSLo, LHSHi;
- GetSplitOp(N->getOperand(0), LHSLo, LHSHi);
- SDOperand RHSLo, RHSHi;
- GetSplitOp(N->getOperand(1), RHSLo, RHSHi);
-
- Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo);
- Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi);
-}
-
-void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
- // Get the dest types. This doesn't always match input types, e.g. int_to_fp.
- MVT LoVT, HiVT;
- GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
-
- GetSplitOp(N->getOperand(0), Lo, Hi);
- Lo = DAG.getNode(N->getOpcode(), LoVT, Lo);
- Hi = DAG.getNode(N->getOpcode(), HiVT, Hi);
-}
-
-void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
- GetSplitOp(N->getOperand(0), Lo, Hi);
- Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1));
- Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1));
-}
-
-
-void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){
- SDOperand LL, LH, RL, RH;
- GetSplitOp(N->getOperand(1), LL, LH);
- GetSplitOp(N->getOperand(2), RL, RH);
-
- SDOperand Cond = N->getOperand(0);
- Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL);
- Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH);
-}
-
-
-//===----------------------------------------------------------------------===//
-// Operand Vector Splitting
-//===----------------------------------------------------------------------===//
-
-/// SplitOperand - This method is called when the specified operand of the
-/// specified node is found to need vector splitting. At this point, all of the
-/// result types of the node are known to be legal, but other operands of the
-/// node may need legalization as well as the specified one.
-bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) {
- DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n");
- SDOperand Res(0, 0);
-
-#if 0
- if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
- TargetLowering::Custom)
- Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
-#endif
-
- if (Res.Val == 0) {
- switch (N->getOpcode()) {
- default:
-#ifndef NDEBUG
- cerr << "SplitOperand Op #" << OpNo << ": ";
- N->dump(&DAG); cerr << "\n";
-#endif
- assert(0 && "Do not know how to split this operator's operand!");
- abort();
- case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N), OpNo); break;
- case ISD::RET: Res = SplitOp_RET(N, OpNo); break;
-
- case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break;
-
- case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break;
- case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break;
- case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break;
- }
- }
-
- // If the result is null, the sub-method took care of registering results etc.
- if (!Res.Val) return false;
-
- // If the result is N, the sub-method updated N in place. Check to see if any
- // operands are new, and if so, mark them.
- if (Res.Val == N) {
- // Mark N as new and remark N and its operands. This allows us to correctly
- // revisit N if it needs another step of promotion and allows us to visit
- // any new operands to N.
- ReanalyzeNode(N);
- return true;
- }
-
- assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
- "Invalid operand expansion");
-
- ReplaceValueWith(SDOperand(N, 0), Res);
- return false;
-}
-
-SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) {
- // FIXME: Add support for indexed stores.
- assert(OpNo == 1 && "Can only split the stored value");
-
- SDOperand Ch = N->getChain();
- SDOperand Ptr = N->getBasePtr();
- int SVOffset = N->getSrcValueOffset();
- unsigned Alignment = N->getAlignment();
- bool isVol = N->isVolatile();
- SDOperand Lo, Hi;
- GetSplitOp(N->getOperand(1), Lo, Hi);
-
- unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8;
-
- Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment);
-
- // Increment the pointer to the other half.
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- DAG.getIntPtrConstant(IncrementSize));
-
- Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
- isVol, MinAlign(Alignment, IncrementSize));
- return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
-}
-
-SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) {
- assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far");
- // FIXME: Returns of gcc generic vectors larger than a legal vector
- // type should be returned by reference!
- SDOperand Lo, Hi;
- GetSplitOp(N->getOperand(1), Lo, Hi);
-
- SDOperand Chain = N->getOperand(0); // The chain.
- SDOperand Sign = N->getOperand(2); // Signness
-
- return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign);
-}
-
-SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) {
- // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will
- // end up being split all the way down to individual components. Convert the
- // split pieces into integers and reassemble.
- SDOperand Lo, Hi;
- GetSplitOp(N->getOperand(0), Lo, Hi);
- Lo = BitConvertToInteger(Lo);
- Hi = BitConvertToInteger(Hi);
-
- if (TLI.isBigEndian())
- std::swap(Lo, Hi);
-
- return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
- JoinIntegers(Lo, Hi));
-}
-
-SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) {
- SDOperand Vec = N->getOperand(0);
- SDOperand Idx = N->getOperand(1);
- MVT VecVT = Vec.getValueType();
-
- if (isa<ConstantSDNode>(Idx)) {
- uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();
- assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!");
-
- SDOperand Lo, Hi;
- GetSplitOp(Vec, Lo, Hi);
-
- uint64_t LoElts = Lo.getValueType().getVectorNumElements();
-
- if (IdxVal < LoElts)
- return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx);
- else
- return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi,
- DAG.getConstant(IdxVal - LoElts,
- Idx.getValueType()));
- }
-
- // Store the vector to the stack.
- MVT EltVT = VecVT.getVectorElementType();
- SDOperand StackPtr = DAG.CreateStackTemporary(VecVT);
- SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
-
- // Load back the required element.
- StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx);
- return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0);
-}
-
-SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) {
- // We know that the extracted result type is legal. For now, assume the index
- // is a constant.
- MVT SubVT = N->getValueType(0);
- SDOperand Idx = N->getOperand(1);
- SDOperand Lo, Hi;
- GetSplitOp(N->getOperand(0), Lo, Hi);
-
- uint64_t LoElts = Lo.getValueType().getVectorNumElements();
- uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();
-
- if (IdxVal < LoElts) {
- assert(IdxVal + SubVT.getVectorNumElements() <= LoElts &&
- "Extracted subvector crosses vector split!");
- return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Lo, Idx);
- } else {
- return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Hi,
- DAG.getConstant(IdxVal - LoElts, Idx.getValueType()));
- }
-}
-
-SDOperand DAGTypeLegalizer::SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo) {
- assert(OpNo == 2 && "Shuffle source type differs from result type?");
- SDOperand Mask = N->getOperand(2);
- unsigned MaskLength = Mask.getValueType().getVectorNumElements();
- unsigned LargestMaskEntryPlusOne = 2 * MaskLength;
- unsigned MinimumBitWidth = Log2_32_Ceil(LargestMaskEntryPlusOne);
-
- // Look for a legal vector type to place the mask values in.
- // Note that there may not be *any* legal vector-of-integer
- // type for which the element type is legal!
- for (MVT::SimpleValueType EltVT = MVT::FIRST_INTEGER_VALUETYPE;
- EltVT <= MVT::LAST_INTEGER_VALUETYPE;
- // Integer values types are consecutively numbered. Exploit this.
- EltVT = MVT::SimpleValueType(EltVT + 1)) {
-
- // Is the element type big enough to hold the values?
- if (MVT(EltVT).getSizeInBits() < MinimumBitWidth)
- // Nope.
- continue;
-
- // Is the vector type legal?
- MVT VecVT = MVT::getVectorVT(EltVT, MaskLength);
- if (!isTypeLegal(VecVT))
- // Nope.
- continue;
-
- // If the element type is not legal, find a larger legal type to use for
- // the BUILD_VECTOR operands. This is an ugly hack, but seems to work!
- // FIXME: The real solution is to change VECTOR_SHUFFLE into a variadic
- // node where the shuffle mask is a list of integer operands, #2 .. #2+n.
- for (MVT::SimpleValueType OpVT = EltVT; OpVT <= MVT::LAST_INTEGER_VALUETYPE;
- // Integer values types are consecutively numbered. Exploit this.
- OpVT = MVT::SimpleValueType(OpVT + 1)) {
- if (!isTypeLegal(OpVT))
- continue;
-
- // Success! Rebuild the vector using the legal types.
- SmallVector<SDOperand, 16> Ops(MaskLength);
- for (unsigned i = 0; i < MaskLength; ++i) {
- uint64_t Idx =
- cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
- Ops[i] = DAG.getConstant(Idx, OpVT);
- }
- return DAG.UpdateNodeOperands(SDOperand(N,0),
- N->getOperand(0), N->getOperand(1),
- DAG.getNode(ISD::BUILD_VECTOR,
- VecVT, &Ops[0], Ops.size()));
- }
-
- // Continuing is pointless - failure is certain.
- break;
- }
- assert(false && "Failed to find an appropriate mask type!");
- return SDOperand(N, 0);
-}
Added: llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp?rev=52408&view=auto
==============================================================================
--- llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp (added)
+++ llvm/trunk/lib/CodeGen/SelectionDAG/LegalizeVectorTypes.cpp Tue Jun 17 09:27:01 2008
@@ -0,0 +1,806 @@
+//===------- LegalizeVectorTypes.cpp - Legalization of vector types -------===//
+//
+// The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+//
+// This file performs vector type splitting and scalarization for LegalizeTypes.
+// Scalarization is the act of changing a computation in an illegal one-element
+// vector type to be a computation in its scalar element type. For example,
+// implementing <1 x f32> arithmetic in a scalar f32 register. This is needed
+// as a base case when scalarizing vector arithmetic like <4 x f32>, which
+// eventually decomposes to scalars if the target doesn't support v4f32 or v2f32
+// types.
+// Splitting is the act of changing a computation in an invalid vector type to
+// be a computation in multiple vectors of a smaller type. For example,
+// implementing <128 x f32> operations in terms of two <64 x f32> operations.
+//
+//===----------------------------------------------------------------------===//
+
+#include "LegalizeTypes.h"
+using namespace llvm;
+
+//===----------------------------------------------------------------------===//
+// Result Vector Scalarization: <1 x ty> -> ty.
+//===----------------------------------------------------------------------===//
+
+void DAGTypeLegalizer::ScalarizeResult(SDNode *N, unsigned ResNo) {
+ DEBUG(cerr << "Scalarize node result " << ResNo << ": "; N->dump(&DAG);
+ cerr << "\n");
+ SDOperand R = SDOperand();
+
+ // FIXME: Custom lowering for scalarization?
+#if 0
+ // See if the target wants to custom expand this node.
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ if (SDNode *P = TLI.ExpandOperationResult(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;
+ }
+ }
+#endif
+
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "ScalarizeResult #" << ResNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to scalarize the result of this operator!");
+ abort();
+
+ case ISD::UNDEF: R = ScalarizeRes_UNDEF(N); break;
+ case ISD::LOAD: R = ScalarizeRes_LOAD(cast<LoadSDNode>(N)); break;
+ case ISD::ADD:
+ case ISD::FADD:
+ case ISD::SUB:
+ case ISD::FSUB:
+ case ISD::MUL:
+ case ISD::FMUL:
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::FDIV:
+ case ISD::SREM:
+ case ISD::UREM:
+ case ISD::FREM:
+ case ISD::FPOW:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR: R = ScalarizeRes_BinOp(N); break;
+ case ISD::FNEG:
+ case ISD::FABS:
+ case ISD::FSQRT:
+ case ISD::FSIN:
+ case ISD::FCOS: R = ScalarizeRes_UnaryOp(N); break;
+ case ISD::FPOWI: R = ScalarizeRes_FPOWI(N); break;
+ case ISD::BUILD_VECTOR: R = N->getOperand(0); break;
+ case ISD::INSERT_VECTOR_ELT: R = ScalarizeRes_INSERT_VECTOR_ELT(N); break;
+ case ISD::VECTOR_SHUFFLE: R = ScalarizeRes_VECTOR_SHUFFLE(N); break;
+ case ISD::BIT_CONVERT: R = ScalarizeRes_BIT_CONVERT(N); break;
+ case ISD::SELECT: R = ScalarizeRes_SELECT(N); break;
+ }
+
+ // If R is null, the sub-method took care of registering the result.
+ if (R.Val)
+ SetScalarizedVector(SDOperand(N, ResNo), R);
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_UNDEF(SDNode *N) {
+ return DAG.getNode(ISD::UNDEF, N->getValueType(0).getVectorElementType());
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_LOAD(LoadSDNode *N) {
+ // FIXME: Add support for indexed loads.
+ SDOperand Result = DAG.getLoad(N->getValueType(0).getVectorElementType(),
+ N->getChain(), N->getBasePtr(),
+ N->getSrcValue(), N->getSrcValueOffset(),
+ N->isVolatile(), N->getAlignment());
+
+ // Legalized the chain result - switch anything that used the old chain to
+ // use the new one.
+ ReplaceValueWith(SDOperand(N, 1), Result.getValue(1));
+ return Result;
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_BinOp(SDNode *N) {
+ SDOperand LHS = GetScalarizedVector(N->getOperand(0));
+ SDOperand RHS = GetScalarizedVector(N->getOperand(1));
+ return DAG.getNode(N->getOpcode(), LHS.getValueType(), LHS, RHS);
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_UnaryOp(SDNode *N) {
+ SDOperand Op = GetScalarizedVector(N->getOperand(0));
+ return DAG.getNode(N->getOpcode(), Op.getValueType(), Op);
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_FPOWI(SDNode *N) {
+ SDOperand Op = GetScalarizedVector(N->getOperand(0));
+ return DAG.getNode(ISD::FPOWI, Op.getValueType(), Op, N->getOperand(1));
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_INSERT_VECTOR_ELT(SDNode *N) {
+ // The value to insert may have a wider type than the vector element type,
+ // so be sure to truncate it to the element type if necessary.
+ SDOperand Op = N->getOperand(1);
+ MVT EltVT = N->getValueType(0).getVectorElementType();
+ if (Op.getValueType().bitsGT(EltVT))
+ Op = DAG.getNode(ISD::TRUNCATE, EltVT, Op);
+ assert(Op.getValueType() == EltVT && "Invalid type for inserted value!");
+ return Op;
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_VECTOR_SHUFFLE(SDNode *N) {
+ // Figure out if the scalar is the LHS or RHS and return it.
+ SDOperand EltNum = N->getOperand(2).getOperand(0);
+ unsigned Op = cast<ConstantSDNode>(EltNum)->getValue() != 0;
+ return GetScalarizedVector(N->getOperand(Op));
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_BIT_CONVERT(SDNode *N) {
+ MVT NewVT = N->getValueType(0).getVectorElementType();
+ return DAG.getNode(ISD::BIT_CONVERT, NewVT, N->getOperand(0));
+}
+
+SDOperand DAGTypeLegalizer::ScalarizeRes_SELECT(SDNode *N) {
+ SDOperand LHS = GetScalarizedVector(N->getOperand(1));
+ return DAG.getNode(ISD::SELECT, LHS.getValueType(), N->getOperand(0), LHS,
+ GetScalarizedVector(N->getOperand(2)));
+}
+
+
+//===----------------------------------------------------------------------===//
+// Operand Vector Scalarization <1 x ty> -> ty.
+//===----------------------------------------------------------------------===//
+
+bool DAGTypeLegalizer::ScalarizeOperand(SDNode *N, unsigned OpNo) {
+ DEBUG(cerr << "Scalarize node operand " << OpNo << ": "; N->dump(&DAG);
+ cerr << "\n");
+ SDOperand Res(0, 0);
+
+ // FIXME: Should we support custom lowering for scalarization?
+#if 0
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom)
+ Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+#endif
+
+ if (Res.Val == 0) {
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "ScalarizeOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to scalarize this operator's operand!");
+ abort();
+
+ case ISD::BIT_CONVERT:
+ Res = ScalarizeOp_BIT_CONVERT(N); break;
+
+ case ISD::EXTRACT_VECTOR_ELT:
+ Res = ScalarizeOp_EXTRACT_VECTOR_ELT(N); break;
+
+ case ISD::STORE:
+ Res = ScalarizeOp_STORE(cast<StoreSDNode>(N), OpNo); break;
+ }
+ }
+
+ // If the result is null, the sub-method took care of registering results etc.
+ if (!Res.Val) return false;
+
+ // If the result is N, the sub-method updated N in place. Check to see if any
+ // operands are new, and if so, mark them.
+ if (Res.Val == N) {
+ // Mark N as new and remark N and its operands. This allows us to correctly
+ // revisit N if it needs another step of promotion and allows us to visit
+ // any new operands to N.
+ ReanalyzeNode(N);
+ return true;
+ }
+
+ assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+ "Invalid operand expansion");
+
+ ReplaceValueWith(SDOperand(N, 0), Res);
+ return false;
+}
+
+/// ScalarizeOp_BIT_CONVERT - If the value to convert is a vector that needs
+/// to be scalarized, it must be <1 x ty>. Convert the element instead.
+SDOperand DAGTypeLegalizer::ScalarizeOp_BIT_CONVERT(SDNode *N) {
+ SDOperand Elt = GetScalarizedVector(N->getOperand(0));
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0), Elt);
+}
+
+/// ScalarizeOp_EXTRACT_VECTOR_ELT - If the input is a vector that needs to be
+/// scalarized, it must be <1 x ty>, so just return the element, ignoring the
+/// index.
+SDOperand DAGTypeLegalizer::ScalarizeOp_EXTRACT_VECTOR_ELT(SDNode *N) {
+ return GetScalarizedVector(N->getOperand(0));
+}
+
+/// ScalarizeOp_STORE - If the value to store is a vector that needs to be
+/// scalarized, it must be <1 x ty>. Just store the element.
+SDOperand DAGTypeLegalizer::ScalarizeOp_STORE(StoreSDNode *N, unsigned OpNo) {
+ // FIXME: Add support for indexed stores.
+ assert(OpNo == 1 && "Do not know how to scalarize this operand!");
+ return DAG.getStore(N->getChain(), GetScalarizedVector(N->getOperand(1)),
+ N->getBasePtr(), N->getSrcValue(), N->getSrcValueOffset(),
+ N->isVolatile(), N->getAlignment());
+}
+
+
+/// GetSplitDestVTs - Compute the VTs needed for the low/hi parts of a vector
+/// type that needs to be split. This handles non-power of two vectors.
+static void GetSplitDestVTs(MVT InVT, MVT &Lo, MVT &Hi) {
+ MVT NewEltVT = InVT.getVectorElementType();
+ unsigned NumElements = InVT.getVectorNumElements();
+ if ((NumElements & (NumElements-1)) == 0) { // Simple power of two vector.
+ NumElements >>= 1;
+ Lo = Hi = MVT::getVectorVT(NewEltVT, NumElements);
+ } else { // Non-power-of-two vectors.
+ unsigned NewNumElts_Lo = 1 << Log2_32(NumElements);
+ unsigned NewNumElts_Hi = NumElements - NewNumElts_Lo;
+ Lo = MVT::getVectorVT(NewEltVT, NewNumElts_Lo);
+ Hi = MVT::getVectorVT(NewEltVT, NewNumElts_Hi);
+ }
+}
+
+
+//===----------------------------------------------------------------------===//
+// Result Vector Splitting
+//===----------------------------------------------------------------------===//
+
+/// SplitResult - This method is called when the specified result of the
+/// specified node is found to need vector splitting. At this point, the node
+/// may also have invalid operands or may have other results that need
+/// legalization, we just know that (at least) one result needs vector
+/// splitting.
+void DAGTypeLegalizer::SplitResult(SDNode *N, unsigned ResNo) {
+ DEBUG(cerr << "Split node result: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Lo, Hi;
+
+#if 0
+ // See if the target wants to custom expand this node.
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ if (SDNode *P = TLI.ExpandOperationResult(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;
+ }
+ }
+#endif
+
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "SplitResult #" << ResNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to split the result of this operator!");
+ abort();
+
+ case ISD::UNDEF: SplitRes_UNDEF(N, Lo, Hi); break;
+ case ISD::LOAD: SplitRes_LOAD(cast<LoadSDNode>(N), Lo, Hi); break;
+ case ISD::BUILD_PAIR: SplitRes_BUILD_PAIR(N, Lo, Hi); break;
+ case ISD::INSERT_VECTOR_ELT:SplitRes_INSERT_VECTOR_ELT(N, Lo, Hi); break;
+ case ISD::VECTOR_SHUFFLE: SplitRes_VECTOR_SHUFFLE(N, Lo, Hi); break;
+ case ISD::BUILD_VECTOR: SplitRes_BUILD_VECTOR(N, Lo, Hi); break;
+ case ISD::CONCAT_VECTORS: SplitRes_CONCAT_VECTORS(N, Lo, Hi); break;
+ case ISD::BIT_CONVERT: SplitRes_BIT_CONVERT(N, Lo, Hi); break;
+ case ISD::CTTZ:
+ case ISD::CTLZ:
+ case ISD::CTPOP:
+ case ISD::FNEG:
+ case ISD::FABS:
+ case ISD::FSQRT:
+ case ISD::FSIN:
+ case ISD::FCOS:
+ case ISD::FP_TO_SINT:
+ case ISD::FP_TO_UINT:
+ case ISD::SINT_TO_FP:
+ case ISD::UINT_TO_FP: SplitRes_UnOp(N, Lo, Hi); break;
+ case ISD::ADD:
+ case ISD::SUB:
+ case ISD::MUL:
+ case ISD::FADD:
+ case ISD::FSUB:
+ case ISD::FMUL:
+ case ISD::SDIV:
+ case ISD::UDIV:
+ case ISD::FDIV:
+ case ISD::FPOW:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR:
+ case ISD::UREM:
+ case ISD::SREM:
+ case ISD::FREM: SplitRes_BinOp(N, Lo, Hi); break;
+ case ISD::FPOWI: SplitRes_FPOWI(N, Lo, Hi); break;
+ case ISD::SELECT: SplitRes_SELECT(N, Lo, Hi); break;
+ }
+
+ // If Lo/Hi is null, the sub-method took care of registering results etc.
+ if (Lo.Val)
+ SetSplitVector(SDOperand(N, ResNo), Lo, Hi);
+}
+
+void DAGTypeLegalizer::SplitRes_UNDEF(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+
+ Lo = DAG.getNode(ISD::UNDEF, LoVT);
+ Hi = DAG.getNode(ISD::UNDEF, HiVT);
+}
+
+void DAGTypeLegalizer::SplitRes_LOAD(LoadSDNode *LD,
+ SDOperand &Lo, SDOperand &Hi) {
+ // FIXME: Add support for indexed loads.
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(LD->getValueType(0), LoVT, HiVT);
+
+ SDOperand Ch = LD->getChain();
+ SDOperand Ptr = LD->getBasePtr();
+ const Value *SV = LD->getSrcValue();
+ int SVOffset = LD->getSrcValueOffset();
+ unsigned Alignment = LD->getAlignment();
+ bool isVolatile = LD->isVolatile();
+
+ Lo = DAG.getLoad(LoVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+ unsigned IncrementSize = LoVT.getSizeInBits()/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+ SVOffset += IncrementSize;
+ Alignment = MinAlign(Alignment, IncrementSize);
+ Hi = DAG.getLoad(HiVT, Ch, Ptr, SV, SVOffset, isVolatile, Alignment);
+
+ // Build a factor node to remember that this load is independent of the
+ // other one.
+ SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ // Legalized the chain result - switch anything that used the old chain to
+ // use the new one.
+ ReplaceValueWith(SDOperand(LD, 1), TF);
+}
+
+void DAGTypeLegalizer::SplitRes_BUILD_PAIR(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ Lo = N->getOperand(0);
+ Hi = N->getOperand(1);
+}
+
+void DAGTypeLegalizer::SplitRes_INSERT_VECTOR_ELT(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ SDOperand Vec = N->getOperand(0);
+ SDOperand Elt = N->getOperand(1);
+ SDOperand Idx = N->getOperand(2);
+ GetSplitVector(Vec, Lo, Hi);
+
+ if (ConstantSDNode *CIdx = dyn_cast<ConstantSDNode>(Idx)) {
+ unsigned IdxVal = CIdx->getValue();
+ unsigned LoNumElts = Lo.getValueType().getVectorNumElements();
+ if (IdxVal < LoNumElts)
+ Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, Lo.getValueType(), Lo, Elt, Idx);
+ else
+ Hi = DAG.getNode(ISD::INSERT_VECTOR_ELT, Hi.getValueType(), Hi, Elt,
+ DAG.getIntPtrConstant(IdxVal - LoNumElts));
+ return;
+ }
+
+ // Spill the vector to the stack.
+ MVT VecVT = Vec.getValueType();
+ SDOperand StackPtr = DAG.CreateStackTemporary(VecVT);
+ SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
+
+ // Store the new element.
+ SDOperand EltPtr = GetVectorElementPointer(StackPtr,
+ VecVT.getVectorElementType(), Idx);
+ Store = DAG.getStore(Store, Elt, EltPtr, NULL, 0);
+
+ // Reload the vector from the stack.
+ SDOperand Load = DAG.getLoad(VecVT, Store, StackPtr, NULL, 0);
+
+ // Split it.
+ SplitRes_LOAD(cast<LoadSDNode>(Load.Val), Lo, Hi);
+}
+
+void DAGTypeLegalizer::SplitRes_VECTOR_SHUFFLE(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Build the low part.
+ SDOperand Mask = N->getOperand(2);
+ SmallVector<SDOperand, 16> Ops;
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+ MVT EltVT = LoVT.getVectorElementType();
+ unsigned LoNumElts = LoVT.getVectorNumElements();
+ unsigned NumElements = Mask.getNumOperands();
+
+ // Insert all of the elements from the input that are needed. We use
+ // buildvector of extractelement here because the input vectors will have
+ // to be legalized, so this makes the code simpler.
+ for (unsigned i = 0; i != LoNumElts; ++i) {
+ unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
+ SDOperand InVec = N->getOperand(0);
+ if (Idx >= NumElements) {
+ InVec = N->getOperand(1);
+ Idx -= NumElements;
+ }
+ Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec,
+ DAG.getIntPtrConstant(Idx)));
+ }
+ Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &Ops[0], Ops.size());
+ Ops.clear();
+
+ for (unsigned i = LoNumElts; i != NumElements; ++i) {
+ unsigned Idx = cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
+ SDOperand InVec = N->getOperand(0);
+ if (Idx >= NumElements) {
+ InVec = N->getOperand(1);
+ Idx -= NumElements;
+ }
+ Ops.push_back(DAG.getNode(ISD::EXTRACT_VECTOR_ELT, EltVT, InVec,
+ DAG.getIntPtrConstant(Idx)));
+ }
+ Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &Ops[0], Ops.size());
+}
+
+void DAGTypeLegalizer::SplitRes_BUILD_VECTOR(SDNode *N, SDOperand &Lo,
+ SDOperand &Hi) {
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+ unsigned LoNumElts = LoVT.getVectorNumElements();
+ SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+LoNumElts);
+ Lo = DAG.getNode(ISD::BUILD_VECTOR, LoVT, &LoOps[0], LoOps.size());
+
+ SmallVector<SDOperand, 8> HiOps(N->op_begin()+LoNumElts, N->op_end());
+ Hi = DAG.getNode(ISD::BUILD_VECTOR, HiVT, &HiOps[0], HiOps.size());
+}
+
+void DAGTypeLegalizer::SplitRes_CONCAT_VECTORS(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // FIXME: Handle non-power-of-two vectors?
+ unsigned NumSubvectors = N->getNumOperands() / 2;
+ if (NumSubvectors == 1) {
+ Lo = N->getOperand(0);
+ Hi = N->getOperand(1);
+ return;
+ }
+
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+
+ SmallVector<SDOperand, 8> LoOps(N->op_begin(), N->op_begin()+NumSubvectors);
+ Lo = DAG.getNode(ISD::CONCAT_VECTORS, LoVT, &LoOps[0], LoOps.size());
+
+ SmallVector<SDOperand, 8> HiOps(N->op_begin()+NumSubvectors, N->op_end());
+ Hi = DAG.getNode(ISD::CONCAT_VECTORS, HiVT, &HiOps[0], HiOps.size());
+}
+
+void DAGTypeLegalizer::SplitRes_BIT_CONVERT(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // We know the result is a vector. The input may be either a vector or a
+ // scalar value.
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+
+ SDOperand InOp = N->getOperand(0);
+ MVT InVT = InOp.getValueType();
+
+ // Handle some special cases efficiently.
+ switch (getTypeAction(InVT)) {
+ default:
+ assert(false && "Unknown type action!");
+ case Legal:
+ case PromoteInteger:
+ case PromoteFloat:
+ case Scalarize:
+ break;
+ case ExpandInteger:
+ case ExpandFloat:
+ // A scalar to vector conversion, where the scalar needs expansion.
+ // If the vector is being split in two then we can just convert the
+ // expanded pieces.
+ if (LoVT == HiVT) {
+ if (InVT.isInteger())
+ GetExpandedInteger(InOp, Lo, Hi);
+ else
+ GetExpandedFloat(InOp, Lo, Hi);
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
+ return;
+ }
+ break;
+ case Split:
+ // If the input is a vector that needs to be split, convert each split
+ // piece of the input now.
+ GetSplitVector(InOp, Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
+ return;
+ }
+
+ // In the general case, convert the input to an integer and split it by hand.
+ MVT LoIntVT = MVT::getIntegerVT(LoVT.getSizeInBits());
+ MVT HiIntVT = MVT::getIntegerVT(HiVT.getSizeInBits());
+ if (TLI.isBigEndian())
+ std::swap(LoIntVT, HiIntVT);
+
+ SplitInteger(BitConvertToInteger(InOp), LoIntVT, HiIntVT, Lo, Hi);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+ Lo = DAG.getNode(ISD::BIT_CONVERT, LoVT, Lo);
+ Hi = DAG.getNode(ISD::BIT_CONVERT, HiVT, Hi);
+}
+
+void DAGTypeLegalizer::SplitRes_BinOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+ SDOperand LHSLo, LHSHi;
+ GetSplitVector(N->getOperand(0), LHSLo, LHSHi);
+ SDOperand RHSLo, RHSHi;
+ GetSplitVector(N->getOperand(1), RHSLo, RHSHi);
+
+ Lo = DAG.getNode(N->getOpcode(), LHSLo.getValueType(), LHSLo, RHSLo);
+ Hi = DAG.getNode(N->getOpcode(), LHSHi.getValueType(), LHSHi, RHSHi);
+}
+
+void DAGTypeLegalizer::SplitRes_UnOp(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+ // Get the dest types. This doesn't always match input types, e.g. int_to_fp.
+ MVT LoVT, HiVT;
+ GetSplitDestVTs(N->getValueType(0), LoVT, HiVT);
+
+ GetSplitVector(N->getOperand(0), Lo, Hi);
+ Lo = DAG.getNode(N->getOpcode(), LoVT, Lo);
+ Hi = DAG.getNode(N->getOpcode(), HiVT, Hi);
+}
+
+void DAGTypeLegalizer::SplitRes_FPOWI(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
+ GetSplitVector(N->getOperand(0), Lo, Hi);
+ Lo = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Lo, N->getOperand(1));
+ Hi = DAG.getNode(ISD::FPOWI, Lo.getValueType(), Hi, N->getOperand(1));
+}
+
+
+void DAGTypeLegalizer::SplitRes_SELECT(SDNode *N, SDOperand &Lo, SDOperand &Hi){
+ SDOperand LL, LH, RL, RH;
+ GetSplitVector(N->getOperand(1), LL, LH);
+ GetSplitVector(N->getOperand(2), RL, RH);
+
+ SDOperand Cond = N->getOperand(0);
+ Lo = DAG.getNode(ISD::SELECT, LL.getValueType(), Cond, LL, RL);
+ Hi = DAG.getNode(ISD::SELECT, LH.getValueType(), Cond, LH, RH);
+}
+
+
+//===----------------------------------------------------------------------===//
+// Operand Vector Splitting
+//===----------------------------------------------------------------------===//
+
+/// SplitOperand - This method is called when the specified operand of the
+/// specified node is found to need vector splitting. At this point, all of the
+/// result types of the node are known to be legal, but other operands of the
+/// node may need legalization as well as the specified one.
+bool DAGTypeLegalizer::SplitOperand(SDNode *N, unsigned OpNo) {
+ DEBUG(cerr << "Split node operand: "; N->dump(&DAG); cerr << "\n");
+ SDOperand Res(0, 0);
+
+#if 0
+ if (TLI.getOperationAction(N->getOpcode(), N->getValueType(0)) ==
+ TargetLowering::Custom)
+ Res = TLI.LowerOperation(SDOperand(N, 0), DAG);
+#endif
+
+ if (Res.Val == 0) {
+ switch (N->getOpcode()) {
+ default:
+#ifndef NDEBUG
+ cerr << "SplitOperand Op #" << OpNo << ": ";
+ N->dump(&DAG); cerr << "\n";
+#endif
+ assert(0 && "Do not know how to split this operator's operand!");
+ abort();
+ case ISD::STORE: Res = SplitOp_STORE(cast<StoreSDNode>(N), OpNo); break;
+ case ISD::RET: Res = SplitOp_RET(N, OpNo); break;
+
+ case ISD::BIT_CONVERT: Res = SplitOp_BIT_CONVERT(N); break;
+
+ case ISD::EXTRACT_VECTOR_ELT: Res = SplitOp_EXTRACT_VECTOR_ELT(N); break;
+ case ISD::EXTRACT_SUBVECTOR: Res = SplitOp_EXTRACT_SUBVECTOR(N); break;
+ case ISD::VECTOR_SHUFFLE: Res = SplitOp_VECTOR_SHUFFLE(N, OpNo); break;
+ }
+ }
+
+ // If the result is null, the sub-method took care of registering results etc.
+ if (!Res.Val) return false;
+
+ // If the result is N, the sub-method updated N in place. Check to see if any
+ // operands are new, and if so, mark them.
+ if (Res.Val == N) {
+ // Mark N as new and remark N and its operands. This allows us to correctly
+ // revisit N if it needs another step of promotion and allows us to visit
+ // any new operands to N.
+ ReanalyzeNode(N);
+ return true;
+ }
+
+ assert(Res.getValueType() == N->getValueType(0) && N->getNumValues() == 1 &&
+ "Invalid operand expansion");
+
+ ReplaceValueWith(SDOperand(N, 0), Res);
+ return false;
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_STORE(StoreSDNode *N, unsigned OpNo) {
+ // FIXME: Add support for indexed stores.
+ assert(OpNo == 1 && "Can only split the stored value");
+
+ SDOperand Ch = N->getChain();
+ SDOperand Ptr = N->getBasePtr();
+ int SVOffset = N->getSrcValueOffset();
+ unsigned Alignment = N->getAlignment();
+ bool isVol = N->isVolatile();
+ SDOperand Lo, Hi;
+ GetSplitVector(N->getOperand(1), Lo, Hi);
+
+ unsigned IncrementSize = Lo.getValueType().getSizeInBits()/8;
+
+ Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset, isVol, Alignment);
+
+ // Increment the pointer to the other half.
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getIntPtrConstant(IncrementSize));
+
+ Hi = DAG.getStore(Ch, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
+ isVol, MinAlign(Alignment, IncrementSize));
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_RET(SDNode *N, unsigned OpNo) {
+ assert(N->getNumOperands() == 3 &&"Can only handle ret of one vector so far");
+ // FIXME: Returns of gcc generic vectors larger than a legal vector
+ // type should be returned by reference!
+ SDOperand Lo, Hi;
+ GetSplitVector(N->getOperand(1), Lo, Hi);
+
+ SDOperand Chain = N->getOperand(0); // The chain.
+ SDOperand Sign = N->getOperand(2); // Signness
+
+ return DAG.getNode(ISD::RET, MVT::Other, Chain, Lo, Sign, Hi, Sign);
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_BIT_CONVERT(SDNode *N) {
+ // For example, i64 = BIT_CONVERT v4i16 on alpha. Typically the vector will
+ // end up being split all the way down to individual components. Convert the
+ // split pieces into integers and reassemble.
+ SDOperand Lo, Hi;
+ GetSplitVector(N->getOperand(0), Lo, Hi);
+ Lo = BitConvertToInteger(Lo);
+ Hi = BitConvertToInteger(Hi);
+
+ if (TLI.isBigEndian())
+ std::swap(Lo, Hi);
+
+ return DAG.getNode(ISD::BIT_CONVERT, N->getValueType(0),
+ JoinIntegers(Lo, Hi));
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_VECTOR_ELT(SDNode *N) {
+ SDOperand Vec = N->getOperand(0);
+ SDOperand Idx = N->getOperand(1);
+ MVT VecVT = Vec.getValueType();
+
+ if (isa<ConstantSDNode>(Idx)) {
+ uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();
+ assert(IdxVal < VecVT.getVectorNumElements() && "Invalid vector index!");
+
+ SDOperand Lo, Hi;
+ GetSplitVector(Vec, Lo, Hi);
+
+ uint64_t LoElts = Lo.getValueType().getVectorNumElements();
+
+ if (IdxVal < LoElts)
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), Lo, Idx);
+ else
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), Hi,
+ DAG.getConstant(IdxVal - LoElts,
+ Idx.getValueType()));
+ }
+
+ // Store the vector to the stack.
+ MVT EltVT = VecVT.getVectorElementType();
+ SDOperand StackPtr = DAG.CreateStackTemporary(VecVT);
+ SDOperand Store = DAG.getStore(DAG.getEntryNode(), Vec, StackPtr, NULL, 0);
+
+ // Load back the required element.
+ StackPtr = GetVectorElementPointer(StackPtr, EltVT, Idx);
+ return DAG.getLoad(EltVT, Store, StackPtr, NULL, 0);
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_EXTRACT_SUBVECTOR(SDNode *N) {
+ // We know that the extracted result type is legal. For now, assume the index
+ // is a constant.
+ MVT SubVT = N->getValueType(0);
+ SDOperand Idx = N->getOperand(1);
+ SDOperand Lo, Hi;
+ GetSplitVector(N->getOperand(0), Lo, Hi);
+
+ uint64_t LoElts = Lo.getValueType().getVectorNumElements();
+ uint64_t IdxVal = cast<ConstantSDNode>(Idx)->getValue();
+
+ if (IdxVal < LoElts) {
+ assert(IdxVal + SubVT.getVectorNumElements() <= LoElts &&
+ "Extracted subvector crosses vector split!");
+ return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Lo, Idx);
+ } else {
+ return DAG.getNode(ISD::EXTRACT_SUBVECTOR, SubVT, Hi,
+ DAG.getConstant(IdxVal - LoElts, Idx.getValueType()));
+ }
+}
+
+SDOperand DAGTypeLegalizer::SplitOp_VECTOR_SHUFFLE(SDNode *N, unsigned OpNo) {
+ assert(OpNo == 2 && "Shuffle source type differs from result type?");
+ SDOperand Mask = N->getOperand(2);
+ unsigned MaskLength = Mask.getValueType().getVectorNumElements();
+ unsigned LargestMaskEntryPlusOne = 2 * MaskLength;
+ unsigned MinimumBitWidth = Log2_32_Ceil(LargestMaskEntryPlusOne);
+
+ // Look for a legal vector type to place the mask values in.
+ // Note that there may not be *any* legal vector-of-integer
+ // type for which the element type is legal!
+ for (MVT::SimpleValueType EltVT = MVT::FIRST_INTEGER_VALUETYPE;
+ EltVT <= MVT::LAST_INTEGER_VALUETYPE;
+ // Integer values types are consecutively numbered. Exploit this.
+ EltVT = MVT::SimpleValueType(EltVT + 1)) {
+
+ // Is the element type big enough to hold the values?
+ if (MVT(EltVT).getSizeInBits() < MinimumBitWidth)
+ // Nope.
+ continue;
+
+ // Is the vector type legal?
+ MVT VecVT = MVT::getVectorVT(EltVT, MaskLength);
+ if (!isTypeLegal(VecVT))
+ // Nope.
+ continue;
+
+ // If the element type is not legal, find a larger legal type to use for
+ // the BUILD_VECTOR operands. This is an ugly hack, but seems to work!
+ // FIXME: The real solution is to change VECTOR_SHUFFLE into a variadic
+ // node where the shuffle mask is a list of integer operands, #2 .. #2+n.
+ for (MVT::SimpleValueType OpVT = EltVT; OpVT <= MVT::LAST_INTEGER_VALUETYPE;
+ // Integer values types are consecutively numbered. Exploit this.
+ OpVT = MVT::SimpleValueType(OpVT + 1)) {
+ if (!isTypeLegal(OpVT))
+ continue;
+
+ // Success! Rebuild the vector using the legal types.
+ SmallVector<SDOperand, 16> Ops(MaskLength);
+ for (unsigned i = 0; i < MaskLength; ++i) {
+ uint64_t Idx =
+ cast<ConstantSDNode>(Mask.getOperand(i))->getValue();
+ Ops[i] = DAG.getConstant(Idx, OpVT);
+ }
+ return DAG.UpdateNodeOperands(SDOperand(N,0),
+ N->getOperand(0), N->getOperand(1),
+ DAG.getNode(ISD::BUILD_VECTOR,
+ VecVT, &Ops[0], Ops.size()));
+ }
+
+ // Continuing is pointless - failure is certain.
+ break;
+ }
+ assert(false && "Failed to find an appropriate mask type!");
+ return SDOperand(N, 0);
+}
More information about the llvm-commits
mailing list