From d32a2d30cbe10cb966d0d98819a657eb209d1b47 Mon Sep 17 00:00:00 2001 From: Simon Dardis Date: Mon, 18 Jul 2016 13:17:31 +0000 Subject: [inlineasm] Propagate operand constraints to the backend When SelectionDAGISel transforms a node representing an inline asm block, memory constraint information is not preserved. This can cause constraints to be broken when a memory offset is of the form: offset + frame index when the frame is resolved. By propagating the constraints all the way to the backend, targets can enforce memory operands of inline assembly to conform to their constraints. For MIPSR6, some instructions had their offsets reduced to 9 bits from 16 bits such as ll/sc. This becomes problematic when using inline assembly to perform atomic operations, as an offset can generated that is too big to encode in the instruction. Reviewers: dsanders, vkalintris Differential Review: https://reviews.llvm.org/D21615 llvm-svn: 275786 --- llvm/lib/CodeGen/MachineInstr.cpp | 35 +++++++++++++++++++++++++++++++++-- 1 file changed, 33 insertions(+), 2 deletions(-) (limited to 'llvm/lib/CodeGen/MachineInstr.cpp') diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index ead239f604d..3cdf8d2941d 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -1201,7 +1201,10 @@ MachineInstr::getRegClassConstraint(unsigned OpIdx, unsigned Flag = getOperand(FlagIdx).getImm(); unsigned RCID; - if (InlineAsm::hasRegClassConstraint(Flag, RCID)) + if ((InlineAsm::getKind(Flag) == InlineAsm::Kind_RegUse || + InlineAsm::getKind(Flag) == InlineAsm::Kind_RegDef || + InlineAsm::getKind(Flag) == InlineAsm::Kind_RegDefEarlyClobber) && + InlineAsm::hasRegClassConstraint(Flag, RCID)) return TRI->getRegClass(RCID); // Assume that all registers in a memory operand are pointers. @@ -1826,13 +1829,41 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST, } unsigned RCID = 0; - if (InlineAsm::hasRegClassConstraint(Flag, RCID)) { + if (!InlineAsm::isImmKind(Flag) && !InlineAsm::isMemKind(Flag) && + InlineAsm::hasRegClassConstraint(Flag, RCID)) { if (TRI) { OS << ':' << TRI->getRegClassName(TRI->getRegClass(RCID)); } else OS << ":RC" << RCID; } + if (InlineAsm::isMemKind(Flag)) { + unsigned MCID = InlineAsm::getMemoryConstraintID(Flag); + switch (MCID) { + case InlineAsm::Constraint_es: OS << ":es"; break; + case InlineAsm::Constraint_i: OS << ":i"; break; + case InlineAsm::Constraint_m: OS << ":m"; break; + case InlineAsm::Constraint_o: OS << ":o"; break; + case InlineAsm::Constraint_v: OS << ":v"; break; + case InlineAsm::Constraint_Q: OS << ":Q"; break; + case InlineAsm::Constraint_R: OS << ":R"; break; + case InlineAsm::Constraint_S: OS << ":S"; break; + case InlineAsm::Constraint_T: OS << ":T"; break; + case InlineAsm::Constraint_Um: OS << ":Um"; break; + case InlineAsm::Constraint_Un: OS << ":Un"; break; + case InlineAsm::Constraint_Uq: OS << ":Uq"; break; + case InlineAsm::Constraint_Us: OS << ":Us"; break; + case InlineAsm::Constraint_Ut: OS << ":Ut"; break; + case InlineAsm::Constraint_Uv: OS << ":Uv"; break; + case InlineAsm::Constraint_Uy: OS << ":Uy"; break; + case InlineAsm::Constraint_X: OS << ":X"; break; + case InlineAsm::Constraint_Z: OS << ":Z"; break; + case InlineAsm::Constraint_ZC: OS << ":ZC"; break; + case InlineAsm::Constraint_Zy: OS << ":Zy"; break; + default: OS << ":?"; break; + } + } + unsigned TiedTo = 0; if (InlineAsm::isUseOperandTiedToDef(Flag, TiedTo)) OS << " tiedto:$" << TiedTo; -- cgit v1.2.3