Skip to content

Commit

Permalink
[Hexagon] Extend OptAddrMode pass to vgather
Browse files Browse the repository at this point in the history
This change extends the addressing mode optimization
pass to HVX vgather. This is specifically intended to
resolve compiler not generating indexed addresses for
vgather stores to vtcm. Changed the vgather pseudo
instructions to accept an immediate operand and handled
addition of appropriate immediate operand in addressing
mode optimization pass.
  • Loading branch information
shubhamp-ca authored and Krzysztof Parzyszek committed Jan 5, 2022
1 parent de731ef commit 4108535
Show file tree
Hide file tree
Showing 7 changed files with 234 additions and 54 deletions.
7 changes: 5 additions & 2 deletions llvm/lib/Target/Hexagon/HexagonISelDAGToDAGHVX.cpp
Expand Up @@ -2393,6 +2393,7 @@ void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) {
SDValue Base = N->getOperand(4);
SDValue Modifier = N->getOperand(5);
SDValue Offset = N->getOperand(6);
SDValue ImmOperand = CurDAG->getTargetConstant(0, dl, MVT::i32);

unsigned Opcode;
unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Expand All @@ -2414,7 +2415,8 @@ void HexagonDAGToDAGISel::SelectV65GatherPred(SDNode *N) {
}

SDVTList VTs = CurDAG->getVTList(MVT::Other);
SDValue Ops[] = { Address, Predicate, Base, Modifier, Offset, Chain };
SDValue Ops[] = { Address, ImmOperand,
Predicate, Base, Modifier, Offset, Chain };
SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops);

MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
Expand All @@ -2430,6 +2432,7 @@ void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) {
SDValue Base = N->getOperand(3);
SDValue Modifier = N->getOperand(4);
SDValue Offset = N->getOperand(5);
SDValue ImmOperand = CurDAG->getTargetConstant(0, dl, MVT::i32);

unsigned Opcode;
unsigned IntNo = cast<ConstantSDNode>(N->getOperand(1))->getZExtValue();
Expand All @@ -2451,7 +2454,7 @@ void HexagonDAGToDAGISel::SelectV65Gather(SDNode *N) {
}

SDVTList VTs = CurDAG->getVTList(MVT::Other);
SDValue Ops[] = { Address, Base, Modifier, Offset, Chain };
SDValue Ops[] = { Address, ImmOperand, Base, Modifier, Offset, Chain };
SDNode *Result = CurDAG->getMachineNode(Opcode, dl, VTs, Ops);

MachineMemOperand *MemOp = cast<MemIntrinsicSDNode>(N)->getMemOperand();
Expand Down
44 changes: 25 additions & 19 deletions llvm/lib/Target/Hexagon/HexagonInstrInfo.cpp
Expand Up @@ -1506,75 +1506,75 @@ HexagonInstrInfo::expandVGatherPseudo(MachineInstr &MI) const {
switch (Opc) {
case Hexagon::V6_vgathermh_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermh))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3));
.add(MI.getOperand(3))
.add(MI.getOperand(4));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();

case Hexagon::V6_vgathermw_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermw))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3));
.add(MI.getOperand(3))
.add(MI.getOperand(4));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();

case Hexagon::V6_vgathermhw_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhw))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3));
.add(MI.getOperand(3))
.add(MI.getOperand(4));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();

case Hexagon::V6_vgathermhq_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhq))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3))
.add(MI.getOperand(4));
.add(MI.getOperand(4))
.add(MI.getOperand(5));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();

case Hexagon::V6_vgathermwq_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermwq))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3))
.add(MI.getOperand(4));
.add(MI.getOperand(4))
.add(MI.getOperand(5));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();

