Index: docs/LangRef.rst =================================================================== --- docs/LangRef.rst +++ docs/LangRef.rst @@ -3590,8 +3590,10 @@ - ``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). Index: lib/Target/SystemZ/README.txt =================================================================== --- lib/Target/SystemZ/README.txt +++ lib/Target/SystemZ/README.txt @@ -7,10 +7,9 @@ -- -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. -- Index: lib/Target/SystemZ/SystemZISelDAGToDAG.cpp =================================================================== --- lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -1322,18 +1322,17 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector &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 @@ 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; } Index: test/CodeGen/SystemZ/asm-03.ll =================================================================== --- test/CodeGen/SystemZ/asm-03.ll +++ test/CodeGen/SystemZ/asm-03.ll @@ -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 -524288(%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 +} + +; 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", "=*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 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 +} Index: test/CodeGen/SystemZ/asm-04.ll =================================================================== --- test/CodeGen/SystemZ/asm-04.ll +++ test/CodeGen/SystemZ/asm-04.ll @@ -13,4 +13,4 @@ } ; 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". Index: test/CodeGen/SystemZ/asm-05.ll =================================================================== --- test/CodeGen/SystemZ/asm-05.ll +++ test/CodeGen/SystemZ/asm-05.ll @@ -12,4 +12,4 @@ } ; 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".