Skip to content

Commit

Permalink
[LLVM][AArch64] Add ASM constraints for reduced GPR register ranges. (#…
Browse files Browse the repository at this point in the history
…70970)

[LLVM][AArch64] Add ASM constraints for reduced GPR register ranges.
    
The patch adds the follow ASM constraints:
  Uci => w8-w11/x8-x11
  Ucj => w12-w15/x12-x15
    
These constraints are required for SME load/store instructions
where a reduced set of GPRs are used to specify ZA array vectors.
    
NOTE: GCC has agreed to use the same constraint syntax.
  • Loading branch information
paulwalker-arm committed Nov 3, 2023
1 parent 05a0d94 commit de88371
Show file tree
Hide file tree
Showing 6 changed files with 136 additions and 1 deletion.
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -738,6 +738,8 @@ Arm and AArch64 Support
This affects C++ functions with SVE ACLE parameters. Clang will use the old
manglings if ``-fclang-abi-compat=17`` or lower is specified.

- New AArch64 asm constraints have been added for r8-r11(Uci) and r12-r15(Ucj).

Android Support
^^^^^^^^^^^^^^^

Expand Down
6 changes: 6 additions & 0 deletions clang/lib/Basic/Targets/AArch64.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1306,6 +1306,12 @@ bool AArch64TargetInfo::validateAsmConstraint(
Name += 2;
return true;
}
if (Name[1] == 'c' && (Name[2] == 'i' || Name[2] == 'j')) {
// Gpr registers ("Uci"=w8-11, "Ucj"=w12-15)
Info.setAllowsRegister();
Name += 2;
return true;
}
// Ump: A memory address suitable for ldp/stp in SI, DI, SF and DF modes.
// Utf: A memory address suitable for ldp/stp in TF mode.
// Usa: An absolute symbolic address.
Expand Down
15 changes: 15 additions & 0 deletions clang/test/CodeGen/aarch64-inline-asm.c
Original file line number Diff line number Diff line change
Expand Up @@ -80,3 +80,18 @@ void test_tied_earlyclobber(void) {
asm("" : "+&r"(a));
// CHECK: call i32 asm "", "=&{x1},0"(i32 %0)
}

void test_reduced_gpr_constraints(int var32, long var64) {
asm("add w0, w0, %0" : : "Uci"(var32) : "w0");
// CHECK: [[ARG1:%.+]] = load i32, ptr
// CHECK: call void asm sideeffect "add w0, w0, $0", "@3Uci,~{w0}"(i32 [[ARG1]])
asm("add x0, x0, %0" : : "Uci"(var64) : "x0");
// CHECK: [[ARG1:%.+]] = load i64, ptr
// CHECK: call void asm sideeffect "add x0, x0, $0", "@3Uci,~{x0}"(i64 [[ARG1]])
asm("add w0, w0, %0" : : "Ucj"(var32) : "w0");
// CHECK: [[ARG2:%.+]] = load i32, ptr
// CHECK: call void asm sideeffect "add w0, w0, $0", "@3Ucj,~{w0}"(i32 [[ARG2]])
asm("add x0, x0, %0" : : "Ucj"(var64) : "x0");
// CHECK: [[ARG2:%.+]] = load i64, ptr
// CHECK: call void asm sideeffect "add x0, x0, $0", "@3Ucj,~{x0}"(i64 [[ARG2]])
}
2 changes: 2 additions & 0 deletions llvm/docs/LangRef.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5094,6 +5094,8 @@ AArch64:
offsets). (However, LLVM currently does this for the ``m`` constraint as
well.)
- ``r``: A 32 or 64-bit integer register (W* or X*).
- ``Uci``: Like r, but restricted to registers 8 to 11 inclusive.
- ``Ucj``: Like r, but restricted to registers 12 to 15 inclusive.
- ``w``: A 32, 64, or 128-bit floating-point, SIMD or SVE vector register.
- ``x``: Like w, but restricted to registers 0 to 15 inclusive.
- ``y``: Like w, but restricted to SVE vector registers Z0 to Z7 inclusive.
Expand Down
34 changes: 33 additions & 1 deletion llvm/lib/Target/AArch64/AArch64ISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10195,6 +10195,31 @@ getPredicateRegisterClass(PredicateConstraint Constraint, EVT VT) {
llvm_unreachable("Missing PredicateConstraint!");
}

enum class ReducedGprConstraint { Uci, Ucj };

static std::optional<ReducedGprConstraint>
parseReducedGprConstraint(StringRef Constraint) {
return StringSwitch<std::optional<ReducedGprConstraint>>(Constraint)
.Case("Uci", ReducedGprConstraint::Uci)
.Case("Ucj", ReducedGprConstraint::Ucj)
.Default(std::nullopt);
}

