Skip to content

Commit

Permalink
MIPS/clang: Fix asm constraint for softfloat
Browse files Browse the repository at this point in the history
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: llvm#64241
  • Loading branch information
wzssyqa committed Feb 2, 2024
1 parent 2e669ff commit 009bd23
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 3 deletions.
3 changes: 3 additions & 0 deletions clang/lib/Basic/Targets/Mips.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
47 changes: 47 additions & 0 deletions clang/test/Driver/mips-float.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,3 +102,50 @@
// CHECK-ABI-SOFT-MIPS16: "-target-feature" "+mips16"
// CHECK-ABI-SOFT-MIPS16: "-msoft-float"
// CHECK-ABI-SOFT-MIPS16: "-mfloat-abi" "soft"

/// On MIPS, don't accept constraint "f" for soft-float.
// RUN: not %clang -S %s -o %t.s 2>&1 \
// RUN: -target mips-linux-gnu -msoft-float \
// RUN: -DSOFT_FLOAT_NO_CONSTRAINT_F \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT-ASM-NO-F %s
// CHECK-SOFTFLOAT-ASM-NO-F: error: invalid input constraint 'f' in asm

#ifdef SOFT_FLOAT_NO_CONSTRAINT_F
void read_float(float* p) {
float result = *p;
__asm__("" ::"f"(result));
}
#endif // SOFT_FLOAT_NO_CONSTRAINT_F

/// On MIPS, accept constraint "r" for soft-float.
// RUN: %clang -S %s -o - -O2 2>&1 \
// RUN: -target mips-linux-gnu -msoft-float -mabi=32 \
// RUN: -DSOFT_FLOAT_USE_CONSTRAINT_R -DFLOAT=float \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT-ASM-USE-R-3232 %s
// CHECK-SOFTFLOAT-ASM-USE-R-3232: lw $2, 0($4)
//
// RUN: %clang -S %s -o - -O2 2>&1 \
// RUN: -target mips-linux-gnu -msoft-float -mabi=32 \
// RUN: -DSOFT_FLOAT_USE_CONSTRAINT_R -DFLOAT=double \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT-ASM-USE-R-3264 %s
// CHECK-SOFTFLOAT-ASM-USE-R-3264: lw $2, 4($4)
// CHECK-SOFTFLOAT-ASM-USE-R-3264: lw $3, 0($4)
//
// RUN: %clang -S %s -o - -O2 2>&1 \
// RUN: -target mips-linux-gnu -msoft-float -mabi=64 \
// RUN: -DSOFT_FLOAT_USE_CONSTRAINT_R -DFLOAT=float \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT-ASM-USE-R-6432 %s
// CHECK-SOFTFLOAT-ASM-USE-R-6432: lw $2, 0($4)
//
// RUN: %clang -S %s -o - -O2 2>&1 \
// RUN: -target mips-linux-gnu -msoft-float -mabi=64 \
// RUN: -DSOFT_FLOAT_USE_CONSTRAINT_R -DFLOAT=double \
// RUN: | FileCheck --check-prefix=CHECK-SOFTFLOAT-ASM-USE-R-6464 %s
// CHECK-SOFTFLOAT-ASM-USE-R-6464: ld $2, 0($4)

#ifdef SOFT_FLOAT_USE_CONSTRAINT_R
void read_float(FLOAT* p) {
FLOAT result = *p;
__asm__("" ::"r"(result));
}
#endif // SOFT_FLOAT_USE_CONSTRAINT_R
10 changes: 7 additions & 3 deletions llvm/lib/Target/Mips/MipsISelLowering.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down

0 comments on commit 009bd23

Please sign in to comment.