case Hexagon::V6_vgathermhwq_pseudo:
First = BuildMI(MBB, MI, DL, get(Hexagon::V6_vgathermhwq))
.add(MI.getOperand(1))
.add(MI.getOperand(2))
.add(MI.getOperand(3))
.add(MI.getOperand(4));
.add(MI.getOperand(4))
.add(MI.getOperand(5));
BuildMI(MBB, MI, DL, get(Hexagon::V6_vS32b_new_ai))
.add(MI.getOperand(0))
.addImm(0)
.addImm(MI.getOperand(1).getImm())
.addReg(Hexagon::VTMP);
MBB.erase(MI);
return First.getInstrIterator();
Expand Down Expand Up @@ -2767,7 +2767,13 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
case Hexagon::V6_vL32b_nt_ai:
case Hexagon::V6_vS32b_nt_ai:
case Hexagon::V6_vL32Ub_ai:
case Hexagon::V6_vS32Ub_ai: {
case Hexagon::V6_vS32Ub_ai:
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo: {
unsigned VectorSize = TRI->getSpillSize(Hexagon::HvxVRRegClass);
assert(isPowerOf2_32(VectorSize));
if (Offset & (VectorSize-1))
Expand Down
101 changes: 83 additions & 18 deletions llvm/lib/Target/Hexagon/HexagonOptAddrMode.cpp
Expand Up @@ -110,6 +110,8 @@ class HexagonOptAddrMode : public MachineFunctionPass {
bool changeAddAsl(NodeAddr<UseNode *> AddAslUN, MachineInstr *AddAslMI,
const MachineOperand &ImmOp, unsigned ImmOpNum);
bool isValidOffset(MachineInstr *MI, int Offset);
unsigned getBaseOpPosition(MachineInstr *MI);
unsigned getOffsetOpPosition(MachineInstr *MI);
};

} // end anonymous namespace
Expand Down Expand Up @@ -322,6 +324,25 @@ bool HexagonOptAddrMode::isSafeToExtLR(NodeAddr<StmtNode *> SN,
}

bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {
if (HII->isHVXVec(*MI)) {
// only HVX vgather instructions handled
// TODO: extend the pass to other vector load/store operations
switch (MI->getOpcode()) {
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo:
return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
default:
return false;
}
}

if (HII->getAddrMode(*MI) != HexagonII::BaseImmOffset)
return false;

unsigned AlignMask = 0;
switch (HII->getMemAccessSize(*MI)) {
case HexagonII::MemAccessSize::DoubleWordAccess:
Expand All @@ -345,29 +366,62 @@ bool HexagonOptAddrMode::isValidOffset(MachineInstr *MI, int Offset) {
return HII->isValidOffset(MI->getOpcode(), Offset, HRI, false);
}

unsigned HexagonOptAddrMode::getBaseOpPosition(MachineInstr *MI) {
const MCInstrDesc &MID = MI->getDesc();
switch (MI->getOpcode()) {
// vgather pseudos are mayLoad and mayStore
// hence need to explicitly specify Base and
// Offset operand positions
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo:
return 0;
default:
return MID.mayLoad() ? 1 : 0;
}
}

unsigned HexagonOptAddrMode::getOffsetOpPosition(MachineInstr *MI) {
const MCInstrDesc &MID = MI->getDesc();
switch (MI->getOpcode()) {
// vgather pseudos are mayLoad and mayStore
// hence need to explicitly specify Base and
// Offset operand positions
case Hexagon::V6_vgathermh_pseudo:
case Hexagon::V6_vgathermw_pseudo:
case Hexagon::V6_vgathermhw_pseudo:
case Hexagon::V6_vgathermhq_pseudo:
case Hexagon::V6_vgathermwq_pseudo:
case Hexagon::V6_vgathermhwq_pseudo:
return 1;
default:
return MID.mayLoad() ? 2 : 1;
}
}

bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
MachineInstr *AddMI,
const NodeList &UNodeList) {

Register AddDefR = AddMI->getOperand(0).getReg();
Register BaseReg = AddMI->getOperand(1).getReg();
for (auto I = UNodeList.rbegin(), E = UNodeList.rend(); I != E; ++I) {
NodeAddr<UseNode *> UN = *I;
NodeAddr<StmtNode *> SN = UN.Addr->getOwner(*DFG);
MachineInstr *MI = SN.Addr->getCode();
const MCInstrDesc &MID = MI->getDesc();
if ((!MID.mayLoad() && !MID.mayStore()) ||
HII->getAddrMode(*MI) != HexagonII::BaseImmOffset ||
HII->isHVXVec(*MI))
return false;
if ((!MID.mayLoad() && !MID.mayStore()))
return false;

MachineOperand BaseOp = MID.mayLoad() ? MI->getOperand(1)
: MI->getOperand(0);
MachineOperand BaseOp = MI->getOperand(getBaseOpPosition(MI));

if (!BaseOp.isReg() || BaseOp.getReg() != AddDefR)
return false;

MachineOperand OffsetOp = MID.mayLoad() ? MI->getOperand(2)
: MI->getOperand(1);
MachineOperand OffsetOp = MI->getOperand(getOffsetOpPosition(MI));
if (!OffsetOp.isImm())
return false;

Expand All @@ -382,11 +436,19 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
// Ex: Rx= add(Rt,#10)
// memw(Rx+#0) = Rs
// will be replaced with => memw(Rt+#10) = Rs
Register BaseReg = AddMI->getOperand(1).getReg();
if (!isSafeToExtLR(AddSN, AddMI, BaseReg, UNodeList))
return false;
}

NodeId LRExtRegRD = 0;
// Iterate through all the UseNodes in SN and find the reaching def
// for the LRExtReg.
for (NodeAddr<UseNode *> UA : AddSN.Addr->members_if(DFG->IsUse, *DFG)) {
RegisterRef RR = UA.Addr->getRegRef(*DFG);
if (BaseReg == RR.Reg)
LRExtRegRD = UA.Addr->getReachingDef();
}

// Update all the uses of 'add' with the appropriate base and offset
// values.
bool Changed = false;
Expand All @@ -400,6 +462,12 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
LLVM_DEBUG(dbgs() << "\t\t[MI <BB#" << UseMI->getParent()->getNumber()
<< ">]: " << *UseMI << "\n");
Changed |= updateAddUses(AddMI, UseMI);

// Set the reachingDef for UseNode under consideration
// after updating the Add use. This local change is
// to avoid rebuilding of the RDF graph after update.
NodeAddr<DefNode *> LRExtRegDN = DFG->addr<DefNode *>(LRExtRegRD);
UseN.Addr->linkToDef(UseN.Id, LRExtRegDN);
}

if (Changed)
Expand All @@ -409,21 +477,18 @@ bool HexagonOptAddrMode::processAddUses(NodeAddr<StmtNode *> AddSN,
}

bool HexagonOptAddrMode::updateAddUses(MachineInstr *AddMI,
MachineInstr *UseMI) {
MachineInstr *UseMI) {
const MachineOperand ImmOp = AddMI->getOperand(2);
const MachineOperand AddRegOp = AddMI->getOperand(1);
Register newReg = AddRegOp.getReg();
const MCInstrDesc &MID = UseMI->getDesc();
Register NewReg = AddRegOp.getReg();

MachineOperand &BaseOp = MID.mayLoad() ? UseMI->getOperand(1)
: UseMI->getOperand(0);
MachineOperand &OffsetOp = MID.mayLoad() ? UseMI->getOperand(2)
: UseMI->getOperand(1);
BaseOp.setReg(newReg);
MachineOperand &BaseOp = UseMI->getOperand(getBaseOpPosition(UseMI));
MachineOperand &OffsetOp = UseMI->getOperand(getOffsetOpPosition(UseMI));
BaseOp.setReg(NewReg);
BaseOp.setIsUndef(AddRegOp.isUndef());
BaseOp.setImplicit(AddRegOp.isImplicit());
OffsetOp.setImm(ImmOp.getImm() + OffsetOp.getImm());
MRI->clearKillFlags(newReg);
MRI->clearKillFlags(NewReg);

return true;
}
Expand Down
27 changes: 15 additions & 12 deletions llvm/lib/Target/Hexagon/HexagonPatternsV65.td
Expand Up @@ -9,26 +9,26 @@
multiclass vgathermh<RegisterClass RC> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, IntRegs:$Rt,
ModRegs:$Mu, RC:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
IntRegs:$Rt, ModRegs:$Mu, RC:$Vv),
".error \"should not emit\" ",
[]>;
}

