]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
LoongArch: When loading an immediate value, promote mode to word_mode.
authorLulu Cheng <chenglulu@loongson.cn>
Thu, 30 Oct 2025 03:16:32 +0000 (11:16 +0800)
committerLulu Cheng <chenglulu@loongson.cn>
Fri, 7 Nov 2025 01:20:22 +0000 (09:20 +0800)
This optimization can eliminate redundant immediate load instructions
during CSE optimization.

gcc/ChangeLog:

* config/loongarch/loongarch.cc
(loongarch_legitimize_move): Optimize.

gcc/testsuite/ChangeLog:

* gcc.target/loongarch/sign-extend-6.c: New test.

gcc/config/loongarch/loongarch.cc
gcc/testsuite/gcc.target/loongarch/sign-extend-6.c [new file with mode: 0644]

index d11fe496a015b2f9141303a07d83bbd6a70cb9c5..4e53635a7b983756b5703e6025ddf5f18956656b 100644 (file)
@@ -3534,7 +3534,20 @@ loongarch_legitimize_move (machine_mode mode, rtx dest, rtx src)
 {
   if (!register_operand (dest, mode) && !reg_or_0_operand (src, mode))
     {
-      loongarch_emit_move (dest, force_reg (mode, src));
+      /* When loading fixed-point scalar data, if the size of the mode
+        is smaller than the size of `word_mode`, the immediate value
+        is first loaded into a register of type `word_mode`.
+        This facilitates the elimination of common self-expressions.
+        This reduces redundant immediate value loading instructions.  */
+      rtx tmp;
+      if (GET_MODE_CLASS (mode) == MODE_INT
+         && GET_CODE (src) == CONST_INT
+         && GET_MODE_SIZE (mode) < UNITS_PER_WORD)
+       tmp = gen_lowpart (mode, force_reg (word_mode, src));
+      else
+       tmp = force_reg (mode, src);
+
+      loongarch_emit_move (dest, tmp);
       return true;
     }
 
diff --git a/gcc/testsuite/gcc.target/loongarch/sign-extend-6.c b/gcc/testsuite/gcc.target/loongarch/sign-extend-6.c
new file mode 100644 (file)
index 0000000..74d0e58
--- /dev/null
@@ -0,0 +1,17 @@
+/* { dg-do compile } */
+/* { dg-options "-mabi=lp64d -O2" } */
+/* { dg-final { scan-assembler-times "addi.w\t\\\$r\[0-9\]+,\\\$r\[0-9\]+,1\t" 1 } } */
+
+extern unsigned short d;
+int
+test (int a, unsigned short b)
+{
+  if (a > 0)
+    {
+      d = 1;
+      if (b > d)
+       return 10;
+    }
+
+  return 50;
+}