From c38385ddbcce9fbeeaa788b6a4f50bd0653b0271 Mon Sep 17 00:00:00 2001
From: Jivan Hakobyan <jivanhakobyan9@gmail.com>
Date: Sat, 12 Oct 2024 19:10:50 -0600
Subject: [PATCH] [RISC-V] Avoid unnecessary extensions when value is already
 extended

This is a minor patch from Jivan from roughly a year ago.  The basic
idea here is similar to what we do when extending values for the sake of
comparisons.  Specifically if the value is already known to be properly
extended, then an extension is just a copy.

The original idea was to use a similar patch, but which aborted to
identify cases where these unnecessary promotions where emitted.  All
that showed up when doing a testsuite run with that abort was the
promotions created by the arithmetic with overflow patterns such as addv.

Things like addv aren't *that* common so this never got high on my todo
list, even after a minor issue in this space was raised in bugzilla.

But with stage1 closing soon and no good reason not to go forward, I'm
submitting this into the pre-commit tester now.  My tester has been
using it since roughly Feb :-)  Plan would be to commit after the
pre-commit tester renders its verdict.

	* config/riscv/riscv.md (zero_extendsidi2): If RHS is already
	zero extended, then this is just a copy.
	(extendsidi2): Similarly, but for sign extension.
---
 gcc/config/riscv/riscv.md | 20 ++++++++++++++++++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md
index 78112afbb261..f1e9bd588500 100644
--- a/gcc/config/riscv/riscv.md
+++ b/gcc/config/riscv/riscv.md
@@ -1813,7 +1813,15 @@
 (define_expand "zero_extendsidi2"
   [(set (match_operand:DI 0 "register_operand")
 	(zero_extend:DI (match_operand:SI 1 "nonimmediate_operand")))]
-  "TARGET_64BIT")
+  "TARGET_64BIT"
+{
+  if (SUBREG_P (operands[1]) && SUBREG_PROMOTED_VAR_P (operands[1])
+      && SUBREG_PROMOTED_UNSIGNED_P (operands[1]))
+    {
+      emit_insn (gen_movdi (operands[0], SUBREG_REG (operands[1])));
+      DONE;
+    }
+})
 
 (define_insn_and_split "*zero_extendsidi2_internal"
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
@@ -1894,7 +1902,15 @@
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
 	(sign_extend:DI
 	    (match_operand:SI 1 "nonimmediate_operand" " r,m")))]
-  "TARGET_64BIT")
+  "TARGET_64BIT"
+{
+  if (SUBREG_P (operands[1]) && SUBREG_PROMOTED_VAR_P (operands[1])
+      && SUBREG_PROMOTED_SIGNED_P (operands[1]))
+    {
+      emit_insn (gen_movdi (operands[0], SUBREG_REG (operands[1])));
+      DONE;
+    }
+})
 
 (define_insn "*extendsidi2_internal"
   [(set (match_operand:DI     0 "register_operand"     "=r,r")
-- 
GitLab