Skip to content

Commit 550a8db

Browse files
apinski-caviumstephanosio
authored andcommitted
[RISCV] Fix PR 106586: riscv32 vs ZBS
The problem here is two fold. With RISCV32, 32bit const_int are always signed extended to 64bit in HWI. So that means for SINGLE_BIT_MASK_OPERAND, it should mask off the upper bits to see it is a single bit for !TARGET_64BIT. Plus there are a few locations which forget to call trunc_int_for_mode when generating a SImode constant so they are not sign extended correctly for HWI. The predicates single_bit_mask_operand and not_single_bit_mask_operand need get the same handling as SINGLE_BIT_MASK_OPERAND so just use SINGLE_BIT_MASK_OPERAND. OK? Built and tested on riscv32-linux-gnu and riscv64-linux-gnu with --with-arch=rvNimafdc_zba_zbb_zbc_zbs where N is replaced with 32 or 64. Thanks, Andrew Pinski gcc/ChangeLog: PR target/106586 * config/riscv/predicates.md (single_bit_mask_operand): Use SINGLE_BIT_MASK_OPERAND instead of directly calling pow2p_hwi. (not_single_bit_mask_operand): Likewise. * config/riscv/riscv.cc (riscv_build_integer_1): Don't special case 1<<31 for 32bits as it is already handled. Call trunc_int_for_mode on the upper part after the subtraction. (riscv_move_integer): Call trunc_int_for_mode before generating the integer just make sure the constant has been sign extended corectly. (riscv_emit_int_compare): Call trunc_int_for_mode after doing the addition for the new rhs. * config/riscv/riscv.h (SINGLE_BIT_MASK_OPERAND): If !TARGET64BIT, then mask off the upper 32bits of the HWI as it will be sign extended. (cherry picked from commit 2c721ea) Signed-off-by: Stephanos Ioannidis <root@stephanos.io>
1 parent 1588d48 commit 550a8db

File tree

3 files changed

+14
-6
lines changed

3 files changed

+14
-6
lines changed

gcc/config/riscv/predicates.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,11 +226,11 @@
226226
;; Predicates for the ZBS extension.
227227
(define_predicate "single_bit_mask_operand"
228228
(and (match_code "const_int")
229-
(match_test "pow2p_hwi (INTVAL (op))")))
229+
(match_test "SINGLE_BIT_MASK_OPERAND (UINTVAL (op))")))
230230

231231
(define_predicate "not_single_bit_mask_operand"
232232
(and (match_code "const_int")
233-
(match_test "pow2p_hwi (~INTVAL (op))")))
233+
(match_test "SINGLE_BIT_MASK_OPERAND (~UINTVAL (op))")))
234234

235235
(define_predicate "const31_operand"
236236
(and (match_code "const_int")

gcc/config/riscv/riscv.cc

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -426,7 +426,7 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
426426
sign-extended (negative) representation (-1 << 31) for the
427427
value, if we want to build (1 << 31) in SImode. This will
428428
then expand to an LUI instruction. */
429-
if (mode == SImode && value == (HOST_WIDE_INT_1U << 31))
429+
if (TARGET_64BIT && mode == SImode && value == (HOST_WIDE_INT_1U << 31))
430430
codes[0].value = (HOST_WIDE_INT_M1U << 31);
431431

432432
return 1;
@@ -439,7 +439,11 @@ riscv_build_integer_1 (struct riscv_integer_op codes[RISCV_MAX_INTEGER_OPS],
439439
&& (mode != HImode
440440
|| value - low_part <= ((1 << (GET_MODE_BITSIZE (HImode) - 1)) - 1)))
441441
{
442-
alt_cost = 1 + riscv_build_integer_1 (alt_codes, value - low_part, mode);
442+
HOST_WIDE_INT upper_part = value - low_part;
443+
if (mode != VOIDmode)
444+
upper_part = trunc_int_for_mode (value - low_part, mode);
445+
446+
alt_cost = 1 + riscv_build_integer_1 (alt_codes, upper_part, mode);
443447
if (alt_cost < cost)
444448
{
445449
alt_codes[alt_cost-1].code = PLUS;
@@ -1544,6 +1548,7 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value,
15441548
x = riscv_split_integer (value, mode);
15451549
else
15461550
{
1551+
codes[0].value = trunc_int_for_mode (codes[0].value, mode);
15471552
/* Apply each binary operation to X. */
15481553
x = GEN_INT (codes[0].value);
15491554

@@ -1553,7 +1558,7 @@ riscv_move_integer (rtx temp, rtx dest, HOST_WIDE_INT value,
15531558
x = riscv_emit_set (temp, x);
15541559
else
15551560
x = force_reg (mode, x);
1556-
1561+
codes[i].value = trunc_int_for_mode (codes[i].value, mode);
15571562
x = gen_rtx_fmt_ee (codes[i].code, mode, x, GEN_INT (codes[i].value));
15581563
}
15591564
}
@@ -2565,6 +2570,7 @@ riscv_emit_int_compare (enum rtx_code *code, rtx *op0, rtx *op1)
25652570
continue;
25662571

25672572
new_rhs = rhs + (increment ? 1 : -1);
2573+
new_rhs = trunc_int_for_mode (new_rhs, GET_MODE (*op0));
25682574
if (riscv_integer_cost (new_rhs) < riscv_integer_cost (rhs)
25692575
&& (rhs < 0) == (new_rhs < 0))
25702576
{

gcc/config/riscv/riscv.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -531,7 +531,9 @@ enum reg_class
531531
/* If this is a single bit mask, then we can load it with bseti. Special
532532
handling of SImode 0x80000000 on RV64 is done in riscv_build_integer_1. */
533533
#define SINGLE_BIT_MASK_OPERAND(VALUE) \
534-
(pow2p_hwi (VALUE))
534+
(pow2p_hwi (TARGET_64BIT \
535+
? (VALUE) \
536+
: ((VALUE) & ((HOST_WIDE_INT_1U << 32)-1))))
535537

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

0 commit comments

Comments
 (0)