multiclass vgathermw<RegisterClass RC> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, IntRegs:$Rt,
ModRegs:$Mu, RC:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
IntRegs:$Rt, ModRegs:$Mu, RC:$Vv),
".error \"should not emit\" ",
[]>;
}

multiclass vgathermhw<RegisterClass RC> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, IntRegs:$Rt,
ModRegs:$Mu, RC:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
IntRegs:$Rt, ModRegs:$Mu, RC:$Vv),
".error \"should not emit\" ",
[]>;
}
Expand All @@ -40,26 +40,29 @@ defm V6_vgathermhw_pseudo : vgathermhw<HvxWR>;
multiclass vgathermhq<RegisterClass RC1, RegisterClass RC2> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, RC2:$Vq, IntRegs:$Rt,
ModRegs:$Mu, RC1:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
RC2:$Vq, IntRegs:$Rt, ModRegs:$Mu,
RC1:$Vv),
".error \"should not emit\" ",
[]>;
}

multiclass vgathermwq<RegisterClass RC1, RegisterClass RC2> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, RC2:$Vq, IntRegs:$Rt,
ModRegs:$Mu, RC1:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
RC2:$Vq, IntRegs:$Rt, ModRegs:$Mu,
RC1:$Vv),
".error \"should not emit\" ",
[]>;
}

multiclass vgathermhwq<RegisterClass RC1, RegisterClass RC2> {
let isCodeGenOnly = 1, isPseudo = 1, mayLoad = 1, mayStore = 1 in
def NAME : CVI_GATHER_TMP_LD_Resource_NoOpcode<(outs ),
(ins IntRegs:$_dst_, RC2:$Vq, IntRegs:$Rt,
ModRegs:$Mu, RC1:$Vv),
(ins IntRegs:$_dst_, s4_0Imm:$Ii,
RC2:$Vq, IntRegs:$Rt, ModRegs:$Mu,
RC1:$Vv),
".error \"should not emit\" ",
[]>;
}
Expand Down
4 changes: 2 additions & 2 deletions llvm/test/CodeGen/Hexagon/packetize-vgather-slot01.mir
Expand Up @@ -15,8 +15,8 @@ body: |
bb.0:
liveins: $r0, $r1, $r2, $r3, $m0, $v0, $v1, $v2
$v0 = V6_vaslw_acc $v0, killed $v1, $r0
V6_vgathermw_pseudo $r1, $r2, $m0, killed $v2
V6_vgathermw_pseudo $r1, 0, $r2, $m0, killed $v2
$r4 = A2_addi $r1, 512
$r5 = A2_addi $r1, 640
V6_vgathermw_pseudo killed $r3, $r2, $m0, killed $v0
V6_vgathermw_pseudo killed $r3, 0, $r2, $m0, killed $v0
...

0 comments on commit 4108535

Please sign in to comment.