summaryrefslogtreecommitdiffstats
path: root/llvm/lib/Target/SystemZ
diff options
context:
space:
mode:
authorRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-07-12 09:08:12 +0000
committerRichard Sandiford <rsandifo@linux.vnet.ibm.com>2013-07-12 09:08:12 +0000
commitb820405b59b12fd9eff51957118bdddd6519b8a4 (patch)
tree35bed6f94339cdef6b87d1765e707e47a2ca9c9a /llvm/lib/Target/SystemZ
parent3f0edc29036dfbd780c42fbe074048b782dd47c9 (diff)
downloadbcm5719-llvm-b820405b59b12fd9eff51957118bdddd6519b8a4.tar.gz
bcm5719-llvm-b820405b59b12fd9eff51957118bdddd6519b8a4.zip
[SystemZ] Fix parsing of inline asm registers
GPR and FPR constraints like "{r2}" and "{f2}" weren't handled correctly because the name-to-regno mapping depends on the value type and (because of that) the internal names in RegStrings are not the same as the AsmName. CC constraints like "{cc}" didn't work either because there was no associated register class. llvm-svn: 186148
Diffstat (limited to 'llvm/lib/Target/SystemZ')
-rw-r--r--llvm/lib/Target/SystemZ/SystemZISelLowering.cpp42
-rw-r--r--llvm/lib/Target/SystemZ/SystemZMCInstLower.cpp9
-rw-r--r--llvm/lib/Target/SystemZ/SystemZMCInstLower.h2
-rw-r--r--llvm/lib/Target/SystemZ/SystemZRegisterInfo.td4
4 files changed, 49 insertions, 8 deletions
diff --git a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
index d344134b24f..a317f0c3f68 100644
--- a/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZISelLowering.cpp
@@ -386,6 +386,22 @@ getSingleConstraintMatchWeight(AsmOperandInfo &info,
return weight;
}
+// Parse a "{tNNN}" register constraint for which the register type "t"
+// has already been verified. MC is the class associated with "t" and
+// Map maps 0-based register numbers to LLVM register numbers.
+static std::pair<unsigned, const TargetRegisterClass *>
+parseRegisterNumber(const std::string &Constraint,
+ const TargetRegisterClass *RC, const unsigned *Map) {
+ assert(*(Constraint.end()-1) == '}' && "Missing '}'");
+ if (isdigit(Constraint[2])) {
+ std::string Suffix(Constraint.data() + 2, Constraint.size() - 2);
+ unsigned Index = atoi(Suffix.c_str());
+ if (Index < 16 && Map[Index])
+ return std::make_pair(Map[Index], RC);
+ }
+ return std::make_pair(0u, static_cast<TargetRegisterClass*>(0));
+}
+
std::pair<unsigned, const TargetRegisterClass *> SystemZTargetLowering::
getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const {
if (Constraint.size() == 1) {
@@ -415,6 +431,32 @@ getRegForInlineAsmConstraint(const std::string &Constraint, MVT VT) const {
return std::make_pair(0U, &SystemZ::FP32BitRegClass);
}
}
+ if (Constraint[0] == '{') {
+ // We need to override the default register parsing for GPRs and FPRs
+ // because the interpretation depends on VT. The internal names of
+ // the registers are also different from the external names
+ // (F0D and F0S instead of F0, etc.).
+ if (Constraint[1] == 'r') {
+ if (VT == MVT::i32)
+ return parseRegisterNumber(Constraint, &SystemZ::GR32BitRegClass,
+ SystemZMC::GR32Regs);
+ if (VT == MVT::i128)
+ return parseRegisterNumber(Constraint, &SystemZ::GR128BitRegClass,
+ SystemZMC::GR128Regs);
+ return parseRegisterNumber(Constraint, &SystemZ::GR64BitRegClass,
+ SystemZMC::GR64Regs);
+ }
+ if (Constraint[1] == 'f') {
+ if (VT == MVT::f32)
+ return parseRegisterNumber(Constraint, &SystemZ::FP32BitRegClass,
+ SystemZMC::FP32Regs);
+ if (VT == MVT::f128)
+ return parseRegisterNumber(Constraint, &SystemZ::FP128BitRegClass,
+ SystemZMC::FP128Regs);
+ return parseRegisterNumber(Constraint, &SystemZ::FP64BitRegClass,
+ SystemZMC::FP64Regs);
+ }
+ }
return TargetLowering::getRegForInlineAsmConstraint(Constraint, VT);
}
diff --git a/llvm/lib/Target/SystemZ/SystemZMCInstLower.cpp b/llvm/lib/Target/SystemZ/SystemZMCInstLower.cpp
index fd3f867015c..432a0d30b62 100644
--- a/llvm/lib/Target/SystemZ/SystemZMCInstLower.cpp
+++ b/llvm/lib/Target/SystemZ/SystemZMCInstLower.cpp
@@ -57,9 +57,6 @@ MCOperand SystemZMCInstLower::lowerOperand(const MachineOperand &MO) const {
llvm_unreachable("unknown operand type");
case MachineOperand::MO_Register:
- // Ignore all implicit register operands.
- if (MO.isImplicit())
- return MCOperand();
return MCOperand::CreateReg(MO.getReg());
case MachineOperand::MO_Immediate:
@@ -104,8 +101,8 @@ void SystemZMCInstLower::lower(const MachineInstr *MI, MCInst &OutMI) const {
OutMI.setOpcode(Opcode);
for (unsigned I = 0, E = MI->getNumOperands(); I != E; ++I) {
const MachineOperand &MO = MI->getOperand(I);
- MCOperand MCOp = lowerOperand(MO);
- if (MCOp.isValid())
- OutMI.addOperand(MCOp);
+ // Ignore all implicit register operands.
+ if (!MO.isReg() || !MO.isImplicit())
+ OutMI.addOperand(lowerOperand(MO));
}
}
diff --git a/llvm/lib/Target/SystemZ/SystemZMCInstLower.h b/llvm/lib/Target/SystemZ/SystemZMCInstLower.h
index afa72f38add..db5bdb05ab2 100644
--- a/llvm/lib/Target/SystemZ/SystemZMCInstLower.h
+++ b/llvm/lib/Target/SystemZ/SystemZMCInstLower.h
@@ -35,7 +35,7 @@ public:
// Lower MachineInstr MI to MCInst OutMI.
void lower(const MachineInstr *MI, MCInst &OutMI) const;
- // Return an MCOperand for MO. Return an empty operand if MO is implicit.
+ // Return an MCOperand for MO.
MCOperand lowerOperand(const MachineOperand& MO) const;
// Return an MCOperand for MO, given that it equals Symbol + Offset.
diff --git a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
index d65553e7500..ffffe721cb7 100644
--- a/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
+++ b/llvm/lib/Target/SystemZ/SystemZRegisterInfo.td
@@ -147,5 +147,7 @@ defm FP128 : SystemZRegClass<"FP128", f128, 128, (add F0Q, F1Q, F4Q, F5Q,
// Other registers
//===----------------------------------------------------------------------===//
-// The 2-bit condition code field of the PSW.
+// The 2-bit condition code field of the PSW. Every register named in an
+// inline asm needs a class associated with it.
def CC : SystemZReg<"cc">;
+def CCRegs : RegisterClass<"SystemZ", [i32], 32, (add CC)>;
OpenPOWER on IntegriCloud