diff options
author | Hans-Peter Nilsson <hp@axis.com> | 2020-02-06 04:46:34 +0100 |
---|---|---|
committer | Hans-Peter Nilsson <hp@axis.com> | 2020-05-09 04:20:26 +0200 |
commit | b73bf8a14dd77531d72426beec22c8e4b80a22a7 (patch) | |
tree | 7193f5f847be8df8670ba68a4eb42a838fc506ed /gcc | |
parent | d137723be6b9bb0f7c0e69aea0c6735ad092f366 (diff) | |
download | gcc-b73bf8a14dd77531d72426beec22c8e4b80a22a7.zip gcc-b73bf8a14dd77531d72426beec22c8e4b80a22a7.tar.gz gcc-b73bf8a14dd77531d72426beec22c8e4b80a22a7.tar.bz2 |
cris: Enable single-bit btst/btstq to set condition codes.
Enables the use of btst / btstq for a single bit (at other bits
than 0, including as indicated by a variable) to set
condition-codes. There's also a bug-fix for the bit-0-btstq
pattern; it shouldn't generate CCmode as only the Z flag is
valid, still using CC_NZmode is ok, as only equality-tests are
generated. The cris_rtx_costs tweak is necessary or else
combine will consider the btst not preferable. It reduces the
difference to cc0-costs beyond the threshold to the
transformation being seen as profitable, but there's still a
difference in values for the pre-split-time btst+branch as
opposed to the cc0 btst and branch, with both appearing to be
the cost of several insns (18 and 22).
gcc:
* config/cris/cris-modes.def (CC_ZnN): New CC_MODE.
* config/cris/cris.c (cris_rtx_costs): Handle pre-split bit-test
* config/cris/cris.md (ZnNNZSET, ZnNNZUSE): New mode_iterators.
(znnCC, rznnCC): New code_attrs.
("*btst<mode>"): Iterator over ZnNNZSET instead of NZVCSET. Remove
obseolete comment. Add belt-and-suspenders mode-test to condition.
Add fixme regarding remaining matched-but-not-generated case.
("*cbranch<mode>4_btstrq1_<CC>"): New insn_and_split.
("*cbranch<mode>4_btstqb0_<CC>"): Rename from
"*cbranch<mode>4_btstq<CC>". Split to CC_NZ instead of CC.
("*b<zcond:code><mode>"): Iterate over ZnNNZUSE instead of NZUSE.
Handle output of CC_ZnNmode.
("*b<nzcond:code>_reversed<mode>"): Ditto.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 14 | ||||
-rw-r--r-- | gcc/config/cris/cris-modes.def | 6 | ||||
-rw-r--r-- | gcc/config/cris/cris.c | 26 | ||||
-rw-r--r-- | gcc/config/cris/cris.md | 70 |
4 files changed, 96 insertions, 20 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 9aca1c3..8f14fdb 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -153,6 +153,20 @@ from "bswapsi2". ("*uminsi3<setcc><setnz><setnzvc>"): Rename from "*uminsi3". + * config/cris/cris-modes.def (CC_ZnN): New CC_MODE. + * config/cris/cris.c (cris_rtx_costs): Handle pre-split bit-test + * config/cris/cris.md (ZnNNZSET, ZnNNZUSE): New mode_iterators. + (znnCC, rznnCC): New code_attrs. + ("*btst<mode>"): Iterator over ZnNNZSET instead of NZVCSET. Remove + obseolete comment. Add belt-and-suspenders mode-test to condition. + Add fixme regarding remaining matched-but-not-generated case. + ("*cbranch<mode>4_btstrq1_<CC>"): New insn_and_split. + ("*cbranch<mode>4_btstqb0_<CC>"): Rename from + "*cbranch<mode>4_btstq<CC>". Split to CC_NZ instead of CC. + ("*b<zcond:code><mode>"): Iterate over ZnNNZUSE instead of NZUSE. + Handle output of CC_ZnNmode. + ("*b<nzcond:code>_reversed<mode>"): Ditto. + 2020-05-08 Vladimir Makarov <vmakarov@redhat.com> * ira-color.c (update_costs_from_allocno): Remove diff --git a/gcc/config/cris/cris-modes.def b/gcc/config/cris/cris-modes.def index 1e72b53..1aaf12a 100644 --- a/gcc/config/cris/cris-modes.def +++ b/gcc/config/cris/cris-modes.def @@ -28,8 +28,6 @@ along with GCC; see the file COPYING3. If not see (fpcraz). The two subsets meaningful to gcc are all of N, Z, V, C versus just N, Z; some CC-users care only about N and/or Z and some that care about at least one of those flags together with V and/or C. - (FIXME: the result of testing a single bit using the btst instruction - should be described as a separate mode.) The plain "CC_MODE (CC)" (which is always present in gcc), is used to reflect the "unoptimized" state, where the CC-setter is a compare @@ -52,3 +50,7 @@ CC_MODE (CC_NZ); are set to usable values, fpcraz. For a condition-code user: at least one of V and C are used and possibly N and Z too. */ CC_MODE (CC_NZVC); + +/* The result of a btst / btstq instruction for extracting a single bit + goes negated into the N flag, or in olde cc0-parlance, CC_Z_IN_NOT_N. */ +CC_MODE (CC_ZnN); diff --git a/gcc/config/cris/cris.c b/gcc/config/cris/cris.c index 04c80c3..d0807ad 100644 --- a/gcc/config/cris/cris.c +++ b/gcc/config/cris/cris.c @@ -1772,8 +1772,30 @@ cris_rtx_costs (rtx x, machine_mode mode, int outer_code, int opno, return false; case ZERO_EXTRACT: - if (outer_code != COMPARE) - return false; + /* Conditionals are split after reload, giving a different look. */ + if (reload_completed) + { + if (outer_code != COMPARE) + return false; + } + else + switch (outer_code) + { + case EQ: + case NE: + case LT: + case LTU: + case LE: + case LEU: + case GT: + case GTU: + case GE: + case GEU: + break; + + default: + return false; + } /* fall through */ case ZERO_EXTEND: case SIGN_EXTEND: diff --git a/gcc/config/cris/cris.md b/gcc/config/cris/cris.md index c085e26..1e895a3 100644 --- a/gcc/config/cris/cris.md +++ b/gcc/config/cris/cris.md @@ -197,6 +197,8 @@ (define_mode_iterator NZUSE [CC CC_NZ CC_NZVC]) (define_mode_iterator NZVCSET [CC CC_NZVC CC_NZ]) (define_mode_iterator NZVCUSE [CC_NZVC]) +(define_mode_iterator ZnNNZSET [CC_ZnN CC_NZ]) +(define_mode_iterator ZnNNZUSE [CC CC_ZnN CC_NZ CC_NZVC]) ;; All conditions. (define_code_iterator cond [eq ne gtu ltu geu leu gt le lt ge]) @@ -230,6 +232,12 @@ ;; Reverse of oCC. (define_code_attr roCC [(lt "pl") (ge "mi") (gtu "eq") (ltu "ne")]) +;; CC_Z_IN_NOT_N, a.k.a. CC_ZnNmode. +(define_code_attr znnCC [(eq "pl") (ne "mi")]) + +;;; ...and the reverse +(define_code_attr rznnCC [(eq "mi") (ne "pl")]) + ;; Required unoptimized CCmode, different for nzcond and nzvccond. (define_code_attr xCC [(eq "CC") (ne "CC") (gtu "CC") (ltu "CC_NZVC") (geu "CC_NZVC") (leu "CC") (lt "CC") (ge "CC") @@ -386,20 +394,20 @@ ;; of zeros starting at bit 0). ;; SImode. This mode is the only one needed, since gcc automatically -;; extends subregs for lower-size modes. FIXME: Add testcase. +;; extends subregs for lower-size modes. (define_insn "*btst<mode>" - [(set (reg:NZVCSET CRIS_CC0_REGNUM) - (compare:NZVCSET + [(set (reg:ZnNNZSET CRIS_CC0_REGNUM) + (compare:ZnNNZSET (zero_extract:SI (match_operand:SI 0 "nonmemory_operand" "r, r,r, r,r, r,Kp") (match_operand:SI 1 "const_int_operand" "Kc,n,Kc,n,Kc,n,n") (match_operand:SI 2 "nonmemory_operand" "M, M,Kc,n,r, r,r")) (const_int 0)))] ;; Either it is a single bit, or consecutive ones starting at 0. - ;; The btst ones depend on stuff in NOTICE_UPDATE_CC. "reload_completed && CONST_INT_P (operands[1]) - && (operands[1] == const1_rtx || operands[2] == const0_rtx) + && ((operands[1] == const1_rtx && <MODE>mode == CC_ZnNmode) + || (operands[2] == const0_rtx && <MODE>mode == CC_NZmode)) && (REG_S_P (operands[0]) || (operands[1] == const1_rtx && REG_S_P (operands[2]) @@ -410,7 +418,7 @@ ;; The next-to-last "&&" condition above should be caught by some kind of ;; canonicalization in gcc, but we can easily help with it here. ;; It results from expressions of the type -;; "power_of_2_value & (1 << y)". +;; "power_of_2_value & (1 << y)". FIXME: Add testcase. ;; ;; Since there may be codes with tests in on bits (in constant position) ;; beyond the size of a word, handle that by assuming those bits are 0. @@ -2099,8 +2107,34 @@ (pc)))] "") -;; FIXME: this matches only a subset of what the "*btst" pattern can handle. -(define_insn_and_split "*cbranch<mode>4_btstq<CC>" +;; Test a single bit at operand[0] against 0/non-0. +(define_insn_and_split "*cbranch<mode>4_btstrq1_<CC>" + [(set (pc) + (if_then_else + (zcond + (zero_extract:BWD + (match_operand:BWD 0 "register_operand" "r,r") + (const_int 1) + (match_operand:SI 1 "nonmemory_operand" "Kc,r")) + (const_int 0)) + (label_ref (match_operand 2 "")) + (pc))) + (clobber (reg:CC CRIS_CC0_REGNUM))] + "" + "#" + "&& reload_completed" + [(set (reg:CC_ZnN CRIS_CC0_REGNUM) + (compare:CC_ZnN + (zero_extract:SI (match_dup 0) (const_int 1) (match_dup 1)) + (const_int 0))) + (set (pc) + (if_then_else (zcond (reg:CC_ZnN CRIS_CC0_REGNUM) (const_int 0)) + (label_ref (match_dup 2)) + (pc)))] + "") + +;; Test a field of bits starting at bit 0 against 0/non-0. +(define_insn_and_split "*cbranch<mode>4_btstqb0_<CC>" [(set (pc) (if_then_else (zcond @@ -2115,12 +2149,12 @@ "" "#" "&& reload_completed" - [(set (reg:CC CRIS_CC0_REGNUM) - (compare:CC + [(set (reg:CC_NZ CRIS_CC0_REGNUM) + (compare:CC_NZ (zero_extract:SI (match_dup 0) (match_dup 1) (const_int 0)) (const_int 0))) (set (pc) - (if_then_else (zcond (reg:CC CRIS_CC0_REGNUM) (const_int 0)) + (if_then_else (zcond (reg:CC_NZ CRIS_CC0_REGNUM) (const_int 0)) (label_ref (match_dup 2)) (pc)))] "") @@ -2132,12 +2166,14 @@ (define_insn "*b<zcond:code><mode>" [(set (pc) - (if_then_else (zcond (reg:NZUSE CRIS_CC0_REGNUM) + (if_then_else (zcond (reg:ZnNNZUSE CRIS_CC0_REGNUM) (const_int 0)) (label_ref (match_operand 0 "" "")) (pc)))] "reload_completed" - "b<CC> %l0%#" +{ + return <MODE>mode == CC_ZnNmode ? "b<znnCC> %l0%#" : "b<CC> %l0%#"; +} [(set_attr "slottable" "has_slot")]) (define_insn "*b<nzvccond:code><mode>" @@ -2166,12 +2202,14 @@ (define_insn "*b<nzcond:code>_reversed<mode>" [(set (pc) - (if_then_else (nzcond (reg:NZUSE CRIS_CC0_REGNUM) - (const_int 0)) + (if_then_else (nzcond (reg:ZnNNZUSE CRIS_CC0_REGNUM) + (const_int 0)) (pc) (label_ref (match_operand 0 "" ""))))] "reload_completed" - "b<rCC> %l0%#" +{ + return <MODE>mode == CC_ZnNmode ? "b<rznnCC> %l0%#" : "b<rCC> %l0%#"; +} [(set_attr "slottable" "has_slot")]) (define_insn "*b<nzvccond:code>_reversed<mode>" |