1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-11-24 03:33:20 +01:00

[SystemZ] Enable long displacement constraints for inline ASM operands

This enables use of the 'S' constraint for inline ASM operands on
SystemZ, which allows for a memory reference with a signed 20-bit
immediate displacement. This patch includes corresponding documentation
and test case updates.

I've changed the 'T' constraint to match the new behavior for 'S', as
'T' also uses a long displacement (though index constraints are still
not implemented). I also changed 'm' to match the behavior for 'S' as
this will allow for a wider range of displacements for 'm', though
correct me if that's not the right decision.

Author: colpell
Differential Revision: http://reviews.llvm.org/D21097

llvm-svn: 272266
This commit is contained in:
Ulrich Weigand 2016-06-09 15:19:16 +00:00
parent 6f243c6798
commit 3a7df35715
6 changed files with 65 additions and 17 deletions

View File

@ -3590,8 +3590,10 @@ SystemZ:
- ``K``: An immediate signed 16-bit integer.
- ``L``: An immediate signed 20-bit integer.
- ``M``: An immediate integer 0x7fffffff.
- ``Q``, ``R``, ``S``, ``T``: A memory address operand, treated the same as
``m``, at the moment.
- ``Q``, ``R``: A memory address operand with a base address and a 12-bit
immediate unsigned displacement.
- ``S``, ``T``: A memory address operand with a base address and a 20-bit
immediate signed displacement.
- ``r`` or ``d``: A 32, 64, or 128-bit integer register.
- ``a``: A 32, 64, or 128-bit integer address register (excludes R0, which in an
address context evaluates as zero).

View File

@ -7,10 +7,9 @@ for later architectures at some point.
--
SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand() is passed "m" for all
inline asm memory constraints; it doesn't get to see the original constraint.
This means that it must conservatively treat all inline asm constraints
as the most restricted type, "R".
SystemZDAGToDAGISel::SelectInlineAsmMemoryOperand() treats the Q and R
constraints the same, and the S and T constraints the same, because the optional
index is not used.
--

View File

@ -1322,18 +1322,17 @@ bool SystemZDAGToDAGISel::
SelectInlineAsmMemoryOperand(const SDValue &Op,
unsigned ConstraintID,
std::vector<SDValue> &OutOps) {
SDValue Base, Disp, Index;
switch(ConstraintID) {
default:
llvm_unreachable("Unexpected asm memory constraint");
case InlineAsm::Constraint_i:
case InlineAsm::Constraint_m:
case InlineAsm::Constraint_Q:
case InlineAsm::Constraint_R:
case InlineAsm::Constraint_S:
case InlineAsm::Constraint_T:
// Accept addresses with short displacements, which are compatible
// with Q, R, S and T. But keep the index operand for future expansion.
SDValue Base, Disp, Index;
// with Q and R. But keep the index operand for future expansion (e.g. the
// index for R).
if (selectBDXAddr(SystemZAddressingMode::FormBD,
SystemZAddressingMode::Disp12Only,
Op, Base, Disp, Index)) {
@ -1343,6 +1342,20 @@ SelectInlineAsmMemoryOperand(const SDValue &Op,
return false;
}
break;
case InlineAsm::Constraint_S:
case InlineAsm::Constraint_T:
case InlineAsm::Constraint_m:
// Accept addresses with long displacements. As above, keep the index for
// future implementation of index for the T constraint.
if (selectBDXAddr(SystemZAddressingMode::FormBD,
SystemZAddressingMode::Disp20Only,
Op, Base, Disp, Index)) {
OutOps.push_back(Base);
OutOps.push_back(Disp);
OutOps.push_back(Index);
return false;
}
break;
}
return true;
}

View File

@ -3,14 +3,48 @@
;
; RUN: llc < %s -mtriple=s390x-linux-gnu -no-integrated-as | FileCheck %s
; Check the lowest range.
define void @f1(i64 %base) {
; CHECK-LABEL: f1:
; CHECK: blah 0(%r2)
; CHECK: blah -524288(%r2)
; CHECK: br %r14
%addr = inttoptr i64 %base to i64 *
%add = add i64 %base, -524288
%addr = inttoptr i64 %add to i64 *
call void asm "blah $0", "=*S" (i64 *%addr)
ret void
}
; FIXME: at the moment the precise constraint is not passed down to
; target code, so we must conservatively treat "S" as "Q".
; Check the next lowest byte.
define void @f2(i64 %base) {
; CHECK-LABEL: f2:
; CHECK: agfi %r2, -524289
; CHECK: blah 0(%r2)
; CHECK: br %r14
%add = add i64 %base, -524289
%addr = inttoptr i64 %add to i64 *
call void asm "blah $0", "=*S" (i64 *%addr)
ret void
}
; Check the highest range.
define void @f3(i64 %base) {
; CHECK-LABEL: f3:
; CHECK: blah 524287(%r2)
; CHECK: br %r14
%add = add i64 %base, 524287
%addr = inttoptr i64 %add to i64 *
call void asm "blah $0", "=*S" (i64 *%addr)
ret void
}
; Check the next highest byte.
define void @f4(i64 %base) {
; CHECK-LABEL: f4:
; CHECK: agfi %r2, 524288
; CHECK: blah 0(%r2)
; CHECK: br %r14
%add = add i64 %base, 524288
%addr = inttoptr i64 %add to i64 *
call void asm "blah $0", "=*S" (i64 *%addr)
ret void
}

View File

@ -13,4 +13,4 @@ define void @f1(i64 %base) {
}
; FIXME: at the moment the precise constraint is not passed down to
; target code, so we must conservatively treat "T" as "Q".
; target code, so we must conservatively treat "T" as "S".

View File

@ -12,4 +12,4 @@ define void @f1(i64 %base) {
}
; FIXME: at the moment the precise constraint is not passed down to
; target code, so we must conservatively treat "m" as "Q".
; target code, so we must conservatively treat "m" as "S".