RISC-V: bitmanip: improve constant-loading for (1ULL << 31) in DImode

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>

(cherry picked from commit 4e72ccad80)
This commit is contained in:
Philipp Tomsich 2020-06-29 15:15:10 +02:00
parent 2d45d5df9a
commit 65d121507d
2 changed files with 13 additions and 7 deletions

View File

@ -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;
}

View File

@ -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. */