[v1,5/8] RISC-V: bitmanip: improvements to rotate instructions
Commit Message
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(-)
@@ -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"