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:
parent
6f243c6798
commit
3a7df35715
@ -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).
|
||||
|
@ -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.
|
||||
|
||||
--
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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".
|
||||
|
@ -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".
|
||||
|
Loading…
Reference in New Issue
Block a user