Commit a3b13564 by Kito Cheng Committed by Chung-Ju Wu

[NDS32] Refine bit-wise operation and shift patterns.

gcc/
	* config/nds32/iterators.md (shift_rotate): New code iterator.
	(shift): New code attribute.
	* config/nds32/nds32-md-auxiliary.c (nds32_expand_constant): New.
	* config/nds32/nds32-protos.h (nds32_expand_constant): Declare.
	* config/nds32/nds32.c (nds32_print_operand): Deal with more cases.
	* config/nds32/nds32.md (addsi3, *add_srli): Refine implementation for
	bit-wise operations.
	(andsi3, *andsi3): Ditto.
	(iorsi3, *iorsi3, *or_slli, *or_srli): Ditto.
	(xorsi3, *xorsi3, *xor_slli, *xor_srli): Ditto.
	(<shift>si3, *ashlsi3, *ashrsi3, *lshrsi3, *rotrsi3): Ditto.
	* config/nds32/predicates.md (nds32_rimm5u_operand, nds32_and_operand,
	nds32_ior_operand, nds32_xor_operand): New predicates.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>

From-SVN: r259117
parent 5c36be57
2018-04-05 Kito Cheng <kito.cheng@gmail.com>
Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/iterators.md (shift_rotate): New code iterator.
(shift): New code attribute.
* config/nds32/nds32-md-auxiliary.c (nds32_expand_constant): New.
* config/nds32/nds32-protos.h (nds32_expand_constant): Declare.
* config/nds32/nds32.c (nds32_print_operand): Deal with more cases.
* config/nds32/nds32.md (addsi3, *add_srli): Refine implementation for
bit-wise operations.
(andsi3, *andsi3): Ditto.
(iorsi3, *iorsi3, *or_slli, *or_srli): Ditto.
(xorsi3, *xorsi3, *xor_slli, *xor_srli): Ditto.
(<shift>si3, *ashlsi3, *ashrsi3, *lshrsi3, *rotrsi3): Ditto.
* config/nds32/predicates.md (nds32_rimm5u_operand, nds32_and_operand,
nds32_ior_operand, nds32_xor_operand): New predicates.
2018-04-05 Chung-Ju Wu <jasonwucj@gmail.com> 2018-04-05 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.md (add<mode>3, sub<mode>3): Rename to ... * config/nds32/nds32.md (add<mode>3, sub<mode>3): Rename to ...
......
...@@ -61,10 +61,16 @@ ...@@ -61,10 +61,16 @@
;; Code iterators. ;; Code iterators.
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
;; shifts
(define_code_iterator shift_rotate [ashift ashiftrt lshiftrt rotatert])
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
;; Code attributes. ;; Code attributes.
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
;; shifts
(define_code_attr shift
[(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr") (rotatert "rotr")])
;;---------------------------------------------------------------------------- ;;----------------------------------------------------------------------------
...@@ -2111,3 +2111,49 @@ nds32_long_call_p (rtx symbol) ...@@ -2111,3 +2111,49 @@ nds32_long_call_p (rtx symbol)
{ {
return TARGET_CMODEL_LARGE; return TARGET_CMODEL_LARGE;
} }
void
nds32_expand_constant (machine_mode mode, HOST_WIDE_INT val,
rtx target, rtx source)
{
rtx temp = gen_reg_rtx (mode);
int clear_sign_bit_copies = 0;
int clear_zero_bit_copies = 0;
unsigned HOST_WIDE_INT remainder = val & 0xffffffffUL;
/* Count number of leading zeros. */
clear_sign_bit_copies = __builtin_clz (remainder);
/* Count number of trailing zeros. */
clear_zero_bit_copies = __builtin_ctz (remainder);
HOST_WIDE_INT sign_shift_mask = ((0xffffffffUL
<< (32 - clear_sign_bit_copies))
& 0xffffffffUL);
HOST_WIDE_INT zero_shift_mask = (1 << clear_zero_bit_copies) - 1;
if (clear_sign_bit_copies > 0 && clear_sign_bit_copies < 17
&& (remainder | sign_shift_mask) == 0xffffffffUL)
{
/* Transfer AND to two shifts, example:
a = b & 0x7fffffff => (b << 1) >> 1 */
rtx shift = GEN_INT (clear_sign_bit_copies);
emit_insn (gen_ashlsi3 (temp, source, shift));
emit_insn (gen_lshrsi3 (target, temp, shift));
}
else if (clear_zero_bit_copies > 0 && clear_sign_bit_copies < 17
&& (remainder | zero_shift_mask) == 0xffffffffUL)
{
/* Transfer AND to two shifts, example:
a = b & 0xfff00000 => (b >> 20) << 20 */
rtx shift = GEN_INT (clear_zero_bit_copies);
emit_insn (gen_lshrsi3 (temp, source, shift));
emit_insn (gen_ashlsi3 (target, temp, shift));
}
else
{
emit_move_insn (temp, GEN_INT (val));
emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp));
}
}
...@@ -154,6 +154,11 @@ extern const char *nds32_output_cbranchsi4_greater_less_zero (rtx_insn *, rtx *) ...@@ -154,6 +154,11 @@ extern const char *nds32_output_cbranchsi4_greater_less_zero (rtx_insn *, rtx *)
extern const char *nds32_output_stack_push (rtx); extern const char *nds32_output_stack_push (rtx);
extern const char *nds32_output_stack_pop (rtx); extern const char *nds32_output_stack_pop (rtx);
/* Auxiliary functions to split large constant RTX pattern. */
extern void nds32_expand_constant (machine_mode,
HOST_WIDE_INT, rtx, rtx);
/* Auxiliary functions to check using return with null epilogue. */ /* Auxiliary functions to check using return with null epilogue. */
extern int nds32_can_use_return_insn (void); extern int nds32_can_use_return_insn (void);
......
...@@ -2402,6 +2402,8 @@ nds32_asm_globalize_label (FILE *stream, const char *name) ...@@ -2402,6 +2402,8 @@ nds32_asm_globalize_label (FILE *stream, const char *name)
static void static void
nds32_print_operand (FILE *stream, rtx x, int code) nds32_print_operand (FILE *stream, rtx x, int code)
{ {
HOST_WIDE_INT one_position;
HOST_WIDE_INT zero_position;
int op_value; int op_value;
switch (code) switch (code)
...@@ -2410,6 +2412,26 @@ nds32_print_operand (FILE *stream, rtx x, int code) ...@@ -2410,6 +2412,26 @@ nds32_print_operand (FILE *stream, rtx x, int code)
/* Do nothing special. */ /* Do nothing special. */
break; break;
case 'b':
/* Use exact_log2() to search the 0-bit position. */
gcc_assert (CONST_INT_P (x));
zero_position = exact_log2 (~UINTVAL (x) & GET_MODE_MASK (SImode));
gcc_assert (zero_position != -1);
fprintf (stream, HOST_WIDE_INT_PRINT_DEC, zero_position);
/* No need to handle following process, so return immediately. */
return;
case 'B':
/* Use exact_log2() to search the 1-bit position. */
gcc_assert (CONST_INT_P (x));
one_position = exact_log2 (UINTVAL (x) & GET_MODE_MASK (SImode));
gcc_assert (one_position != -1);
fprintf (stream, HOST_WIDE_INT_PRINT_DEC, one_position);
/* No need to handle following process, so return immediately. */
return;
case 'V': case 'V':
/* 'x' is supposed to be CONST_INT, get the value. */ /* 'x' is supposed to be CONST_INT, get the value. */
gcc_assert (CONST_INT_P (x)); gcc_assert (CONST_INT_P (x));
......
...@@ -51,6 +51,10 @@ ...@@ -51,6 +51,10 @@
(and (match_operand 0 "const_int_operand") (and (match_operand 0 "const_int_operand")
(match_test "satisfies_constraint_Iu05 (op)"))) (match_test "satisfies_constraint_Iu05 (op)")))
(define_predicate "nds32_rimm5u_operand"
(ior (match_operand 0 "register_operand")
(match_operand 0 "nds32_imm5u_operand")))
(define_predicate "nds32_move_operand" (define_predicate "nds32_move_operand"
(and (match_operand 0 "general_operand") (and (match_operand 0 "general_operand")
(not (match_code "high,const,symbol_ref,label_ref"))) (not (match_code "high,const,symbol_ref,label_ref")))
...@@ -65,6 +69,40 @@ ...@@ -65,6 +69,40 @@
return true; return true;
}) })
(define_predicate "nds32_and_operand"
(match_operand 0 "nds32_reg_constant_operand")
{
return REG_P (op)
|| GET_CODE (op) == SUBREG
|| satisfies_constraint_Izeb (op)
|| satisfies_constraint_Izeh (op)
|| satisfies_constraint_Ixls (op)
|| satisfies_constraint_Ix11 (op)
|| satisfies_constraint_Ibms (op)
|| satisfies_constraint_Ifex (op)
|| satisfies_constraint_Iu15 (op)
|| satisfies_constraint_Ii15 (op)
|| satisfies_constraint_Ic15 (op);
})
(define_predicate "nds32_ior_operand"
(match_operand 0 "nds32_reg_constant_operand")
{
return REG_P (op)
|| GET_CODE (op) == SUBREG
|| satisfies_constraint_Iu15 (op)
|| satisfies_constraint_Ie15 (op);
})
(define_predicate "nds32_xor_operand"
(match_operand 0 "nds32_reg_constant_operand")
{
return REG_P (op)
|| GET_CODE (op) == SUBREG
|| satisfies_constraint_Iu15 (op)
|| satisfies_constraint_It15 (op);
})
(define_predicate "nds32_general_register_operand" (define_predicate "nds32_general_register_operand"
(match_code "reg,subreg") (match_code "reg,subreg")
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment