#include "llvm/CodeGen/MachineFunction.h"
#include "llvm/CodeGen/MachineFrameInfo.h"
#include "llvm/CodeGen/MachineJumpTableInfo.h"
+#include "llvm/Target/TargetFrameInfo.h"
#include "llvm/Target/TargetLowering.h"
#include "llvm/Target/TargetData.h"
#include "llvm/Target/TargetMachine.h"
return Result;
}
+/// ExpandUnalignedStore - Expands an unaligned store to 2 half-size stores.
+static
+SDOperand ExpandUnalignedStore(StoreSDNode *ST, SelectionDAG &DAG,
+ TargetLowering &TLI) {
+ assert(MVT::isInteger(ST->getStoredVT()) &&
+ "Non integer unaligned stores not implemented.");
+ int SVOffset = ST->getSrcValueOffset();
+ SDOperand Chain = ST->getChain();
+ SDOperand Ptr = ST->getBasePtr();
+ SDOperand Val = ST->getValue();
+ MVT::ValueType VT = Val.getValueType();
+ // Get the half-size VT
+ MVT::ValueType NewStoredVT = ST->getStoredVT() - 1;
+ int NumBits = MVT::getSizeInBits(NewStoredVT);
+ int Alignment = ST->getAlignment();
+ int IncrementSize = NumBits / 8;
+
+ // Divide the stored value in two parts.
+ SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+ SDOperand Lo = Val;
+ SDOperand Hi = DAG.getNode(ISD::SRL, VT, Val, ShiftAmount);
+
+ // Store the two parts
+ SDOperand Store1, Store2;
+ Store1 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Lo:Hi, Ptr,
+ ST->getSrcValue(), SVOffset, NewStoredVT,
+ ST->isVolatile(), Alignment);
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+ Store2 = DAG.getTruncStore(Chain, TLI.isLittleEndian()?Hi:Lo, Ptr,
+ ST->getSrcValue(), SVOffset + IncrementSize,
+ NewStoredVT, ST->isVolatile(), Alignment);
+
+ return DAG.getNode(ISD::TokenFactor, MVT::Other, Store1, Store2);
+}
+
+/// ExpandUnalignedLoad - Expands an unaligned load to 2 half-size loads.
+static
+SDOperand ExpandUnalignedLoad(LoadSDNode *LD, SelectionDAG &DAG,
+ TargetLowering &TLI) {
+ assert(MVT::isInteger(LD->getLoadedVT()) &&
+ "Non integer unaligned loads not implemented.");
+ int SVOffset = LD->getSrcValueOffset();
+ SDOperand Chain = LD->getChain();
+ SDOperand Ptr = LD->getBasePtr();
+ MVT::ValueType VT = LD->getValueType(0);
+ MVT::ValueType NewLoadedVT = LD->getLoadedVT() - 1;
+ int NumBits = MVT::getSizeInBits(NewLoadedVT);
+ int Alignment = LD->getAlignment();
+ int IncrementSize = NumBits / 8;
+ ISD::LoadExtType HiExtType = LD->getExtensionType();
+
+ // If the original load is NON_EXTLOAD, the hi part load must be ZEXTLOAD.
+ if (HiExtType == ISD::NON_EXTLOAD)
+ HiExtType = ISD::ZEXTLOAD;
+
+ // Load the value in two parts
+ SDOperand Lo, Hi;
+ if (TLI.isLittleEndian()) {
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset, NewLoadedVT, LD->isVolatile(), Alignment);
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+ Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+ Alignment);
+ } else {
+ Hi = DAG.getExtLoad(HiExtType, VT, Chain, Ptr, LD->getSrcValue(), SVOffset,
+ NewLoadedVT,LD->isVolatile(), Alignment);
+ Ptr = DAG.getNode(ISD::ADD, Ptr.getValueType(), Ptr,
+ DAG.getConstant(IncrementSize, TLI.getPointerTy()));
+ Lo = DAG.getExtLoad(ISD::ZEXTLOAD, VT, Chain, Ptr, LD->getSrcValue(),
+ SVOffset + IncrementSize, NewLoadedVT, LD->isVolatile(),
+ Alignment);
+ }
+
+ // aggregate the two parts
+ SDOperand ShiftAmount = DAG.getConstant(NumBits, TLI.getShiftAmountTy());
+ SDOperand Result = DAG.getNode(ISD::SHL, VT, Hi, ShiftAmount);
+ Result = DAG.getNode(ISD::OR, VT, Result, Lo);
+
+ SDOperand TF = DAG.getNode(ISD::TokenFactor, MVT::Other, Lo.getValue(1),
+ Hi.getValue(1));
+
+ SDOperand Ops[] = { Result, TF };
+ return DAG.getNode(ISD::MERGE_VALUES, DAG.getVTList(VT, MVT::Other), Ops, 2);
+}
/// LegalizeOp - We know that the specified value has a legal type, and
/// that its operands are legal. Now ensure that the operation itself
}
break;
- case ISD::Constant:
+ case ISD::Constant: {
+ ConstantSDNode *CN = cast<ConstantSDNode>(Node);
+ unsigned opAction =
+ TLI.getOperationAction(ISD::Constant, CN->getValueType(0));
+
// We know we don't need to expand constants here, constants only have one
// value and we check that it is fine above.
- // FIXME: Maybe we should handle things like targets that don't support full
- // 32-bit immediates?
+ if (opAction == TargetLowering::Custom) {
+ Tmp1 = TLI.LowerOperation(Result, DAG);
+ if (Tmp1.Val)
+ Result = Tmp1;
+ }
break;
+ }
case ISD::ConstantFP: {
// Spill FP immediates to the constant pool if the target cannot directly
// codegen them. Targets often have some immediate values that can be
AddLegalizedOperand(SDOperand(Node, i), Tmp1);
}
return Tmp2;
-
+ case ISD::EXTRACT_SUBREG: {
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(1));
+ assert(idx && "Operand must be a constant");
+ Tmp2 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2);
+ }
+ break;
+ case ISD::INSERT_SUBREG: {
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ Tmp2 = LegalizeOp(Node->getOperand(1));
+ ConstantSDNode *idx = dyn_cast<ConstantSDNode>(Node->getOperand(2));
+ assert(idx && "Operand must be a constant");
+ Tmp3 = DAG.getTargetConstant(idx->getValue(), idx->getValueType(0));
+ Result = DAG.UpdateNodeOperands(Result, Tmp1, Tmp2, Tmp3);
+ }
+ break;
case ISD::BUILD_VECTOR:
switch (TLI.getOperationAction(ISD::BUILD_VECTOR, Node->getValueType(0))) {
default: assert(0 && "This action is not supported yet!");
AddLegalizedOperand(SDOperand(Node, 1), Result.getValue(1));
return Result.getValue(Op.ResNo);
case ISD::DYNAMIC_STACKALLOC: {
+ MVT::ValueType VT = Node->getValueType(0);
Tmp1 = LegalizeOp(Node->getOperand(0)); // Legalize the chain.
Tmp2 = LegalizeOp(Node->getOperand(1)); // Legalize the size.
Tmp3 = LegalizeOp(Node->getOperand(2)); // Legalize the alignment.
Tmp1 = Result.getValue(0);
Tmp2 = Result.getValue(1);
- switch (TLI.getOperationAction(Node->getOpcode(),
- Node->getValueType(0))) {
+ switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action is not supported yet!");
case TargetLowering::Expand: {
unsigned SPReg = TLI.getStackPointerRegisterToSaveRestore();
" not tell us which reg is the stack pointer!");
SDOperand Chain = Tmp1.getOperand(0);
SDOperand Size = Tmp2.getOperand(1);
- SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, Node->getValueType(0));
- Tmp1 = DAG.getNode(ISD::SUB, Node->getValueType(0), SP, Size); // Value
- Tmp2 = DAG.getCopyToReg(SP.getValue(1), SPReg, Tmp1); // Output chain
+ SDOperand SP = DAG.getCopyFromReg(Chain, SPReg, VT);
+ Chain = SP.getValue(1);
+ unsigned Align = cast<ConstantSDNode>(Tmp3)->getValue();
+ unsigned StackAlign =
+ TLI.getTargetMachine().getFrameInfo()->getStackAlignment();
+ if (Align > StackAlign)
+ SP = DAG.getNode(ISD::AND, VT, SP,
+ DAG.getConstant(-(uint64_t)Align, VT));
+ Tmp1 = DAG.getNode(ISD::SUB, VT, SP, Size); // Value
+ Tmp2 = DAG.getCopyToReg(Chain, SPReg, Tmp1); // Output chain
Tmp1 = LegalizeOp(Tmp1);
Tmp2 = LegalizeOp(Tmp2);
break;
switch (TLI.getOperationAction(Node->getOpcode(), VT)) {
default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal: break;
+ case TargetLowering::Legal:
+ // If this is an unaligned load and the target doesn't support it,
+ // expand it.
+ if (!TLI.allowsUnalignedMemoryAccesses()) {
+ unsigned ABIAlignment = TLI.getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+ if (LD->getAlignment() < ABIAlignment){
+ Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+ TLI);
+ Tmp3 = Result.getOperand(0);
+ Tmp4 = Result.getOperand(1);
+ LegalizeOp(Tmp3);
+ LegalizeOp(Tmp4);
+ }
+ }
+ break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Tmp3, DAG);
if (Tmp1.Val) {
Tmp1 = LegalizeOp(Tmp3);
Tmp2 = LegalizeOp(Tmp3.getValue(1));
}
+ } else {
+ // If this is an unaligned load and the target doesn't support it,
+ // expand it.
+ if (!TLI.allowsUnalignedMemoryAccesses()) {
+ unsigned ABIAlignment = TLI.getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(LD->getLoadedVT()));
+ if (LD->getAlignment() < ABIAlignment){
+ Result = ExpandUnalignedLoad(cast<LoadSDNode>(Result.Val), DAG,
+ TLI);
+ Tmp1 = Result.getOperand(0);
+ Tmp2 = Result.getOperand(1);
+ LegalizeOp(Tmp1);
+ LegalizeOp(Tmp2);
+ }
+ }
}
break;
case TargetLowering::Expand:
MVT::ValueType VT = Tmp3.getValueType();
switch (TLI.getOperationAction(ISD::STORE, VT)) {
default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal: break;
+ case TargetLowering::Legal:
+ // If this is an unaligned store and the target doesn't support it,
+ // expand it.
+ if (!TLI.allowsUnalignedMemoryAccesses()) {
+ unsigned ABIAlignment = TLI.getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+ if (ST->getAlignment() < ABIAlignment)
+ Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+ TLI);
+ }
+ break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
MVT::ValueType StVT = cast<StoreSDNode>(Result.Val)->getStoredVT();
switch (TLI.getStoreXAction(StVT)) {
default: assert(0 && "This action is not supported yet!");
- case TargetLowering::Legal: break;
+ case TargetLowering::Legal:
+ // If this is an unaligned store and the target doesn't support it,
+ // expand it.
+ if (!TLI.allowsUnalignedMemoryAccesses()) {
+ unsigned ABIAlignment = TLI.getTargetData()->
+ getABITypeAlignment(MVT::getTypeForValueType(ST->getStoredVT()));
+ if (ST->getAlignment() < ABIAlignment)
+ Result = ExpandUnalignedStore(cast<StoreSDNode>(Result.Val), DAG,
+ TLI);
+ }
+ break;
case TargetLowering::Custom:
Tmp1 = TLI.LowerOperation(Result, DAG);
if (Tmp1.Val) Result = Tmp1;
case ISD::CTLZ:
Tmp1 = LegalizeOp(Node->getOperand(0)); // Op
switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
- case TargetLowering::Custom: assert(0 && "Cannot custom handle this yet!");
+ case TargetLowering::Custom:
case TargetLowering::Legal:
Result = DAG.UpdateNodeOperands(Result, Tmp1);
+ if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
+ TargetLowering::Custom) {
+ Tmp1 = TLI.LowerOperation(Result, DAG);
+ if (Tmp1.Val) {
+ Result = Tmp1;
+ }
+ }
break;
case TargetLowering::Promote: {
MVT::ValueType OVT = Tmp1.getValueType();
DAG.getConstant(MVT::getSizeInBits(NVT), NVT),
ISD::SETEQ);
Result = DAG.getNode(ISD::SELECT, NVT, Tmp2,
- DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
+ DAG.getConstant(MVT::getSizeInBits(OVT),NVT), Tmp1);
break;
case ISD::CTLZ:
// Tmp1 = Tmp1 - (sizeinbits(NVT) - sizeinbits(Old VT))
// type. If so, convert to the vector type.
MVT::ValueType TVT = MVT::getVectorType(EVT, NumElems);
if (TLI.isTypeLegal(TVT)) {
- // Turn this into a bit convert of the packed input.
+ // Turn this into a bit convert of the vector input.
Result = DAG.getNode(ISD::BIT_CONVERT, Node->getValueType(0),
LegalizeOp(Node->getOperand(0)));
break;
}
break;
- case ISD::FP_ROUND:
- if (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0)) ==
- TargetLowering::Expand) {
- // The only way we can lower this is to turn it into a TRUNCSTORE,
- // EXTLOAD pair, targetting a temporary location (a stack slot).
-
- // NOTE: there is a choice here between constantly creating new stack
- // slots and always reusing the same one. We currently always create
- // new ones, as reuse may inhibit scheduling.
- MVT::ValueType VT = Op.getValueType(); // 32
- const Type *Ty = MVT::getTypeForValueType(VT);
- uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
- unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
- MachineFunction &MF = DAG.getMachineFunction();
- int SSFI =
- MF.getFrameInfo()->CreateStackObject(TySize, Align);
- SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
- Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
- StackSlot, NULL, 0, VT);
- Result = DAG.getLoad(VT, Result, StackSlot, NULL, 0, VT);
- break;
+ case ISD::FP_EXTEND:
+ case ISD::FP_ROUND: {
+ MVT::ValueType newVT = Op.getValueType();
+ MVT::ValueType oldVT = Op.getOperand(0).getValueType();
+ if (TLI.getConvertAction(oldVT, newVT) == TargetLowering::Expand) {
+ // The only way we can lower this is to turn it into a STORE,
+ // LOAD pair, targetting a temporary location (a stack slot).
+
+ // NOTE: there is a choice here between constantly creating new stack
+ // slots and always reusing the same one. We currently always create
+ // new ones, as reuse may inhibit scheduling.
+ MVT::ValueType slotVT =
+ (Node->getOpcode() == ISD::FP_EXTEND) ? oldVT : newVT;
+ const Type *Ty = MVT::getTypeForValueType(slotVT);
+ uint64_t TySize = TLI.getTargetData()->getTypeSize(Ty);
+ unsigned Align = TLI.getTargetData()->getPrefTypeAlignment(Ty);
+ MachineFunction &MF = DAG.getMachineFunction();
+ int SSFI =
+ MF.getFrameInfo()->CreateStackObject(TySize, Align);
+ SDOperand StackSlot = DAG.getFrameIndex(SSFI, TLI.getPointerTy());
+ if (Node->getOpcode() == ISD::FP_EXTEND) {
+ Result = DAG.getStore(DAG.getEntryNode(), Node->getOperand(0),
+ StackSlot, NULL, 0);
+ Result = DAG.getExtLoad(ISD::EXTLOAD, newVT,
+ Result, StackSlot, NULL, 0, oldVT);
+ } else {
+ Result = DAG.getTruncStore(DAG.getEntryNode(), Node->getOperand(0),
+ StackSlot, NULL, 0, newVT);
+ Result = DAG.getLoad(newVT, Result, StackSlot, NULL, 0, newVT);
+ }
+ break;
+ }
}
// FALL THROUGH
case ISD::ANY_EXTEND:
case ISD::ZERO_EXTEND:
case ISD::SIGN_EXTEND:
- case ISD::FP_EXTEND:
switch (getTypeAction(Node->getOperand(0).getValueType())) {
case Expand: assert(0 && "Shouldn't need to expand other operators here!");
case Legal:
}
break;
}
+ case ISD::ADJUST_TRAMP: {
+ Tmp1 = LegalizeOp(Node->getOperand(0));
+ switch (TLI.getOperationAction(Node->getOpcode(), Node->getValueType(0))) {
+ default: assert(0 && "This action is not supported yet!");
+ case TargetLowering::Custom:
+ Result = DAG.UpdateNodeOperands(Result, Tmp1);
+ Result = TLI.LowerOperation(Result, DAG);
+ if (Result.Val) break;
+ // FALL THROUGH
+ case TargetLowering::Expand:
+ Result = Tmp1;
+ break;
+ }
+ break;
+ }
+ case ISD::TRAMPOLINE: {
+ SDOperand Ops[6];
+ for (unsigned i = 0; i != 6; ++i)
+ Ops[i] = LegalizeOp(Node->getOperand(i));
+ Result = DAG.UpdateNodeOperands(Result, Ops, 6);
+ // The only option for this node is to custom lower it.
+ Result = TLI.LowerOperation(Result, DAG);
+ assert(Result.Val && "Should always custom lower!");
+ break;
+ }
}
assert(Result.getValueType() == Op.getValueType() &&
if (isTypeLegal(TVT)) {
Vec = LegalizeOp(Vec);
Op = DAG.UpdateNodeOperands(Op, Vec, Idx);
- Op = LegalizeOp(Op);
+ return Op;
}
break;
case TargetLowering::Expand:
/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't
-/// support the operation, but do support the resultant packed vector type.
+/// support the operation, but do support the resultant vector type.
SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
// If the only non-undef value is the low element, turn this into a
case ISD::FP_ROUND:
Lo = ExpandLibCall(TLI.getLibcallName(RTLIB::FPROUND_F64_F32),Node,true,Hi);
break;
+ case ISD::FPOWI:
+ Lo = ExpandLibCall(TLI.getLibcallName((VT == MVT::f32)
+ ? RTLIB::POWI_F32 : RTLIB::POWI_F64),
+ Node, false, Hi);
+ break;
case ISD::FSQRT:
case ISD::FSIN:
case ISD::FCOS: {