From 455f940eda3fec6a0e71143dd37f06cfe5ef4556 Mon Sep 17 00:00:00 2001 From: Alexey Gerenkov Date: Mon, 8 Jun 2026 16:29:38 +0300 Subject: [PATCH] [Xtensa] Support 'f' Inline Assembly Constraint This adds the 'f' inline assembly constraint, as supported by GCC. An 'f'-constrained operand is passed in a floating point register. --- llvm/lib/Target/Xtensa/XtensaISelLowering.cpp | 8 +++++++ .../CodeGen/Xtensa/inline-asm-constraints.ll | 23 +++++++++++++++++++ .../test/CodeGen/Xtensa/inline-asm-invalid.ll | 11 ++------- 3 files changed, 33 insertions(+), 9 deletions(-) create mode 100644 llvm/test/CodeGen/Xtensa/inline-asm-constraints.ll diff --git a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp index 923afb2ec1b3d..fbe497cc66056 100644 --- a/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp +++ b/llvm/lib/Target/Xtensa/XtensaISelLowering.cpp @@ -287,6 +287,7 @@ XtensaTargetLowering::getConstraintType(StringRef Constraint) const { if (Constraint.size() == 1) { switch (Constraint[0]) { case 'r': + case 'f': return C_RegisterClass; default: break; @@ -316,6 +317,10 @@ XtensaTargetLowering::getSingleConstraintMatchWeight( if (Ty->isIntegerTy()) Weight = CW_Register; break; + case 'f': + if (Ty->isFloatingPointTy()) + Weight = CW_Register; + break; } return Weight; } @@ -330,6 +335,9 @@ XtensaTargetLowering::getRegForInlineAsmConstraint( break; case 'r': // General-purpose register return std::make_pair(0U, &Xtensa::ARRegClass); + case 'f': // Floating-point register + if (Subtarget.hasSingleFloat()) + return std::make_pair(0U, &Xtensa::FPRRegClass); } } return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); diff --git a/llvm/test/CodeGen/Xtensa/inline-asm-constraints.ll b/llvm/test/CodeGen/Xtensa/inline-asm-constraints.ll new file mode 100644 index 0000000000000..7dbb0f07debda --- /dev/null +++ b/llvm/test/CodeGen/Xtensa/inline-asm-constraints.ll @@ -0,0 +1,23 @@ +; RUN: llc -mtriple=xtensa -mcpu=esp32 -verify-machineinstrs < %s \ +; RUN: | FileCheck -check-prefix=Xtensa %s + + +@gf = external global float + +define float @constraint_f_float(float %a) nounwind { +; Xtensa-LABEL: constraint_f_float: +; Xtensa: # %bb.0: +; Xtensa-NEXT: entry a1, 32 +; Xtensa-NEXT: wfr f8, a2 +; Xtensa-NEXT: l32r a8, .LCPI0_0 +; Xtensa-NEXT: lsi f9, a8, 0 +; Xtensa-NEXT: #APP +; Xtensa-NEXT: add.s f8, f8, f9 +; Xtensa-NEXT: #NO_APP +; Xtensa-NEXT: rfr a2, f8 +; Xtensa-NEXT: retw + %1 = load float, float* @gf + %2 = tail call float asm "add.s $0, $1, $2", "=f,f,f"(float %a, float %1) + ret float %2 +} + diff --git a/llvm/test/CodeGen/Xtensa/inline-asm-invalid.ll b/llvm/test/CodeGen/Xtensa/inline-asm-invalid.ll index cb9cd83fbc156..2da5fcc3fb97b 100644 --- a/llvm/test/CodeGen/Xtensa/inline-asm-invalid.ll +++ b/llvm/test/CodeGen/Xtensa/inline-asm-invalid.ll @@ -1,14 +1,7 @@ -; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 5 -; RUN: not llc --mtriple=xtensa < %s 2>&1 | FileCheck %s +; RUN: not llc -mtriple=xtensa -mcpu=generic < %s 2>&1 | FileCheck %s +; CHECK: error: could not allocate input reg for constraint 'f' define void @constraint_f() nounwind { -; CHECK: error: unknown asm constraint 'f' tail call void asm "add.s f0, f1, $0", "f"(float 0.0) ret void } - -define i32 @register_a100(i32 %a) nounwind { -; CHECK: error: could not allocate input reg for constraint '{$a100}' - %1 = tail call i32 asm "addi $0, $1, 1", "=r,{$a100}"(i32 %a) - ret i32 %1 -}