#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;
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 &&
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) {
return DAG.getNode(NewOpc, NVT, Op);
}
-
SDOperand DAGTypeLegalizer::PromoteResult_SETCC(SDNode *N) {
assert(isTypeLegal(TLI.getSetCCResultTy()) && "SetCC type is not legal??");
return DAG.getNode(ISD::SETCC, TLI.getSetCCResultTy(), N->getOperand(0),
N->getOperand(1), LHS, RHS, N->getOperand(4));
}
+
//===----------------------------------------------------------------------===//
// Result Expansion
//===----------------------------------------------------------------------===//
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.
getIntPtrConstant(IncrementSize));
Hi = DAG.getExtLoad(ExtType, NVT, Ch, Ptr, N->getSrcValue(),
SVOffset+IncrementSize, NEVT,
- isVolatile, std::max(Alignment, IncrementSize));
+ isVolatile, MinAlign(Alignment, IncrementSize));
// Build a factor node to remember that this load is independent of the
// other one.
// Load the rest of the low bits.
Lo = DAG.getExtLoad(ISD::ZEXTLOAD, NVT, Ch, Ptr, N->getSrcValue(),
SVOffset+IncrementSize, MVT::getIntegerType(ExcessBits),
- isVolatile, std::max(Alignment, IncrementSize));
+ isVolatile, MinAlign(Alignment, IncrementSize));
// Build a factor node to remember that this load is independent of the
// other one.
Hi = DAG.getNode(ISD::BSWAP, Hi.getValueType(), Hi);
}
-
void DAGTypeLegalizer::ExpandResult_SELECT(SDNode *N,
SDOperand &Lo, SDOperand &Hi) {
SDOperand LL, LH, RL, RH;
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));
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
//===----------------------------------------------------------------------===//
return DAG.UpdateNodeOperands(SDOperand(N, 0), In);
}
-
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.
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.
return;
}
}
-
SDOperand DAGTypeLegalizer::PromoteOperand_STORE(StoreSDNode *N, unsigned OpNo){
SDOperand Ch = N->getChain(), Ptr = N->getBasePtr();
return DAG.getNode(ISD::FADD, DestTy, SignedConv, FudgeInReg);
}
-
SDOperand DAGTypeLegalizer::ExpandOperand_EXTRACT_ELEMENT(SDNode *N) {
SDOperand Lo, Hi;
GetExpandedOp(N->getOperand(0), Lo, Hi);
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();
}
-