#define DEBUG_TYPE "legalize-types"
#include "llvm/CodeGen/SelectionDAG.h"
+#include "llvm/Constants.h"
+#include "llvm/DerivedTypes.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/ADT/DenseMap.h"
+#include "llvm/Support/Alignment.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/Debug.h"
using namespace llvm;
};
enum LegalizeAction {
- Legal, // The target natively supports this operation.
- Promote, // This operation should be executed in a larger type.
- Expand // Try to expand this to other ops, otherwise use a libcall.
+ 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.
};
/// ValueTypeActions - This is a bitvector that contains two bits for each
SmallVector<SDNode*, 128> Worklist;
public:
- DAGTypeLegalizer(SelectionDAG &dag)
+ explicit DAGTypeLegalizer(SelectionDAG &dag)
: TLI(dag.getTargetLoweringInfo()), DAG(dag),
ValueTypeActions(TLI.getValueTypeActions()) {
assert(MVT::LAST_VALUETYPE <= 32 &&
}
void SetPromotedOp(SDOperand Op, SDOperand Result);
+ /// GetPromotedZExtOp - Get a promoted operand and zero extend it to the final
+ /// size.
+ SDOperand GetPromotedZExtOp(SDOperand Op) {
+ MVT::ValueType OldVT = Op.getValueType();
+ Op = GetPromotedOp(Op);
+ return DAG.getZeroExtendInReg(Op, OldVT);
+ }
+
void GetExpandedOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
void SetExpandedOp(SDOperand Op, SDOperand Lo, SDOperand Hi);
-
+
+ // Common routines.
+ SDOperand CreateStackStoreLoad(SDOperand Op, MVT::ValueType DestVT);
+ SDOperand HandleMemIntrinsic(SDNode *N);
+ void SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi);
+
// Result Promotion.
void PromoteResult(SDNode *N, unsigned ResNo);
SDOperand PromoteResult_UNDEF(SDNode *N);
SDOperand PromoteResult_TRUNCATE(SDNode *N);
SDOperand PromoteResult_INT_EXTEND(SDNode *N);
SDOperand PromoteResult_FP_ROUND(SDNode *N);
+ SDOperand PromoteResult_FP_TO_XINT(SDNode *N);
SDOperand PromoteResult_SETCC(SDNode *N);
SDOperand PromoteResult_LOAD(LoadSDNode *N);
SDOperand PromoteResult_SimpleIntBinOp(SDNode *N);
+ SDOperand PromoteResult_SHL(SDNode *N);
+ SDOperand PromoteResult_SRA(SDNode *N);
+ SDOperand PromoteResult_SRL(SDNode *N);
+ SDOperand PromoteResult_SELECT (SDNode *N);
+ SDOperand PromoteResult_SELECT_CC(SDNode *N);
// Result Expansion.
void ExpandResult(SDNode *N, unsigned ResNo);
void ExpandResult_ANY_EXTEND (SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_ZERO_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_SIGN_EXTEND(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandResult_BIT_CONVERT(SDNode *N, SDOperand &Lo, SDOperand &Hi);
+ void ExpandResult_SIGN_EXTEND_INREG(SDNode *N, SDOperand &Lo, SDOperand &Hi);
void ExpandResult_LOAD (LoadSDNode *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);
SDOperand PromoteOperand_ANY_EXTEND(SDNode *N);
SDOperand PromoteOperand_ZERO_EXTEND(SDNode *N);
SDOperand PromoteOperand_SIGN_EXTEND(SDNode *N);
+ SDOperand PromoteOperand_TRUNCATE(SDNode *N);
SDOperand PromoteOperand_FP_EXTEND(SDNode *N);
SDOperand PromoteOperand_FP_ROUND(SDNode *N);
+ SDOperand PromoteOperand_INT_TO_FP(SDNode *N);
SDOperand PromoteOperand_SELECT(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_BRCOND(SDNode *N, unsigned OpNo);
+ SDOperand PromoteOperand_BR_CC(SDNode *N, unsigned OpNo);
+ SDOperand PromoteOperand_SETCC(SDNode *N, unsigned OpNo);
SDOperand PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo);
-
+
+ void PromoteSetCCOperands(SDOperand &LHS,SDOperand &RHS, ISD::CondCode Code);
+
// Operand Expansion.
bool ExpandOperand(SDNode *N, unsigned OperandNo);
SDOperand ExpandOperand_TRUNCATE(SDNode *N);
+ SDOperand ExpandOperand_BIT_CONVERT(SDNode *N);
+ SDOperand ExpandOperand_UINT_TO_FP(SDOperand Source, MVT::ValueType DestTy);
+ SDOperand ExpandOperand_SINT_TO_FP(SDOperand Source, MVT::ValueType DestTy);
SDOperand ExpandOperand_EXTRACT_ELEMENT(SDNode *N);
SDOperand ExpandOperand_SETCC(SDNode *N);
SDOperand ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo);
}
}
- // If the node needs revisitation, don't add all users to the worklist etc.
+ // If the node needs revisiting, don't add all users to the worklist etc.
if (NeedsRevisit)
continue;
// Okay, we know that this node is new. Recursively walk all of its operands
// to see if they are new also. The depth of this walk is bounded by the size
// of the new tree that was constructed (usually 2-3 nodes), so we don't worry
- // about revisitation of nodes.
+ // about revisiting of nodes.
//
// As we walk the operands, keep track of the number of nodes that are
// processed. If non-zero, this will become the new nodeid of this node.
OpEntry = Result;
}
-
void DAGTypeLegalizer::GetExpandedOp(SDOperand Op, SDOperand &Lo,
SDOperand &Hi) {
std::pair<SDOperand, SDOperand> &Entry = ExpandedNodes[Op];
MarkNewNodes(Hi.Val);
}
+SDOperand DAGTypeLegalizer::CreateStackStoreLoad(SDOperand Op,
+ MVT::ValueType 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.
+ return DAG.getLoad(DestVT, Store, FIPtr, NULL, 0);
+}
+
+/// HandleMemIntrinsic - This handles memcpy/memset/memmove with invalid
+/// operands. This promotes or expands the operands as required.
+SDOperand DAGTypeLegalizer::HandleMemIntrinsic(SDNode *N) {
+ // The chain and pointer [operands #0 and #1] are always valid types.
+ SDOperand Chain = N->getOperand(0);
+ SDOperand Ptr = N->getOperand(1);
+ SDOperand Op2 = N->getOperand(2);
+
+ // Op #2 is either a value (memset) or a pointer. Promote it if required.
+ switch (getTypeAction(Op2.getValueType())) {
+ default: assert(0 && "Unknown action for pointer/value operand");
+ case Legal: break;
+ case Promote: Op2 = GetPromotedOp(Op2); break;
+ }
+
+ // The length could have any action required.
+ SDOperand Length = N->getOperand(3);
+ switch (getTypeAction(Length.getValueType())) {
+ default: assert(0 && "Unknown action for memop operand");
+ case Legal: break;
+ case Promote: Length = GetPromotedZExtOp(Length); break;
+ case Expand:
+ SDOperand Dummy; // discard the high part.
+ GetExpandedOp(Length, Length, Dummy);
+ break;
+ }
+
+ SDOperand Align = N->getOperand(4);
+ switch (getTypeAction(Align.getValueType())) {
+ default: assert(0 && "Unknown action for memop operand");
+ case Legal: break;
+ case Promote: Align = GetPromotedZExtOp(Align); break;
+ }
+
+ SDOperand AlwaysInline = N->getOperand(5);
+ switch (getTypeAction(AlwaysInline.getValueType())) {
+ default: assert(0 && "Unknown action for memop operand");
+ case Legal: break;
+ case Promote: AlwaysInline = GetPromotedZExtOp(AlwaysInline); break;
+ }
+
+ SDOperand Ops[] = { Chain, Ptr, Op2, Length, Align, AlwaysInline };
+ return DAG.UpdateNodeOperands(SDOperand(N, 0), Ops, 6);
+}
+
+/// SplitOp - Return the lower and upper halves of Op's bits in a value type
+/// half the size of Op's.
+void DAGTypeLegalizer::SplitOp(SDOperand Op, SDOperand &Lo, SDOperand &Hi) {
+ unsigned NVTBits = MVT::getSizeInBits(Op.getValueType())/2;
+ assert(MVT::getSizeInBits(Op.getValueType()) == 2*NVTBits &&
+ "Cannot split odd sized integer type");
+ MVT::ValueType NVT = MVT::getIntegerType(NVTBits);
+ Lo = DAG.getNode(ISD::TRUNCATE, NVT, Op);
+ Hi = DAG.getNode(ISD::SRL, Op.getValueType(), Op,
+ DAG.getConstant(NVTBits, TLI.getShiftAmountTy()));
+ Hi = DAG.getNode(ISD::TRUNCATE, NVT, Hi);
+}
+
+
//===----------------------------------------------------------------------===//
// Result Promotion
//===----------------------------------------------------------------------===//
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::AND:
case ISD::OR:
case ISD::XOR:
case ISD::ADD:
case ISD::SUB:
case ISD::MUL: Result = PromoteResult_SimpleIntBinOp(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;
+
}
// If Result is null, the sub-method took care of registering the result.
}
SDOperand DAGTypeLegalizer::PromoteResult_TRUNCATE(SDNode *N) {
- MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ SDOperand Res;
+
switch (getTypeAction(N->getOperand(0).getValueType())) {
default: assert(0 && "Unknown type action!");
- case Legal: {
- SDOperand Res = N->getOperand(0);
- assert(Res.getValueType() >= NVT && "Truncation doesn't make sense!");
- if (Res.getValueType() > NVT) // Truncate to NVT instead of VT
- return DAG.getNode(ISD::TRUNCATE, NVT, Res);
- return Res;
- }
- case Promote:
- // The truncation is not required, because we don't guarantee anything
- // about high bits anyway.
- return GetPromotedOp(N->getOperand(0));
+ case Legal:
case Expand:
- // Truncate the low part of the expanded value to the result type
- SDOperand Lo, Hi;
- GetExpandedOp(N->getOperand(0), Lo, Hi);
- return DAG.getNode(ISD::TRUNCATE, NVT, Lo);
+ Res = N->getOperand(0);
+ break;
+ case Promote:
+ Res = GetPromotedOp(N->getOperand(0));
+ break;
}
+
+ MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
+ assert(MVT::getSizeInBits(Res.getValueType()) >= MVT::getSizeInBits(NVT) &&
+ "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::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- switch (getTypeAction(N->getOperand(0).getValueType())) {
- default: assert(0 && "BUG: Smaller reg should have been promoted!");
- case Legal:
- // Input is legal? Just do extend all the way to the larger type.
- return DAG.getNode(N->getOpcode(), NVT, N->getOperand(0));
- case Promote:
- // Get promoted operand if it is smaller.
+
+ if (getTypeAction(N->getOperand(0).getValueType()) == Promote) {
SDOperand Res = GetPromotedOp(N->getOperand(0));
- // 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;
+ assert(MVT::getSizeInBits(Res.getValueType()) <= MVT::getSizeInBits(NVT) &&
+ "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) {
N->getOperand(0), DAG.getValueType(N->getValueType(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::ValueType 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.getSetCCResultTy()) && "SetCC type is not legal??");
N->getSrcValue(), N->getSrcValueOffset(),
N->getLoadedVT(), N->isVolatile(),
N->getAlignment());
-
- // Legalized the chain result, switching anything that used the old chain to
+
+ // Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceLegalValueWith(SDOperand(N, 1), Res.getValue(1));
return Res;
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::ValueType VT = N->getValueType(0);
+ MVT::ValueType 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::ValueType VT = N->getValueType(0);
+ MVT::ValueType 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));
+}
+
+
//===----------------------------------------------------------------------===//
// Result Expansion
//===----------------------------------------------------------------------===//
DEBUG(cerr << "Expand node result: "; N->dump(&DAG); cerr << "\n");
SDOperand Lo, Hi;
Lo = Hi = SDOperand();
+
+ // If this is a single-result node, see if the target wants to custom expand
+ // it.
+ if (N->getNumValues() == 1 &&
+ TLI.getOperationAction(N->getOpcode(),
+ N->getValueType(0)) == TargetLowering::Custom) {
+ // If the target wants to, allow it to lower this itself.
+ std::pair<SDOperand,SDOperand> P = TLI.ExpandOperationResult(N, DAG);
+ if (P.first.Val) {
+ Lo = P.first;
+ Hi = P.second;
+ return;
+ }
+ }
+
switch (N->getOpcode()) {
default:
#ifndef NDEBUG
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::BIT_CONVERT: ExpandResult_BIT_CONVERT(N, Lo, Hi); break;
+ case ISD::SIGN_EXTEND_INREG: ExpandResult_SIGN_EXTEND_INREG(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;
Hi = N->getOperand(1);
}
-void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
+void DAGTypeLegalizer::ExpandResult_ANY_EXTEND(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
-
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- // The low part is any extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::ANY_EXTEND, NVT, N->getOperand(0));
- Hi = DAG.getNode(ISD::UNDEF, NVT); // The high part is undefined.
+ SDOperand Op = N->getOperand(0);
+ if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(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 &&
+ "Don't know how to expand 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.
+ SplitOp(Res, Lo, Hi);
+ }
}
void DAGTypeLegalizer::ExpandResult_ZERO_EXTEND(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- // 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.
+ SDOperand Op = N->getOperand(0);
+ if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(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 &&
+ "Don't know how to expand 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.
+ SplitOp(Res, Lo, Hi);
+ unsigned ExcessBits =
+ MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+ Hi = DAG.getZeroExtendInReg(Hi, MVT::getIntegerType(ExcessBits));
+ }
}
void DAGTypeLegalizer::ExpandResult_SIGN_EXTEND(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
- // The low part is sign extension of the input (which degenerates to a copy).
- Lo = DAG.getNode(ISD::SIGN_EXTEND, NVT, N->getOperand(0));
+ SDOperand Op = N->getOperand(0);
+ if (MVT::getSizeInBits(Op.getValueType()) <= MVT::getSizeInBits(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 = MVT::getSizeInBits(NVT);
+ 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 &&
+ "Don't know how to expand 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.
+ SplitOp(Res, Lo, Hi);
+ unsigned ExcessBits =
+ MVT::getSizeInBits(Op.getValueType()) - MVT::getSizeInBits(NVT);
+ Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+ DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+ }
+}
- // The high part is obtained by SRA'ing all but one of the bits of low part.
- unsigned LoSize = MVT::getSizeInBits(NVT);
- Hi = DAG.getNode(ISD::SRA, NVT, Lo,
- DAG.getConstant(LoSize-1, TLI.getShiftAmountTy()));
+void DAGTypeLegalizer::ExpandResult_BIT_CONVERT(SDNode *N,
+ SDOperand &Lo, SDOperand &Hi) {
+ // Lower the bit-convert to a store/load from the stack, then expand the load.
+ SDOperand Op = CreateStackStoreLoad(N->getOperand(0), 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::ValueType EVT = cast<VTSDNode>(N->getOperand(1))->getVT();
+
+ if (MVT::getSizeInBits(EVT) <= MVT::getSizeInBits(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(MVT::getSizeInBits(Hi.getValueType())-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 =
+ MVT::getSizeInBits(EVT) - MVT::getSizeInBits(Lo.getValueType());
+ Hi = DAG.getNode(ISD::SIGN_EXTEND_INREG, Hi.getValueType(), Hi,
+ DAG.getValueType(MVT::getIntegerType(ExcessBits)));
+ }
+}
void DAGTypeLegalizer::ExpandResult_LOAD(LoadSDNode *N,
SDOperand &Lo, SDOperand &Hi) {
int SVOffset = N->getSrcValueOffset();
unsigned Alignment = N->getAlignment();
bool isVolatile = N->isVolatile();
-
+
+ assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!");
+
if (ExtType == ISD::NON_EXTLOAD) {
Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset,
isVolatile, Alignment);
- if (VT == MVT::f32 || VT == MVT::f64) {
- assert(0 && "FIXME: softfp should use promotion!");
-#if 0
- // f32->i32 or f64->i64 one to one expansion.
- // Remember that we legalized the chain.
- AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Lo.getValue(1)));
- // Recursively expand the new load.
- if (getTypeAction(NVT) == Expand)
- ExpandOp(Lo, Lo, Hi);
- break;
-#endif
- }
-
// Increment the pointer to the other half.
- unsigned IncrementSize = MVT::getSizeInBits(Lo.getValueType())/8;
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
getIntPtrConstant(IncrementSize));
Hi = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
- isVolatile, std::max(Alignment, 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),
// Handle endianness of the load.
if (!TLI.isLittleEndian())
std::swap(Lo, Hi);
- } else {
+ } else if (MVT::getSizeInBits(N->getLoadedVT()) <= MVT::getSizeInBits(NVT)) {
MVT::ValueType EVT = N->getLoadedVT();
-
- if (VT == MVT::f64 && EVT == MVT::f32) {
- assert(0 && "FIXME: softfp should use promotion!");
-#if 0
- // f64 = EXTLOAD f32 should expand to LOAD, FP_EXTEND
- SDOperand Load = DAG.getLoad(EVT, Ch, Ptr, N->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- // Remember that we legalized the chain.
- AddLegalizedOperand(SDOperand(Node, 1), LegalizeOp(Load.getValue(1)));
- ExpandOp(DAG.getNode(ISD::FP_EXTEND, VT, Load), Lo, Hi);
- break;
-#endif
- }
-
- if (EVT == NVT)
- Lo = DAG.getLoad(NVT, Ch, Ptr, N->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- else
- Lo = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
- SVOffset, EVT, isVolatile,
- Alignment);
+
+ 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.
// 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 =
+ MVT::getSizeInBits(N->getLoadedVT()) - MVT::getSizeInBits(NVT);
+ MVT::ValueType NEVT = MVT::getIntegerType(ExcessBits);
+
+ // Increment the pointer to the other half.
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ 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::ValueType EVT = N->getLoadedVT();
+ unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8;
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/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::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits),
+ isVolatile, Alignment);
+
+ // Increment the pointer to the other half.
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ getIntPtrConstant(IncrementSize));
+ // Load the rest of the low bits.
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize, MVT::getIntegerType(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 < MVT::getSizeInBits(NVT)) {
+ // 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(MVT::getSizeInBits(NVT) - ExcessBits,
+ TLI.getShiftAmountTy()));
+ }
}
-
- // Legalized the chain result, switching anything that used the old chain to
+
+ // Legalized the chain result - switch anything that used the old chain to
// use the new one.
ReplaceLegalValueWith(SDOperand(N, 1), Ch);
-}
-
+}
void DAGTypeLegalizer::ExpandResult_Logical(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
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;
void DAGTypeLegalizer::ExpandResult_ADDSUB(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
- MVT::ValueType VT = N->getValueType(0);
-
- // If the target wants to custom expand this, let them.
- if (TLI.getOperationAction(N->getOpcode(), VT) ==
- TargetLowering::Custom) {
- SDOperand Op = TLI.LowerOperation(SDOperand(N, 0), DAG);
- // FIXME: Do a replace all uses with here!
- assert(0 && "Custom not impl yet!");
- if (Op.Val) {
-#if 0
- ExpandOp(Op, Lo, Hi);
-#endif
- return;
- }
- }
-
// 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], HiOps[3];
- LoOps[0] = LHSL;
- LoOps[1] = RHSL;
- HiOps[0] = LHSH;
- HiOps[1] = RHSH;
+ 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);
}
}
+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.
+ ReplaceLegalValueWith(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.
+ ReplaceLegalValueWith(SDOperand(N, 1), Hi.getValue(1));
+}
void DAGTypeLegalizer::ExpandResult_MUL(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType VT = N->getValueType(0);
MVT::ValueType NVT = TLI.getTypeToTransformTo(VT);
- // If the target wants to custom expand this, let them.
- if (TLI.getOperationAction(ISD::MUL, VT) == TargetLowering::Custom) {
- SDOperand New = TLI.LowerOperation(SDOperand(N, 0), DAG);
- if (New.Val) {
- // FIXME: Do a replace all uses with here!
- assert(0 && "Custom not impl yet!");
-#if 0
- ExpandOp(New, Lo, Hi);
-#endif
- return;
- }
- }
-
bool HasMULHS = TLI.isOperationLegal(ISD::MULHS, NVT);
bool HasMULHU = TLI.isOperationLegal(ISD::MULHU, NVT);
bool HasSMUL_LOHI = TLI.isOperationLegal(ISD::SMUL_LOHI, NVT);
SDOperand LL, LH, RL, RH;
GetExpandedOp(N->getOperand(0), LL, LH);
GetExpandedOp(N->getOperand(1), RL, RH);
- unsigned BitSize = MVT::getSizeInBits(RH.getValueType());
+ unsigned BitSize = MVT::getSizeInBits(NVT);
unsigned LHSSB = DAG.ComputeNumSignBits(N->getOperand(0));
unsigned RHSSB = DAG.ComputeNumSignBits(N->getOperand(1));
SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType VT = N->getValueType(0);
- // If the target wants custom lowering, do so.
- if (TLI.getOperationAction(N->getOpcode(), VT) == TargetLowering::Custom) {
- SDOperand Op = TLI.LowerOperation(SDOperand(N, 0), DAG);
- if (Op.Val) {
- // Now that the custom expander is done, expand the result, which is
- // still VT.
- // FIXME: Do a replace all uses with here!
- abort();
-#if 0
- ExpandOp(Op, Lo, Hi);
-#endif
- return;
- }
- }
-
// 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)))
ExpandShiftWithKnownAmountBit(SDNode *N, SDOperand &Lo, SDOperand &Hi) {
MVT::ValueType NVT = TLI.getTypeToTransformTo(N->getValueType(0));
unsigned NVTBits = MVT::getSizeInBits(NVT);
+ assert(!(NVTBits & (NVTBits - 1)) &&
+ "Expanded integer type size not a power of two!");
uint64_t HighBitMask = NVTBits, KnownZero, KnownOne;
DAG.ComputeMaskedBits(N->getOperand(1), HighBitMask, KnownZero, KnownOne);
return true;
}
+
//===----------------------------------------------------------------------===//
// Operand Promotion
//===----------------------------------------------------------------------===//
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::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::MEMSET:
+ case ISD::MEMCPY:
+ case ISD::MEMMOVE: Res = HandleMemIntrinsic(N); break;
}
// If the result is null, the sub-method took care of registering results etc.
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);
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);
}
+SDOperand DAGTypeLegalizer::PromoteOperand_INT_TO_FP(SDNode *N) {
+ SDOperand In = GetPromotedOp(N->getOperand(0));
+ MVT::ValueType 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_SELECT(SDNode *N, unsigned OpNo) {
assert(OpNo == 0 && "Only know how to promote condition");
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.
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::ValueType 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 (!MVT::isInteger(NewLHS.getValueType()))
+ 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){
SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
int SVOffset = N->getSrcValueOffset();
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::SETCC: Res = ExpandOperand_SETCC(N); break;
case ISD::STORE: Res = ExpandOperand_STORE(cast<StoreSDNode>(N), OpNo); break;
+ case ISD::MEMSET:
+ case ISD::MEMCPY:
+ case ISD::MEMMOVE: Res = HandleMemIntrinsic(N); break;
}
// If the result is null, the sub-method took care of registering results etc.
return DAG.getNode(ISD::TRUNCATE, N->getValueType(0), InL);
}
+SDOperand DAGTypeLegalizer::ExpandOperand_BIT_CONVERT(SDNode *N) {
+ return CreateStackStoreLoad(N->getOperand(0), N->getValueType(0));
+}
+
+SDOperand DAGTypeLegalizer::ExpandOperand_SINT_TO_FP(SDOperand Source,
+ MVT::ValueType DestTy) {
+ // We know the destination is legal, but that the input needs to be expanded.
+ assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!");
+
+ // Check to see if the target has a custom way to lower this. If so, use it.
+ switch (TLI.getOperationAction(ISD::SINT_TO_FP, Source.getValueType())) {
+ default: assert(0 && "This action not implemented for this operation!");
+ case TargetLowering::Legal:
+ case TargetLowering::Expand:
+ break; // This case is handled below.
+ case TargetLowering::Custom:
+ SDOperand NV = TLI.LowerOperation(DAG.getNode(ISD::SINT_TO_FP, DestTy,
+ Source), DAG);
+ if (NV.Val) return NV;
+ break; // The target lowered this.
+ }
+
+ RTLIB::Libcall LC;
+ if (DestTy == MVT::f32)
+ LC = RTLIB::SINTTOFP_I64_F32;
+ else {
+ assert(DestTy == MVT::f64 && "Unknown fp value type!");
+ LC = RTLIB::SINTTOFP_I64_F64;
+ }
+
+ assert(0 && "FIXME: no libcalls yet!");
+ abort();
+#if 0
+ assert(TLI.getLibcallName(LC) && "Don't know how to expand this SINT_TO_FP!");
+ Source = DAG.getNode(ISD::SINT_TO_FP, DestTy, Source);
+ SDOperand UnusedHiPart;
+ return ExpandLibCall(TLI.getLibcallName(LC), Source.Val, true, UnusedHiPart);
+#endif
+}
+
+SDOperand DAGTypeLegalizer::ExpandOperand_UINT_TO_FP(SDOperand Source,
+ MVT::ValueType 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!");
+ assert(Source.getValueType() == MVT::i64 && "Only handle expand from i64!");
+
+ // 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.getSetCCResultTy(), Hi,
+ DAG.getConstant(0, Hi.getValueType()),
+ ISD::SETLT);
+ SDOperand Zero = getIntPtrConstant(0), Four = getIntPtrConstant(4);
+ SDOperand CstOffset = DAG.getNode(ISD::SELECT, Zero.getValueType(),
+ SignSet, Four, Zero);
+ uint64_t FF = 0x5f800000ULL;
+ if (TLI.isLittleEndian()) FF <<= 32;
+ 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 (DestTy == MVT::f32)
+ FudgeInReg = DAG.getLoad(MVT::f32, DAG.getEntryNode(), CPIdx, NULL, 0);
+ else if (MVT::getSizeInBits(DestTy) > MVT::getSizeInBits(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);
DAG.getCondCode(CCCode));
}
-/// ExpandSetCCOperands - Expand the operands to a comparison. This code is
+/// 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) {
NewRHS = SDOperand();
}
-
SDOperand DAGTypeLegalizer::ExpandOperand_STORE(StoreSDNode *N, unsigned OpNo) {
assert(OpNo == 1 && "Can only expand the stored value so far");
- assert(!N->isTruncatingStore() && "Can't expand truncstore!");
- unsigned IncrementSize = 0;
+ MVT::ValueType VT = N->getOperand(1).getValueType();
+ MVT::ValueType 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;
-
- // If this is a vector type, then we have to calculate the increment as
- // the product of the element size in bytes, and the number of elements
- // in the high half of the vector.
- if (MVT::isVector(N->getValue().getValueType())) {
- assert(0 && "Vectors not supported yet");
-#if 0
- SDNode *InVal = ST->getValue().Val;
- unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
- MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
-
- // Figure out if there is a simple type corresponding to this Vector
- // type. If so, convert to the vector type.
- MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
- if (TLI.isTypeLegal(TVT)) {
- // Turn this into a normal store of the vector type.
- Tmp3 = LegalizeOp(Node->getOperand(1));
- Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- Result = LegalizeOp(Result);
- break;
- } else if (NumElems == 1) {
- // Turn this into a normal store of the scalar type.
- Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
- Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
- SVOffset, isVolatile, Alignment);
- // The scalarized value type may not be legal, e.g. it might require
- // promotion or expansion. Relegalize the scalar store.
- return LegalizeOp(Result);
+
+ assert(!(MVT::getSizeInBits(NVT) & 7) && "Expanded type not byte sized!");
+
+ if (!N->isTruncatingStore()) {
+ unsigned IncrementSize = 0;
+
+ // If this is a vector type, then we have to calculate the increment as
+ // the product of the element size in bytes, and the number of elements
+ // in the high half of the vector.
+ if (MVT::isVector(N->getValue().getValueType())) {
+ assert(0 && "Vectors not supported yet");
+ #if 0
+ SDNode *InVal = ST->getValue().Val;
+ unsigned NumElems = MVT::getVectorNumElements(InVal->getValueType(0));
+ MVT::ValueType EVT = MVT::getVectorElementType(InVal->getValueType(0));
+
+ // Figure out if there is a simple type corresponding to this Vector
+ // type. If so, convert to the vector type.
+ MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
+ if (TLI.isTypeLegal(TVT)) {
+ // Turn this into a normal store of the vector type.
+ Tmp3 = LegalizeOp(Node->getOperand(1));
+ Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+ Result = LegalizeOp(Result);
+ break;
+ } else if (NumElems == 1) {
+ // Turn this into a normal store of the scalar type.
+ Tmp3 = ScalarizeVectorOp(Node->getOperand(1));
+ Result = DAG.getStore(Tmp1, Tmp3, Tmp2, ST->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+ // The scalarized value type may not be legal, e.g. it might require
+ // promotion or expansion. Relegalize the scalar store.
+ return LegalizeOp(Result);
+ } else {
+ SplitVectorOp(Node->getOperand(1), Lo, Hi);
+ IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+ }
+ #endif
} else {
- SplitVectorOp(Node->getOperand(1), Lo, Hi);
- IncrementSize = NumElems/2 * MVT::getSizeInBits(EVT)/8;
+ GetExpandedOp(N->getValue(), Lo, Hi);
+ IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
+
+ if (!TLI.isLittleEndian())
+ std::swap(Lo, Hi);
}
-#endif
+
+ Lo = DAG.getStore(Ch, Lo, Ptr, N->getSrcValue(),
+ SVOffset, isVolatile, Alignment);
+
+ assert(Hi.Val && "FIXME: int <-> float should be handled with promote!");
+ #if 0
+ if (Hi.Val == NULL) {
+ // Must be int <-> float one-to-one expansion.
+ return Lo;
+ }
+ #endif
+
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ 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 (MVT::getSizeInBits(N->getStoredVT()) <= MVT::getSizeInBits(NVT)) {
+ GetExpandedOp(N->getValue(), Lo, Hi);
+ return DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(), SVOffset,
+ N->getStoredVT(), 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 =
+ MVT::getSizeInBits(N->getStoredVT()) - MVT::getSizeInBits(NVT);
+ MVT::ValueType NEVT = MVT::getIntegerType(ExcessBits);
+
+ // Increment the pointer to the other half.
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ 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);
- IncrementSize = Hi.Val ? MVT::getSizeInBits(Hi.getValueType())/8 : 0;
-
- if (!TLI.isLittleEndian())
- std::swap(Lo, Hi);
- }
-
- SDOperand Chain = N->getChain();
- SDOperand Ptr = N->getBasePtr();
- int SVOffset = N->getSrcValueOffset();
- unsigned Alignment = N->getAlignment();
- bool isVolatile = N->isVolatile();
-
- Lo = DAG.getStore(Chain, Lo, Ptr, N->getSrcValue(),
- SVOffset, isVolatile, Alignment);
-
- assert(Hi.Val && "FIXME: int <-> float should be handled with promote!");
-#if 0
- if (Hi.Val == NULL) {
- // Must be int <-> float one-to-one expansion.
- return Lo;
+
+ MVT::ValueType EVT = N->getStoredVT();
+ unsigned EBytes = (MVT::getSizeInBits(EVT) + 7)/8;
+ unsigned IncrementSize = MVT::getSizeInBits(NVT)/8;
+ unsigned ExcessBits = (EBytes - IncrementSize)*8;
+ MVT::ValueType HiVT =
+ MVT::getIntegerType(MVT::getSizeInBits(EVT)-ExcessBits);
+
+ if (ExcessBits < MVT::getSizeInBits(NVT)) {
+ // Transfer high bits from the top of Lo to the bottom of Hi.
+ Hi = DAG.getNode(ISD::SHL, NVT, Hi,
+ DAG.getConstant(MVT::getSizeInBits(NVT) - 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,
+ getIntPtrConstant(IncrementSize));
+ // Store the lowest ExcessBits bits in the second half.
+ Lo = DAG.getTruncStore(Ch, Lo, Ptr, N->getSrcValue(),
+ SVOffset+IncrementSize,
+ MVT::getIntegerType(ExcessBits),
+ isVolatile, MinAlign(Alignment, IncrementSize));
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
}
-#endif
-
- Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
- getIntPtrConstant(IncrementSize));
- assert(isTypeLegal(Ptr.getValueType()) && "Pointers must be legal!");
- Hi = DAG.getStore(Chain, Hi, Ptr, N->getSrcValue(), SVOffset+IncrementSize,
- isVolatile, std::max(Alignment, IncrementSize));
- return DAG.getNode(ISD::TokenFactor, MVT::Other, Lo, Hi);
}
+
//===----------------------------------------------------------------------===//
// Entry Point
//===----------------------------------------------------------------------===//
void SelectionDAG::LegalizeTypes() {
DAGTypeLegalizer(*this).run();
}
-