From: Pan Li <pan2...@intel.com> This patch would like to refactor the helper function of the SAT_* scalar. The helper function will convert the define_pattern ops to the xmode reg for the underlying code-gen. This patch add new parameter for ZERO_EXTEND or SIGN_EXTEND if the input is const_int or the mode is non-Xmode.
The below test suites are passed for this patch. * The rv64gcv fully regression test. gcc/ChangeLog: * config/riscv/riscv.cc (riscv_gen_zero_extend_rtx): Rename from ... (riscv_extend_to_xmode_reg): Rename to and add rtx_code for zero/sign extend if non-Xmode. (riscv_expand_usadd): Leverage the renamed function with ZERO_EXTEND. (riscv_expand_ussub): Ditto. Signed-off-by: Pan Li <pan2...@intel.com> --- gcc/config/riscv/riscv.cc | 77 ++++++++++++++++++++++++--------------- 1 file changed, 48 insertions(+), 29 deletions(-) diff --git a/gcc/config/riscv/riscv.cc b/gcc/config/riscv/riscv.cc index dd50fe4eddf..34f0a888c5c 100644 --- a/gcc/config/riscv/riscv.cc +++ b/gcc/config/riscv/riscv.cc @@ -12644,14 +12644,26 @@ riscv_get_raw_result_mode (int regno) /* Generate a REG rtx of Xmode from the given rtx and mode. The rtx x can be REG (QI/HI/SI/DI) or const_int. The machine_mode mode is the original mode from define pattern. + The rtx_code can be ZERO_EXTEND or SIGN_EXTEND. - If rtx is REG and Xmode, the RTX x will be returned directly. + If rtx is REG: - If rtx is REG and non-Xmode, the zero extended to new REG of Xmode will be - returned. + 1. If rtx Xmode, the RTX x will be returned directly. + 2. If rtx non-Xmode, the extended to new REG of Xmode will be returned. - If rtx is const_int, a new REG rtx will be created to hold the value of - const_int and then returned. + The scalar ALU like add don't support non-Xmode like QI/HI. Then the + gen_lowpart will have problem here. For example, when we would like + to add -1 (0xff if QImode) and 2 (0x2 if QImode). The 0xff and 0x2 will + be loaded to register for adding. Aka: + + 0xff + 0x2 = 0x101 instead of -1 + 2 = 1. + + Thus we need to sign extend 0xff to 0xffffffffffffffff if Xmode is DImode + for correctness. Similar the unsigned also need zero extend. + + If rtx is const_int: + + 1. A new REG rtx will be created to hold the value of const_int. According to the gccint doc, the constants generated for modes with fewer bits than in HOST_WIDE_INT must be sign extended to full width. Thus there @@ -12669,34 +12681,41 @@ riscv_get_raw_result_mode (int regno) the REG rtx of Xmode, instead of taking care of these in expand func. */ static rtx -riscv_gen_zero_extend_rtx (rtx x, machine_mode mode) +riscv_extend_to_xmode_reg (rtx x, machine_mode mode, enum rtx_code rcode) { + gcc_assert (rcode == ZERO_EXTEND || rcode == SIGN_EXTEND); + rtx xmode_reg = gen_reg_rtx (Xmode); - if (!CONST_INT_P (x)) + if (CONST_INT_P (x)) { if (mode == Xmode) - return x; - - riscv_emit_unary (ZERO_EXTEND, xmode_reg, x); - return xmode_reg; - } - - if (mode == Xmode) - emit_move_insn (xmode_reg, x); - else - { - /* Combine deliberately does not simplify extensions of constants - (long story). So try to generate the zero extended constant - efficiently. + emit_move_insn (xmode_reg, x); + else if (rcode == ZERO_EXTEND) + { + /* Combine deliberately does not simplify extensions of constants + (long story). So try to generate the zero extended constant + efficiently. - First extract the constant and mask off all the bits not in MODE. */ - HOST_WIDE_INT val = INTVAL (x); - val &= GET_MODE_MASK (mode); + First extract the constant and mask off all the bits not in + MODE. */ + HOST_WIDE_INT val = INTVAL (x); + val &= GET_MODE_MASK (mode); - /* X may need synthesis, so do not blindly copy it. */ - xmode_reg = force_reg (Xmode, gen_int_mode (val, Xmode)); + /* X may need synthesis, so do not blindly copy it. */ + xmode_reg = force_reg (Xmode, gen_int_mode (val, Xmode)); + } + else /* SIGN_EXTEND. */ + { + rtx x_reg = gen_reg_rtx (mode); + emit_move_insn (x_reg, x); + riscv_emit_unary (rcode, xmode_reg, x_reg); + } } + else if (mode == Xmode) + return x; + else + riscv_emit_unary (rcode, xmode_reg, x); return xmode_reg; } @@ -12717,8 +12736,8 @@ riscv_expand_usadd (rtx dest, rtx x, rtx y) machine_mode mode = GET_MODE (dest); rtx xmode_sum = gen_reg_rtx (Xmode); rtx xmode_lt = gen_reg_rtx (Xmode); - rtx xmode_x = riscv_gen_zero_extend_rtx (x, mode); - rtx xmode_y = riscv_gen_zero_extend_rtx (y, mode); + rtx xmode_x = riscv_extend_to_xmode_reg (x, mode, ZERO_EXTEND); + rtx xmode_y = riscv_extend_to_xmode_reg (y, mode, ZERO_EXTEND); rtx xmode_dest = gen_reg_rtx (Xmode); /* Step-1: sum = x + y */ @@ -12852,8 +12871,8 @@ void riscv_expand_ussub (rtx dest, rtx x, rtx y) { machine_mode mode = GET_MODE (dest); - rtx xmode_x = riscv_gen_zero_extend_rtx (x, mode); - rtx xmode_y = riscv_gen_zero_extend_rtx (y, mode); + rtx xmode_x = riscv_extend_to_xmode_reg (x, mode, ZERO_EXTEND); + rtx xmode_y = riscv_extend_to_xmode_reg (y, mode, ZERO_EXTEND); rtx xmode_lt = gen_reg_rtx (Xmode); rtx xmode_minus = gen_reg_rtx (Xmode); rtx xmode_dest = gen_reg_rtx (Xmode); -- 2.43.0