static const TargetRegisterClass *
getReducedGprRegisterClass(ReducedGprConstraint Constraint, EVT VT) {
if (!VT.isScalarInteger() || VT.getFixedSizeInBits() > 64)
return nullptr;

switch (Constraint) {
case ReducedGprConstraint::Uci:
return &AArch64::MatrixIndexGPR32_8_11RegClass;
case ReducedGprConstraint::Ucj:
return &AArch64::MatrixIndexGPR32_12_15RegClass;
}

llvm_unreachable("Missing ReducedGprConstraint!");
}

// The set of cc code supported is from
// https://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html#Flag-Output-Operands
static AArch64CC::CondCode parseConstraintCode(llvm::StringRef Constraint) {
Expand Down Expand Up @@ -10292,6 +10317,8 @@ AArch64TargetLowering::getConstraintType(StringRef Constraint) const {
}
} else if (parsePredicateConstraint(Constraint))
return C_RegisterClass;
else if (parseReducedGprConstraint(Constraint))
return C_RegisterClass;
else if (parseConstraintCode(Constraint) != AArch64CC::Invalid)
return C_Other;
return TargetLowering::getConstraintType(Constraint);
Expand Down Expand Up @@ -10325,7 +10352,8 @@ AArch64TargetLowering::getSingleConstraintMatchWeight(
weight = CW_Constant;
break;
case 'U':
if (parsePredicateConstraint(constraint))
if (parsePredicateConstraint(constraint) ||
parseReducedGprConstraint(constraint))
weight = CW_Register;
break;
}
Expand Down Expand Up @@ -10385,6 +10413,10 @@ AArch64TargetLowering::getRegForInlineAsmConstraint(
if (const auto PC = parsePredicateConstraint(Constraint))
if (const auto *RegClass = getPredicateRegisterClass(*PC, VT))
return std::make_pair(0U, RegClass);

if (const auto RGC = parseReducedGprConstraint(Constraint))
if (const auto *RegClass = getReducedGprRegisterClass(*RGC, VT))
return std::make_pair(0U, RegClass);
}
if (StringRef("{cc}").equals_insensitive(Constraint) ||
parseConstraintCode(Constraint) != AArch64CC::Invalid)
Expand Down
78 changes: 78 additions & 0 deletions llvm/test/CodeGen/AArch64/inlineasm-Uc-constraint.ll
Original file line number Diff line number Diff line change
@@ -0,0 +1,78 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 3
; RUN: llc < %s -o - | FileCheck %s

target triple = "arm64-none-linux-gnu"

define void @test_constraints_Uci_w(i32 %a) {
; CHECK-LABEL: test_constraints_Uci_w:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: //APP
; CHECK-NEXT: add x0, x0, x8
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: ret
call void asm sideeffect "add x0, x0, $0", "@3Uci,~{x0}"(i32 %a)
ret void
}

; As test_constraints_Uci_w but ensures non-legal types are also covered.
define void @test_constraints_Uci_w_i8(i8 %a) {
; CHECK-LABEL: test_constraints_Uci_w_i8:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w8, w0
; CHECK-NEXT: //APP
; CHECK-NEXT: add x0, x0, x8
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: ret
call void asm sideeffect "add x0, x0, $0", "@3Uci,~{x0}"(i8 %a)
ret void
}

define void @test_constraints_Uci_x(i64 %a) {
; CHECK-LABEL: test_constraints_Uci_x:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x8, x0
; CHECK-NEXT: //APP
; CHECK-NEXT: add x0, x0, x8
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: ret
call void asm sideeffect "add x0, x0, $0", "@3Uci,~{x0}"(i64 %a)
ret void
}

define void @test_constraint_Ucj_w(i32 %a) {
; CHECK-LABEL: test_constraint_Ucj_w:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w12, w0
; CHECK-NEXT: //APP
; CHECK-NEXT: add x0, x0, x12
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: ret
call void asm sideeffect "add x0, x0, $0", "@3Ucj,~{x0}"(i32 %a)
ret void
}

; As test_constraints_Ucj_w but ensures non-legal types are also covered.
define void @test_constraint_Ucj_w_i8(i8 %a) {
; CHECK-LABEL: test_constraint_Ucj_w_i8:
; CHECK: // %bb.0:
; CHECK-NEXT: mov w12, w0
; CHECK-NEXT: //APP
; CHECK-NEXT: add x0, x0, x12
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: ret
call void asm sideeffect "add x0, x0, $0", "@3Ucj,~{x0}"(i8 %a)
ret void
}

define void @test_constraint_Ucj_x(i64 %a) {
; CHECK-LABEL: test_constraint_Ucj_x:
; CHECK: // %bb.0:
; CHECK-NEXT: mov x12, x0
; CHECK-NEXT: //APP
; CHECK-NEXT: add x0, x0, x12
; CHECK-NEXT: //NO_APP
; CHECK-NEXT: ret
call void asm sideeffect "add x0, x0, $0", "@3Ucj,~{x0}"(i64 %a)
ret void
}

0 comments on commit de88371

Please sign in to comment.