mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-05-15 11:36:18 +00:00
[Hexagon] Start using regmasks on calls
Reapply r295371 with a fix for the Windows bot failures. llvm-svn: 295504
This commit is contained in:
parent
f90433a932
commit
3eceaa547a
@ -306,6 +306,8 @@ void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap,
|
|||||||
LastUse[R] = LastDef[R] = IndexType::None;
|
LastUse[R] = LastDef[R] = IndexType::None;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
RegisterSet Defs, Clobbers;
|
||||||
|
|
||||||
for (auto &In : B) {
|
for (auto &In : B) {
|
||||||
if (In.isDebugValue())
|
if (In.isDebugValue())
|
||||||
continue;
|
continue;
|
||||||
@ -324,18 +326,67 @@ void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap,
|
|||||||
closeRange(S);
|
closeRange(S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Process defs.
|
// Process defs and clobbers.
|
||||||
|
Defs.clear();
|
||||||
|
Clobbers.clear();
|
||||||
for (auto &Op : In.operands()) {
|
for (auto &Op : In.operands()) {
|
||||||
if (!Op.isReg() || !Op.isDef() || Op.isUndef())
|
if (!Op.isReg() || !Op.isDef() || Op.isUndef())
|
||||||
continue;
|
continue;
|
||||||
RegisterRef R = { Op.getReg(), Op.getSubReg() };
|
RegisterRef R = { Op.getReg(), Op.getSubReg() };
|
||||||
if (TargetRegisterInfo::isPhysicalRegister(R.Reg) && Reserved[R.Reg])
|
|
||||||
continue;
|
|
||||||
for (auto S : expandToSubRegs(R, MRI, TRI)) {
|
for (auto S : expandToSubRegs(R, MRI, TRI)) {
|
||||||
|
if (TargetRegisterInfo::isPhysicalRegister(S.Reg) && Reserved[S.Reg])
|
||||||
|
continue;
|
||||||
|
if (Op.isDead())
|
||||||
|
Clobbers.insert(S);
|
||||||
|
else
|
||||||
|
Defs.insert(S);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto &Op : In.operands()) {
|
||||||
|
if (!Op.isRegMask())
|
||||||
|
continue;
|
||||||
|
const uint32_t *BM = Op.getRegMask();
|
||||||
|
for (unsigned PR = 1, N = TRI.getNumRegs(); PR != N; ++PR) {
|
||||||
|
// Skip registers that have subregisters. A register is preserved
|
||||||
|
// iff its bit is set in the regmask, so if R1:0 was preserved, both
|
||||||
|
// R1 and R0 would also be present.
|
||||||
|
if (MCSubRegIterator(PR, &TRI, false).isValid())
|
||||||
|
continue;
|
||||||
|
if (Reserved[PR])
|
||||||
|
continue;
|
||||||
|
if (BM[PR/32] & (1u << (PR%32)))
|
||||||
|
continue;
|
||||||
|
RegisterRef R = { PR, 0 };
|
||||||
|
if (!Defs.count(R))
|
||||||
|
Clobbers.insert(R);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifndef NDEBUG
|
||||||
|
for (RegisterRef R : Defs)
|
||||||
|
assert(!Clobbers.count(R));
|
||||||
|
for (RegisterRef R : Clobbers)
|
||||||
|
assert(!Defs.count(R));
|
||||||
|
#endif
|
||||||
|
// Update maps for defs.
|
||||||
|
for (RegisterRef S : Defs) {
|
||||||
|
// Defs should already be expanded into subregs.
|
||||||
|
assert(!TargetRegisterInfo::isPhysicalRegister(S.Reg) ||
|
||||||
|
!MCSubRegIterator(S.Reg, &TRI, false).isValid());
|
||||||
if (LastDef[S] != IndexType::None || LastUse[S] != IndexType::None)
|
if (LastDef[S] != IndexType::None || LastUse[S] != IndexType::None)
|
||||||
closeRange(S);
|
closeRange(S);
|
||||||
LastDef[S] = Index;
|
LastDef[S] = Index;
|
||||||
}
|
}
|
||||||
|
// Update maps for clobbers.
|
||||||
|
for (RegisterRef S : Clobbers) {
|
||||||
|
// Clobbers should already be expanded into subregs.
|
||||||
|
assert(!TargetRegisterInfo::isPhysicalRegister(S.Reg) ||
|
||||||
|
!MCSubRegIterator(S.Reg, &TRI, false).isValid());
|
||||||
|
if (LastDef[S] != IndexType::None || LastUse[S] != IndexType::None)
|
||||||
|
closeRange(S);
|
||||||
|
// Create a single-instruction range.
|
||||||
|
LastDef[S] = LastUse[S] = Index;
|
||||||
|
closeRange(S);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,17 +440,21 @@ HexagonCopyToCombine::findPotentialNewifiableTFRs(MachineBasicBlock &BB) {
|
|||||||
|
|
||||||
// Put instructions that last defined integer or double registers into the
|
// Put instructions that last defined integer or double registers into the
|
||||||
// map.
|
// map.
|
||||||
for (unsigned I = 0, E = MI.getNumOperands(); I != E; ++I) {
|
for (MachineOperand &Op : MI.operands()) {
|
||||||
MachineOperand &Op = MI.getOperand(I);
|
if (Op.isReg()) {
|
||||||
if (!Op.isReg() || !Op.isDef() || !Op.getReg())
|
if (!Op.isDef() || !Op.getReg())
|
||||||
continue;
|
continue;
|
||||||
unsigned Reg = Op.getReg();
|
unsigned Reg = Op.getReg();
|
||||||
if (Hexagon::DoubleRegsRegClass.contains(Reg)) {
|
if (Hexagon::DoubleRegsRegClass.contains(Reg)) {
|
||||||
for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
|
for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs)
|
||||||
LastDef[*SubRegs] = &MI;
|
LastDef[*SubRegs] = &MI;
|
||||||
}
|
|
||||||
} else if (Hexagon::IntRegsRegClass.contains(Reg))
|
} else if (Hexagon::IntRegsRegClass.contains(Reg))
|
||||||
LastDef[Reg] = &MI;
|
LastDef[Reg] = &MI;
|
||||||
|
} else if (Op.isRegMask()) {
|
||||||
|
for (unsigned Reg : Hexagon::IntRegsRegClass)
|
||||||
|
if (Op.clobbersPhysReg(Reg))
|
||||||
|
LastDef[Reg] = &MI;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4665,7 +4665,6 @@ let Defs = [PC, R31];
|
|||||||
let BaseOpcode = "J2_call";
|
let BaseOpcode = "J2_call";
|
||||||
let isPredicable = 1;
|
let isPredicable = 1;
|
||||||
let hasSideEffects = 1;
|
let hasSideEffects = 1;
|
||||||
let Defs = VolatileV3.Regs;
|
|
||||||
let isExtendable = 1;
|
let isExtendable = 1;
|
||||||
let opExtendable = 0;
|
let opExtendable = 0;
|
||||||
let isExtentSigned = 1;
|
let isExtentSigned = 1;
|
||||||
@ -4690,7 +4689,6 @@ let Defs = [PC, R31];
|
|||||||
let BaseOpcode = "J2_call";
|
let BaseOpcode = "J2_call";
|
||||||
let hasSideEffects = 1;
|
let hasSideEffects = 1;
|
||||||
let isTaken = Inst{12};
|
let isTaken = Inst{12};
|
||||||
let Defs = VolatileV3.Regs;
|
|
||||||
let isExtendable = 1;
|
let isExtendable = 1;
|
||||||
let opExtendable = 1;
|
let opExtendable = 1;
|
||||||
let isExtentSigned = 1;
|
let isExtentSigned = 1;
|
||||||
@ -4710,7 +4708,6 @@ let prefersSlot3 = 1;
|
|||||||
let Uses = [R29];
|
let Uses = [R29];
|
||||||
let Defs = [PC, R31];
|
let Defs = [PC, R31];
|
||||||
let hasSideEffects = 1;
|
let hasSideEffects = 1;
|
||||||
let Defs = VolatileV3.Regs;
|
|
||||||
}
|
}
|
||||||
def J2_callrf : HInst<
|
def J2_callrf : HInst<
|
||||||
(outs),
|
(outs),
|
||||||
@ -4729,7 +4726,6 @@ let Uses = [R29];
|
|||||||
let Defs = [PC, R31];
|
let Defs = [PC, R31];
|
||||||
let hasSideEffects = 1;
|
let hasSideEffects = 1;
|
||||||
let isTaken = Inst{12};
|
let isTaken = Inst{12};
|
||||||
let Defs = VolatileV3.Regs;
|
|
||||||
}
|
}
|
||||||
def J2_callrt : HInst<
|
def J2_callrt : HInst<
|
||||||
(outs),
|
(outs),
|
||||||
@ -4747,7 +4743,6 @@ let Uses = [R29];
|
|||||||
let Defs = [PC, R31];
|
let Defs = [PC, R31];
|
||||||
let hasSideEffects = 1;
|
let hasSideEffects = 1;
|
||||||
let isTaken = Inst{12};
|
let isTaken = Inst{12};
|
||||||
let Defs = VolatileV3.Regs;
|
|
||||||
}
|
}
|
||||||
def J2_callt : HInst<
|
def J2_callt : HInst<
|
||||||
(outs),
|
(outs),
|
||||||
@ -4766,7 +4761,6 @@ let Defs = [PC, R31];
|
|||||||
let BaseOpcode = "J2_call";
|
let BaseOpcode = "J2_call";
|
||||||
let hasSideEffects = 1;
|
let hasSideEffects = 1;
|
||||||
let isTaken = Inst{12};
|
let isTaken = Inst{12};
|
||||||
let Defs = VolatileV3.Regs;
|
|
||||||
let isExtendable = 1;
|
let isExtendable = 1;
|
||||||
let opExtendable = 1;
|
let opExtendable = 1;
|
||||||
let isExtentSigned = 1;
|
let isExtentSigned = 1;
|
||||||
|
@ -301,8 +301,7 @@ static bool needsStackFrame(const MachineBasicBlock &MBB, const BitVector &CSR,
|
|||||||
// the frame creation/destruction instructions.
|
// the frame creation/destruction instructions.
|
||||||
if (MO.isFI())
|
if (MO.isFI())
|
||||||
return true;
|
return true;
|
||||||
if (!MO.isReg())
|
if (MO.isReg()) {
|
||||||
continue;
|
|
||||||
unsigned R = MO.getReg();
|
unsigned R = MO.getReg();
|
||||||
// Virtual registers will need scavenging, which then may require
|
// Virtual registers will need scavenging, which then may require
|
||||||
// a stack slot.
|
// a stack slot.
|
||||||
@ -311,6 +310,21 @@ static bool needsStackFrame(const MachineBasicBlock &MBB, const BitVector &CSR,
|
|||||||
for (MCSubRegIterator S(R, &HRI, true); S.isValid(); ++S)
|
for (MCSubRegIterator S(R, &HRI, true); S.isValid(); ++S)
|
||||||
if (CSR[*S])
|
if (CSR[*S])
|
||||||
return true;
|
return true;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (MO.isRegMask()) {
|
||||||
|
// A regmask would normally have all callee-saved registers marked
|
||||||
|
// as preserved, so this check would not be needed, but in case of
|
||||||
|
// ever having other regmasks (for other calling conventions),
|
||||||
|
// make sure they would be processed correctly.
|
||||||
|
const uint32_t *BM = MO.getRegMask();
|
||||||
|
for (int x = CSR.find_first(); x >= 0; x = CSR.find_next(x)) {
|
||||||
|
unsigned R = x;
|
||||||
|
// If this regmask does not preserve a CSR, a frame will be needed.
|
||||||
|
if (!(BM[R/32] & (1u << (R%32))))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -1651,7 +1665,7 @@ bool HexagonFrameLowering::expandStoreVec2(MachineBasicBlock &B,
|
|||||||
// Dead defs are recorded in Clobbers, but are not automatically removed
|
// Dead defs are recorded in Clobbers, but are not automatically removed
|
||||||
// from the live set.
|
// from the live set.
|
||||||
for (auto &C : Clobbers)
|
for (auto &C : Clobbers)
|
||||||
if (C.second->isDead())
|
if (C.second->isReg() && C.second->isDead())
|
||||||
LPR.removeReg(C.first);
|
LPR.removeReg(C.first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -100,6 +100,7 @@ namespace {
|
|||||||
MachineRegisterInfo *MRI;
|
MachineRegisterInfo *MRI;
|
||||||
MachineDominatorTree *MDT;
|
MachineDominatorTree *MDT;
|
||||||
const HexagonInstrInfo *TII;
|
const HexagonInstrInfo *TII;
|
||||||
|
const HexagonRegisterInfo *TRI;
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
static int Counter;
|
static int Counter;
|
||||||
#endif
|
#endif
|
||||||
@ -381,7 +382,9 @@ bool HexagonHardwareLoops::runOnMachineFunction(MachineFunction &MF) {
|
|||||||
MLI = &getAnalysis<MachineLoopInfo>();
|
MLI = &getAnalysis<MachineLoopInfo>();
|
||||||
MRI = &MF.getRegInfo();
|
MRI = &MF.getRegInfo();
|
||||||
MDT = &getAnalysis<MachineDominatorTree>();
|
MDT = &getAnalysis<MachineDominatorTree>();
|
||||||
TII = MF.getSubtarget<HexagonSubtarget>().getInstrInfo();
|
const HexagonSubtarget &HST = MF.getSubtarget<HexagonSubtarget>();
|
||||||
|
TII = HST.getInstrInfo();
|
||||||
|
TRI = HST.getRegisterInfo();
|
||||||
|
|
||||||
for (auto &L : *MLI)
|
for (auto &L : *MLI)
|
||||||
if (!L->getParentLoop()) {
|
if (!L->getParentLoop()) {
|
||||||
@ -960,24 +963,21 @@ CountValue *HexagonHardwareLoops::computeCount(MachineLoop *Loop,
|
|||||||
/// \brief Return true if the operation is invalid within hardware loop.
|
/// \brief Return true if the operation is invalid within hardware loop.
|
||||||
bool HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI,
|
bool HexagonHardwareLoops::isInvalidLoopOperation(const MachineInstr *MI,
|
||||||
bool IsInnerHWLoop) const {
|
bool IsInnerHWLoop) const {
|
||||||
|
|
||||||
// Call is not allowed because the callee may use a hardware loop except for
|
// Call is not allowed because the callee may use a hardware loop except for
|
||||||
// the case when the call never returns.
|
// the case when the call never returns.
|
||||||
if (MI->getDesc().isCall())
|
if (MI->getDesc().isCall())
|
||||||
return !TII->doesNotReturn(*MI);
|
return !TII->doesNotReturn(*MI);
|
||||||
|
|
||||||
// Check if the instruction defines a hardware loop register.
|
// Check if the instruction defines a hardware loop register.
|
||||||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
using namespace Hexagon;
|
||||||
const MachineOperand &MO = MI->getOperand(i);
|
static const unsigned Regs01[] = { LC0, SA0, LC1, SA1 };
|
||||||
if (!MO.isReg() || !MO.isDef())
|
static const unsigned Regs1[] = { LC1, SA1 };
|
||||||
continue;
|
auto CheckRegs = IsInnerHWLoop ? makeArrayRef(Regs01, array_lengthof(Regs01))
|
||||||
unsigned R = MO.getReg();
|
: makeArrayRef(Regs1, array_lengthof(Regs1));
|
||||||
if (IsInnerHWLoop && (R == Hexagon::LC0 || R == Hexagon::SA0 ||
|
for (unsigned R : CheckRegs)
|
||||||
R == Hexagon::LC1 || R == Hexagon::SA1))
|
if (MI->modifiesRegister(R, TRI))
|
||||||
return true;
|
return true;
|
||||||
if (!IsInnerHWLoop && (R == Hexagon::LC1 || R == Hexagon::SA1))
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -644,11 +644,11 @@ bool HexagonTargetLowering::mayBeEmittedAsTailCall(CallInst *CI) const {
|
|||||||
|
|
||||||
/// LowerCallResult - Lower the result values of an ISD::CALL into the
|
/// LowerCallResult - Lower the result values of an ISD::CALL into the
|
||||||
/// appropriate copies out of appropriate physical registers. This assumes that
|
/// appropriate copies out of appropriate physical registers. This assumes that
|
||||||
/// Chain/InFlag are the input chain/flag to use, and that TheCall is the call
|
/// Chain/Glue are the input chain/glue to use, and that TheCall is the call
|
||||||
/// being lowered. Returns a SDNode with the same number of values as the
|
/// being lowered. Returns a SDNode with the same number of values as the
|
||||||
/// ISD::CALL.
|
/// ISD::CALL.
|
||||||
SDValue HexagonTargetLowering::LowerCallResult(
|
SDValue HexagonTargetLowering::LowerCallResult(
|
||||||
SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool isVarArg,
|
SDValue Chain, SDValue Glue, CallingConv::ID CallConv, bool isVarArg,
|
||||||
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
|
const SmallVectorImpl<ISD::InputArg> &Ins, const SDLoc &dl,
|
||||||
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
|
SelectionDAG &DAG, SmallVectorImpl<SDValue> &InVals,
|
||||||
const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
|
const SmallVectorImpl<SDValue> &OutVals, SDValue Callee) const {
|
||||||
@ -671,21 +671,24 @@ SDValue HexagonTargetLowering::LowerCallResult(
|
|||||||
// predicate register as the call result.
|
// predicate register as the call result.
|
||||||
auto &MRI = DAG.getMachineFunction().getRegInfo();
|
auto &MRI = DAG.getMachineFunction().getRegInfo();
|
||||||
SDValue FR0 = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
SDValue FR0 = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
||||||
MVT::i32, InFlag);
|
MVT::i32, Glue);
|
||||||
// FR0 = (Value, Chain, Glue)
|
// FR0 = (Value, Chain, Glue)
|
||||||
unsigned PredR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
|
unsigned PredR = MRI.createVirtualRegister(&Hexagon::PredRegsRegClass);
|
||||||
SDValue TPR = DAG.getCopyToReg(FR0.getValue(1), dl, PredR,
|
SDValue TPR = DAG.getCopyToReg(FR0.getValue(1), dl, PredR,
|
||||||
FR0.getValue(0), FR0.getValue(2));
|
FR0.getValue(0), FR0.getValue(2));
|
||||||
// TPR = (Chain, Glue)
|
// TPR = (Chain, Glue)
|
||||||
RetVal = DAG.getCopyFromReg(TPR.getValue(0), dl, PredR, MVT::i1,
|
// Don't glue this CopyFromReg, because it copies from a virtual
|
||||||
TPR.getValue(1));
|
// register. If it is glued to the call, InstrEmitter will add it
|
||||||
|
// as an implicit def to the call (EmitMachineNode).
|
||||||
|
RetVal = DAG.getCopyFromReg(TPR.getValue(0), dl, PredR, MVT::i1);
|
||||||
|
Glue = TPR.getValue(1);
|
||||||
} else {
|
} else {
|
||||||
RetVal = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
RetVal = DAG.getCopyFromReg(Chain, dl, RVLocs[i].getLocReg(),
|
||||||
RVLocs[i].getValVT(), InFlag);
|
RVLocs[i].getValVT(), Glue);
|
||||||
|
Glue = RetVal.getValue(2);
|
||||||
}
|
}
|
||||||
InVals.push_back(RetVal.getValue(0));
|
InVals.push_back(RetVal.getValue(0));
|
||||||
Chain = RetVal.getValue(1);
|
Chain = RetVal.getValue(1);
|
||||||
InFlag = RetVal.getValue(2);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Chain;
|
return Chain;
|
||||||
@ -840,16 +843,17 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|||||||
if (!MemOpChains.empty())
|
if (!MemOpChains.empty())
|
||||||
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
|
Chain = DAG.getNode(ISD::TokenFactor, dl, MVT::Other, MemOpChains);
|
||||||
|
|
||||||
|
SDValue Glue;
|
||||||
if (!IsTailCall) {
|
if (!IsTailCall) {
|
||||||
SDValue C = DAG.getConstant(NumBytes, dl, PtrVT, true);
|
SDValue C = DAG.getConstant(NumBytes, dl, PtrVT, true);
|
||||||
Chain = DAG.getCALLSEQ_START(Chain, C, dl);
|
Chain = DAG.getCALLSEQ_START(Chain, C, dl);
|
||||||
|
Glue = Chain.getValue(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Build a sequence of copy-to-reg nodes chained together with token
|
// Build a sequence of copy-to-reg nodes chained together with token
|
||||||
// chain and flag operands which copy the outgoing args into registers.
|
// chain and flag operands which copy the outgoing args into registers.
|
||||||
// The Glue is necessary since all emitted instructions must be
|
// The Glue is necessary since all emitted instructions must be
|
||||||
// stuck together.
|
// stuck together.
|
||||||
SDValue Glue;
|
|
||||||
if (!IsTailCall) {
|
if (!IsTailCall) {
|
||||||
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
for (unsigned i = 0, e = RegsToPass.size(); i != e; ++i) {
|
||||||
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
Chain = DAG.getCopyToReg(Chain, dl, RegsToPass[i].first,
|
||||||
@ -902,6 +906,10 @@ HexagonTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI,
|
|||||||
RegsToPass[i].second.getValueType()));
|
RegsToPass[i].second.getValueType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallConv);
|
||||||
|
assert(Mask && "Missing call preserved mask for calling convention");
|
||||||
|
Ops.push_back(DAG.getRegisterMask(Mask));
|
||||||
|
|
||||||
if (Glue.getNode())
|
if (Glue.getNode())
|
||||||
Ops.push_back(Glue);
|
Ops.push_back(Glue);
|
||||||
|
|
||||||
@ -1571,9 +1579,10 @@ HexagonTargetLowering::LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG)
|
|||||||
|
|
||||||
SDValue
|
SDValue
|
||||||
HexagonTargetLowering::GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
|
HexagonTargetLowering::GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
|
||||||
GlobalAddressSDNode *GA, SDValue *InFlag, EVT PtrVT, unsigned ReturnReg,
|
GlobalAddressSDNode *GA, SDValue Glue, EVT PtrVT, unsigned ReturnReg,
|
||||||
unsigned char OperandFlags) const {
|
unsigned char OperandFlags) const {
|
||||||
MachineFrameInfo &MFI = DAG.getMachineFunction().getFrameInfo();
|
MachineFunction &MF = DAG.getMachineFunction();
|
||||||
|
MachineFrameInfo &MFI = MF.getFrameInfo();
|
||||||
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
|
SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue);
|
||||||
SDLoc dl(GA);
|
SDLoc dl(GA);
|
||||||
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
|
SDValue TGA = DAG.getTargetGlobalAddress(GA->getGlobal(), dl,
|
||||||
@ -1585,23 +1594,21 @@ HexagonTargetLowering::GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
|
|||||||
// 2. Callee which in this case is the Global address value.
|
// 2. Callee which in this case is the Global address value.
|
||||||
// 3. Registers live into the call.In this case its R0, as we
|
// 3. Registers live into the call.In this case its R0, as we
|
||||||
// have just one argument to be passed.
|
// have just one argument to be passed.
|
||||||
// 4. InFlag if there is any.
|
// 4. Glue.
|
||||||
// Note: The order is important.
|
// Note: The order is important.
|
||||||
|
|
||||||
if (InFlag) {
|
const auto &HRI = *Subtarget.getRegisterInfo();
|
||||||
SDValue Ops[] = { Chain, TGA,
|
const uint32_t *Mask = HRI.getCallPreservedMask(MF, CallingConv::C);
|
||||||
DAG.getRegister(Hexagon::R0, PtrVT), *InFlag };
|
assert(Mask && "Missing call preserved mask for calling convention");
|
||||||
|
SDValue Ops[] = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT),
|
||||||
|
DAG.getRegisterMask(Mask), Glue };
|
||||||
Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
|
Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
|
||||||
} else {
|
|
||||||
SDValue Ops[] = { Chain, TGA, DAG.getRegister(Hexagon::R0, PtrVT)};
|
|
||||||
Chain = DAG.getNode(HexagonISD::CALL, dl, NodeTys, Ops);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Inform MFI that function has calls.
|
// Inform MFI that function has calls.
|
||||||
MFI.setAdjustsStack(true);
|
MFI.setAdjustsStack(true);
|
||||||
|
|
||||||
SDValue Flag = Chain.getValue(1);
|
Glue = Chain.getValue(1);
|
||||||
return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Flag);
|
return DAG.getCopyFromReg(Chain, dl, ReturnReg, PtrVT, Glue);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@ -1694,7 +1701,7 @@ HexagonTargetLowering::LowerToTLSGeneralDynamicModel(GlobalAddressSDNode *GA,
|
|||||||
Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InFlag);
|
Chain = DAG.getCopyToReg(DAG.getEntryNode(), dl, Hexagon::R0, Chain, InFlag);
|
||||||
InFlag = Chain.getValue(1);
|
InFlag = Chain.getValue(1);
|
||||||
|
|
||||||
return GetDynamicTLSAddr(DAG, Chain, GA, &InFlag, PtrVT,
|
return GetDynamicTLSAddr(DAG, Chain, GA, InFlag, PtrVT,
|
||||||
Hexagon::R0, HexagonII::MO_GDPLT);
|
Hexagon::R0, HexagonII::MO_GDPLT);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +163,7 @@ namespace HexagonISD {
|
|||||||
SDValue LowerToTLSLocalExecModel(GlobalAddressSDNode *GA,
|
SDValue LowerToTLSLocalExecModel(GlobalAddressSDNode *GA,
|
||||||
SelectionDAG &DAG) const;
|
SelectionDAG &DAG) const;
|
||||||
SDValue GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
|
SDValue GetDynamicTLSAddr(SelectionDAG &DAG, SDValue Chain,
|
||||||
GlobalAddressSDNode *GA, SDValue *InFlag, EVT PtrVT,
|
GlobalAddressSDNode *GA, SDValue InFlag, EVT PtrVT,
|
||||||
unsigned ReturnReg, unsigned char OperandFlags) const;
|
unsigned ReturnReg, unsigned char OperandFlags) const;
|
||||||
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const;
|
SDValue LowerGLOBAL_OFFSET_TABLE(SDValue Op, SelectionDAG &DAG) const;
|
||||||
|
|
||||||
|
@ -1413,12 +1413,22 @@ bool HexagonInstrInfo::DefinesPredicate(
|
|||||||
auto &HRI = getRegisterInfo();
|
auto &HRI = getRegisterInfo();
|
||||||
for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) {
|
for (unsigned oper = 0; oper < MI.getNumOperands(); ++oper) {
|
||||||
MachineOperand MO = MI.getOperand(oper);
|
MachineOperand MO = MI.getOperand(oper);
|
||||||
if (MO.isReg() && MO.isDef()) {
|
if (MO.isReg()) {
|
||||||
|
if (!MO.isDef())
|
||||||
|
continue;
|
||||||
const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg());
|
const TargetRegisterClass* RC = HRI.getMinimalPhysRegClass(MO.getReg());
|
||||||
if (RC == &Hexagon::PredRegsRegClass) {
|
if (RC == &Hexagon::PredRegsRegClass) {
|
||||||
Pred.push_back(MO);
|
Pred.push_back(MO);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
continue;
|
||||||
|
} else if (MO.isRegMask()) {
|
||||||
|
for (unsigned PR : Hexagon::PredRegsRegClass) {
|
||||||
|
if (!MI.modifiesRegister(PR, &HRI))
|
||||||
|
continue;
|
||||||
|
Pred.push_back(MO);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -3009,10 +3019,12 @@ bool HexagonInstrInfo::producesStall(const MachineInstr &MI,
|
|||||||
|
|
||||||
bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI,
|
bool HexagonInstrInfo::predCanBeUsedAsDotNew(const MachineInstr &MI,
|
||||||
unsigned PredReg) const {
|
unsigned PredReg) const {
|
||||||
for (unsigned opNum = 0; opNum < MI.getNumOperands(); opNum++) {
|
for (const MachineOperand &MO : MI.operands()) {
|
||||||
const MachineOperand &MO = MI.getOperand(opNum);
|
// Predicate register must be explicitly defined.
|
||||||
|
if (MO.isRegMask() && MO.clobbersPhysReg(PredReg))
|
||||||
|
return false;
|
||||||
if (MO.isReg() && MO.isDef() && MO.isImplicit() && (MO.getReg() == PredReg))
|
if (MO.isReg() && MO.isDef() && MO.isImplicit() && (MO.getReg() == PredReg))
|
||||||
return false; // Predicate register must be explicitly defined.
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Hexagon Programmer's Reference says that decbin, memw_locked, and
|
// Hexagon Programmer's Reference says that decbin, memw_locked, and
|
||||||
|
@ -111,9 +111,12 @@ void llvm::HexagonLowerToMC(const MCInstrInfo &MCII, const MachineInstr *MI,
|
|||||||
default:
|
default:
|
||||||
MI->print(errs());
|
MI->print(errs());
|
||||||
llvm_unreachable("unknown operand type");
|
llvm_unreachable("unknown operand type");
|
||||||
|
case MachineOperand::MO_RegisterMask:
|
||||||
|
continue;
|
||||||
case MachineOperand::MO_Register:
|
case MachineOperand::MO_Register:
|
||||||
// Ignore all implicit register operands.
|
// Ignore all implicit register operands.
|
||||||
if (MO.isImplicit()) continue;
|
if (MO.isImplicit())
|
||||||
|
continue;
|
||||||
MCO = MCOperand::createReg(MO.getReg());
|
MCO = MCOperand::createReg(MO.getReg());
|
||||||
break;
|
break;
|
||||||
case MachineOperand::MO_FPImmediate: {
|
case MachineOperand::MO_FPImmediate: {
|
||||||
|
@ -141,13 +141,12 @@ defm J2_loop1 : LOOP_ri<"loop1">;
|
|||||||
let isCall = 1, hasSideEffects = 1, isPredicable = 0,
|
let isCall = 1, hasSideEffects = 1, isPredicable = 0,
|
||||||
isExtended = 0, isExtendable = 1, opExtendable = 0,
|
isExtended = 0, isExtendable = 1, opExtendable = 0,
|
||||||
isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in
|
isExtentSigned = 1, opExtentBits = 24, opExtentAlign = 2 in
|
||||||
class T_Call<bit CSR, string ExtStr>
|
class T_Call<string ExtStr>
|
||||||
: JInst<(outs), (ins a30_2Imm:$dst),
|
: JInst<(outs), (ins a30_2Imm:$dst),
|
||||||
"call " # ExtStr # "$dst", [], "", J_tc_2early_SLOT23> {
|
"call " # ExtStr # "$dst", [], "", J_tc_2early_SLOT23> {
|
||||||
let BaseOpcode = "call";
|
let BaseOpcode = "call";
|
||||||
bits<24> dst;
|
bits<24> dst;
|
||||||
|
|
||||||
let Defs = !if (CSR, VolatileV3.Regs, []);
|
|
||||||
let IClass = 0b0101;
|
let IClass = 0b0101;
|
||||||
let Inst{27-25} = 0b101;
|
let Inst{27-25} = 0b101;
|
||||||
let Inst{24-16,13-1} = dst{23-2};
|
let Inst{24-16,13-1} = dst{23-2};
|
||||||
@ -156,11 +155,11 @@ class T_Call<bit CSR, string ExtStr>
|
|||||||
|
|
||||||
let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],
|
let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1, Defs = [R16],
|
||||||
isPredicable = 0 in
|
isPredicable = 0 in
|
||||||
def CALLProfile : T_Call<1, "">;
|
def CALLProfile : T_Call<"">;
|
||||||
|
|
||||||
let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,
|
let isCodeGenOnly = 1, isCall = 1, hasSideEffects = 1,
|
||||||
Defs = [PC, R31, R6, R7, P0] in
|
Defs = [PC, R31, R6, R7, P0] in
|
||||||
def PS_call_stk : T_Call<0, "">;
|
def PS_call_stk : T_Call<"">;
|
||||||
|
|
||||||
let isCall = 1, hasSideEffects = 1, cofMax1 = 1 in
|
let isCall = 1, hasSideEffects = 1, cofMax1 = 1 in
|
||||||
class JUMPR_MISC_CALLR<bit isPred, bit isPredNot,
|
class JUMPR_MISC_CALLR<bit isPred, bit isPredNot,
|
||||||
@ -185,11 +184,11 @@ class JUMPR_MISC_CALLR<bit isPred, bit isPredNot,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
let isCodeGenOnly = 1, Defs = VolatileV3.Regs in {
|
let isCodeGenOnly = 1 in {
|
||||||
def PS_callr_nr : JUMPR_MISC_CALLR<0, 1>; // Call, no return.
|
def PS_callr_nr : JUMPR_MISC_CALLR<0, 1>; // Call, no return.
|
||||||
}
|
}
|
||||||
|
|
||||||
let isCall = 1, hasSideEffects = 1, Defs = VolatileV3.Regs,
|
let isCall = 1, hasSideEffects = 1,
|
||||||
isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,
|
isExtended = 0, isExtendable = 1, opExtendable = 0, isCodeGenOnly = 1,
|
||||||
BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2,
|
BaseOpcode = "PS_call_nr", isExtentSigned = 1, opExtentAlign = 2,
|
||||||
Itinerary = J_tc_2early_SLOT23 in
|
Itinerary = J_tc_2early_SLOT23 in
|
||||||
@ -375,43 +374,43 @@ let isCall = 1, isBarrier = 1, isReturn = 1, isTerminator = 1,
|
|||||||
|
|
||||||
// Restore registers and dealloc frame before a tail call.
|
// Restore registers and dealloc frame before a tail call.
|
||||||
let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {
|
let isCall = 1, Defs = [R29, R30, R31, PC], isAsmParserOnly = 1 in {
|
||||||
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<0, "">, PredRel;
|
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4 : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let isExtended = 1, opExtendable = 0 in
|
let isExtended = 1, opExtendable = 0 in
|
||||||
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<0, "">, PredRel;
|
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
|
let Defs = [R14, R15, R28, R29, R30, R31, PC] in {
|
||||||
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<0, "">, PredRel;
|
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_PIC : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let isExtended = 1, opExtendable = 0 in
|
let isExtended = 1, opExtendable = 0 in
|
||||||
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<0, "">, PredRel;
|
def RESTORE_DEALLOC_BEFORE_TAILCALL_V4_EXT_PIC : T_Call<"">, PredRel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Save registers function call.
|
// Save registers function call.
|
||||||
let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
|
let isCall = 1, Uses = [R29, R31], isAsmParserOnly = 1 in {
|
||||||
def SAVE_REGISTERS_CALL_V4 : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4 : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let isExtended = 1, opExtendable = 0 in
|
let isExtended = 1, opExtendable = 0 in
|
||||||
def SAVE_REGISTERS_CALL_V4_EXT : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4_EXT : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [P0] in
|
let Defs = [P0] in
|
||||||
def SAVE_REGISTERS_CALL_V4STK : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4STK : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [P0], isExtended = 1, opExtendable = 0 in
|
let Defs = [P0], isExtended = 1, opExtendable = 0 in
|
||||||
def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4STK_EXT : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [R14, R15, R28] in
|
let Defs = [R14, R15, R28] in
|
||||||
def SAVE_REGISTERS_CALL_V4_PIC : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4_PIC : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in
|
let Defs = [R14, R15, R28], isExtended = 1, opExtendable = 0 in
|
||||||
def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4_EXT_PIC : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [R14, R15, R28, P0] in
|
let Defs = [R14, R15, R28, P0] in
|
||||||
def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4STK_PIC : T_Call<"">, PredRel;
|
||||||
|
|
||||||
let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in
|
let Defs = [R14, R15, R28, P0], isExtended = 1, opExtendable = 0 in
|
||||||
def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<0, "">, PredRel;
|
def SAVE_REGISTERS_CALL_V4STK_EXT_PIC : T_Call<"">, PredRel;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Vector load/store pseudos
|
// Vector load/store pseudos
|
||||||
|
@ -36,6 +36,9 @@
|
|||||||
#include "llvm/Target/TargetMachine.h"
|
#include "llvm/Target/TargetMachine.h"
|
||||||
#include "llvm/Target/TargetOptions.h"
|
#include "llvm/Target/TargetOptions.h"
|
||||||
|
|
||||||
|
#define GET_REGINFO_TARGET_DESC
|
||||||
|
#include "HexagonGenRegisterInfo.inc"
|
||||||
|
|
||||||
using namespace llvm;
|
using namespace llvm;
|
||||||
|
|
||||||
HexagonRegisterInfo::HexagonRegisterInfo()
|
HexagonRegisterInfo::HexagonRegisterInfo()
|
||||||
@ -134,6 +137,12 @@ HexagonRegisterInfo::getCalleeSavedRegs(const MachineFunction *MF) const {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
const uint32_t *HexagonRegisterInfo::getCallPreservedMask(
|
||||||
|
const MachineFunction &MF, CallingConv::ID) const {
|
||||||
|
return HexagonCSR_RegMask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
|
BitVector HexagonRegisterInfo::getReservedRegs(const MachineFunction &MF)
|
||||||
const {
|
const {
|
||||||
BitVector Reserved(getNumRegs());
|
BitVector Reserved(getNumRegs());
|
||||||
@ -284,6 +293,3 @@ unsigned HexagonRegisterInfo::getFirstCallerSavedNonParamReg() const {
|
|||||||
return Hexagon::R6;
|
return Hexagon::R6;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#define GET_REGINFO_TARGET_DESC
|
|
||||||
#include "HexagonGenRegisterInfo.inc"
|
|
||||||
|
@ -35,7 +35,8 @@ public:
|
|||||||
/// Code Generation virtual methods...
|
/// Code Generation virtual methods...
|
||||||
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF)
|
const MCPhysReg *getCalleeSavedRegs(const MachineFunction *MF)
|
||||||
const override;
|
const override;
|
||||||
|
const uint32_t *getCallPreservedMask(const MachineFunction &MF,
|
||||||
|
CallingConv::ID) const override;
|
||||||
|
|
||||||
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
BitVector getReservedRegs(const MachineFunction &MF) const override;
|
||||||
|
|
||||||
|
@ -301,16 +301,7 @@ def V62Regs : RegisterClass<"Hexagon", [i32], 32,
|
|||||||
PKTCOUNTLO, PKTCOUNTHI, PKTCOUNT,
|
PKTCOUNTLO, PKTCOUNTHI, PKTCOUNT,
|
||||||
UTIMERLO, UTIMERHI, UTIMER)>;
|
UTIMERLO, UTIMERHI, UTIMER)>;
|
||||||
|
|
||||||
def VolatileV3 {
|
|
||||||
list<Register> Regs = [D0, D1, D2, D3, D4, D5, D6, D7,
|
def HexagonCSR
|
||||||
R28, R31,
|
: CalleeSavedRegs<(add R16, R17, R18, R19, R20, R21, R22, R23,
|
||||||
P0, P1, P2, P3,
|
R24, R25, R26, R27)>;
|
||||||
M0, M1,
|
|
||||||
LC0, LC1, SA0, SA1, USR, USR_OVF, CS0, CS1,
|
|
||||||
V0, V1, V2, V3, V4, V5, V6, V7, V8, V9, V10, V11,
|
|
||||||
V12, V13, V14, V15, V16, V17, V18, V19, V20, V21,
|
|
||||||
V22, V23, V24, V25, V26, V27, V28, V29, V30, V31,
|
|
||||||
W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11,
|
|
||||||
W12, W13, W14, W15,
|
|
||||||
Q0, Q1, Q2, Q3];
|
|
||||||
}
|
|
||||||
|
@ -720,6 +720,8 @@ bool HexagonPacketizerList::canPromoteToNewValueStore(const MachineInstr &MI,
|
|||||||
// %R9<def> = ZXTH %R12, %D6<imp-use>, %R12<imp-def>
|
// %R9<def> = ZXTH %R12, %D6<imp-use>, %R12<imp-def>
|
||||||
// S2_storerh_io %R8, 2, %R12<kill>; mem:ST2[%scevgep343]
|
// S2_storerh_io %R8, 2, %R12<kill>; mem:ST2[%scevgep343]
|
||||||
for (auto &MO : PacketMI.operands()) {
|
for (auto &MO : PacketMI.operands()) {
|
||||||
|
if (MO.isRegMask() && MO.clobbersPhysReg(DepReg))
|
||||||
|
return false;
|
||||||
if (!MO.isReg() || !MO.isDef() || !MO.isImplicit())
|
if (!MO.isReg() || !MO.isDef() || !MO.isImplicit())
|
||||||
continue;
|
continue;
|
||||||
unsigned R = MO.getReg();
|
unsigned R = MO.getReg();
|
||||||
@ -759,9 +761,12 @@ bool HexagonPacketizerList::canPromoteToNewValue(const MachineInstr &MI,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool isImplicitDependency(const MachineInstr &I, unsigned DepReg) {
|
static bool isImplicitDependency(const MachineInstr &I, unsigned DepReg) {
|
||||||
for (auto &MO : I.operands())
|
for (auto &MO : I.operands()) {
|
||||||
|
if (MO.isRegMask() && MO.clobbersPhysReg(DepReg))
|
||||||
|
return true;
|
||||||
if (MO.isReg() && MO.isDef() && (MO.getReg() == DepReg) && MO.isImplicit())
|
if (MO.isReg() && MO.isDef() && (MO.getReg() == DepReg) && MO.isImplicit())
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1173,6 +1178,36 @@ bool HexagonPacketizerList::hasControlDependence(const MachineInstr &I,
|
|||||||
(J.isBranch() || J.isCall() || J.isBarrier());
|
(J.isBranch() || J.isCall() || J.isBarrier());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool HexagonPacketizerList::hasRegMaskDependence(const MachineInstr &I,
|
||||||
|
const MachineInstr &J) {
|
||||||
|
// Adding I to a packet that has J.
|
||||||
|
|
||||||
|
// Regmasks are not reflected in the scheduling dependency graph, so
|
||||||
|
// we need to check them manually. This code assumes that regmasks only
|
||||||
|
// occur on calls, and the problematic case is when we add an instruction
|
||||||
|
// defining a register R to a packet that has a call that clobbers R via
|
||||||
|
// a regmask. Those cannot be packetized together, because the call will
|
||||||
|
// be executed last. That's also a reson why it is ok to add a call
|
||||||
|
// clobbering R to a packet that defines R.
|
||||||
|
|
||||||
|
// Look for regmasks in J.
|
||||||
|
for (const MachineOperand &OpJ : J.operands()) {
|
||||||
|
if (!OpJ.isRegMask())
|
||||||
|
continue;
|
||||||
|
assert((J.isCall() || HII->isTailCall(J)) && "Regmask on a non-call");
|
||||||
|
for (const MachineOperand &OpI : I.operands()) {
|
||||||
|
if (OpI.isReg()) {
|
||||||
|
if (OpJ.clobbersPhysReg(OpI.getReg()))
|
||||||
|
return true;
|
||||||
|
} else if (OpI.isRegMask()) {
|
||||||
|
// Both are regmasks. Assume that they intersect.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool HexagonPacketizerList::hasV4SpecificDependence(const MachineInstr &I,
|
bool HexagonPacketizerList::hasV4SpecificDependence(const MachineInstr &I,
|
||||||
const MachineInstr &J) {
|
const MachineInstr &J) {
|
||||||
bool SysI = isSystemInstr(I), SysJ = isSystemInstr(J);
|
bool SysI = isSystemInstr(I), SysJ = isSystemInstr(J);
|
||||||
@ -1219,6 +1254,14 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
|
|||||||
if (Dependence)
|
if (Dependence)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
|
// Regmasks are not accounted for in the scheduling graph, so we need
|
||||||
|
// to explicitly check for dependencies caused by them. They should only
|
||||||
|
// appear on calls, so it's not too pessimistic to reject all regmask
|
||||||
|
// dependencies.
|
||||||
|
Dependence = hasRegMaskDependence(I, J);
|
||||||
|
if (Dependence)
|
||||||
|
return false;
|
||||||
|
|
||||||
// V4 allows dual stores. It does not allow second store, if the first
|
// V4 allows dual stores. It does not allow second store, if the first
|
||||||
// store is not in SLOT0. New value store, new value jump, dealloc_return
|
// store is not in SLOT0. New value store, new value jump, dealloc_return
|
||||||
// and memop always take SLOT0. Arch spec 3.4.4.2.
|
// and memop always take SLOT0. Arch spec 3.4.4.2.
|
||||||
@ -1467,13 +1510,19 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
|
|||||||
// R0 = ... ; SUI
|
// R0 = ... ; SUI
|
||||||
// Those cannot be packetized together, since the call will observe
|
// Those cannot be packetized together, since the call will observe
|
||||||
// the effect of the assignment to R0.
|
// the effect of the assignment to R0.
|
||||||
if (DepType == SDep::Anti && J.isCall()) {
|
if ((DepType == SDep::Anti || DepType == SDep::Output) && J.isCall()) {
|
||||||
// Check if I defines any volatile register. We should also check
|
// Check if I defines any volatile register. We should also check
|
||||||
// registers that the call may read, but these happen to be a
|
// registers that the call may read, but these happen to be a
|
||||||
// subset of the volatile register set.
|
// subset of the volatile register set.
|
||||||
for (const MCPhysReg *P = J.getDesc().ImplicitDefs; P && *P; ++P) {
|
for (const MachineOperand &Op : I.operands()) {
|
||||||
if (!I.modifiesRegister(*P, HRI))
|
if (Op.isReg() && Op.isDef()) {
|
||||||
|
unsigned R = Op.getReg();
|
||||||
|
if (!J.readsRegister(R, HRI) && !J.modifiesRegister(R, HRI))
|
||||||
continue;
|
continue;
|
||||||
|
} else if (!Op.isRegMask()) {
|
||||||
|
// If I has a regmask assume dependency.
|
||||||
|
continue;
|
||||||
|
}
|
||||||
FoundSequentialDependence = true;
|
FoundSequentialDependence = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -112,6 +112,7 @@ protected:
|
|||||||
void reserveResourcesForConstExt();
|
void reserveResourcesForConstExt();
|
||||||
bool hasDeadDependence(const MachineInstr &I, const MachineInstr &J);
|
bool hasDeadDependence(const MachineInstr &I, const MachineInstr &J);
|
||||||
bool hasControlDependence(const MachineInstr &I, const MachineInstr &J);
|
bool hasControlDependence(const MachineInstr &I, const MachineInstr &J);
|
||||||
|
bool hasRegMaskDependence(const MachineInstr &I, const MachineInstr &J);
|
||||||
bool hasV4SpecificDependence(const MachineInstr &I, const MachineInstr &J);
|
bool hasV4SpecificDependence(const MachineInstr &I, const MachineInstr &J);
|
||||||
bool producesStall(const MachineInstr &MI);
|
bool producesStall(const MachineInstr &MI);
|
||||||
};
|
};
|
||||||
|
@ -62,9 +62,19 @@ bool DeadCodeElimination::isLiveInstr(const MachineInstr *MI) const {
|
|||||||
return true;
|
return true;
|
||||||
if (MI->isPHI())
|
if (MI->isPHI())
|
||||||
return false;
|
return false;
|
||||||
for (auto &Op : MI->operands())
|
for (auto &Op : MI->operands()) {
|
||||||
if (Op.isReg() && MRI.isReserved(Op.getReg()))
|
if (Op.isReg() && MRI.isReserved(Op.getReg()))
|
||||||
return true;
|
return true;
|
||||||
|
if (Op.isRegMask()) {
|
||||||
|
const uint32_t *BM = Op.getRegMask();
|
||||||
|
for (unsigned R = 0, RN = DFG.getTRI().getNumRegs(); R != RN; ++R) {
|
||||||
|
if (BM[R/32] & (1u << (R%32)))
|
||||||
|
continue;
|
||||||
|
if (MRI.isReserved(R))
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -70,18 +70,27 @@ std::set<RegisterId> PhysicalRegisterInfo::getAliasSet(RegisterId Reg) const {
|
|||||||
assert(isRegMaskId(Reg) || TargetRegisterInfo::isPhysicalRegister(Reg));
|
assert(isRegMaskId(Reg) || TargetRegisterInfo::isPhysicalRegister(Reg));
|
||||||
if (isRegMaskId(Reg)) {
|
if (isRegMaskId(Reg)) {
|
||||||
// XXX SLOW
|
// XXX SLOW
|
||||||
// XXX Add other regmasks to the set.
|
|
||||||
const uint32_t *MB = getRegMaskBits(Reg);
|
const uint32_t *MB = getRegMaskBits(Reg);
|
||||||
for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) {
|
for (unsigned i = 1, e = TRI.getNumRegs(); i != e; ++i) {
|
||||||
if (MB[i/32] & (1u << (i%32)))
|
if (MB[i/32] & (1u << (i%32)))
|
||||||
continue;
|
continue;
|
||||||
AS.insert(i);
|
AS.insert(i);
|
||||||
}
|
}
|
||||||
|
for (const uint32_t *RM : RegMasks) {
|
||||||
|
RegisterId MI = getRegMaskId(RM);
|
||||||
|
if (MI != Reg && aliasMM(RegisterRef(Reg), RegisterRef(MI)))
|
||||||
|
AS.insert(MI);
|
||||||
|
}
|
||||||
return AS;
|
return AS;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (MCRegAliasIterator AI(Reg, &TRI, false); AI.isValid(); ++AI)
|
for (MCRegAliasIterator AI(Reg, &TRI, false); AI.isValid(); ++AI)
|
||||||
AS.insert(*AI);
|
AS.insert(*AI);
|
||||||
|
for (const uint32_t *RM : RegMasks) {
|
||||||
|
RegisterId MI = getRegMaskId(RM);
|
||||||
|
if (aliasRM(RegisterRef(Reg), RegisterRef(MI)))
|
||||||
|
AS.insert(MI);
|
||||||
|
}
|
||||||
return AS;
|
return AS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -153,10 +162,10 @@ bool PhysicalRegisterInfo::aliasRM(RegisterRef RR, RegisterRef RM) const {
|
|||||||
// is a superset of the lane mask from the register class, check the regmask
|
// is a superset of the lane mask from the register class, check the regmask
|
||||||
// bit directly.
|
// bit directly.
|
||||||
if (RR.Mask == LaneBitmask::getAll())
|
if (RR.Mask == LaneBitmask::getAll())
|
||||||
return Preserved;
|
return !Preserved;
|
||||||
const TargetRegisterClass *RC = RegInfos[RR.Reg].RegClass;
|
const TargetRegisterClass *RC = RegInfos[RR.Reg].RegClass;
|
||||||
if (RC != nullptr && (RR.Mask & RC->LaneMask) == RC->LaneMask)
|
if (RC != nullptr && (RR.Mask & RC->LaneMask) == RC->LaneMask)
|
||||||
return Preserved;
|
return !Preserved;
|
||||||
|
|
||||||
// Otherwise, check all subregisters whose lane mask overlaps the given
|
// Otherwise, check all subregisters whose lane mask overlaps the given
|
||||||
// mask. For each such register, if it is preserved by the regmask, then
|
// mask. For each such register, if it is preserved by the regmask, then
|
||||||
|
@ -51,6 +51,10 @@ namespace rdf {
|
|||||||
return F - Map.begin() + 1;
|
return F - Map.begin() + 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef typename std::vector<T>::const_iterator const_iterator;
|
||||||
|
const_iterator begin() const { return Map.begin(); }
|
||||||
|
const_iterator end() const { return Map.end(); }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<T> Map;
|
std::vector<T> Map;
|
||||||
};
|
};
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
; without adding an extra spill of that register.
|
; without adding an extra spill of that register.
|
||||||
;
|
;
|
||||||
; CHECK: PredSpill:
|
; CHECK: PredSpill:
|
||||||
; CHECK: memd(r29{{.*}}) = r17:16
|
|
||||||
; CHECK-DAG: r{{[0-9]+}} = p0
|
; CHECK-DAG: r{{[0-9]+}} = p0
|
||||||
; CHECK-DAG: p0 = r{{[0-9]+}}
|
; CHECK-DAG: p0 = r{{[0-9]+}}
|
||||||
; CHECK-NOT: = memw(r29
|
; CHECK-NOT: = memw(r29
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
; RUN: llc -march=hexagon -filetype=obj -o - %s | llvm-objdump -d - | FileCheck %s
|
; RUN: llc -march=hexagon -filetype=obj -ifcvt-limit=0 -o - %s | llvm-objdump -d - | FileCheck %s
|
||||||
|
|
||||||
; CHECK: p0 = cmp.gt(r0,#-1); if (!p0.new) jump:nt
|
; CHECK: p0 = cmp.gt(r0,#-1); if (!p0.new) jump:nt
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user