diff --git a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp --- a/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp +++ b/llvm/lib/Target/AArch64/AArch64ISelDAGToDAG.cpp @@ -369,6 +369,7 @@ default: llvm_unreachable("Unexpected asm memory constraint"); case InlineAsm::Constraint_m: + case InlineAsm::Constraint_o: case InlineAsm::Constraint_Q: // We need to make sure that this one operand does not end up in XZR, thus // require the address to be in a PointerRegClass register. diff --git a/llvm/lib/Target/AArch64/AArch64ISelLowering.h b/llvm/lib/Target/AArch64/AArch64ISelLowering.h --- a/llvm/lib/Target/AArch64/AArch64ISelLowering.h +++ b/llvm/lib/Target/AArch64/AArch64ISelLowering.h @@ -1027,6 +1027,8 @@ unsigned getInlineAsmMemConstraint(StringRef ConstraintCode) const override { if (ConstraintCode == "Q") return InlineAsm::Constraint_Q; + if (ConstraintCode == "o") + return InlineAsm::Constraint_o; // FIXME: clang has code for 'Ump', 'Utf', 'Usa', and 'Ush' but these are // followed by llvm_unreachable so we'll leave them unimplemented in // the backend for now. diff --git a/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll b/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll --- a/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll +++ b/llvm/test/CodeGen/AArch64/arm64-inline-asm.ll @@ -297,3 +297,14 @@ call void asm sideeffect "", "=*r|m,0,~{memory}"(<9 x float>* nonnull %m.addr, <9 x float> %m) ret void } + +; PR49956 +define void @test_o_output_constraint() { +; CHECK-LABEL: test_o_output_constraint +; CHECK: sub sp, sp, #16 +; CHECK: add x[[REG:[0-9]+]], sp, #15 +; CHECK: mov [x[[REG]]], 7 + %b = alloca i8, align 1 + call void asm "mov $0, 7", "=*o"(i8* %b) + ret void +}