Skip to content

Commit

Permalink
RISC-V: bitmanip: improve constant-loading for (1ULL << 31) in DImode
Browse files Browse the repository at this point in the history
The SINGLE_BIT_MASK_OPERAND() is overly restrictive, triggering for
bits above 31 only (to side-step any issues with the negative SImode
value 0x80000000/(-1ull << 31)/(1 << 31)).  This moves the special
handling of this SImode value (i.e. the check for (-1ull << 31) to
riscv.cc and relaxes the SINGLE_BIT_MASK_OPERAND() test.

With this, the code-generation for loading (1ULL << 31) from:
	li	a0,1
	slli	a0,a0,31
to:
	bseti	a0,zero,31

gcc/ChangeLog:

	* config/riscv/riscv.cc (riscv_build_integer_1): Rewrite value as
	(-1 << 31) for the single-bit case, when operating on (1 << 31)
	in SImode.
	* config/riscv/riscv.h (SINGLE_BIT_MASK_OPERAND): Allow for
	any single-bit value, moving the special case for (1 << 31) to
	riscv_build_integer_1 (in riscv.c).

Signed-off-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
  • Loading branch information
ptomsich committed Jun 2, 2022
1 parent d19b434 commit 4e72cca
Show file tree
Hide file tree
Showing 2 changed files with 13 additions and 7 deletions.
9 changes: 9 additions & 0 deletions gcc/config/riscv/riscv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -420,6 +420,15 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
/* Simply BSETI. */
codes[0].code = UNKNOWN;
codes[0].value = value;

/* RISC-V sign-extends all 32bit values that live in a 32bit
register. To avoid paradoxes, we thus need to use the
sign-extended (negative) representation (-1 << 31) for the
value, if we want to build (1 << 31) in SImode. This will
then expand to an LUI instruction. */
if (mode == SImode && value == (HOST_WIDE_INT_1U << 31))
codes[0].value = (HOST_WIDE_INT_M1U << 31);

return 1;
}

Expand Down
11 changes: 4 additions & 7 deletions gcc/config/riscv/riscv.h
Original file line number Diff line number Diff line change
Expand Up @@ -528,13 +528,10 @@ enum reg_class
(((VALUE) | ((1UL<<31) - IMM_REACH)) == ((1UL<<31) - IMM_REACH) \
|| ((VALUE) | ((1UL<<31) - IMM_REACH)) + IMM_REACH == 0)

/* If this is a single bit mask, then we can load it with bseti. But this
is not useful for any of the low 31 bits because we can use addi or lui
to load them. It is wrong for loading SImode 0x80000000 on rv64 because it
needs to be sign-extended. So we restrict this to the upper 32-bits
only. */
#define SINGLE_BIT_MASK_OPERAND(VALUE) \
(pow2p_hwi (VALUE) && (ctz_hwi (VALUE) >= 32))
/* If this is a single bit mask, then we can load it with bseti. Special
handling of SImode 0x80000000 on RV64 is done in riscv_build_integer_1. */
#define SINGLE_BIT_MASK_OPERAND(VALUE) \
(pow2p_hwi (VALUE))

/* Stack layout; function entry, exit and calling. */

Expand Down

0 comments on commit 4e72cca

Please sign in to comment.