[Hexagon] Handle double-vector registers as new-value producers

Patch by Colin LeMahieu.

llvm-svn: 267897
This commit is contained in:
Krzysztof Parzyszek 2016-04-28 15:54:48 +00:00
parent e5447574c8
commit e737b86f8c
4 changed files with 54 additions and 3 deletions

View File

@ -88,6 +88,19 @@ void HexagonMCCodeEmitter::encodeInstruction(MCInst const &MI, raw_ostream &OS,
return;
}
static bool RegisterMatches(unsigned Consumer, unsigned Producer,
unsigned Producer2) {
if (Consumer == Producer)
return true;
if (Consumer == Producer2)
return true;
// Calculate if we're a single vector consumer referencing a double producer
if (Producer >= Hexagon::W0 && Producer <= Hexagon::W15)
if (Consumer >= Hexagon::V0 && Consumer <= Hexagon::V31)
return ((Consumer - Hexagon::V0) >> 1) == (Producer - Hexagon::W0);
return false;
}
/// EncodeSingleInstruction - Emit a single
void HexagonMCCodeEmitter::EncodeSingleInstruction(
const MCInst &MI, raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups,
@ -125,8 +138,10 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
MCOperand &MCO =
HMB.getOperand(HexagonMCInstrInfo::getNewValueOp(MCII, HMB));
unsigned SOffset = 0;
unsigned VOffset = 0;
unsigned Register = MCO.getReg();
unsigned Register1;
unsigned Register2;
auto Instructions = HexagonMCInstrInfo::bundleInstructions(**CurrentBundle);
auto i = Instructions.begin() + Index - 1;
for (;; --i) {
@ -135,11 +150,18 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
if (HexagonMCInstrInfo::isImmext(Inst))
continue;
++SOffset;
if (HexagonMCInstrInfo::isVector(MCII, Inst))
// Vector instructions don't count scalars
++VOffset;
Register1 =
HexagonMCInstrInfo::hasNewValue(MCII, Inst)
? HexagonMCInstrInfo::getNewValueOperand(MCII, Inst).getReg()
: static_cast<unsigned>(Hexagon::NoRegister);
if (Register != Register1)
Register2 =
HexagonMCInstrInfo::hasNewValue2(MCII, Inst)
? HexagonMCInstrInfo::getNewValueOperand2(MCII, Inst).getReg()
: static_cast<unsigned>(Hexagon::NoRegister);
if (!RegisterMatches(Register, Register1, Register2))
// This isn't the register we're looking for
continue;
if (!HexagonMCInstrInfo::isPredicated(MCII, Inst))
@ -153,8 +175,11 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
break;
}
// Hexagon PRM 10.11 Construct Nt from distance
unsigned Offset = SOffset;
unsigned Offset =
HexagonMCInstrInfo::isVector(MCII, HMB) ? VOffset : SOffset;
Offset <<= 1;
Offset |=
HexagonMCInstrInfo::SubregisterBit(Register, Register1, Register2);
MCO.setReg(Offset + Hexagon::R0);
}
@ -165,7 +190,6 @@ void HexagonMCCodeEmitter::EncodeSingleInstruction(
((HMB.getOpcode() != DuplexIClass0) && (HMB.getOpcode() != A4_ext) &&
(HMB.getOpcode() != A4_ext_b) && (HMB.getOpcode() != A4_ext_c) &&
(HMB.getOpcode() != A4_ext_g))) {
// Use a A2_nop for unimplemented instructions.
DEBUG(dbgs() << "Unimplemented inst: "
" `" << HexagonMCInstrInfo::getName(MCII, HMB) << "'"
"\n");

View File

@ -788,4 +788,17 @@ void HexagonMCInstrInfo::setOuterLoop(MCInst &MCI) {
MCOperand &Operand = MCI.getOperand(0);
Operand.setImm(Operand.getImm() | outerLoopMask);
}
unsigned HexagonMCInstrInfo::SubregisterBit(unsigned Consumer,
unsigned Producer,
unsigned Producer2) {
// If we're a single vector consumer of a double producer, set subreg bit
// based on if we're accessing the lower or upper register component
if (Producer >= Hexagon::W0 && Producer <= Hexagon::W15)
if (Consumer >= Hexagon::V0 && Consumer <= Hexagon::V31)
return (Consumer - Hexagon::V0) & 0x1;
if (Consumer == Producer2)
return 0x1;
return 0;
}
}

View File

@ -290,6 +290,8 @@ void setOuterLoop(MCInst &MCI);
// Would duplexing this instruction create a requirement to extend
bool subInstWouldBeExtended(MCInst const &potentialDuplex);
unsigned SubregisterBit(unsigned Consumer, unsigned Producer,
unsigned Producer2);
// Attempt to find and replace compound pairs
void tryCompound(MCInstrInfo const &MCII, MCContext &Context, MCInst &MCI);

View File

@ -0,0 +1,12 @@
# RUN: llvm-mc -arch=hexagon -mcpu=hexagonv60 -filetype=obj %s | llvm-objdump -d - | FileCheck %s
{
v1:0 = vshuff(v1,v0,r7)
v2.w = vadd(v13.w,v15.w)
v3.w = vadd(v8.w,v14.w)
vmem(r2+#-2) = v0.new
}
# CHECK: 60 61 07 1b
# CHECK: 02 4d 4f 1c
# CHECK: 03 48 4e 1c
# CHECK: 26 e6 22 28