Index: llvm/trunk/docs/LangRef.rst =================================================================== --- llvm/trunk/docs/LangRef.rst +++ llvm/trunk/docs/LangRef.rst @@ -3590,10 +3590,14 @@ - ``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). Index: llvm/trunk/lib/Target/SystemZ/README.txt =================================================================== --- llvm/trunk/lib/Target/SystemZ/README.txt +++ llvm/trunk/lib/Target/SystemZ/README.txt @@ -7,12 +7,6 @@ -- -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: Index: llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp =================================================================== --- llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ llvm/trunk/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -1323,6 +1323,8 @@ SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintID, std::vector &OutOps) { + SystemZAddressingMode::AddrForm Form; + SystemZAddressingMode::DispRange DispRange; SDValue Base, Disp, Index; switch(ConstraintID) { @@ -1330,33 +1332,35 @@ 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; } Index: llvm/trunk/test/CodeGen/SystemZ/asm-02.ll =================================================================== --- llvm/trunk/test/CodeGen/SystemZ/asm-02.ll +++ llvm/trunk/test/CodeGen/SystemZ/asm-02.ll @@ -48,5 +48,38 @@ 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 +} Index: llvm/trunk/test/CodeGen/SystemZ/asm-04.ll =================================================================== --- llvm/trunk/test/CodeGen/SystemZ/asm-04.ll +++ llvm/trunk/test/CodeGen/SystemZ/asm-04.ll @@ -3,14 +3,71 @@ ; ; 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 +} Index: llvm/trunk/test/CodeGen/SystemZ/asm-05.ll =================================================================== --- llvm/trunk/test/CodeGen/SystemZ/asm-05.ll +++ llvm/trunk/test/CodeGen/SystemZ/asm-05.ll @@ -10,6 +10,3 @@ 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".