riscvarchive/riscv-gcc

rotatert with imm emits an unnecessary load if imm > __riscv_xlen/2

marcfedorow opened this issue · 1 comments

https://github.com/riscv-collab/riscv-gcc/blob/3a004f3c3bd941d79adba5e7c0bc643f745027be/gcc/config/riscv/bitmanip.md#L297

gcc/simplify-rtx.c has such statement:

#if defined(HAVE_rotate) && defined(HAVE_rotatert)
      if (CONST_INT_P (trueop1)
	  && IN_RANGE (INTVAL (trueop1),
		       GET_MODE_UNIT_PRECISION (mode) / 2 + (code == ROTATE),
		       GET_MODE_UNIT_PRECISION (mode) - 1))
	{
	  int new_amount = GET_MODE_UNIT_PRECISION (mode) - INTVAL (trueop1);
	  rtx new_amount_rtx = gen_int_shift_amount (mode, new_amount);
	  return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE,
				      mode, op0, new_amount_rtx);
	}
#endif

Thus gcc emits li reg2, 15; rol reg1, reg2; instead of rori reg1, 17 on RV32.

This may fix it:

(define_expand "riscv_rolw"
  [(match_operand:SI 0 "register_operand" "=r")
   (match_operand:SI 1 "register_operand" "r")
   (match_operand:SI 2 "register_operand" "r")]
  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
{
  emit_insn (gen_rotl64si3 (operands[0], operands[1], operands[2]));
  DONE;
})

(define_insn "rotlsi3"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(rotate:SI (match_operand:SI 1 "register_operand" "r,r")
		   (match_operand:QI 2 "arith_operand" "r,I")))]
  "!TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
  "@
  rol\t%0,%1,%2
  rori\t%0,%1,32-%2"
  [(set_attr "type" "bitmanip")])

(define_insn "rotl64si3"
  [(set (match_operand:SI 0 "register_operand" "=r,r")
	(rotate:SI (match_operand:SI 1 "register_operand" "r,r")
		   (match_operand:QI 2 "arith_operand" "r,I")))]
  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
  "@
  rolw\t%0,%1,%2
  roriw\t%0,%1,32-%2"
  [(set_attr "type" "bitmanip")])

(define_insn "rotldi3"
  [(set (match_operand:DI 0 "register_operand" "=r,r")
	(rotate:DI (match_operand:DI 1 "register_operand" "r,r")
		   (match_operand:QI 2 "arith_operand" "r,I")))]
  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
  "@
  rol\t%0,%1,%2
  rori\t%0,%1,64-%2"
  [(set_attr "type" "bitmanip")])

(define_insn "rotlsi3_sext"
  [(set (match_operand:DI 0 "register_operand" "=r,r")
	(sign_extend:DI (rotate:SI (match_operand:SI 1 "register_operand" "r,r")
				   (match_operand:QI 2 "arith_operand" "r,I"))))]
  "TARGET_64BIT && (TARGET_ZBB || TARGET_ZBKB)"
  "@
  rolw\t%0,%1,%2
  roriw\t%0,%1,%2"
  [(set_attr "type" "bitmanip")])

Thanks for reporting this issue.

Please, note that this bug tracker is not meant to track RISC-V-related backend issues in GCC.
Please report to GCC's bugzilla (https://gcc.gnu.org/bugzilla/).

Also, note that a patch to address this has been posted recently on gcc-patches:
https://gcc.gnu.org/pipermail/gcc-patches/2021-November/584143.html