From 22307666bcd3f82234c424ec2ad8bb03326198a8 Mon Sep 17 00:00:00 2001 From: Kito Cheng Date: Thu, 5 Apr 2018 02:51:45 +0000 Subject: [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. (si3, *ashlsi3, *ashrsi3, *lshrsi3, *rotrsi3): Ditto. * config/nds32/predicates.md (nds32_rimm5u_operand, nds32_and_operand, nds32_ior_operand, nds32_xor_operand): New predicates. git-svn-id: https://gcc.gnu.org/svn/gcc/trunk@259117 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 17 +++ gcc/config/nds32/iterators.md | 6 + gcc/config/nds32/nds32-md-auxiliary.c | 46 +++++++ gcc/config/nds32/nds32-protos.h | 5 + gcc/config/nds32/nds32.c | 22 ++++ gcc/config/nds32/nds32.md | 219 +++++++++++++++++----------------- gcc/config/nds32/predicates.md | 38 ++++++ 7 files changed, 242 insertions(+), 111 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index da7eed24019..19ea1ab7f62 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,20 @@ +2018-04-05 Kito Cheng + Chung-Ju Wu + + * 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. + (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 * config/nds32/nds32.md (add3, sub3): Rename to ... diff --git a/gcc/config/nds32/iterators.md b/gcc/config/nds32/iterators.md index c587921a39d..e0798ff812f 100644 --- a/gcc/config/nds32/iterators.md +++ b/gcc/config/nds32/iterators.md @@ -61,10 +61,16 @@ ;; Code iterators. ;;---------------------------------------------------------------------------- +;; shifts +(define_code_iterator shift_rotate [ashift ashiftrt lshiftrt rotatert]) ;;---------------------------------------------------------------------------- ;; Code attributes. ;;---------------------------------------------------------------------------- +;; shifts +(define_code_attr shift + [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr") (rotatert "rotr")]) + ;;---------------------------------------------------------------------------- diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c index f707f198530..607bcc21211 100644 --- a/gcc/config/nds32/nds32-md-auxiliary.c +++ b/gcc/config/nds32/nds32-md-auxiliary.c @@ -2111,3 +2111,49 @@ nds32_long_call_p (rtx symbol) { 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)); + } +} diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h index 97aad41840b..42f8dd9d762 100644 --- a/gcc/config/nds32/nds32-protos.h +++ b/gcc/config/nds32/nds32-protos.h @@ -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_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. */ extern int nds32_can_use_return_insn (void); diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index 829e097eae2..74ff621664f 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -2402,6 +2402,8 @@ nds32_asm_globalize_label (FILE *stream, const char *name) static void nds32_print_operand (FILE *stream, rtx x, int code) { + HOST_WIDE_INT one_position; + HOST_WIDE_INT zero_position; int op_value; switch (code) @@ -2410,6 +2412,26 @@ nds32_print_operand (FILE *stream, rtx x, int code) /* Do nothing special. */ 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': /* 'x' is supposed to be CONST_INT, get the value. */ gcc_assert (CONST_INT_P (x)); diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md index 95345ff7af8..b7c82b69798 100644 --- a/gcc/config/nds32/nds32.md +++ b/gcc/config/nds32/nds32.md @@ -323,7 +323,7 @@ (define_insn "addsi3" [(set (match_operand:SI 0 "register_operand" "= d, l, d, l, d, l, k, l, r, r") (plus:SI (match_operand:SI 1 "register_operand" "% 0, l, 0, l, 0, l, 0, k, r, r") - (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))] + (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,Iu06, Is15, r")))] "" { switch (which_alternative) @@ -400,10 +400,10 @@ (set_attr "length" "4")]) (define_insn "*add_srli" - [(set (match_operand:SI 0 "register_operand" "= r") - (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "immediate_operand" " Iu05")) - (match_operand:SI 3 "register_operand" " r")))] + [(set (match_operand:SI 0 "register_operand" "= r") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] "TARGET_ISA_V3" "add_srli\t%0, %3, %1, %2" [(set_attr "type" "alu_shift") @@ -555,14 +555,28 @@ (set_attr "length" "4")] ) -(define_insn "andsi3" - [(set (match_operand:SI 0 "register_operand" "=w, r, l, l, l, l, l, l, r, r, r, r, r") - (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r") - (match_operand:SI 2 "general_operand" " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))] +(define_expand "andsi3" + [(set (match_operand:SI 0 "register_operand" "") + (and:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nds32_reg_constant_operand" "")))] + "" +{ + if (CONST_INT_P (operands[2]) + && !nds32_and_operand (operands[2], SImode)) + { + nds32_expand_constant (SImode, INTVAL (operands[2]), + operands[0], operands[1]); + DONE; + } +}) + +(define_insn "*andsi3" + [(set (match_operand:SI 0 "register_operand" "=l, r, l, l, l, l, l, l, r, r, r, r, r") + (and:SI (match_operand:SI 1 "register_operand" "%0, r, l, l, l, l, 0, 0, r, r, r, r, r") + (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))] "" { HOST_WIDE_INT mask = INTVAL (operands[2]); - int zero_position; /* 16-bit andi instructions: andi Rt3,Ra3,0xff -> zeb33 Rt3,Ra3 @@ -587,8 +601,7 @@ case 5: return "x11b33\t%0, %1"; case 6: - operands[2] = GEN_INT (floor_log2 (mask)); - return "bmski33\t%0, %2"; + return "bmski33\t%0, %B2"; case 7: operands[2] = GEN_INT (floor_log2 (mask + 1) - 1); return "fexti33\t%0, %2"; @@ -602,20 +615,7 @@ operands[2] = GEN_INT (~mask); return "bitci\t%0, %1, %2"; case 12: - /* If we reach this alternative, - it must pass the nds32_can_use_bclr_p() test, - so that we can guarantee there is only one 0-bit - within the immediate value. */ - for (zero_position = 31; zero_position >= 0; zero_position--) - { - if ((INTVAL (operands[2]) & (1 << zero_position)) == 0) - { - /* Found the 0-bit position. */ - operands[2] = GEN_INT (zero_position); - break; - } - } - return "bclr\t%0, %1, %2"; + return "bclr\t%0, %1, %b2"; default: gcc_unreachable (); @@ -652,54 +652,46 @@ ;; For V3/V3M ISA, we have 'or33' instruction. ;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2. -(define_insn "iorsi3" - [(set (match_operand:SI 0 "register_operand" "=w, r, r, r") - (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") - (match_operand:SI 2 "general_operand" " w, r, Iu15, Ie15")))] + +(define_expand "iorsi3" + [(set (match_operand:SI 0 "register_operand" "") + (ior:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "general_operand" "")))] "" { - int one_position; - - switch (which_alternative) - { - case 0: - return "or33\t%0, %2"; - case 1: - return "or\t%0, %1, %2"; - case 2: - return "ori\t%0, %1, %2"; - case 3: - /* If we reach this alternative, - it must pass the nds32_can_use_bset_p() test, - so that we can guarantee there is only one 1-bit - within the immediate value. */ - /* Use exact_log2() to search the 1-bit position. */ - one_position = exact_log2 (INTVAL (operands[2])); - operands[2] = GEN_INT (one_position); - return "bset\t%0, %1, %2"; + if (!nds32_ior_operand (operands[2], SImode)) + operands[2] = force_reg (SImode, operands[2]); +}) - default: - gcc_unreachable (); - } -} - [(set_attr "type" "alu,alu,alu,alu") - (set_attr "length" " 2, 4, 4, 4")]) +(define_insn "*iorsi3" + [(set (match_operand:SI 0 "register_operand" "=l, r, r, r") + (ior:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") + (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))] + "" + "@ + or33\t%0, %2 + or\t%0, %1, %2 + ori\t%0, %1, %2 + bset\t%0, %1, %B2" + [(set_attr "type" "alu,alu,alu,alu") + (set_attr "length" " 2, 4, 4, 4") + (set_attr "feature" "v3m, v1, v1,pe1")]) (define_insn "*or_slli" - [(set (match_operand:SI 0 "register_operand" "= r") - (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "immediate_operand" " Iu05")) - (match_operand:SI 3 "register_operand" " r")))] + [(set (match_operand:SI 0 "register_operand" "= r") + (ior:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] "TARGET_ISA_V3" "or_slli\t%0, %3, %1, %2" [(set_attr "type" "alu_shift") (set_attr "length" "4")]) (define_insn "*or_srli" - [(set (match_operand:SI 0 "register_operand" "= r") - (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "immediate_operand" " Iu05")) - (match_operand:SI 3 "register_operand" " r")))] + [(set (match_operand:SI 0 "register_operand" "= r") + (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] "TARGET_ISA_V3" "or_srli\t%0, %3, %1, %2" [(set_attr "type" "alu_shift") @@ -712,36 +704,27 @@ ;; For V3/V3M ISA, we have 'xor33' instruction. ;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2. -(define_insn "xorsi3" - [(set (match_operand:SI 0 "register_operand" "=w, r, r, r") - (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") - (match_operand:SI 2 "general_operand" " w, r, Iu15, It15")))] + +(define_expand "xorsi3" + [(set (match_operand:SI 0 "register_operand" "") + (xor:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "general_operand" "")))] "" { - int one_position; - - switch (which_alternative) - { - case 0: - return "xor33\t%0, %2"; - case 1: - return "xor\t%0, %1, %2"; - case 2: - return "xori\t%0, %1, %2"; - case 3: - /* If we reach this alternative, - it must pass the nds32_can_use_btgl_p() test, - so that we can guarantee there is only one 1-bit - within the immediate value. */ - /* Use exact_log2() to search the 1-bit position. */ - one_position = exact_log2 (INTVAL (operands[2])); - operands[2] = GEN_INT (one_position); - return "btgl\t%0, %1, %2"; + if (!nds32_xor_operand (operands[2], SImode)) + operands[2] = force_reg (SImode, operands[2]); +}) - default: - gcc_unreachable (); - } -} +(define_insn "*xorsi3" + [(set (match_operand:SI 0 "register_operand" "=l, r, r, r") + (xor:SI (match_operand:SI 1 "register_operand" "%0, r, r, r") + (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))] + "" + "@ + xor33\t%0, %2 + xor\t%0, %1, %2 + xori\t%0, %1, %2 + btgl\t%0, %1, %B2" [(set_attr "type" "alu,alu,alu,alu") (set_attr "length" " 2, 4, 4, 4") (set_attr "feature" "v3m, v1, v1,pe1")]) @@ -749,7 +732,7 @@ (define_insn "*xor_slli" [(set (match_operand:SI 0 "register_operand" "= r") (xor:SI (ashift:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "immediate_operand" " Iu05")) + (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) (match_operand:SI 3 "register_operand" " r")))] "TARGET_ISA_V3" "xor_slli\t%0, %3, %1, %2" @@ -757,10 +740,10 @@ (set_attr "length" "4")]) (define_insn "*xor_srli" - [(set (match_operand:SI 0 "register_operand" "= r") - (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") - (match_operand:SI 2 "immediate_operand" " Iu05")) - (match_operand:SI 3 "register_operand" " r")))] + [(set (match_operand:SI 0 "register_operand" "= r") + (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand" " r") + (match_operand:SI 2 "nds32_imm5u_operand" " Iu05")) + (match_operand:SI 3 "register_operand" " r")))] "TARGET_ISA_V3" "xor_srli\t%0, %3, %1, %2" [(set_attr "type" "alu_shift") @@ -768,10 +751,10 @@ ;; Rotate Right Instructions. -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "= r, r") - (rotatert:SI (match_operand:SI 1 "register_operand" " r, r") - (match_operand:SI 2 "nonmemory_operand" " Iu05, r")))] +(define_insn "*rotrsi3" + [(set (match_operand:SI 0 "register_operand" "= r, r") + (rotatert:SI (match_operand:SI 1 "register_operand" " r, r") + (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))] "" "@ rotri\t%0, %1, %2 @@ -822,10 +805,23 @@ ;; Shift instructions. -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "= l, r, r") - (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r") - (match_operand:SI 2 "nonmemory_operand" " Iu03, Iu05, r")))] +(define_expand "si3" + [(set (match_operand:SI 0 "register_operand" "") + (shift_rotate:SI (match_operand:SI 1 "register_operand" "") + (match_operand:SI 2 "nds32_rimm5u_operand" "")))] + "" +{ + if (operands[2] == const0_rtx) + { + emit_move_insn (operands[0], operands[1]); + DONE; + } +}) + +(define_insn "*ashlsi3" + [(set (match_operand:SI 0 "register_operand" "= l, r, r") + (ashift:SI (match_operand:SI 1 "register_operand" " l, r, r") + (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))] "" "@ slli333\t%0, %1, %2 @@ -834,10 +830,11 @@ [(set_attr "type" " alu, alu, alu") (set_attr "subtype" "shift,shift,shift") (set_attr "length" " 2, 4, 4")]) -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "register_operand" "= d, r, r") - (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") - (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))] + +(define_insn "*ashrsi3" + [(set (match_operand:SI 0 "register_operand" "= d, r, r") + (ashiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") + (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))] "" "@ srai45\t%0, %2 @@ -847,10 +844,10 @@ (set_attr "subtype" "shift,shift,shift") (set_attr "length" " 2, 4, 4")]) -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "= d, r, r") - (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") - (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))] +(define_insn "*lshrsi3" + [(set (match_operand:SI 0 "register_operand" "= d, r, r") + (lshiftrt:SI (match_operand:SI 1 "register_operand" " 0, r, r") + (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))] "" "@ srli45\t%0, %2 diff --git a/gcc/config/nds32/predicates.md b/gcc/config/nds32/predicates.md index 7cf4635e1cf..066ec3471ea 100644 --- a/gcc/config/nds32/predicates.md +++ b/gcc/config/nds32/predicates.md @@ -51,6 +51,10 @@ (and (match_operand 0 "const_int_operand") (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" (and (match_operand 0 "general_operand") (not (match_code "high,const,symbol_ref,label_ref"))) @@ -65,6 +69,40 @@ 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" (match_code "reg,subreg") { -- cgit v1.2.3