mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-11-01 15:17:25 +00:00
R600/SI: adjust writemask to only the used components
Signed-off-by: Christian König <christian.koenig@amd.com> Reviewed-by: Michel Dänzer <michel.daenzer@amd.com> git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@179165 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@@ -569,8 +569,9 @@ void SITargetLowering::ensureSRegLimit(SelectionDAG &DAG, SDValue &Operand,
|
||||
Operand = SDValue(Node, 0);
|
||||
}
|
||||
|
||||
SDNode *SITargetLowering::PostISelFolding(MachineSDNode *Node,
|
||||
SelectionDAG &DAG) const {
|
||||
/// \brief Try to fold the Nodes operands into the Node
|
||||
SDNode *SITargetLowering::foldOperands(MachineSDNode *Node,
|
||||
SelectionDAG &DAG) const {
|
||||
|
||||
// Original encoding (either e32 or e64)
|
||||
int Opcode = Node->getMachineOpcode();
|
||||
@@ -703,3 +704,79 @@ SDNode *SITargetLowering::PostISelFolding(MachineSDNode *Node,
|
||||
return DAG.getMachineNode(Desc->Opcode, Node->getDebugLoc(),
|
||||
Node->getVTList(), Ops.data(), Ops.size());
|
||||
}
|
||||
|
||||
/// \brief Helper function for adjustWritemask
|
||||
unsigned SubIdx2Lane(unsigned Idx) {
|
||||
switch (Idx) {
|
||||
default: return 0;
|
||||
case AMDGPU::sub0: return 0;
|
||||
case AMDGPU::sub1: return 1;
|
||||
case AMDGPU::sub2: return 2;
|
||||
case AMDGPU::sub3: return 3;
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Adjust the writemask of MIMG instructions
|
||||
void SITargetLowering::adjustWritemask(MachineSDNode *&Node,
|
||||
SelectionDAG &DAG) const {
|
||||
SDNode *Users[4] = { };
|
||||
unsigned Writemask = 0;
|
||||
|
||||
// Try to figure out the used register components
|
||||
for (SDNode::use_iterator I = Node->use_begin(), E = Node->use_end();
|
||||
I != E; ++I) {
|
||||
|
||||
// Abort if we can't understand the usage
|
||||
if (!I->isMachineOpcode() ||
|
||||
I->getMachineOpcode() != TargetOpcode::EXTRACT_SUBREG)
|
||||
return;
|
||||
|
||||
unsigned Lane = SubIdx2Lane(I->getConstantOperandVal(1));
|
||||
|
||||
// Abort if we have more than one user per component
|
||||
if (Users[Lane])
|
||||
return;
|
||||
|
||||
Users[Lane] = *I;
|
||||
Writemask |= 1 << Lane;
|
||||
}
|
||||
|
||||
// Abort if all components are used
|
||||
if (Writemask == 0xf)
|
||||
return;
|
||||
|
||||
// Adjust the writemask in the node
|
||||
std::vector<SDValue> Ops;
|
||||
Ops.push_back(DAG.getTargetConstant(Writemask, MVT::i32));
|
||||
for (unsigned i = 1, e = Node->getNumOperands(); i != e; ++i)
|
||||
Ops.push_back(Node->getOperand(i));
|
||||
Node = (MachineSDNode*)DAG.UpdateNodeOperands(Node, Ops.data(), Ops.size());
|
||||
|
||||
// Update the users of the node with the new indices
|
||||
for (unsigned i = 0, Idx = AMDGPU::sub0; i < 4; ++i) {
|
||||
|
||||
SDNode *User = Users[i];
|
||||
if (!User)
|
||||
continue;
|
||||
|
||||
SDValue Op = DAG.getTargetConstant(Idx, MVT::i32);
|
||||
DAG.UpdateNodeOperands(User, User->getOperand(0), Op);
|
||||
|
||||
switch (Idx) {
|
||||
default: break;
|
||||
case AMDGPU::sub0: Idx = AMDGPU::sub1; break;
|
||||
case AMDGPU::sub1: Idx = AMDGPU::sub2; break;
|
||||
case AMDGPU::sub2: Idx = AMDGPU::sub3; break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// \brief Fold the instructions after slecting them
|
||||
SDNode *SITargetLowering::PostISelFolding(MachineSDNode *Node,
|
||||
SelectionDAG &DAG) const {
|
||||
|
||||
if (AMDGPU::isMIMG(Node->getMachineOpcode()) != -1)
|
||||
adjustWritemask(Node, DAG);
|
||||
|
||||
return foldOperands(Node, DAG);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user