mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2024-07-18 12:29:27 +00:00
Add SCALAR_TO_VECTOR support
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@26866 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
parent
ab515b09bf
commit
ce87215131
@ -160,12 +160,15 @@ private:
|
|||||||
|
|
||||||
void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
|
void LegalizeSetCCOperands(SDOperand &LHS, SDOperand &RHS, SDOperand &CC);
|
||||||
|
|
||||||
|
SDOperand CreateStackTemporary(MVT::ValueType VT);
|
||||||
|
|
||||||
SDOperand ExpandLibCall(const char *Name, SDNode *Node,
|
SDOperand ExpandLibCall(const char *Name, SDNode *Node,
|
||||||
SDOperand &Hi);
|
SDOperand &Hi);
|
||||||
SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
|
SDOperand ExpandIntToFP(bool isSigned, MVT::ValueType DestTy,
|
||||||
SDOperand Source);
|
SDOperand Source);
|
||||||
|
|
||||||
SDOperand ExpandBIT_CONVERT(MVT::ValueType DestVT, SDOperand SrcOp);
|
SDOperand ExpandBIT_CONVERT(MVT::ValueType DestVT, SDOperand SrcOp);
|
||||||
|
SDOperand ExpandBUILD_VECTOR(SDNode *Node);
|
||||||
SDOperand ExpandLegalINT_TO_FP(bool isSigned,
|
SDOperand ExpandLegalINT_TO_FP(bool isSigned,
|
||||||
SDOperand LegalOp,
|
SDOperand LegalOp,
|
||||||
MVT::ValueType DestVT);
|
MVT::ValueType DestVT);
|
||||||
@ -737,91 +740,10 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
// FALLTHROUGH
|
// FALLTHROUGH
|
||||||
case TargetLowering::Expand: {
|
case TargetLowering::Expand:
|
||||||
// We assume that built vectors are not legal, and will be immediately
|
Result = ExpandBUILD_VECTOR(Result.Val);
|
||||||
// spilled to memory. If the values are all constants, turn this into a
|
|
||||||
// load from the constant pool.
|
|
||||||
bool isConstant = true;
|
|
||||||
for (SDNode::op_iterator I = Node->op_begin(), E = Node->op_end();
|
|
||||||
I != E; ++I) {
|
|
||||||
if (!isa<ConstantFPSDNode>(I) && !isa<ConstantSDNode>(I) &&
|
|
||||||
I->getOpcode() != ISD::UNDEF) {
|
|
||||||
isConstant = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a ConstantPacked, and put it in the constant pool.
|
|
||||||
if (isConstant) {
|
|
||||||
MVT::ValueType VT = Node->getValueType(0);
|
|
||||||
const Type *OpNTy =
|
|
||||||
MVT::getTypeForValueType(Node->getOperand(0).getValueType());
|
|
||||||
std::vector<Constant*> CV;
|
|
||||||
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
|
||||||
if (ConstantFPSDNode *V =
|
|
||||||
dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
|
|
||||||
CV.push_back(ConstantFP::get(OpNTy, V->getValue()));
|
|
||||||
} else if (ConstantSDNode *V =
|
|
||||||
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
|
|
||||||
CV.push_back(ConstantUInt::get(OpNTy, V->getValue()));
|
|
||||||
} else {
|
|
||||||
assert(Node->getOperand(i).getOpcode() == ISD::UNDEF);
|
|
||||||
CV.push_back(UndefValue::get(OpNTy));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Constant *CP = ConstantPacked::get(CV);
|
|
||||||
SDOperand CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy());
|
|
||||||
Result = DAG.getLoad(VT, DAG.getEntryNode(), CPIdx,
|
|
||||||
DAG.getSrcValue(NULL));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Otherwise, this isn't a constant entry. Allocate a sufficiently
|
|
||||||
// aligned object on the stack, store each element into it, then load
|
|
||||||
// the result as a vector.
|
|
||||||
MVT::ValueType VT = Node->getValueType(0);
|
|
||||||
// Create the stack frame object.
|
|
||||||
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
|
||||||
unsigned ByteSize = MVT::getSizeInBits(VT)/8;
|
|
||||||
int FrameIdx = FrameInfo->CreateStackObject(ByteSize, ByteSize);
|
|
||||||
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, TLI.getPointerTy());
|
|
||||||
|
|
||||||
// Emit a store of each element to the stack slot.
|
|
||||||
std::vector<SDOperand> Stores;
|
|
||||||
bool isLittleEndian = TLI.isLittleEndian();
|
|
||||||
unsigned TypeByteSize =
|
|
||||||
MVT::getSizeInBits(Node->getOperand(0).getValueType())/8;
|
|
||||||
unsigned VectorSize = MVT::getSizeInBits(VT)/8;
|
|
||||||
// Store (in the right endianness) the elements to memory.
|
|
||||||
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
|
||||||
// Ignore undef elements.
|
|
||||||
if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
|
||||||
|
|
||||||
unsigned Offset;
|
|
||||||
if (isLittleEndian)
|
|
||||||
Offset = TypeByteSize*i;
|
|
||||||
else
|
|
||||||
Offset = TypeByteSize*(e-i-1);
|
|
||||||
|
|
||||||
SDOperand Idx = DAG.getConstant(Offset, FIPtr.getValueType());
|
|
||||||
Idx = DAG.getNode(ISD::ADD, FIPtr.getValueType(), FIPtr, Idx);
|
|
||||||
|
|
||||||
Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
|
||||||
Node->getOperand(i), Idx,
|
|
||||||
DAG.getSrcValue(NULL)));
|
|
||||||
}
|
|
||||||
|
|
||||||
SDOperand StoreChain;
|
|
||||||
if (!Stores.empty()) // Not all undef elements?
|
|
||||||
StoreChain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
|
|
||||||
else
|
|
||||||
StoreChain = DAG.getEntryNode();
|
|
||||||
|
|
||||||
// Result is a load from the stack slot.
|
|
||||||
Result = DAG.getLoad(VT, StoreChain, FIPtr, DAG.getSrcValue(0));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case ISD::INSERT_VECTOR_ELT:
|
case ISD::INSERT_VECTOR_ELT:
|
||||||
Tmp1 = LegalizeOp(Node->getOperand(0)); // InVec
|
Tmp1 = LegalizeOp(Node->getOperand(0)); // InVec
|
||||||
@ -853,6 +775,29 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ISD::SCALAR_TO_VECTOR:
|
||||||
|
Tmp1 = LegalizeOp(Node->getOperand(0)); // InVal
|
||||||
|
Result = DAG.UpdateNodeOperands(Result, Tmp1);
|
||||||
|
switch (TLI.getOperationAction(ISD::SCALAR_TO_VECTOR,
|
||||||
|
Node->getValueType(0))) {
|
||||||
|
default: assert(0 && "This action is not supported yet!");
|
||||||
|
case TargetLowering::Legal:
|
||||||
|
break;
|
||||||
|
case TargetLowering::Expand: {
|
||||||
|
// If the target doesn't support this, store the value to a temporary
|
||||||
|
// stack slot, then EXTLOAD the vector back out.
|
||||||
|
SDOperand StackPtr =
|
||||||
|
CreateStackTemporary(Node->getOperand(0).getValueType());
|
||||||
|
SDOperand Ch = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
||||||
|
Node->getOperand(0), StackPtr,
|
||||||
|
DAG.getSrcValue(NULL));
|
||||||
|
Result = DAG.getExtLoad(ISD::EXTLOAD, Node->getValueType(0), Ch, StackPtr,
|
||||||
|
DAG.getSrcValue(NULL),
|
||||||
|
Node->getOperand(0).getValueType());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ISD::CALLSEQ_START: {
|
case ISD::CALLSEQ_START: {
|
||||||
SDNode *CallEnd = FindCallEndFromCallStart(Node);
|
SDNode *CallEnd = FindCallEndFromCallStart(Node);
|
||||||
|
|
||||||
@ -3005,10 +2950,7 @@ void SelectionDAGLegalize::LegalizeSetCCOperands(SDOperand &LHS,
|
|||||||
SDOperand SelectionDAGLegalize::ExpandBIT_CONVERT(MVT::ValueType DestVT,
|
SDOperand SelectionDAGLegalize::ExpandBIT_CONVERT(MVT::ValueType DestVT,
|
||||||
SDOperand SrcOp) {
|
SDOperand SrcOp) {
|
||||||
// Create the stack frame object.
|
// Create the stack frame object.
|
||||||
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
SDOperand FIPtr = CreateStackTemporary(DestVT);
|
||||||
unsigned ByteSize = MVT::getSizeInBits(DestVT)/8;
|
|
||||||
int FrameIdx = FrameInfo->CreateStackObject(ByteSize, ByteSize);
|
|
||||||
SDOperand FIPtr = DAG.getFrameIndex(FrameIdx, TLI.getPointerTy());
|
|
||||||
|
|
||||||
// Emit a store to the stack slot.
|
// Emit a store to the stack slot.
|
||||||
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
SDOperand Store = DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
||||||
@ -3017,6 +2959,117 @@ SDOperand SelectionDAGLegalize::ExpandBIT_CONVERT(MVT::ValueType DestVT,
|
|||||||
return DAG.getLoad(DestVT, Store, FIPtr, DAG.getSrcValue(0));
|
return DAG.getLoad(DestVT, Store, FIPtr, DAG.getSrcValue(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// ExpandBUILD_VECTOR - Expand a BUILD_VECTOR node on targets that don't
|
||||||
|
/// support the operation, but do support the resultant packed vector type.
|
||||||
|
SDOperand SelectionDAGLegalize::ExpandBUILD_VECTOR(SDNode *Node) {
|
||||||
|
|
||||||
|
// If the only non-undef value is the low element, turn this into a
|
||||||
|
// SCALAR_TO_VECTOR node.
|
||||||
|
bool isOnlyLowElement = true;
|
||||||
|
for (SDNode::op_iterator I = Node->op_begin()+1, E = Node->op_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
if (I->getOpcode() != ISD::UNDEF) {
|
||||||
|
isOnlyLowElement = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isOnlyLowElement) {
|
||||||
|
// If the low element is an undef too, then this whole things is an undef.
|
||||||
|
if (Node->getOperand(0).getOpcode() == ISD::UNDEF)
|
||||||
|
return DAG.getNode(ISD::UNDEF, Node->getValueType(0));
|
||||||
|
// Otherwise, turn this into a scalar_to_vector node.
|
||||||
|
return DAG.getNode(ISD::SCALAR_TO_VECTOR, Node->getValueType(0),
|
||||||
|
Node->getOperand(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If the elements are all constants, turn this into a load from the constant
|
||||||
|
// pool.
|
||||||
|
bool isConstant = true;
|
||||||
|
for (SDNode::op_iterator I = Node->op_begin(), E = Node->op_end();
|
||||||
|
I != E; ++I) {
|
||||||
|
if (!isa<ConstantFPSDNode>(I) && !isa<ConstantSDNode>(I) &&
|
||||||
|
I->getOpcode() != ISD::UNDEF) {
|
||||||
|
isConstant = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a ConstantPacked, and put it in the constant pool.
|
||||||
|
if (isConstant) {
|
||||||
|
MVT::ValueType VT = Node->getValueType(0);
|
||||||
|
const Type *OpNTy =
|
||||||
|
MVT::getTypeForValueType(Node->getOperand(0).getValueType());
|
||||||
|
std::vector<Constant*> CV;
|
||||||
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
||||||
|
if (ConstantFPSDNode *V =
|
||||||
|
dyn_cast<ConstantFPSDNode>(Node->getOperand(i))) {
|
||||||
|
CV.push_back(ConstantFP::get(OpNTy, V->getValue()));
|
||||||
|
} else if (ConstantSDNode *V =
|
||||||
|
dyn_cast<ConstantSDNode>(Node->getOperand(i))) {
|
||||||
|
CV.push_back(ConstantUInt::get(OpNTy, V->getValue()));
|
||||||
|
} else {
|
||||||
|
assert(Node->getOperand(i).getOpcode() == ISD::UNDEF);
|
||||||
|
CV.push_back(UndefValue::get(OpNTy));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Constant *CP = ConstantPacked::get(CV);
|
||||||
|
SDOperand CPIdx = DAG.getConstantPool(CP, TLI.getPointerTy());
|
||||||
|
return DAG.getLoad(VT, DAG.getEntryNode(), CPIdx,
|
||||||
|
DAG.getSrcValue(NULL));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Otherwise, we can't handle this case efficiently. Allocate a sufficiently
|
||||||
|
// aligned object on the stack, store each element into it, then load
|
||||||
|
// the result as a vector.
|
||||||
|
MVT::ValueType VT = Node->getValueType(0);
|
||||||
|
// Create the stack frame object.
|
||||||
|
SDOperand FIPtr = CreateStackTemporary(VT);
|
||||||
|
|
||||||
|
// Emit a store of each element to the stack slot.
|
||||||
|
std::vector<SDOperand> Stores;
|
||||||
|
bool isLittleEndian = TLI.isLittleEndian();
|
||||||
|
unsigned TypeByteSize =
|
||||||
|
MVT::getSizeInBits(Node->getOperand(0).getValueType())/8;
|
||||||
|
unsigned VectorSize = MVT::getSizeInBits(VT)/8;
|
||||||
|
// Store (in the right endianness) the elements to memory.
|
||||||
|
for (unsigned i = 0, e = Node->getNumOperands(); i != e; ++i) {
|
||||||
|
// Ignore undef elements.
|
||||||
|
if (Node->getOperand(i).getOpcode() == ISD::UNDEF) continue;
|
||||||
|
|
||||||
|
unsigned Offset;
|
||||||
|
if (isLittleEndian)
|
||||||
|
Offset = TypeByteSize*i;
|
||||||
|
else
|
||||||
|
Offset = TypeByteSize*(e-i-1);
|
||||||
|
|
||||||
|
SDOperand Idx = DAG.getConstant(Offset, FIPtr.getValueType());
|
||||||
|
Idx = DAG.getNode(ISD::ADD, FIPtr.getValueType(), FIPtr, Idx);
|
||||||
|
|
||||||
|
Stores.push_back(DAG.getNode(ISD::STORE, MVT::Other, DAG.getEntryNode(),
|
||||||
|
Node->getOperand(i), Idx,
|
||||||
|
DAG.getSrcValue(NULL)));
|
||||||
|
}
|
||||||
|
|
||||||
|
SDOperand StoreChain;
|
||||||
|
if (!Stores.empty()) // Not all undef elements?
|
||||||
|
StoreChain = DAG.getNode(ISD::TokenFactor, MVT::Other, Stores);
|
||||||
|
else
|
||||||
|
StoreChain = DAG.getEntryNode();
|
||||||
|
|
||||||
|
// Result is a load from the stack slot.
|
||||||
|
return DAG.getLoad(VT, StoreChain, FIPtr, DAG.getSrcValue(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// CreateStackTemporary - Create a stack temporary, suitable for holding the
|
||||||
|
/// specified value type.
|
||||||
|
SDOperand SelectionDAGLegalize::CreateStackTemporary(MVT::ValueType VT) {
|
||||||
|
MachineFrameInfo *FrameInfo = DAG.getMachineFunction().getFrameInfo();
|
||||||
|
unsigned ByteSize = MVT::getSizeInBits(VT)/8;
|
||||||
|
int FrameIdx = FrameInfo->CreateStackObject(ByteSize, ByteSize);
|
||||||
|
return DAG.getFrameIndex(FrameIdx, TLI.getPointerTy());
|
||||||
|
}
|
||||||
|
|
||||||
void SelectionDAGLegalize::ExpandShiftParts(unsigned NodeOp,
|
void SelectionDAGLegalize::ExpandShiftParts(unsigned NodeOp,
|
||||||
SDOperand Op, SDOperand Amt,
|
SDOperand Op, SDOperand Amt,
|
||||||
SDOperand &Lo, SDOperand &Hi) {
|
SDOperand &Lo, SDOperand &Hi) {
|
||||||
|
@ -1092,6 +1092,11 @@ SDOperand SelectionDAG::getNode(unsigned Opcode, MVT::ValueType VT,
|
|||||||
if (OpOpcode == ISD::BIT_CONVERT) // bitconv(bitconv(x)) -> bitconv(x)
|
if (OpOpcode == ISD::BIT_CONVERT) // bitconv(bitconv(x)) -> bitconv(x)
|
||||||
return getNode(ISD::BIT_CONVERT, VT, Operand.getOperand(0));
|
return getNode(ISD::BIT_CONVERT, VT, Operand.getOperand(0));
|
||||||
break;
|
break;
|
||||||
|
case ISD::SCALAR_TO_VECTOR:
|
||||||
|
assert(MVT::isVector(VT) && !MVT::isVector(Operand.getValueType()) &&
|
||||||
|
MVT::getVectorBaseType(VT) == Operand.getValueType() &&
|
||||||
|
"Illegal SCALAR_TO_VECTOR node!");
|
||||||
|
break;
|
||||||
case ISD::FNEG:
|
case ISD::FNEG:
|
||||||
if (OpOpcode == ISD::FSUB) // -(X-Y) -> (Y-X)
|
if (OpOpcode == ISD::FSUB) // -(X-Y) -> (Y-X)
|
||||||
return getNode(ISD::FSUB, VT, Operand.Val->getOperand(1),
|
return getNode(ISD::FSUB, VT, Operand.Val->getOperand(1),
|
||||||
@ -1555,10 +1560,15 @@ SDOperand SelectionDAG::getNode(unsigned Opcode,
|
|||||||
// normal load.
|
// normal load.
|
||||||
if (ResultTys[0] == EVT)
|
if (ResultTys[0] == EVT)
|
||||||
return getLoad(ResultTys[0], Ops[0], Ops[1], Ops[2]);
|
return getLoad(ResultTys[0], Ops[0], Ops[1], Ops[2]);
|
||||||
assert(EVT < ResultTys[0] &&
|
if (MVT::isVector(ResultTys[0])) {
|
||||||
"Should only be an extending load, not truncating!");
|
assert(EVT == MVT::getVectorBaseType(ResultTys[0]) &&
|
||||||
|
"Invalid vector extload!");
|
||||||
|
} else {
|
||||||
|
assert(EVT < ResultTys[0] &&
|
||||||
|
"Should only be an extending load, not truncating!");
|
||||||
|
}
|
||||||
assert((Opcode == ISD::EXTLOAD || MVT::isInteger(ResultTys[0])) &&
|
assert((Opcode == ISD::EXTLOAD || MVT::isInteger(ResultTys[0])) &&
|
||||||
"Cannot sign/zero extend a FP load!");
|
"Cannot sign/zero extend a FP/Vector load!");
|
||||||
assert(MVT::isInteger(ResultTys[0]) == MVT::isInteger(EVT) &&
|
assert(MVT::isInteger(ResultTys[0]) == MVT::isInteger(EVT) &&
|
||||||
"Cannot convert from FP to Int or Int -> FP!");
|
"Cannot convert from FP to Int or Int -> FP!");
|
||||||
break;
|
break;
|
||||||
@ -2654,6 +2664,7 @@ const char *SDNode::getOperationName(const SelectionDAG *G) const {
|
|||||||
case ISD::SELECT_CC: return "select_cc";
|
case ISD::SELECT_CC: return "select_cc";
|
||||||
case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt";
|
case ISD::INSERT_VECTOR_ELT: return "insert_vector_elt";
|
||||||
case ISD::VINSERT_VECTOR_ELT: return "vinsert_vector_elt";
|
case ISD::VINSERT_VECTOR_ELT: return "vinsert_vector_elt";
|
||||||
|
case ISD::SCALAR_TO_VECTOR: return "scalar_to_vector";
|
||||||
case ISD::ADDC: return "addc";
|
case ISD::ADDC: return "addc";
|
||||||
case ISD::ADDE: return "adde";
|
case ISD::ADDE: return "adde";
|
||||||
case ISD::SUBC: return "subc";
|
case ISD::SUBC: return "subc";
|
||||||
|
Loading…
Reference in New Issue
Block a user