- ``K``: An immediate signed 16-bit integer.
- ``L``: An immediate signed 20-bit integer.
- ``M``: An immediate integer 0x7fffffff.
-- ``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.
+- ``Q``: A memory address operand with a base address and a 12-bit immediate
+ unsigned displacement.
+- ``R``: A memory address operand with a base address, a 12-bit immediate
+ unsigned displacement, and an index register.
+- ``S``: A memory address operand with a base address and a 20-bit immediate
+ signed displacement.
+- ``T``: A memory address operand with a base address, a 20-bit immediate
+ signed displacement, and an index register.
- ``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).
--
-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.
-
---
-
If an inline asm ties an i32 "r" result to an i64 input, the input
will be treated as an i32, leaving the upper bits uninitialised.
For example:
SelectInlineAsmMemoryOperand(const SDValue &Op,
unsigned ConstraintID,
std::vector<SDValue> &OutOps) {
+ SystemZAddressingMode::AddrForm Form;
+ SystemZAddressingMode::DispRange DispRange;
SDValue Base, Disp, Index;
switch(ConstraintID) {
llvm_unreachable("Unexpected asm memory constraint");
case InlineAsm::Constraint_i:
case InlineAsm::Constraint_Q:
+ // Accept an address with a short displacement, but no index.
+ Form = SystemZAddressingMode::FormBD;
+ DispRange = SystemZAddressingMode::Disp12Only;
+ break;
case InlineAsm::Constraint_R:
- // Accept addresses with short displacements, which are compatible
- // 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)) {
- OutOps.push_back(Base);
- OutOps.push_back(Disp);
- OutOps.push_back(Index);
- return false;
- }
+ // Accept an address with a short displacement and an index.
+ Form = SystemZAddressingMode::FormBDXNormal;
+ DispRange = SystemZAddressingMode::Disp12Only;
break;
case InlineAsm::Constraint_S:
+ // Accept an address with a long displacement, but no index.
+ Form = SystemZAddressingMode::FormBD;
+ DispRange = SystemZAddressingMode::Disp20Only;
+ break;
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;
- }
+ // Accept an address with a long displacement and an index.
+ // m works the same as T, as this is the most general case.
+ Form = SystemZAddressingMode::FormBDXNormal;
+ DispRange = SystemZAddressingMode::Disp20Only;
break;
}
+
+ if (selectBDXAddr(Form, DispRange, Op, Base, Disp, Index)) {
+ OutOps.push_back(Base);
+ OutOps.push_back(Disp);
+ OutOps.push_back(Index);
+ return false;
+ }
+
return true;
}
ret void
}
-; FIXME: at the moment the precise constraint is not passed down to
-; target code, so we must conservatively treat "R" as "Q".
+; Check that indices are allowed
+define void @f5(i64 %base, i64 %index) {
+; CHECK-LABEL: f5:
+; CHECK: blah 0(%r3,%r2)
+; CHECK: br %r14
+ %add = add i64 %base, %index
+ %addr = inttoptr i64 %add to i64 *
+ call void asm "blah $0", "=*R" (i64 *%addr)
+ ret void
+}
+
+; Check that indices and displacements are allowed simultaneously
+define void @f6(i64 %base, i64 %index) {
+; CHECK-LABEL: f6:
+; CHECK: blah 4095(%r3,%r2)
+; CHECK: br %r14
+ %add = add i64 %base, 4095
+ %addi = add i64 %add, %index
+ %addr = inttoptr i64 %addi to i64 *
+ call void asm "blah $0", "=*R" (i64 *%addr)
+ ret void
+}
+
+; Check that LAY is used if there is an index but the displacement is too large
+define void @f7(i64 %base, i64 %index) {
+; CHECK-LABEL: f7:
+; CHECK: lay %r0, 4096(%r3,%r2)
+; CHECK: blah 0(%r0)
+; CHECK: br %r14
+ %add = add i64 %base, 4096
+ %addi = add i64 %add, %index
+ %addr = inttoptr i64 %addi to i64 *
+ call void asm "blah $0", "=*R" (i64 *%addr)
+ ret void
+}
;
; 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 -524288(%r2)
+; CHECK: br %r14
+ %add = add i64 %base, -524288
+ %addr = inttoptr i64 %add to i64 *
+ call void asm "blah $0", "=*T" (i64 *%addr)
+ ret void
+}
+
+; Check the next lowest byte.
+define void @f2(i64 %base) {
+; CHECK-LABEL: f2:
+; CHECK: agfi %r2, -524289
; CHECK: blah 0(%r2)
; CHECK: br %r14
- %addr = inttoptr i64 %base to i64 *
+ %add = add i64 %base, -524289
+ %addr = inttoptr i64 %add to i64 *
call void asm "blah $0", "=*T" (i64 *%addr)
ret void
}
-; FIXME: at the moment the precise constraint is not passed down to
-; target code, so we must conservatively treat "T" as "S".
+; 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", "=*T" (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", "=*T" (i64 *%addr)
+ ret void
+}
+
+; Check that indices are allowed
+define void @f5(i64 %base, i64 %index) {
+; CHECK-LABEL: f5:
+; CHECK: blah 0(%r3,%r2)
+; CHECK: br %r14
+ %add = add i64 %base, %index
+ %addr = inttoptr i64 %add to i64 *
+ call void asm "blah $0", "=*T" (i64 *%addr)
+ ret void
+}
+
+; Check that indices and displacements are allowed simultaneously
+define void @f6(i64 %base, i64 %index) {
+; CHECK-LABEL: f6:
+; CHECK: blah 524287(%r3,%r2)
+; CHECK: br %r14
+ %add = add i64 %base, 524287
+ %addi = add i64 %add, %index
+ %addr = inttoptr i64 %addi to i64 *
+ call void asm "blah $0", "=*T" (i64 *%addr)
+ ret void
+}
call void asm "blah $0", "=*m" (i64 *%addr)
ret void
}
-
-; FIXME: at the moment the precise constraint is not passed down to
-; target code, so we must conservatively treat "m" as "S".