#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"
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))
MFI.setObjectAlignment(i, 8);
LFS = alignTo(LFS+S, A);
MFI.mapLocalFrameObject(i, -static_cast<int64_t>(LFS));
+ DealignSlots.insert(i);
}
MFI.setLocalFrameSize(LFS);
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))
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)
// 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)
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)
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();
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)
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();
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)
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;
}
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);
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,
.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");
}
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,
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");
}
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);
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;
// 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:
// 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
// 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_vloadrv_nt_ai: LDriv_template<HvxVR, V6_vL32b_nt_ai>,
Requires<[HasV60,UseHVX]>;
-def PS_vloadrw_nt_ai: LDrivv_template<HvxWR, V6_vL32b_nt_ai>,
+def PS_vloadrw_ai: LDriv_template<HvxWR, V6_vL32b_ai>,
Requires<[HasV60,UseHVX]>;
-def PS_vloadrwu_ai: LDrivv_template<HvxWR, V6_vL32Ub_ai>,
+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
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:
return VecSgl;
case HvxWRRegClassID:
return VecDbl;
+ case HvxQRRegClassID:
+ return VecPred;
default:
break;
}
--- /dev/null
+# 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
+...
; 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 }