diff --git a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp --- a/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp +++ b/llvm/lib/Target/RISCV/RISCVAsmPrinter.cpp @@ -181,13 +181,18 @@ if (ExtraCode) return AsmPrinter::PrintAsmMemoryOperand(MI, OpNo, ExtraCode, OS); - const MachineOperand &MO = MI->getOperand(OpNo); - // For now, we only support register memory operands in registers and - // assume there is no addend - if (!MO.isReg()) + const MachineOperand &AddrReg = MI->getOperand(OpNo); + assert(MI->getNumOperands() > OpNo + 1 && "Expected additional operand"); + const MachineOperand &DispImm = MI->getOperand(OpNo + 1); + // All memory operands should have a register and an immediate operand (see + // RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand). + if (!AddrReg.isReg()) + return true; + if (!DispImm.isImm()) return true; - OS << "0(" << RISCVInstPrinter::getRegisterName(MO.getReg()) << ")"; + OS << DispImm.getImm() << "(" + << RISCVInstPrinter::getRegisterName(AddrReg.getReg()) << ")"; return false; } diff --git a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp --- a/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ b/llvm/lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -2115,14 +2115,22 @@ bool RISCVDAGToDAGISel::SelectInlineAsmMemoryOperand( const SDValue &Op, unsigned ConstraintID, std::vector &OutOps) { + // Always produce a register and immediate operand, as expected by + // RISCVAsmPrinter::PrintAsmMemoryOperand. switch (ConstraintID) { - case InlineAsm::Constraint_m: - // We just support simple memory operands that have a single address - // operand and need no special handling. - OutOps.push_back(Op); + case InlineAsm::Constraint_m: { + SDValue Op0, Op1; + bool Found = SelectAddrRegImm(Op, Op0, Op1); + assert(Found && "SelectAddrRegImm should always succeed"); + (void)Found; + OutOps.push_back(Op0); + OutOps.push_back(Op1); return false; + } case InlineAsm::Constraint_A: OutOps.push_back(Op); + OutOps.push_back( + CurDAG->getTargetConstant(0, SDLoc(Op), Subtarget->getXLenVT())); return false; default: break; diff --git a/llvm/test/CodeGen/RISCV/inline-asm.ll b/llvm/test/CodeGen/RISCV/inline-asm.ll --- a/llvm/test/CodeGen/RISCV/inline-asm.ll +++ b/llvm/test/CodeGen/RISCV/inline-asm.ll @@ -85,17 +85,15 @@ define i32 @constraint_m_with_offset(ptr %a) nounwind { ; RV32I-LABEL: constraint_m_with_offset: ; RV32I: # %bb.0: -; RV32I-NEXT: addi a0, a0, 4 ; RV32I-NEXT: #APP -; RV32I-NEXT: lw a0, 0(a0) +; RV32I-NEXT: lw a0, 4(a0) ; RV32I-NEXT: #NO_APP ; RV32I-NEXT: ret ; ; RV64I-LABEL: constraint_m_with_offset: ; RV64I: # %bb.0: -; RV64I-NEXT: addi a0, a0, 4 ; RV64I-NEXT: #APP -; RV64I-NEXT: lw a0, 0(a0) +; RV64I-NEXT: lw a0, 4(a0) ; RV64I-NEXT: #NO_APP ; RV64I-NEXT: ret %1 = getelementptr i32, ptr %a, i32 1