mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-08-15 06:29:05 +00:00
Pull the code to perform an INSERT_VECTOR_ELT in memory out into its own
function, and then use it to fix a bug in SplitVectorOp that expected inserts to always have constant insertion indices. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@50273 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -156,6 +156,13 @@ private:
|
|||||||
/// operating on each element individually.
|
/// operating on each element individually.
|
||||||
SDOperand UnrollVectorOp(SDOperand O);
|
SDOperand UnrollVectorOp(SDOperand O);
|
||||||
|
|
||||||
|
/// PerformInsertVectorEltInMemory - Some target cannot handle a variable
|
||||||
|
/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it
|
||||||
|
/// is necessary to spill the vector being inserted into to memory, perform
|
||||||
|
/// the insert there, and then read the result back.
|
||||||
|
SDOperand PerformInsertVectorEltInMemory(SDOperand Vec, SDOperand Val,
|
||||||
|
SDOperand Idx);
|
||||||
|
|
||||||
/// PromoteOp - Given an operation that produces a value in an invalid type,
|
/// PromoteOp - Given an operation that produces a value in an invalid type,
|
||||||
/// promote it to compute the value into a larger type. The produced value
|
/// promote it to compute the value into a larger type. The produced value
|
||||||
/// will have the correct bits for the low portion of the register, but no
|
/// will have the correct bits for the low portion of the register, but no
|
||||||
@@ -757,6 +764,50 @@ static RTLIB::Libcall GetFPLibCall(MVT::ValueType VT,
|
|||||||
RTLIB::UNKNOWN_LIBCALL;
|
RTLIB::UNKNOWN_LIBCALL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// PerformInsertVectorEltInMemory - Some target cannot handle a variable
|
||||||
|
/// insertion index for the INSERT_VECTOR_ELT instruction. In this case, it
|
||||||
|
/// is necessary to spill the vector being inserted into to memory, perform
|
||||||
|
/// the insert there, and then read the result back.
|
||||||
|
SDOperand SelectionDAGLegalize::
|
||||||
|
PerformInsertVectorEltInMemory(SDOperand Vec, SDOperand Val, SDOperand Idx) {
|
||||||
|
SDOperand Tmp1 = Vec;
|
||||||
|
SDOperand Tmp2 = Val;
|
||||||
|
SDOperand Tmp3 = Idx;
|
||||||
|
|
||||||
|
// If the target doesn't support this, we have to spill the input vector
|
||||||
|
// to a temporary stack slot, update the element, then reload it. This is
|
||||||
|
// badness. We could also load the value into a vector register (either
|
||||||
|
// with a "move to register" or "extload into register" instruction, then
|
||||||
|
// permute it into place, if the idx is a constant and if the idx is
|
||||||
|
// supported by the target.
|
||||||
|
MVT::ValueType VT = Tmp1.getValueType();
|
||||||
|
MVT::ValueType EltVT = MVT::getVectorElementType(VT);
|
||||||
|
MVT::ValueType IdxVT = Tmp3.getValueType();
|
||||||
|
MVT::ValueType PtrVT = TLI.getPointerTy();
|
||||||
|
SDOperand StackPtr = DAG.CreateStackTemporary(VT);
|
||||||
|
|
||||||
|
FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(StackPtr.Val);
|
||||||
|
int SPFI = StackPtrFI->getIndex();
|
||||||
|
|
||||||
|
// Store the vector.
|
||||||
|
SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Tmp1, StackPtr,
|
||||||
|
PseudoSourceValue::getFixedStack(),
|
||||||
|
SPFI);
|
||||||
|
|
||||||
|
// Truncate or zero extend offset to target pointer type.
|
||||||
|
unsigned CastOpc = (IdxVT > PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND;
|
||||||
|
Tmp3 = DAG.getNode(CastOpc, PtrVT, Tmp3);
|
||||||
|
// Add the offset to the index.
|
||||||
|
unsigned EltSize = MVT::getSizeInBits(EltVT)/8;
|
||||||
|
Tmp3 = DAG.getNode(ISD::MUL, IdxVT, Tmp3,DAG.getConstant(EltSize, IdxVT));
|
||||||
|
SDOperand StackPtr2 = DAG.getNode(ISD::ADD, IdxVT, Tmp3, StackPtr);
|
||||||
|
// Store the scalar value.
|
||||||
|
Ch = DAG.getTruncStore(Ch, Tmp2, StackPtr2,
|
||||||
|
PseudoSourceValue::getFixedStack(), SPFI, EltVT);
|
||||||
|
// Load the updated vector.
|
||||||
|
return DAG.getLoad(VT, Ch, StackPtr, PseudoSourceValue::getFixedStack(),SPFI);
|
||||||
|
}
|
||||||
|
|
||||||
/// LegalizeOp - We know that the specified value has a legal type, and
|
/// LegalizeOp - We know that the specified value has a legal type, and
|
||||||
/// that its operands are legal. Now ensure that the operation itself
|
/// that its operands are legal. Now ensure that the operation itself
|
||||||
/// is legal, recursively ensuring that the operands' operations remain
|
/// is legal, recursively ensuring that the operands' operations remain
|
||||||
@@ -1404,40 +1455,7 @@ SDOperand SelectionDAGLegalize::LegalizeOp(SDOperand Op) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Result = PerformInsertVectorEltInMemory(Tmp1, Tmp2, Tmp3);
|
||||||
// If the target doesn't support this, we have to spill the input vector
|
|
||||||
// to a temporary stack slot, update the element, then reload it. This is
|
|
||||||
// badness. We could also load the value into a vector register (either
|
|
||||||
// with a "move to register" or "extload into register" instruction, then
|
|
||||||
// permute it into place, if the idx is a constant and if the idx is
|
|
||||||
// supported by the target.
|
|
||||||
MVT::ValueType VT = Tmp1.getValueType();
|
|
||||||
MVT::ValueType EltVT = MVT::getVectorElementType(VT);
|
|
||||||
MVT::ValueType IdxVT = Tmp3.getValueType();
|
|
||||||
MVT::ValueType PtrVT = TLI.getPointerTy();
|
|
||||||
SDOperand StackPtr = DAG.CreateStackTemporary(VT);
|
|
||||||
|
|
||||||
FrameIndexSDNode *StackPtrFI = cast<FrameIndexSDNode>(StackPtr.Val);
|
|
||||||
int SPFI = StackPtrFI->getIndex();
|
|
||||||
|
|
||||||
// Store the vector.
|
|
||||||
SDOperand Ch = DAG.getStore(DAG.getEntryNode(), Tmp1, StackPtr,
|
|
||||||
PseudoSourceValue::getFixedStack(),
|
|
||||||
SPFI);
|
|
||||||
|
|
||||||
// Truncate or zero extend offset to target pointer type.
|
|
||||||
unsigned CastOpc = (IdxVT > PtrVT) ? ISD::TRUNCATE : ISD::ZERO_EXTEND;
|
|
||||||
Tmp3 = DAG.getNode(CastOpc, PtrVT, Tmp3);
|
|
||||||
// Add the offset to the index.
|
|
||||||
unsigned EltSize = MVT::getSizeInBits(EltVT)/8;
|
|
||||||
Tmp3 = DAG.getNode(ISD::MUL, IdxVT, Tmp3,DAG.getConstant(EltSize, IdxVT));
|
|
||||||
SDOperand StackPtr2 = DAG.getNode(ISD::ADD, IdxVT, Tmp3, StackPtr);
|
|
||||||
// Store the scalar value.
|
|
||||||
Ch = DAG.getTruncStore(Ch, Tmp2, StackPtr2,
|
|
||||||
PseudoSourceValue::getFixedStack(), SPFI, EltVT);
|
|
||||||
// Load the updated vector.
|
|
||||||
Result = DAG.getLoad(VT, Ch, StackPtr,
|
|
||||||
PseudoSourceValue::getFixedStack(), SPFI);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -6714,8 +6732,9 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
|
|||||||
Hi = Node->getOperand(1);
|
Hi = Node->getOperand(1);
|
||||||
break;
|
break;
|
||||||
case ISD::INSERT_VECTOR_ELT: {
|
case ISD::INSERT_VECTOR_ELT: {
|
||||||
|
if (ConstantSDNode *Idx = dyn_cast<ConstantSDNode>(Node->getOperand(2))) {
|
||||||
SplitVectorOp(Node->getOperand(0), Lo, Hi);
|
SplitVectorOp(Node->getOperand(0), Lo, Hi);
|
||||||
unsigned Index = cast<ConstantSDNode>(Node->getOperand(2))->getValue();
|
unsigned Index = Idx->getValue();
|
||||||
SDOperand ScalarOp = Node->getOperand(1);
|
SDOperand ScalarOp = Node->getOperand(1);
|
||||||
if (Index < NewNumElts_Lo)
|
if (Index < NewNumElts_Lo)
|
||||||
Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Lo, Lo, ScalarOp,
|
Lo = DAG.getNode(ISD::INSERT_VECTOR_ELT, NewVT_Lo, Lo, ScalarOp,
|
||||||
@@ -6725,6 +6744,12 @@ void SelectionDAGLegalize::SplitVectorOp(SDOperand Op, SDOperand &Lo,
|
|||||||
DAG.getIntPtrConstant(Index - NewNumElts_Lo));
|
DAG.getIntPtrConstant(Index - NewNumElts_Lo));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
SDOperand Tmp = PerformInsertVectorEltInMemory(Node->getOperand(0),
|
||||||
|
Node->getOperand(1),
|
||||||
|
Node->getOperand(2));
|
||||||
|
SplitVectorOp(Tmp, Lo, Hi);
|
||||||
|
break;
|
||||||
|
}
|
||||||
case ISD::VECTOR_SHUFFLE: {
|
case ISD::VECTOR_SHUFFLE: {
|
||||||
// Build the low part.
|
// Build the low part.
|
||||||
SDOperand Mask = Node->getOperand(2);
|
SDOperand Mask = Node->getOperand(2);
|
||||||
|
Reference in New Issue
Block a user