[PowerPC] [NFC] Refactor code for printing register operands
We have an unfortunate situation in our back end where we have to keep pairs of
functions synchronized. Needless to say that this is not an ideal situation as
it is very difficult to enforce. Even without bugs, it's annoying to have to do
the same thing in two places.
This patch just refactors the code so that the two pairs of those functions that
pertain to printing register operands are unified:
- stripRegisterPrefix() - this just removes the letter prefixes from registers
for the InstrPrinter and AsmPrinter. This patch provides this as a static
member of PPCRegisterInfo
- Handling of PPCII::UseVSXReg - there are 3 places where we do something
special for instructions with that flag set. Each of those places does its
own checking of this flag and implements code customization. Any changes to
how we print/encode VSX/VMX registers require modifying all 3 places. This
patch unifies this into a static function in PPCInstrInfo that returns the
register number adjusted as needed.
Differential revision: https://reviews.llvm.org/D52467
llvm-svn: 343195
diff --git a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
index fd7f815..fc29e4e 100644
--- a/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/InstPrinter/PPCInstPrinter.cpp
@@ -499,43 +499,14 @@
return TT.isOSDarwin() || FullRegNamesWithPercent || FullRegNames;
}
-/// stripRegisterPrefix - This method strips the character prefix from a
-/// register name so that only the number is left.
-static const char *stripRegisterPrefix(const char *RegName) {
- switch (RegName[0]) {
- case 'r':
- case 'f':
- case 'q': // for QPX
- case 'v':
- if (RegName[1] == 's')
- return RegName + 2;
- return RegName + 1;
- case 'c': if (RegName[1] == 'r') return RegName + 2;
- }
-
- return RegName;
-}
-
void PPCInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
raw_ostream &O) {
const MCOperand &Op = MI->getOperand(OpNo);
if (Op.isReg()) {
unsigned Reg = Op.getReg();
-
- // There are VSX instructions that use VSX register numbering (vs0 - vs63)
- // as well as those that use VMX register numbering (v0 - v31 which
- // correspond to vs32 - vs63). If we have an instruction that uses VSX
- // numbering, we need to convert the VMX registers to VSX registers.
- // Namely, we print 32-63 when the instruction operates on one of the
- // VMX registers.
- // (Please synchronize with PPCAsmPrinter::printOperand)
- if ((MII.get(MI->getOpcode()).TSFlags & PPCII::UseVSXReg) &&
- !ShowVSRNumsAsVR) {
- if (PPCInstrInfo::isVRRegister(Reg))
- Reg = PPC::VSX32 + (Reg - PPC::V0);
- else if (PPCInstrInfo::isVFRegister(Reg))
- Reg = PPC::VSX32 + (Reg - PPC::VF0);
- }
+ if (!ShowVSRNumsAsVR)
+ Reg = PPCInstrInfo::getRegNumForOperand(MII.get(MI->getOpcode()),
+ Reg, OpNo);
const char *RegName;
RegName = getVerboseConditionRegName(Reg, MRI.getEncodingValue(Reg));
@@ -544,7 +515,7 @@
if (showRegistersWithPercentPrefix(RegName))
O << "%";
if (!showRegistersWithPrefix())
- RegName = stripRegisterPrefix(RegName);
+ RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
O << RegName;
return;
diff --git a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
index 5a0b35a..7c0f5f0 100644
--- a/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
+++ b/llvm/lib/Target/PowerPC/MCTargetDesc/PPCMCCodeEmitter.cpp
@@ -360,6 +360,20 @@
return 0x80 >> CTX.getRegisterInfo()->getEncodingValue(MO.getReg());
}
+// Get the index for this operand in this instruction. This is needed for
+// computing the register number in PPCInstrInfo::getRegNumForOperand() for
+// any instructions that use a different numbering scheme for registers in
+// different operands.
+static unsigned getOpIdxForMO(const MCInst &MI, const MCOperand &MO) {
+ for (unsigned i = 0; i < MI.getNumOperands(); i++) {
+ const MCOperand &Op = MI.getOperand(i);
+ if (&Op == &MO)
+ return i;
+ }
+ llvm_unreachable("This operand is not part of this instruction");
+ return ~0U; // Silence any warnings about no return.
+}
+
unsigned PPCMCCodeEmitter::
getMachineOpValue(const MCInst &MI, const MCOperand &MO,
SmallVectorImpl<MCFixup> &Fixups,
@@ -370,14 +384,11 @@
assert((MI.getOpcode() != PPC::MTOCRF && MI.getOpcode() != PPC::MTOCRF8 &&
MI.getOpcode() != PPC::MFOCRF && MI.getOpcode() != PPC::MFOCRF8) ||
MO.getReg() < PPC::CR0 || MO.getReg() > PPC::CR7);
- unsigned Reg = MO.getReg();
- unsigned Encode = CTX.getRegisterInfo()->getEncodingValue(Reg);
-
- if ((MCII.get(MI.getOpcode()).TSFlags & PPCII::UseVSXReg))
- if (PPCInstrInfo::isVRRegister(Reg))
- Encode += 32;
-
- return Encode;
+ unsigned OpNo = getOpIdxForMO(MI, MO);
+ unsigned Reg =
+ PPCInstrInfo::getRegNumForOperand(MCII.get(MI.getOpcode()),
+ MO.getReg(), OpNo);
+ return CTX.getRegisterInfo()->getEncodingValue(Reg);
}
assert(MO.isImm() &&
diff --git a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
index 34c58b2..a00f5bd 100644
--- a/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
+++ b/llvm/lib/Target/PowerPC/PPCAsmPrinter.cpp
@@ -158,23 +158,6 @@
} // end anonymous namespace
-/// stripRegisterPrefix - This method strips the character prefix from a
-/// register name so that only the number is left. Used by for linux asm.
-static const char *stripRegisterPrefix(const char *RegName) {
- switch (RegName[0]) {
- case 'r':
- case 'f':
- case 'q': // for QPX
- case 'v':
- if (RegName[1] == 's')
- return RegName + 2;
- return RegName + 1;
- case 'c': if (RegName[1] == 'r') return RegName + 2;
- }
-
- return RegName;
-}
-
void PPCAsmPrinter::printOperand(const MachineInstr *MI, unsigned OpNo,
raw_ostream &O) {
const DataLayout &DL = getDataLayout();
@@ -182,27 +165,15 @@
switch (MO.getType()) {
case MachineOperand::MO_Register: {
- unsigned Reg = MO.getReg();
+ unsigned Reg = PPCInstrInfo::getRegNumForOperand(MI->getDesc(),
+ MO.getReg(), OpNo);
- // There are VSX instructions that use VSX register numbering (vs0 - vs63)
- // as well as those that use VMX register numbering (v0 - v31 which
- // correspond to vs32 - vs63). If we have an instruction that uses VSX
- // numbering, we need to convert the VMX registers to VSX registers.
- // Namely, we print 32-63 when the instruction operates on one of the
- // VMX registers.
- // (Please synchronize with PPCInstPrinter::printOperand)
- if (MI->getDesc().TSFlags & PPCII::UseVSXReg) {
- if (PPCInstrInfo::isVRRegister(Reg))
- Reg = PPC::VSX32 + (Reg - PPC::V0);
- else if (PPCInstrInfo::isVFRegister(Reg))
- Reg = PPC::VSX32 + (Reg - PPC::VF0);
- }
const char *RegName = PPCInstPrinter::getRegisterName(Reg);
// Linux assembler (Others?) does not take register mnemonics.
// FIXME - What about special registers used in mfspr/mtspr?
if (!Subtarget->isDarwin())
- RegName = stripRegisterPrefix(RegName);
+ RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
O << RegName;
return;
}
@@ -291,7 +262,7 @@
Reg = PPC::VSX32 + (Reg - PPC::VF0);
const char *RegName;
RegName = PPCInstPrinter::getRegisterName(Reg);
- RegName = stripRegisterPrefix(RegName);
+ RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
O << RegName;
return false;
}
@@ -318,7 +289,7 @@
{
const char *RegName = "r0";
if (!Subtarget->isDarwin())
- RegName = stripRegisterPrefix(RegName);
+ RegName = PPCRegisterInfo::stripRegisterPrefix(RegName);
O << RegName << ", ";
printOperand(MI, OpNo, O);
return false;
diff --git a/llvm/lib/Target/PowerPC/PPCInstrInfo.h b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
index a8549e3..42e4333 100644
--- a/llvm/lib/Target/PowerPC/PPCInstrInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCInstrInfo.h
@@ -405,6 +405,25 @@
void replaceInstrWithLI(MachineInstr &MI, const LoadImmediateInfo &LII) const;
bool instrHasImmForm(const MachineInstr &MI, ImmInstrInfo &III) const;
+
+ /// getRegNumForOperand - some operands use different numbering schemes
+ /// for the same registers. For example, a VSX instruction may have any of
+ /// vs0-vs63 allocated whereas an Altivec instruction could only have
+ /// vs32-vs63 allocated (numbered as v0-v31). This function returns the actual
+ /// register number needed for the opcode/operand number combination.
+ /// The operand number argument will be useful when we need to extend this
+ /// to instructions that use both Altivec and VSX numbering (for different
+ /// operands).
+ static unsigned getRegNumForOperand(const MCInstrDesc &Desc, unsigned Reg,
+ unsigned OpNo) {
+ if (Desc.TSFlags & PPCII::UseVSXReg) {
+ if (isVRRegister(Reg))
+ Reg = PPC::VSX32 + (Reg - PPC::V0);
+ else if (isVFRegister(Reg))
+ Reg = PPC::VSX32 + (Reg - PPC::VF0);
+ }
+ return Reg;
+ }
};
}
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
index 91a98ee..3534058 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.h
@@ -141,6 +141,23 @@
// Base pointer (stack realignment) support.
unsigned getBaseRegister(const MachineFunction &MF) const;
bool hasBasePointer(const MachineFunction &MF) const;
+
+ /// stripRegisterPrefix - This method strips the character prefix from a
+ /// register name so that only the number is left. Used by for linux asm.
+ static const char *stripRegisterPrefix(const char *RegName) {
+ switch (RegName[0]) {
+ case 'r':
+ case 'f':
+ case 'q': // for QPX
+ case 'v':
+ if (RegName[1] == 's')
+ return RegName + 2;
+ return RegName + 1;
+ case 'c': if (RegName[1] == 'r') return RegName + 2;
+ }
+
+ return RegName;
+ }
};
} // end namespace llvm
diff --git a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
index 0e641cf..d0d29b6 100644
--- a/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
+++ b/llvm/lib/Target/PowerPC/PPCRegisterInfo.td
@@ -85,6 +85,12 @@
let SubRegIndices = [sub_64];
}
+// VSXReg - One of the VSX registers in the range vs32-vs63 with numbering
+// and encoding to match.
+class VSXReg<bits<6> num, string n> : PPCReg<n> {
+ let HWEncoding{5-0} = num;
+}
+
// CR - One of the 8 4-bit condition registers
class CR<bits<3> num, string n, list<Register> subregs> : PPCReg<n> {
let HWEncoding{2-0} = num;
@@ -148,7 +154,7 @@
// Dummy VSX registers, this defines string: "vs32"-"vs63", and is only used for
// asm printing.
foreach Index = 32-63 in {
- def VSX#Index : PPCReg<"vs"#Index>;
+ def VSX#Index : VSXReg<Index, "vs"#Index>;
}
// The reprsentation of r0 when treated as the constant 0.