Make scalar int mode and scalar fp mode tieable, so movgr2fr and
movfr2gr can be used instead of memory access.
For example, in pattern '*movsi_internal', when matching gr->fr,
due to the constraint '*' in alt4, it will match alt5, resulting
in memory access instead of movgr2fr.
gcc/ChangeLog:
* config/loongarch/loongarch.cc (loongarch_modes_tieable_p):
Make MODE_FLOAT and MODE_INT tieable.
* config/loongarch/loongarch.md: Adjust constraints.
gcc/testsuite/ChangeLog:
* gcc.target/loongarch/mode-tieable-opt.c: New test.
---
gcc/config/loongarch/loongarch.cc | 6 +++++-
gcc/config/loongarch/loongarch.md | 4 ++--
.../gcc.target/loongarch/mode-tieable-opt.c | 17 +++++++++++++++++
3 files changed, 24 insertions(+), 3 deletions(-)
create mode 100644 gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c
diff --git a/gcc/config/loongarch/loongarch.cc
b/gcc/config/loongarch/loongarch.cc
index 740c8611a71..29b78e214af 100644
--- a/gcc/config/loongarch/loongarch.cc
+++ b/gcc/config/loongarch/loongarch.cc
@@ -7133,7 +7133,11 @@ loongarch_modes_tieable_p (machine_mode mode1,
machine_mode mode2)
prefer to put one of them in FPRs. */
return (mode1 == mode2
|| (!loongarch_mode_ok_for_mov_fmt_p (mode1)
- && !loongarch_mode_ok_for_mov_fmt_p (mode2)));
+ && !loongarch_mode_ok_for_mov_fmt_p (mode2))
+ || (GET_MODE_CLASS(mode1) == MODE_FLOAT
+ && GET_MODE_CLASS(mode2) == MODE_INT)
+ || (GET_MODE_CLASS(mode2) == MODE_FLOAT
+ && GET_MODE_CLASS(mode1) == MODE_INT));
}
/* Implement TARGET_PREFERRED_RELOAD_CLASS. */
diff --git a/gcc/config/loongarch/loongarch.md
b/gcc/config/loongarch/loongarch.md
index 625f30ca265..2a58ac2c2df 100644
--- a/gcc/config/loongarch/loongarch.md
+++ b/gcc/config/loongarch/loongarch.md
@@ -2306,8 +2306,8 @@
})
(define_insn_and_split "*movsi_internal"
- [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,w,*f,f,*r,*m")
- (match_operand:SI 1 "move_operand" "r,Yd,w,rJ,*r*J,m,*f,*f"))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,w,f,f,r,*m")
+ (match_operand:SI 1 "move_operand" "r,Yd,w,rJ,rJ,m,f,*f"))]
"(register_operand (operands[0], SImode)
|| reg_or_0_operand (operands[1], SImode))"
{ return loongarch_output_move (operands); }
diff --git a/gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c
b/gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c
new file mode 100644
index 00000000000..d6a6577bfe5
--- /dev/null
+++ b/gcc/testsuite/gcc.target/loongarch/mode-tieable-opt.c
@@ -0,0 +1,17 @@
+/* { dg-do compile { target { loongarch64*-*-* } } } */
+/* { dg-options "-O3 -mno-lsx" } */
+/* { dg-final { scan-assembler-not "stptr\.d" } } */
+/* { dg-final { scan-assembler-not "fld\.d" } } */
+/* { dg-final { scan-assembler-not "fst\.d" } } */
+/* { dg-final { scan-assembler-not "ldptr\.d" } } */
+/* { dg-final { scan-assembler "movgr2fr\.d" } } */
+/* { dg-final { scan-assembler "movfr2gr\.d" } } */
+
+typedef double vec __attribute__ ((vector_size(16)));
+
+vec
+foo (vec x, double a)
+{
+ x[0] -= a;
+ return x;
+}
--
2.38.1