diff options
| author | Simon Dardis <simon.dardis@imgtec.com> | 2016-07-18 13:17:31 +0000 |
|---|---|---|
| committer | Simon Dardis <simon.dardis@imgtec.com> | 2016-07-18 13:17:31 +0000 |
| commit | d32a2d30cbe10cb966d0d98819a657eb209d1b47 (patch) | |
| tree | 62023d4a385b771a72ac2bcb4464be96910bb71e /llvm/lib/Target/Mips | |
| parent | de69d406862c7978f35bdbcb0bd10a510e77560c (diff) | |
| download | bcm5719-llvm-d32a2d30cbe10cb966d0d98819a657eb209d1b47.tar.gz bcm5719-llvm-d32a2d30cbe10cb966d0d98819a657eb209d1b47.zip | |
[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
Diffstat (limited to 'llvm/lib/Target/Mips')
| -rw-r--r-- | llvm/lib/Target/Mips/MipsSERegisterInfo.cpp | 51 |
1 files changed, 48 insertions, 3 deletions
diff --git a/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp b/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp index b43993cace5..e3431cd118a 100644 --- a/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp +++ b/llvm/lib/Target/Mips/MipsSERegisterInfo.cpp @@ -60,10 +60,11 @@ MipsSERegisterInfo::intRegClass(unsigned Size) const { return &Mips::GPR64RegClass; } -/// Get the size of the offset supported by the given load/store. +/// Get the size of the offset supported by the given load/store/inline asm. /// The result includes the effects of any scale factors applied to the /// instruction immediate. -static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) { +static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode, + MachineOperand MO) { switch (Opcode) { case Mips::LD_B: case Mips::ST_B: @@ -77,6 +78,49 @@ static inline unsigned getLoadStoreOffsetSizeInBits(const unsigned Opcode) { case Mips::LD_D: case Mips::ST_D: return 10 + 3 /* scale factor */; + case Mips::LL: + case Mips::LL64: + case Mips::LLD: + case Mips::LLE: + case Mips::SC: + case Mips::SC64: + case Mips::SCD: + case Mips::SCE: + return 16; + case Mips::LLE_MM: + case Mips::LLE_MMR6: + case Mips::LL_MM: + case Mips::SCE_MM: + case Mips::SCE_MMR6: + case Mips::SC_MM: + return 12; + case Mips::LL64_R6: + case Mips::LL_R6: + case Mips::LLD_R6: + case Mips::SC64_R6: + case Mips::SCD_R6: + case Mips::SC_R6: + return 9; + case Mips::INLINEASM: { + unsigned ConstraintID = InlineAsm::getMemoryConstraintID(MO.getImm()); + switch (ConstraintID) { + case InlineAsm::Constraint_ZC: { + const MipsSubtarget &Subtarget = MO.getParent() + ->getParent() + ->getParent() + ->getSubtarget<MipsSubtarget>(); + if (Subtarget.inMicroMipsMode()) + return 12; + + if (Subtarget.hasMips32r6()) + return 9; + + return 16; + } + default: + return 16; + } + } default: return 16; } @@ -166,7 +210,8 @@ void MipsSERegisterInfo::eliminateFI(MachineBasicBlock::iterator II, // Make sure Offset fits within the field available. // For MSA instructions, this is a 10-bit signed immediate (scaled by // element size), otherwise it is a 16-bit signed immediate. - unsigned OffsetBitSize = getLoadStoreOffsetSizeInBits(MI.getOpcode()); + unsigned OffsetBitSize = + getLoadStoreOffsetSizeInBits(MI.getOpcode(), MI.getOperand(OpNo - 1)); unsigned OffsetAlign = getLoadStoreOffsetAlign(MI.getOpcode()); if (OffsetBitSize < 16 && isInt<16>(Offset) && |

