From 14ea44a352d547f3c2736f16a47f3dad449446f5 Mon Sep 17 00:00:00 2001 From: YunQiang Su Date: Tue, 23 Jan 2024 18:14:48 +0800 Subject: [PATCH 1/2] MIPS/clang: Fix asm constraint for softfloat This include 2 fixes: 1. Disallow 'f' for softfloat. 2. Allow 'r' for softfloat. Currently, 'f' is accpeted by clang, then LLVM meet an internal error. 'r' is rejected by LLVM by: couldn't allocate input reg for constraint 'r' Fixes: #64241 --- clang/lib/Basic/Targets/Mips.h | 3 +++ .../CodeGen/Mips/inline-asm-constraints.c | 18 +++++++++++++ clang/test/Sema/inline-asm-validate-mips.c | 8 ++++++ llvm/lib/Target/Mips/MipsISelLowering.cpp | 10 +++++--- .../Mips/inlineasm-constraints-softfloat.ll | 25 +++++++++++++++++++ 5 files changed, 61 insertions(+), 3 deletions(-) create mode 100644 clang/test/CodeGen/Mips/inline-asm-constraints.c create mode 100644 clang/test/Sema/inline-asm-validate-mips.c create mode 100644 llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index f46b95abfd75c..2b8ad6645e605 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -238,6 +238,9 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { case 'd': // Equivalent to "r" unless generating MIPS16 code. case 'y': // Equivalent to "r", backward compatibility only. case 'f': // floating-point registers. + if (*Name == 'f' && FloatABI == SoftFloat) + return false; + LLVM_FALLTHROUGH; case 'c': // $25 for indirect jumps case 'l': // lo register case 'x': // hilo register pair diff --git a/clang/test/CodeGen/Mips/inline-asm-constraints.c b/clang/test/CodeGen/Mips/inline-asm-constraints.c new file mode 100644 index 0000000000000..0a4cb0b34570e --- /dev/null +++ b/clang/test/CodeGen/Mips/inline-asm-constraints.c @@ -0,0 +1,18 @@ +// RUN: %clang_cc1 %s -triple mips -target-feature +soft-float \ +// RUN: -DSOFT_FLOAT_CONSTRAINT_R \ +// RUN: -DFLOAT=float -emit-llvm -o - \ +// RUN: | FileCheck %s --check-prefix SOFT_FLOAT_CONSTRAINT_R_SINGLE + +// RUN: %clang_cc1 %s -triple mips -target-feature +soft-float \ +// RUN: -DSOFT_FLOAT_CONSTRAINT_R \ +// RUN: -DFLOAT=double -emit-llvm -o - \ +// RUN: | FileCheck %s --check-prefix SOFT_FLOAT_CONSTRAINT_R_DOUBLE + +#ifdef SOFT_FLOAT_CONSTRAINT_R +// SOFT_FLOAT_CONSTRAINT_R_SINGLE: call void asm sideeffect "", "r,~{$1}"(float %2) #1, !srcloc !2 +// SOFT_FLOAT_CONSTRAINT_R_DOUBLE: call void asm sideeffect "", "r,~{$1}"(double %2) #1, !srcloc !2 +void read_float(FLOAT* p) { + FLOAT result = *p; + __asm__("" ::"r"(result)); +} +#endif // SOFT_FLOAT_CONSTRAINT_R diff --git a/clang/test/Sema/inline-asm-validate-mips.c b/clang/test/Sema/inline-asm-validate-mips.c new file mode 100644 index 0000000000000..5a123cc5fa79c --- /dev/null +++ b/clang/test/Sema/inline-asm-validate-mips.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple mips -target-feature +soft-float -DSOFT_FLOAT_NO_CONSTRAINT_F -fsyntax-only -verify %s + +#ifdef SOFT_FLOAT_NO_CONSTRAINT_F +void read_float(float p) { + float result = p; + __asm__("" ::"f"(result)); // expected-error{{invalid input constraint 'f' in asm}} +} +#endif // SOFT_FLOAT_NO_CONSTRAINT_F diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp index b2812f87914df..97e830cec27ca 100644 --- a/llvm/lib/Target/Mips/MipsISelLowering.cpp +++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp @@ -4128,14 +4128,18 @@ MipsTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, case 'd': // Address register. Same as 'r' unless generating MIPS16 code. case 'y': // Same as 'r'. Exists for compatibility. case 'r': - if (VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8 || VT == MVT::i1) { + if ((VT == MVT::i32 || VT == MVT::i16 || VT == MVT::i8 || + VT == MVT::i1) || + (VT == MVT::f32 && Subtarget.useSoftFloat())) { if (Subtarget.inMips16Mode()) return std::make_pair(0U, &Mips::CPU16RegsRegClass); return std::make_pair(0U, &Mips::GPR32RegClass); } - if (VT == MVT::i64 && !Subtarget.isGP64bit()) + if ((VT == MVT::i64 || (VT == MVT::f64 && Subtarget.useSoftFloat())) && + !Subtarget.isGP64bit()) return std::make_pair(0U, &Mips::GPR32RegClass); - if (VT == MVT::i64 && Subtarget.isGP64bit()) + if ((VT == MVT::i64 || (VT == MVT::f64 && Subtarget.useSoftFloat())) && + Subtarget.isGP64bit()) return std::make_pair(0U, &Mips::GPR64RegClass); // This will generate an error message return std::make_pair(0U, nullptr); diff --git a/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll b/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll new file mode 100644 index 0000000000000..7e0b7a0c33b55 --- /dev/null +++ b/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=mips < %s | FileCheck %s --check-prefix=MIPS32 +; RUN: llc -march=mips64 < %s | FileCheck %s --check-prefix=MIPS64 + +define dso_local void @read_double(ptr nocapture noundef readonly %0) local_unnamed_addr #0 { + %2 = load double, ptr %0, align 8 +; MIPS32-LABEL: read_double: +; MIPS32: lw $2, 4($4) +; MIPS32-NEXT: lw $3, 0($4) +; MIPS64-LABEL: read_double: +; MIPS64: ld $2, 0($4) + tail call void asm sideeffect "", "r,~{$1}"(double %2) + ret void +} + +define dso_local void @read_float(ptr nocapture noundef readonly %0) local_unnamed_addr #0 { + %2 = load float, ptr %0, align 8 +; MIPS32-LABEL: read_float: +; MIPS32: lw $2, 0($4) +; MIPS64-LABEL: read_float: +; MIPS64: lw $2, 0($4) + tail call void asm sideeffect "", "r,~{$1}"(float %2) + ret void +} + +attributes #0 = { "target-features"="+soft-float" "use-soft-float"="true" } From 97dd952c6a8a1969b36f2007e675c3fbea73cca6 Mon Sep 17 00:00:00 2001 From: Fangrui Song Date: Mon, 26 Feb 2024 21:47:19 -0800 Subject: [PATCH 2/2] use separate case handler for f and improve/simplify tests --- clang/lib/Basic/Targets/Mips.h | 7 ++-- .../CodeGen/Mips/inline-asm-constraints.c | 23 ++++------- clang/test/Sema/inline-asm-validate-mips.c | 13 +++--- .../Mips/inlineasm-constraints-softfloat.ll | 41 +++++++++++++++---- 4 files changed, 50 insertions(+), 34 deletions(-) diff --git a/clang/lib/Basic/Targets/Mips.h b/clang/lib/Basic/Targets/Mips.h index 2b8ad6645e605..23d4e1b598fa1 100644 --- a/clang/lib/Basic/Targets/Mips.h +++ b/clang/lib/Basic/Targets/Mips.h @@ -237,15 +237,14 @@ class LLVM_LIBRARY_VISIBILITY MipsTargetInfo : public TargetInfo { case 'r': // CPU registers. case 'd': // Equivalent to "r" unless generating MIPS16 code. case 'y': // Equivalent to "r", backward compatibility only. - case 'f': // floating-point registers. - if (*Name == 'f' && FloatABI == SoftFloat) - return false; - LLVM_FALLTHROUGH; case 'c': // $25 for indirect jumps case 'l': // lo register case 'x': // hilo register pair Info.setAllowsRegister(); return true; + case 'f': // floating-point registers. + Info.setAllowsRegister(); + return FloatABI != SoftFloat; case 'I': // Signed 16-bit constant case 'J': // Integer 0 case 'K': // Unsigned 16-bit constant diff --git a/clang/test/CodeGen/Mips/inline-asm-constraints.c b/clang/test/CodeGen/Mips/inline-asm-constraints.c index 0a4cb0b34570e..88afe8735083b 100644 --- a/clang/test/CodeGen/Mips/inline-asm-constraints.c +++ b/clang/test/CodeGen/Mips/inline-asm-constraints.c @@ -1,18 +1,11 @@ -// RUN: %clang_cc1 %s -triple mips -target-feature +soft-float \ -// RUN: -DSOFT_FLOAT_CONSTRAINT_R \ -// RUN: -DFLOAT=float -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix SOFT_FLOAT_CONSTRAINT_R_SINGLE +// RUN: %clang_cc1 -emit-llvm -triple mips -target-feature +soft-float %s -o - | FileCheck %s --check-prefix=SOFT_FLOAT -// RUN: %clang_cc1 %s -triple mips -target-feature +soft-float \ -// RUN: -DSOFT_FLOAT_CONSTRAINT_R \ -// RUN: -DFLOAT=double -emit-llvm -o - \ -// RUN: | FileCheck %s --check-prefix SOFT_FLOAT_CONSTRAINT_R_DOUBLE +// SOFT_FLOAT: call void asm sideeffect "", "r,~{$1}"(float %1) +void read_float(float *p) { + __asm__("" ::"r"(*p)); +} -#ifdef SOFT_FLOAT_CONSTRAINT_R -// SOFT_FLOAT_CONSTRAINT_R_SINGLE: call void asm sideeffect "", "r,~{$1}"(float %2) #1, !srcloc !2 -// SOFT_FLOAT_CONSTRAINT_R_DOUBLE: call void asm sideeffect "", "r,~{$1}"(double %2) #1, !srcloc !2 -void read_float(FLOAT* p) { - FLOAT result = *p; - __asm__("" ::"r"(result)); +// SOFT_FLOAT: call void asm sideeffect "", "r,~{$1}"(double %1) +void read_double(double *p) { + __asm__("" :: "r"(*p)); } -#endif // SOFT_FLOAT_CONSTRAINT_R diff --git a/clang/test/Sema/inline-asm-validate-mips.c b/clang/test/Sema/inline-asm-validate-mips.c index 5a123cc5fa79c..7da248fe417b5 100644 --- a/clang/test/Sema/inline-asm-validate-mips.c +++ b/clang/test/Sema/inline-asm-validate-mips.c @@ -1,8 +1,9 @@ -// RUN: %clang_cc1 -triple mips -target-feature +soft-float -DSOFT_FLOAT_NO_CONSTRAINT_F -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple mips64 -fsyntax-only -verify %s +// RUN: %clang_cc1 -triple mips64 -target-feature +soft-float -fsyntax-only -verify=softfloat %s -#ifdef SOFT_FLOAT_NO_CONSTRAINT_F -void read_float(float p) { - float result = p; - __asm__("" ::"f"(result)); // expected-error{{invalid input constraint 'f' in asm}} +// expected-no-diagnostics + +void test_f(float p) { + float result = p; + __asm__("" :: "f"(result)); // softfloat-error{{invalid input constraint 'f' in asm}} } -#endif // SOFT_FLOAT_NO_CONSTRAINT_F diff --git a/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll b/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll index 7e0b7a0c33b55..705570f808ce0 100644 --- a/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll +++ b/llvm/test/CodeGen/Mips/inlineasm-constraints-softfloat.ll @@ -1,23 +1,46 @@ -; RUN: llc -march=mips < %s | FileCheck %s --check-prefix=MIPS32 -; RUN: llc -march=mips64 < %s | FileCheck %s --check-prefix=MIPS64 +; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py UTC_ARGS: --version 4 +; RUN: llc -march=mips < %s | FileCheck %s --check-prefix=MIPS32 +; RUN: llc -march=mips64 < %s | FileCheck %s --check-prefix=MIPS64 define dso_local void @read_double(ptr nocapture noundef readonly %0) local_unnamed_addr #0 { - %2 = load double, ptr %0, align 8 ; MIPS32-LABEL: read_double: -; MIPS32: lw $2, 4($4) -; MIPS32-NEXT: lw $3, 0($4) +; MIPS32: # %bb.0: +; MIPS32-NEXT: lw $2, 4($4) +; MIPS32-NEXT: lw $3, 0($4) +; MIPS32-NEXT: #APP +; MIPS32-NEXT: #NO_APP +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +; ; MIPS64-LABEL: read_double: -; MIPS64: ld $2, 0($4) +; MIPS64: # %bb.0: +; MIPS64-NEXT: ld $2, 0($4) +; MIPS64-NEXT: #APP +; MIPS64-NEXT: #NO_APP +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: nop + %2 = load double, ptr %0, align 8 tail call void asm sideeffect "", "r,~{$1}"(double %2) ret void } define dso_local void @read_float(ptr nocapture noundef readonly %0) local_unnamed_addr #0 { - %2 = load float, ptr %0, align 8 ; MIPS32-LABEL: read_float: -; MIPS32: lw $2, 0($4) +; MIPS32: # %bb.0: +; MIPS32-NEXT: lw $2, 0($4) +; MIPS32-NEXT: #APP +; MIPS32-NEXT: #NO_APP +; MIPS32-NEXT: jr $ra +; MIPS32-NEXT: nop +; ; MIPS64-LABEL: read_float: -; MIPS64: lw $2, 0($4) +; MIPS64: # %bb.0: +; MIPS64-NEXT: lw $2, 0($4) +; MIPS64-NEXT: #APP +; MIPS64-NEXT: #NO_APP +; MIPS64-NEXT: jr $ra +; MIPS64-NEXT: nop + %2 = load float, ptr %0, align 8 tail call void asm sideeffect "", "r,~{$1}"(float %2) ret void }