Index: include/llvm/IR/InlineAsm.h =================================================================== --- include/llvm/IR/InlineAsm.h +++ include/llvm/IR/InlineAsm.h @@ -244,6 +244,7 @@ Constraint_m, Constraint_o, Constraint_v, + Constraint_A, Constraint_Q, Constraint_R, Constraint_S, Index: lib/Target/RISCV/RISCVISelDAGToDAG.cpp =================================================================== --- lib/Target/RISCV/RISCVISelDAGToDAG.cpp +++ lib/Target/RISCV/RISCVISelDAGToDAG.cpp @@ -179,6 +179,9 @@ // operand and need no special handling. OutOps.push_back(Op); return false; + case InlineAsm::Constraint_A: + OutOps.push_back(Op); + return false; default: break; } Index: lib/Target/RISCV/RISCVISelLowering.h =================================================================== --- lib/Target/RISCV/RISCVISelLowering.h +++ lib/Target/RISCV/RISCVISelLowering.h @@ -92,6 +92,11 @@ // This method returns the name of a target specific DAG node. const char *getTargetNodeName(unsigned Opcode) const override; + // Get the type of an inline asm constraint. + ConstraintType getConstraintType(StringRef Constraint) const override; + + unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override; + std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; Index: lib/Target/RISCV/RISCVISelLowering.cpp =================================================================== --- lib/Target/RISCV/RISCVISelLowering.cpp +++ lib/Target/RISCV/RISCVISelLowering.cpp @@ -2397,6 +2397,21 @@ return nullptr; } +RISCVTargetLowering::ConstraintType +RISCVTargetLowering::getConstraintType(StringRef Constraint) const { + // Currently only support length 1 constraints. + if (Constraint.size() == 1) { + switch (Constraint[0]) { + case 'A': + return C_Memory; + default: + break; + } + } + + return TargetLowering::getConstraintType(Constraint); +} + std::pair RISCVTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, @@ -2415,6 +2430,21 @@ return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); } +unsigned +RISCVTargetLowering::getInlineAsmMemConstraint(StringRef ConstraintCode) const { + // Currently only support length 1 constraints. + if (ConstraintCode.size() == 1) { + switch (ConstraintCode[0]) { + case 'A': + return InlineAsm::Constraint_A; + default: + break; + } + } + + return TargetLowering::getInlineAsmMemConstraint(ConstraintCode); +} + void RISCVTargetLowering::LowerAsmOperandForConstraint( SDValue Op, std::string &Constraint, std::vector &Ops, SelectionDAG &DAG) const { Index: test/CodeGen/RISCV/inline-asm.ll =================================================================== --- test/CodeGen/RISCV/inline-asm.ll +++ test/CodeGen/RISCV/inline-asm.ll @@ -150,6 +150,31 @@ ret void } +define void @constraint_A(i8* %a) nounwind { +; RV32I-LABEL: constraint_A: +; RV32I: # %bb.0: +; RV32I-NEXT: #APP +; RV32I-NEXT: sb s0, 0(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: #APP +; RV32I-NEXT: lb s1, 0(a0) +; RV32I-NEXT: #NO_APP +; RV32I-NEXT: ret +; +; RV64I-LABEL: constraint_A: +; RV64I: # %bb.0: +; RV64I-NEXT: #APP +; RV64I-NEXT: sb s0, 0(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: #APP +; RV64I-NEXT: lb s1, 0(a0) +; RV64I-NEXT: #NO_APP +; RV64I-NEXT: ret + tail call void asm sideeffect "sb s0, $0", "*A"(i8* %a) + tail call void asm sideeffect "lb s1, $0", "*A"(i8* %a) + ret void +} + define i32 @modifier_z_zero(i32 %a) nounwind { ; RV32I-LABEL: modifier_z_zero: ; RV32I: # %bb.0: