Index: llvm/docs/LangRef.rst =================================================================== --- llvm/docs/LangRef.rst +++ llvm/docs/LangRef.rst @@ -4050,7 +4050,7 @@ - ``r``: A 32 or 64-bit integer register. - ``[0-9]v``: The 32-bit VGPR register, number 0-9. - ``[0-9]s``: The 32-bit SGPR register, number 0-9. - +- ``A``: An immediate integer in the range from -16 to 64. All ARM modes: Index: llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp =================================================================== --- llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ llvm/lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -1311,6 +1311,9 @@ AMDGPUInstPrinter::printRegOperand(MO.getReg(), O, *MF->getSubtarget().getRegisterInfo()); return false; + } else if (MO.isImm()) { + O << MO.getImm(); + return false; } return true; Index: llvm/lib/Target/AMDGPU/SIISelLowering.h =================================================================== --- llvm/lib/Target/AMDGPU/SIISelLowering.h +++ llvm/lib/Target/AMDGPU/SIISelLowering.h @@ -383,6 +383,10 @@ getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, StringRef Constraint, MVT VT) const override; ConstraintType getConstraintType(StringRef Constraint) const override; + void LowerAsmOperandForConstraint(SDValue Op, + std::string &Constraint, + std::vector &Ops, + SelectionDAG &DAG) const override; SDValue copyToM0(SelectionDAG &DAG, SDValue Chain, const SDLoc &DL, SDValue V) const; Index: llvm/lib/Target/AMDGPU/SIISelLowering.cpp =================================================================== --- llvm/lib/Target/AMDGPU/SIISelLowering.cpp +++ llvm/lib/Target/AMDGPU/SIISelLowering.cpp @@ -10707,11 +10707,30 @@ case 'v': case 'a': return C_RegisterClass; + case 'A': + return C_Immediate; } } return TargetLowering::getConstraintType(Constraint); } +void SITargetLowering::LowerAsmOperandForConstraint(SDValue Op, + std::string &Constraint, + std::vector&Ops, + SelectionDAG &DAG) const { + if (Constraint.length() == 1 && Constraint[0] == 'A') { + if (ConstantSDNode *C = dyn_cast(Op)) { + auto Val = C->getSExtValue(); + if (-16 <= Val && Val <= 64) { + auto Res = DAG.getTargetConstant(Val, SDLoc(Op), Op.getValueType()); + Ops.push_back(Res); + } + } + } else { + TargetLowering::LowerAsmOperandForConstraint(Op, Constraint, Ops, DAG); + } +} + // Figure out which registers should be reserved for stack access. Only after // the function is legalized do we know all of the non-spill stack objects or if // calls are present. Index: llvm/test/CodeGen/AMDGPU/inline-constraints.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/inline-constraints.ll +++ llvm/test/CodeGen/AMDGPU/inline-constraints.ll @@ -74,3 +74,24 @@ tail call void asm sideeffect "; use $0", "s"(double 1.0) ret void } + +; GCN-LABEL: {{^}}inline_A_constraint_1: +; GCN: v_mov_b32 {{v[0-9]+}}, -16 +define i32 @inline_A_constraint_1() { + %v0 = tail call i32 asm "v_mov_b32 $0, $1", "=v,A"(i32 -16) + ret i32 %v0 +} + +; GCN-LABEL: {{^}}inline_A_constraint_2: +; GCN: v_mov_b32 {{v[0-9]+}}, -16 +define i32 @inline_A_constraint_2() { + %v0 = tail call i32 asm "v_mov_b32 $0, $1", "=v,A"(i64 -16) + ret i32 %v0 +} + +; GCN-LABEL: {{^}}inline_A_constraint_3: +; GCN: v_mov_b32 {{v[0-9]+}}, 64 +define i32 @inline_A_constraint_3() { + %v0 = tail call i32 asm "v_mov_b32 $0, $1", "=v,A"(i16 64) + ret i32 %v0 +} Index: llvm/test/CodeGen/AMDGPU/inlineasm-illegal-type.ll =================================================================== --- llvm/test/CodeGen/AMDGPU/inlineasm-illegal-type.ll +++ llvm/test/CodeGen/AMDGPU/inlineasm-illegal-type.ll @@ -59,3 +59,21 @@ ; tail call void asm sideeffect "; use $0", "s"(i3 %v) ; ret void ; } + +; GCN: error: value out of range for constraint 'A' +define i32 @inline_A_constraint_1() { + %v0 = tail call i32 asm "v_mov_b32 $0, $1", "=v,A"(i32 65) + ret i32 %v0 +} + +; GCN: error: value out of range for constraint 'A' +define i32 @inline_A_constraint_2() { + %v0 = tail call i32 asm "v_mov_b32 $0, $1", "=v,A"(i32 -17) + ret i32 %v0 +} + +; GCN: error: constraint 'A' expects an integer constant expression +define i32 @inline_A_constraint_3(i32 %x) { + %v0 = tail call i32 asm "v_mov_b32 $0, $1", "=v,A"(i32 %x) + ret i32 %v0 +}