aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorHans-Peter Nilsson <hp@axis.com>2020-02-06 04:46:34 +0100
committerHans-Peter Nilsson <hp@axis.com>2020-05-09 04:20:26 +0200
commitb73bf8a14dd77531d72426beec22c8e4b80a22a7 (patch)
tree7193f5f847be8df8670ba68a4eb42a838fc506ed /gcc
parentd137723be6b9bb0f7c0e69aea0c6735ad092f366 (diff)
downloadgcc-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/ChangeLog14
-rw-r--r--gcc/config/cris/cris-modes.def6
-rw-r--r--gcc/config/cris/cris.c26
-rw-r--r--gcc/config/cris/cris.md70
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>"