[Hexagon] Fix vector spill expansion to use proper alignment

1. Add pseudos PS_vloadrv_ai and PS_vstorerv_ai: those are now used
   for single vector registers in loadRegFromStackSlot (and store...).
2. Remove pseudos PS_vloadrwu_ai and PS_vstorerwu_ai. The alignment is
   now checked when expanding spill pseudos (both in frame lowering
   and in expand-post-ra-pseudos), and a proper instruction is generated.
3. Update MachineMemOperands when dealigning vector spill slots.
4. Return vector predicate registers in getCallerSavedRegs.
This commit is contained in:
Krzysztof Parzyszek 2019-11-11 09:05:21 -06:00
parent e3eb10c541
commit 592dd45924
6 changed files with 190 additions and 106 deletions

View File

@ -36,6 +36,7 @@
#include "llvm/CodeGen/MachineOperand.h"
#include "llvm/CodeGen/MachinePostDominators.h"
#include "llvm/CodeGen/MachineRegisterInfo.h"
#include "llvm/CodeGen/PseudoSourceValue.h"
#include "llvm/CodeGen/RegisterScavenging.h"
#include "llvm/CodeGen/TargetRegisterInfo.h"
#include "llvm/IR/Attributes.h"
@ -1362,6 +1363,7 @@ void HexagonFrameLowering::processFunctionBeforeFrameFinalized(
if (!HasAlloca || !NeedsAlign)
return;
SmallSet<int, 4> DealignSlots;
unsigned LFS = MFI.getLocalFrameSize();
for (int i = 0, e = MFI.getObjectIndexEnd(); i != e; ++i) {
if (!MFI.isSpillSlotObjectIndex(i) || MFI.isDeadObjectIndex(i))
@ -1373,6 +1375,7 @@ void HexagonFrameLowering::processFunctionBeforeFrameFinalized(
MFI.setObjectAlignment(i, 8);
LFS = alignTo(LFS+S, A);
MFI.mapLocalFrameObject(i, -static_cast<int64_t>(LFS));
DealignSlots.insert(i);
}
MFI.setLocalFrameSize(LFS);
@ -1382,6 +1385,38 @@ void HexagonFrameLowering::processFunctionBeforeFrameFinalized(
MFI.setLocalFrameMaxAlign(Align(8));
MFI.setUseLocalStackAllocationBlock(true);
// Go over all MachineMemOperands in the code, and change the ones that
// refer to the dealigned stack slots to reflect the new alignment.
if (!DealignSlots.empty()) {
for (MachineBasicBlock &BB : MF) {
for (MachineInstr &MI : BB) {
bool KeepOld = true;
ArrayRef<MachineMemOperand*> memops = MI.memoperands();
SmallVector<MachineMemOperand*,1> new_memops;
for (MachineMemOperand *MMO : memops) {
auto *PV = MMO->getPseudoValue();
if (auto *FS = dyn_cast_or_null<FixedStackPseudoSourceValue>(PV)) {
int FI = FS->getFrameIndex();
if (DealignSlots.count(FI)) {
unsigned A = MFI.getObjectAlignment(FI);
auto *NewMMO = MF.getMachineMemOperand(MMO->getPointerInfo(),
MMO->getFlags(), MMO->getSize(), A,
MMO->getAAInfo(), MMO->getRanges(),
MMO->getSyncScopeID(), MMO->getOrdering(),
MMO->getFailureOrdering());
new_memops.push_back(NewMMO);
KeepOld = false;
continue;
}
}
new_memops.push_back(MMO);
}
if (!KeepOld)
MI.setMemRefs(MF, new_memops);
}
}
}
// Set the physical aligned-stack base address register.
unsigned AP = 0;
if (const MachineInstr *AI = getAlignaInstr(MF))
@ -1749,16 +1784,21 @@ bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
Register SrcHi = HRI.getSubReg(SrcR, Hexagon::vsub_hi);
bool IsKill = MI->getOperand(2).isKill();
int FI = MI->getOperand(0).getIndex();
bool NeedsAligna = needsAligna(MF);
unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned StoreOpc;
auto UseAligned = [&] (unsigned NeedAlign, unsigned HasAlign) {
return !NeedsAligna && (NeedAlign <= HasAlign);
};
// Store low part.
if (LPR.contains(SrcLo)) {
StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
StoreOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
BuildMI(B, It, DL, HII.get(StoreOpc))
.addFrameIndex(FI)
.addImm(0)
@ -1768,8 +1808,8 @@ bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
// Store high part.
if (LPR.contains(SrcHi)) {
StoreOpc = NeedAlign <= MinAlign(HasAlign, Size) ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
StoreOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
BuildMI(B, It, DL, HII.get(StoreOpc))
.addFrameIndex(FI)
.addImm(Size)
@ -1796,23 +1836,28 @@ bool HexagonFrameLowering::expandLoadVec2(MachineBasicBlock &B,
Register DstHi = HRI.getSubReg(DstR, Hexagon::vsub_hi);
Register DstLo = HRI.getSubReg(DstR, Hexagon::vsub_lo);
int FI = MI->getOperand(1).getIndex();
bool NeedsAligna = needsAligna(MF);
unsigned Size = HRI.getSpillSize(Hexagon::HvxVRRegClass);
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned LoadOpc;
auto UseAligned = [&] (unsigned NeedAlign, unsigned HasAlign) {
return !NeedsAligna && (NeedAlign <= HasAlign);
};
// Load low part.
LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
LoadOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
BuildMI(B, It, DL, HII.get(LoadOpc), DstLo)
.addFrameIndex(FI)
.addImm(0)
.cloneMemRefs(*MI);
// Load high part.
LoadOpc = NeedAlign <= MinAlign(HasAlign, Size) ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
LoadOpc = UseAligned(NeedAlign, HasAlign) ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
BuildMI(B, It, DL, HII.get(LoadOpc), DstHi)
.addFrameIndex(FI)
.addImm(Size)
@ -1831,6 +1876,7 @@ bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &B,
if (!MI->getOperand(0).isFI())
return false;
bool NeedsAligna = needsAligna(MF);
auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
DebugLoc DL = MI->getDebugLoc();
Register SrcR = MI->getOperand(2).getReg();
@ -1839,8 +1885,9 @@ bool HexagonFrameLowering::expandStoreVec(MachineBasicBlock &B,
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned StoreOpc = NeedAlign <= HasAlign ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
unsigned StoreOpc = UseAligned ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
BuildMI(B, It, DL, HII.get(StoreOpc))
.addFrameIndex(FI)
.addImm(0)
@ -1860,6 +1907,7 @@ bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &B,
if (!MI->getOperand(1).isFI())
return false;
bool NeedsAligna = needsAligna(MF);
auto &HRI = *MF.getSubtarget<HexagonSubtarget>().getRegisterInfo();
DebugLoc DL = MI->getDebugLoc();
Register DstR = MI->getOperand(0).getReg();
@ -1867,8 +1915,9 @@ bool HexagonFrameLowering::expandLoadVec(MachineBasicBlock &B,
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned HasAlign = MFI.getObjectAlignment(FI);
unsigned LoadOpc = NeedAlign <= HasAlign ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
bool UseAligned = !NeedsAligna && (NeedAlign <= HasAlign);
unsigned LoadOpc = UseAligned ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
BuildMI(B, It, DL, HII.get(LoadOpc), DstR)
.addFrameIndex(FI)
.addImm(0)
@ -1911,11 +1960,9 @@ bool HexagonFrameLowering::expandSpillMacros(MachineFunction &MF,
Changed |= expandLoadVecPred(B, I, MRI, HII, NewRegs);
break;
case Hexagon::PS_vloadrw_ai:
case Hexagon::PS_vloadrwu_ai:
Changed |= expandLoadVec2(B, I, MRI, HII, NewRegs);
break;
case Hexagon::PS_vstorerw_ai:
case Hexagon::PS_vstorerwu_ai:
Changed |= expandStoreVec2(B, I, MRI, HII, NewRegs);
break;
}
@ -1960,7 +2007,15 @@ void HexagonFrameLowering::determineCalleeSaves(MachineFunction &MF,
for (auto *RC : SpillRCs) {
if (!needToReserveScavengingSpillSlots(MF, HRI, RC))
continue;
unsigned Num = RC == &Hexagon::IntRegsRegClass ? NumberScavengerSlots : 1;
unsigned Num = 1;
switch (RC->getID()) {
case Hexagon::IntRegsRegClassID:
Num = NumberScavengerSlots;
break;
case Hexagon::HvxQRRegClassID:
Num = 2; // Vector predicate spills also need a vector register.
break;
}
unsigned S = HRI.getSpillSize(*RC), A = HRI.getSpillAlignment(*RC);
for (unsigned i = 0; i < Num; i++) {
int NewFI = MFI.CreateSpillStackObject(S, A);

View File

@ -888,10 +888,7 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned SlotAlign = MFI.getObjectAlignment(FI);
unsigned RegAlign = TRI->getSpillAlignment(*RC);
unsigned KillFlag = getKillRegState(isKill);
bool HasAlloca = MFI.hasVarSizedObjects();
const HexagonFrameLowering &HFI = *Subtarget.getFrameLowering();
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
@ -918,29 +915,13 @@ void HexagonInstrInfo::storeRegToStackSlot(MachineBasicBlock &MBB,
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
SlotAlign = HFI.getStackAlignment();
unsigned Opc = SlotAlign < RegAlign ? Hexagon::V6_vS32Ub_ai
: Hexagon::V6_vS32b_ai;
MachineMemOperand *MMOA = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc))
BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerv_ai))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMOA);
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else if (Hexagon::HvxWRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
SlotAlign = HFI.getStackAlignment();
unsigned Opc = SlotAlign < RegAlign ? Hexagon::PS_vstorerwu_ai
: Hexagon::PS_vstorerw_ai;
MachineMemOperand *MMOA = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOStore,
MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc))
BuildMI(MBB, I, DL, get(Hexagon::PS_vstorerw_ai))
.addFrameIndex(FI).addImm(0)
.addReg(SrcReg, KillFlag).addMemOperand(MMOA);
.addReg(SrcReg, KillFlag).addMemOperand(MMO);
} else {
llvm_unreachable("Unimplemented");
}
@ -954,9 +935,6 @@ void HexagonInstrInfo::loadRegFromStackSlot(
MachineFunction &MF = *MBB.getParent();
MachineFrameInfo &MFI = MF.getFrameInfo();
unsigned SlotAlign = MFI.getObjectAlignment(FI);
unsigned RegAlign = TRI->getSpillAlignment(*RC);
bool HasAlloca = MFI.hasVarSizedObjects();
const HexagonFrameLowering &HFI = *Subtarget.getFrameLowering();
MachineMemOperand *MMO = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
@ -978,27 +956,11 @@ void HexagonInstrInfo::loadRegFromStackSlot(
BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrq_ai), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::HvxVRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
SlotAlign = HFI.getStackAlignment();
unsigned Opc = SlotAlign < RegAlign ? Hexagon::V6_vL32Ub_ai
: Hexagon::V6_vL32b_ai;
MachineMemOperand *MMOA = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMOA);
BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrv_ai), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else if (Hexagon::HvxWRRegClass.hasSubClassEq(RC)) {
// If there are variable-sized objects, spills will not be aligned.
if (HasAlloca)
SlotAlign = HFI.getStackAlignment();
unsigned Opc = SlotAlign < RegAlign ? Hexagon::PS_vloadrwu_ai
: Hexagon::PS_vloadrw_ai;
MachineMemOperand *MMOA = MF.getMachineMemOperand(
MachinePointerInfo::getFixedStack(MF, FI), MachineMemOperand::MOLoad,
MFI.getObjectSize(FI), SlotAlign);
BuildMI(MBB, I, DL, get(Opc), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMOA);
BuildMI(MBB, I, DL, get(Hexagon::PS_vloadrw_ai), DestReg)
.addFrameIndex(FI).addImm(0).addMemOperand(MMO);
} else {
llvm_unreachable("Can't store this register to stack slot");
}
@ -1040,6 +1002,15 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
return true;
};
auto UseAligned = [&] (const MachineInstr &MI, unsigned NeedAlign) {
if (MI.memoperands().empty())
return false;
return all_of(MI.memoperands(),
[NeedAlign] (const MachineMemOperand *MMO) {
return NeedAlign <= MMO->getAlignment();
});
};
switch (Opc) {
case TargetOpcode::COPY: {
MachineOperand &MD = MI.getOperand(0);
@ -1086,47 +1057,78 @@ bool HexagonInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
MRI.clearKillFlags(SrcSubHi);
return true;
}
case Hexagon::PS_vstorerw_ai:
case Hexagon::PS_vstorerwu_ai: {
bool Aligned = Opc == Hexagon::PS_vstorerw_ai;
Register SrcReg = MI.getOperand(2).getReg();
Register SrcSubHi = HRI.getSubReg(SrcReg, Hexagon::vsub_hi);
Register SrcSubLo = HRI.getSubReg(SrcReg, Hexagon::vsub_lo);
unsigned NewOpc = Aligned ? Hexagon::V6_vS32b_ai : Hexagon::V6_vS32Ub_ai;
unsigned Offset = HRI.getSpillSize(Hexagon::HvxVRRegClass);
MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc))
.add(MI.getOperand(0))
.addImm(MI.getOperand(1).getImm())
.addReg(SrcSubLo)
.cloneMemRefs(MI);
MI1New->getOperand(0).setIsKill(false);
BuildMI(MBB, MI, DL, get(NewOpc))
.add(MI.getOperand(0))
// The Vectors are indexed in multiples of vector size.
.addImm(MI.getOperand(1).getImm() + Offset)
.addReg(SrcSubHi)
case Hexagon::PS_vloadrv_ai: {
Register DstReg = MI.getOperand(0).getReg();
const MachineOperand &BaseOp = MI.getOperand(1);
assert(BaseOp.getSubReg() == 0);
int Offset = MI.getOperand(2).getImm();
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
BuildMI(MBB, MI, DL, get(NewOpc), DstReg)
.addReg(BaseOp.getReg(), getRegState(BaseOp))
.addImm(Offset)
.cloneMemRefs(MI);
MBB.erase(MI);
return true;
}
case Hexagon::PS_vloadrw_ai:
case Hexagon::PS_vloadrwu_ai: {
bool Aligned = Opc == Hexagon::PS_vloadrw_ai;
case Hexagon::PS_vloadrw_ai: {
Register DstReg = MI.getOperand(0).getReg();
unsigned NewOpc = Aligned ? Hexagon::V6_vL32b_ai : Hexagon::V6_vL32Ub_ai;
unsigned Offset = HRI.getSpillSize(Hexagon::HvxVRRegClass);
MachineInstr *MI1New = BuildMI(MBB, MI, DL, get(NewOpc),
HRI.getSubReg(DstReg, Hexagon::vsub_lo))
.add(MI.getOperand(1))
.addImm(MI.getOperand(2).getImm())
.cloneMemRefs(MI);
MI1New->getOperand(1).setIsKill(false);
BuildMI(MBB, MI, DL, get(NewOpc), HRI.getSubReg(DstReg, Hexagon::vsub_hi))
.add(MI.getOperand(1))
// The Vectors are indexed in multiples of vector size.
.addImm(MI.getOperand(2).getImm() + Offset)
const MachineOperand &BaseOp = MI.getOperand(1);
assert(BaseOp.getSubReg() == 0);
int Offset = MI.getOperand(2).getImm();
unsigned VecOffset = HRI.getSpillSize(Hexagon::HvxVRRegClass);
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vL32b_ai
: Hexagon::V6_vL32Ub_ai;
BuildMI(MBB, MI, DL, get(NewOpc),
HRI.getSubReg(DstReg, Hexagon::vsub_lo))
.addReg(BaseOp.getReg(), getRegState(BaseOp) & ~RegState::Kill)
.addImm(Offset)
.cloneMemRefs(MI);
BuildMI(MBB, MI, DL, get(NewOpc),
HRI.getSubReg(DstReg, Hexagon::vsub_hi))
.addReg(BaseOp.getReg(), getRegState(BaseOp))
.addImm(Offset + VecOffset)
.cloneMemRefs(MI);
MBB.erase(MI);
return true;
}
case Hexagon::PS_vstorerv_ai: {
const MachineOperand &SrcOp = MI.getOperand(2);
assert(SrcOp.getSubReg() == 0);
const MachineOperand &BaseOp = MI.getOperand(0);
assert(BaseOp.getSubReg() == 0);
int Offset = MI.getOperand(1).getImm();
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
BuildMI(MBB, MI, DL, get(NewOpc))
.addReg(BaseOp.getReg(), getRegState(BaseOp))
.addImm(Offset)
.addReg(SrcOp.getReg(), getRegState(SrcOp))
.cloneMemRefs(MI);
MBB.erase(MI);
return true;
}
case Hexagon::PS_vstorerw_ai: {
Register SrcReg = MI.getOperand(2).getReg();
const MachineOperand &BaseOp = MI.getOperand(0);
assert(BaseOp.getSubReg() == 0);
int Offset = MI.getOperand(1).getImm();
unsigned VecOffset = HRI.getSpillSize(Hexagon::HvxVRRegClass);
unsigned NeedAlign = HRI.getSpillAlignment(Hexagon::HvxVRRegClass);
unsigned NewOpc = UseAligned(MI, NeedAlign) ? Hexagon::V6_vS32b_ai
: Hexagon::V6_vS32Ub_ai;
BuildMI(MBB, MI, DL, get(NewOpc))
.addReg(BaseOp.getReg(), getRegState(BaseOp) & ~RegState::Kill)
.addImm(Offset)
.addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_lo))
.cloneMemRefs(MI);
BuildMI(MBB, MI, DL, get(NewOpc))
.addReg(BaseOp.getReg(), getRegState(BaseOp))
.addImm(Offset + VecOffset)
.addReg(HRI.getSubReg(SrcReg, Hexagon::vsub_hi))
.cloneMemRefs(MI);
MBB.erase(MI);
return true;
@ -2683,9 +2685,11 @@ bool HexagonInstrInfo::isValidOffset(unsigned Opcode, int Offset,
// misaligns with respect to load size.
switch (Opcode) {
case Hexagon::PS_vstorerq_ai:
case Hexagon::PS_vstorerv_ai:
case Hexagon::PS_vstorerw_ai:
case Hexagon::PS_vstorerw_nt_ai:
case Hexagon::PS_vloadrq_ai:
case Hexagon::PS_vloadrv_ai:
case Hexagon::PS_vloadrw_ai:
case Hexagon::PS_vloadrw_nt_ai:
case Hexagon::V6_vL32b_ai:

View File

@ -408,15 +408,17 @@ let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
// Vector store pseudos
let Predicates = [HasV60,UseHVX], isPseudo = 1, isCodeGenOnly = 1,
mayStore = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
class STrivv_template<RegisterClass RC, InstHexagon rootInst>
class STriv_template<RegisterClass RC, InstHexagon rootInst>
: InstHexagon<(outs), (ins IntRegs:$addr, s32_0Imm:$off, RC:$src),
"", [], "", rootInst.Itinerary, rootInst.Type>;
def PS_vstorerw_ai: STrivv_template<HvxWR, V6_vS32b_ai>,
def PS_vstorerv_ai: STriv_template<HvxVR, V6_vS32b_ai>,
Requires<[HasV60,UseHVX]>;
def PS_vstorerw_nt_ai: STrivv_template<HvxWR, V6_vS32b_nt_ai>,
def PS_vstorerv_nt_ai: STriv_template<HvxVR, V6_vS32b_nt_ai>,
Requires<[HasV60,UseHVX]>;
def PS_vstorerwu_ai: STrivv_template<HvxWR, V6_vS32Ub_ai>,
def PS_vstorerw_ai: STriv_template<HvxWR, V6_vS32b_ai>,
Requires<[HasV60,UseHVX]>;
def PS_vstorerw_nt_ai: STriv_template<HvxWR, V6_vS32b_nt_ai>,
Requires<[HasV60,UseHVX]>;
let isPseudo = 1, isCodeGenOnly = 1, mayStore = 1, hasSideEffects = 0 in
@ -427,15 +429,17 @@ def PS_vstorerq_ai: Pseudo<(outs),
// Vector load pseudos
let Predicates = [HasV60, UseHVX], isPseudo = 1, isCodeGenOnly = 1,
mayLoad = 1, accessSize = HVXVectorAccess, hasSideEffects = 0 in
class LDrivv_template<RegisterClass RC, InstHexagon rootInst>
class LDriv_template<RegisterClass RC, InstHexagon rootInst>
: InstHexagon<(outs RC:$dst), (ins IntRegs:$addr, s32_0Imm:$off),
"", [], "", rootInst.Itinerary, rootInst.Type>;
def PS_vloadrw_ai: LDrivv_template<HvxWR, V6_vL32b_ai>,
def PS_vloadrv_ai: LDriv_template<HvxVR, V6_vL32b_ai>,
Requires<[HasV60,UseHVX]>;
def PS_vloadrw_nt_ai: LDrivv_template<HvxWR, V6_vL32b_nt_ai>,
def PS_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>,
Requires<[HasV60,UseHVX]>;
def PS_vloadrwu_ai: LDrivv_template<HvxWR, V6_vL32Ub_ai>,
def PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>,
Requires<[HasV60,UseHVX]>;
def PS_vloadrw_nt_ai: LDriv_template<HvxWR, V6_vL32b_nt_ai>,
Requires<[HasV60,UseHVX]>;
let isPseudo = 1, isCodeGenOnly = 1, mayLoad = 1, hasSideEffects = 0 in

View File

@ -73,6 +73,9 @@ HexagonRegisterInfo::getCallerSavedRegs(const MachineFunction *MF,
static const MCPhysReg VecDbl[] = {
W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, 0
};
static const MCPhysReg VecPred[] = {
Q0, Q1, Q2, Q3, 0
};
switch (RC->getID()) {
case IntRegsRegClassID:
@ -85,6 +88,8 @@ HexagonRegisterInfo::getCallerSavedRegs(const MachineFunction *MF,
return VecSgl;
case HvxWRRegClassID:
return VecDbl;
case HvxQRRegClassID:
return VecPred;
default:
break;
}

View File

@ -0,0 +1,16 @@
# RUN: llc -march=hexagon -run-pass prologepilog %s -o - | FileCheck %s
# Check that the spill of $q0 uses unaligned store instruction.
# CHECK: V6_vS32Ub_ai $r30, -128, killed $v0
---
name: test
tracksRegLiveness: true
stack:
- { id: 0, type: variable-sized, offset: 0, alignment: 1 }
- { id: 1, type: spill-slot, size: 128, alignment: 128 }
body: |
bb.0:
liveins: $q0
PS_vstorerq_ai %stack.1, 0, $q0
...

View File

@ -4,7 +4,7 @@
; has an alloca. Also, make sure the addressing mode for unaligned store does
; is not a base+offset with a non-zero offset that is not a multiple of 128.
; CHECK: vmemu(r{{[0-9]+}}+#0)
; CHECK: vmemu({{.*}}) =
%s.0 = type { [5 x [4 x i8]], i32, i32, i32, i32 }