[PATCH v1 5/8] RISC-V: bitmanip: improvements to rotate instructions

Philipp Tomsich philipp.tomsich@vrull.eu
Thu Nov 11 14:10:17 GMT 2021


This change improves rotate instructions (motivated by a review of the
code generated for OpenSSL): rotate-left by a constant are synthesized
using a rotate-right-immediate to avoid putting the shift-amount into
a temporary; to do so, we allow either a register or an immediate for
the expansion of rotl<mode>3 and then check if the shift-amount is a
constant.

Without these changes, the function
    unsigned int f(unsigned int a)
    {
      return (a << 2) | (a >> 30);
    }
turns into
    li      a5,2
    rolw    a0,a0,a5
while these changes give us:
    roriw   a0,a0,30

gcc/ChangeLog:

	* config/riscv/bitmanip.md (rotlsi3, rotldi3, rotlsi3_sext):
	Synthesize rotate-left-by-immediate from a rotate-right insn.

Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
---

 gcc/config/riscv/bitmanip.md | 39 ++++++++++++++++++++++++++++++------
 1 file changed, 33 insertions(+), 6 deletions(-)

diff --git a/gcc/config/riscv/bitmanip.md b/gcc/config/riscv/bitmanip.md
index 59779b48f27..178d1ca0e4b 100644
--- a/gcc/config/riscv/bitmanip.md
+++ b/gcc/config/riscv/bitmanip.md
@@ -204,25 +204,52 @@ (define_insn "rotrsi3_sext"
 (define_insn "rotlsi3"
   [(set (match_operand:SI 0 "register_operand" "=r")
 	(rotate:SI (match_operand:SI 1 "register_operand" "r")
-		   (match_operand:QI 2 "register_operand" "r")))]
+		   (match_operand:QI 2 "arith_operand" "rI")))]
   "TARGET_ZBB"
-  { return TARGET_64BIT ? "rolw\t%0,%1,%2" : "rol\t%0,%1,%2"; }
+  {
+    /* If the rotate-amount is constant, let's synthesize using a
+       rotate-right-immediate instead of using a temporary. */
+
+    if (CONST_INT_P(operands[2])) {
+      operands[2] = GEN_INT(32 - INTVAL(operands[2]));
+      return TARGET_64BIT ? "roriw\t%0,%1,%2" : "rori\t%0,%1,%2";
+    }
+
+    return TARGET_64BIT ? "rolw\t%0,%1,%2" : "rol\t%0,%1,%2";
+  }
   [(set_attr "type" "bitmanip")])
 
 (define_insn "rotldi3"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(rotate:DI (match_operand:DI 1 "register_operand" "r")
-		   (match_operand:QI 2 "register_operand" "r")))]
+		   (match_operand:QI 2 "arith_operand" "rI")))]
   "TARGET_64BIT && TARGET_ZBB"
-  "rol\t%0,%1,%2"
+  {
+    if (CONST_INT_P(operands[2])) {
+      operands[2] = GEN_INT(64 - INTVAL(operands[2]));
+      return "rori\t%0,%1,%2";
+    }
+
+    return "rol\t%0,%1,%2";
+  }
   [(set_attr "type" "bitmanip")])
 
+;; Until we have improved REE to understand that sign-extending the result of
+;; an implicitly sign-extending operation is redundant, we need an additional
+;; pattern to gobble up the redundant sign-extension.
 (define_insn "rotlsi3_sext"
   [(set (match_operand:DI 0 "register_operand" "=r")
 	(sign_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "r")
-				   (match_operand:QI 2 "register_operand" "r"))))]
+				   (match_operand:QI 2 "arith_operand" "rI"))))]
   "TARGET_64BIT && TARGET_ZBB"
-  "rolw\t%0,%1,%2"
+  {
+    if (CONST_INT_P(operands[2])) {
+      operands[2] = GEN_INT(32 - INTVAL(operands[2]));
+      return "roriw\t%0,%1,%2";
+    }
+
+    return "rolw\t%0,%1,%2";
+  }
   [(set_attr "type" "bitmanip")])
 
 (define_insn "bswap<mode>2"
-- 
2.32.0



More information about the Gcc-patches mailing list