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.toms...@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