GCC Bugzilla – Attachment 36012 Details for
Bug 54236
[SH] Improve addc and subc insn utilization
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Help
|
New Account
|
Log In
Remember
[x]
|
Forgot Password
Login:
[x]
[patch]
addsicc pattern
sh_pr54236_10.patch (text/plain), 9.50 KB, created by
Oleg Endo
on 2015-07-19 06:47:47 UTC
(
hide
)
Description:
addsicc pattern
Filename:
MIME Type:
Creator:
Oleg Endo
Created:
2015-07-19 06:47:47 UTC
Size:
9.50 KB
patch
obsolete
>Index: gcc/config/sh/predicates.md >=================================================================== >--- gcc/config/sh/predicates.md (revision 223478) >+++ gcc/config/sh/predicates.md (working copy) >@@ -1158,10 +1158,18 @@ > > ;; A predicate describing the T bit register in any form. > (define_predicate "t_reg_operand" >- (match_code "reg,subreg,sign_extend,zero_extend") >+ (match_code "reg,subreg,sign_extend,zero_extend,ne,eq") > { > switch (GET_CODE (op)) > { >+ case EQ: >+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) >+ && XEXP (op, 1) == const1_rtx; >+ >+ case NE: >+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) >+ && XEXP (op, 1) == const0_rtx; >+ > case REG: > return REGNO (op) == T_REG; > >@@ -1183,13 +1191,21 @@ > > ;; A predicate describing a negated T bit register. > (define_predicate "negt_reg_operand" >- (match_code "subreg,xor") >+ (match_code "subreg,xor,ne,eq") > { > switch (GET_CODE (op)) > { >+ case EQ: >+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) >+ && XEXP (op, 1) == const0_rtx; >+ >+ case NE: >+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) >+ && XEXP (op, 1) == const1_rtx; >+ > case XOR: > return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))) >- && satisfies_constraint_M (XEXP (op, 1)); >+ && XEXP (op, 1) == const1_rtx; > > case SUBREG: > return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0))); >Index: gcc/config/sh/sh.c >=================================================================== >--- gcc/config/sh/sh.c (revision 223478) >+++ gcc/config/sh/sh.c (working copy) >@@ -3589,13 +3589,12 @@ > > case EQ: > /* An and with a constant compared against zero is >- most likely going to be a TST #imm, R0 instruction. >- Notice that this does not catch the zero_extract variants from >- the md file. */ >+ most likely going to be a TST #imm, R0 instruction. */ > if (XEXP (x, 1) == const0_rtx >- && (GET_CODE (XEXP (x, 0)) == AND >- || (SUBREG_P (XEXP (x, 0)) >- && GET_CODE (SUBREG_REG (XEXP (x, 0))) == AND))) >+ && ((GET_CODE (XEXP (x, 0)) == AND >+ || (SUBREG_P (XEXP (x, 0)) >+ && GET_CODE (SUBREG_REG (XEXP (x, 0))) == AND)) >+ || GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT)) > { > *total = 1; > return true; >@@ -14150,7 +14149,8 @@ > return false; > > /* Early accept known possible operands before doing recog. */ >- if (op == const0_rtx || op == const1_rtx || t_reg_operand (op, mode)) >+ if (op == const0_rtx || op == const1_rtx || t_reg_operand (op, mode) >+ || negt_reg_operand (op, mode)) > return true; > > /* Early reject impossible operands before doing recog. >@@ -14159,8 +14159,8 @@ > such as lower-subreg will bail out. Some insns such as SH4A movua are > done with UNSPEC, so must reject those, too, or else it would result > in an invalid reg -> treg move. */ >- if (register_operand (op, mode) || memory_operand (op, mode) >- || sh_unspec_insn_p (op)) >+ if (CONST_INT_P (op) || register_operand (op, mode) >+ || memory_operand (op, mode) || sh_unspec_insn_p (op)) > return false; > > if (!can_create_pseudo_p ()) >@@ -14174,26 +14174,30 @@ > SET_PREV_INSN (i) = NULL; > SET_NEXT_INSN (i) = NULL; > >+ /* If the comparison op doesn't have a result mode, set it to SImode. */ >+ machine_mode prev_op_mode = GET_MODE (op); >+ if (COMPARISON_P (op) && prev_op_mode == VOIDmode) >+ PUT_MODE (op, SImode); >+ > int result = recog (PATTERN (i), i, 0); > >- /* It seems there is no insn like that. Create a simple negated >- version and try again. If we hit a negated form, we'll allow that >- and append a nott sequence when splitting out the insns. Insns that >- do the split can then remove the trailing nott if they know how to >- deal with it. */ >- if (result < 0 && GET_CODE (op) == EQ) >+ /* It seems there is no insn like that. Create a negated version and >+ try again. If we hit a negated form, we'll allow that and append a >+ nott sequence when splitting out the insns. Insns that do the split >+ can then remove the trailing nott if they know how to deal with it. */ >+ if (result < 0 && COMPARISON_P (op)) > { >- PUT_CODE (op, NE); >+ machine_mode cmp_mode = GET_MODE (XEXP (op, 0)); >+ if (cmp_mode == VOIDmode) >+ cmp_mode = GET_MODE (XEXP (op, 1)); >+ >+ rtx_code prev_code = GET_CODE (op); >+ PUT_CODE (op, reverse_condition (GET_CODE (op))); > result = recog (PATTERN (i), i, 0); >- PUT_CODE (op, EQ); >+ PUT_CODE (op, prev_code); > } >- if (result < 0 && GET_CODE (op) == NE) >- { >- PUT_CODE (op, EQ); >- result = recog (PATTERN (i), i, 0); >- PUT_CODE (op, NE); >- } > >+ PUT_MODE (op, prev_op_mode); > recog_data = prev_recog_data; > return result >= 0; > } >@@ -14294,37 +14298,43 @@ > fprintf (dump_file, "\n"); > } > >+ /* If the insn is not found, we will try a negated form and append >+ a nott. */ >+ bool append_nott = false; >+ > /* We are going to invoke recog/split_insns in a re-entrant way and thus > have to capture its current state and restore it afterwards. */ > recog_data_d prev_recog_data = recog_data; > >- int insn_code = recog (PATTERN (i), i, 0); >- >- /* If the insn was not found, see if we matched the negated form before >- and append a nott. */ >- bool append_nott = false; >- >- if (insn_code < 0 && GET_CODE (x) == EQ) >+ if (negt_reg_operand (x, GET_MODE (x))) > { >- PUT_CODE (x, NE); >- insn_code = recog (PATTERN (i), i, 0); >- if (insn_code >= 0) >- append_nott = true; >- else >- PUT_CODE (x, EQ); >+ /* This is a normal movt followed by a nott. It will be converted >+ into a movrt after initial expansion. */ >+ XEXP (PATTERN (i), 1) = get_t_reg_rtx (); >+ append_nott = true; > } >- if (insn_code < 0 && GET_CODE (x) == NE) >+ else > { >- PUT_CODE (x, EQ); >- insn_code = recog (PATTERN (i), i, 0); >- if (insn_code >= 0) >- append_nott = true; >- else >- PUT_CODE (x, NE); >+ /* If the comparison op doesn't have a mode set, set it to SImode. */ >+ if (COMPARISON_P (x) && GET_MODE (x) == VOIDmode) >+ PUT_MODE (x, SImode); >+ >+ int insn_code = recog (PATTERN (i), i, 0); >+ >+ if (insn_code < 0 && COMPARISON_P (x)) >+ { >+ machine_mode cmp_mode = GET_MODE (XEXP (x, 0)); >+ if (cmp_mode == VOIDmode) >+ cmp_mode = GET_MODE (XEXP (x, 1)); >+ >+ PUT_CODE (x, reverse_condition (GET_CODE (x))); >+ insn_code = recog (PATTERN (i), i, 0); >+ append_nott = true; >+ } >+ >+ gcc_assert (insn_code >= 0); > } > >- gcc_assert (insn_code >= 0); >- > /* Try to recursively split the insn. Some insns might refuse to split > any further while we are in the treg_set_expr splitting phase. They > will be emitted as part of the outer insn and then split again. */ >Index: gcc/config/sh/sh.md >=================================================================== >--- gcc/config/sh/sh.md (revision 223479) >+++ gcc/config/sh/sh.md (working copy) >@@ -1918,7 +1918,7 @@ > ;; T bit doesn't matter. This is easier for combine to pick up. > ;; We allow a reg or 0 for one of the operands in order to be able to > ;; do 'reg + T' sequences. >-(define_insn_and_split "*addc" >+(define_insn_and_split "addc_1" > [(set (match_operand:SI 0 "arith_reg_dest") > (plus:SI (plus:SI (match_operand:SI 1 "arith_reg_operand") > (match_operand:SI 2 "arith_reg_or_0_operand")) >@@ -2189,6 +2189,37 @@ > } > [(set_attr "type" "arith")]) > >+;; Conditional addition can be done using the addc/subc insn for >+;; constants 1 and -1. >+;; The addsicc pattern is usually used by the ifcvt pass, which tries >+;; to replace a conditional branch with an addition of the original comparison >+;; result. The original comparison will not be propagated into addsicc, >+;; but rather the result of that tested for 0 or 1 again. As a consequence, >+;; there might be some T bit toggling insns between the addsicc and the >+;; original comparison. Combine will fold this away for us. >+(define_expand "addsicc" >+ [(match_operand:SI 0 "register_operand") >+ (match_operand 1 "treg_set_expr") >+ (match_operand:SI 2 "register_operand") >+ (match_operand:SI 3 "const_int_operand")] >+ "TARGET_SH1 && can_create_pseudo_p ()" >+{ >+ if (operands[3] == const1_rtx) >+ { >+ emit_insn (gen_addc_1 (operands[0], >+ operands[2], const0_rtx, operands[1])); >+ DONE; >+ } >+ if (operands[3] == constm1_rtx) >+ { >+ emit_insn (gen_subc_1 (operands[0], >+ operands[2], const0_rtx, operands[1])); >+ DONE; >+ } >+ >+ FAIL; >+}) >+ > ;; ------------------------------------------------------------------------- > ;; Subtraction instructions > ;; ------------------------------------------------------------------------- >@@ -2262,7 +2293,7 @@ > ;; We allow a reg or 0 for one of the operands in order to be able to > ;; do 'reg - T' sequences. Reload will load the constant 0 into the reg > ;; as needed. >-(define_insn_and_split "*subc" >+(define_insn_and_split "subc_1" > [(set (match_operand:SI 0 "arith_reg_dest") > (minus:SI (minus:SI (match_operand:SI 1 "arith_reg_operand") > (match_operand:SI 2 "arith_reg_or_0_operand")) >@@ -12090,6 +12121,14 @@ > } > [(set_attr "type" "arith")]) > >+(define_peephole2 >+ [(set (match_operand:SI 0 "arith_reg_dest") >+ (neg:SI (match_operand 1 "t_reg_operand"))) >+ (set (match_operand:SI 2 "arith_reg_dest") >+ (match_dup 0))] >+ "TARGET_SH1 && peep2_reg_dead_p (2, operands[0])" >+ [(set (match_dup 2) (neg:SI (match_dup 1)))]) >+ > ;; The *movtt pattern eliminates redundant T bit to T bit moves / tests. > (define_insn_and_split "*movtt" > [(set (reg:SI T_REG)
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 54236
:
31141
|
31144
| 36012