@@ -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"
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(-)