This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH, MIPS] Add bbit* Octeon instructions
Richard Sandiford wrote:
> OK, but it still seems odd to remove SImode stuff from 64-bit targets.
> They generally ought to allow both. The concern isn't so much the number
> of bbit instructions, but the number of mode changes (and the effect they
> can have on optimisation).
OK. I think the argument that even if the backend does not emit SI mode
zero_extract the middle end is free to do so is a convincing one.
Trying to be a minimalist, I was adding tests to try to catch this.
> The target can logically do both 32-bit and 64-bit ops, so I think the
> fallback position is to keep things simple and stick to :GPR.
Sure. To describe the HW as having bbit SI is certainly more accurate.
> (define_delay (and (eq_attr "type" "branch")
> (eq (symbol_ref "TARGET_MIPS16") (const_int 0))
> (eq_attr "branch_likely" "yes"))
> [(eq_attr "can_delay" "yes")
> (nil)
> (eq_attr "can_delay" "yes")])
>
> ;; Branches that don't have likely variants do not annul on false.
> (define_delay (and (eq_attr "type" "branch")
> (eq (symbol_ref "TARGET_MIPS16") (const_int 0))
> (eq_attr "branch_likely" "no"))
> [(eq_attr "can_delay" "yes")
> (nil)
> (nil)])
>
> (I believe "and" can take more than 2 arguments in this context.)
Sure, it works. Also for some reason I thought "and" was not completely
like in Lisp.
> OK with that change, if it works.
I had to remove const from the definition of branch_likely. This is
what I committed after reboostrapping and retesting.
Adam
* config/mips/mips.h (ISA_HAS_BBIT): New macro.
* config/mips/mips.md (branch_likely): Remove const. Fix
comment formatting.
(define_delay for type "branch"): Change to only apply for branch
with likely variant.
(define_delay for type "branch" and "branch_likely" no). New delay
definition.
(equality_op): New code iterator.
(bbv, bbinv): New code attributes.
(*branch_bit<bbv><mode>, *branch_bit<bbv><mode>_inverted): New
patterns.
testsuite/
* gcc.target/mips/octeon-bbit-1.c: New test.
* gcc.target/mips/octeon-bbit-2.c: New test.
* gcc.target/mips/octeon-bbit-3.c: New test.
Index: gcc/config/mips/mips.h
===================================================================
*** gcc.orig/config/mips/mips.h 2008-08-28 16:46:50.000000000 -0700
--- gcc/config/mips/mips.h 2008-08-28 16:49:41.000000000 -0700
*************** enum mips_code_readable_setting {
*** 1006,1011 ****
--- 1006,1014 ----
? TARGET_LLSC && !TARGET_MIPS16 \
: ISA_HAS_LL_SC)
+ /* ISA includes the bbit* instructions. */
+ #define ISA_HAS_BBIT TARGET_OCTEON
+
/* ISA includes the pop instruction. */
#define ISA_HAS_POP TARGET_OCTEON
Index: gcc/config/mips/mips.md
===================================================================
*** gcc.orig/config/mips/mips.md 2008-08-28 16:49:17.000000000 -0700
--- gcc/config/mips/mips.md 2008-08-28 16:53:59.000000000 -0700
***************
*** 599,610 ****
(const_string "yes")
(const_string "no")))
! ;; Attribute defining whether or not we can use the branch-likely instructions
(define_attr "branch_likely" "no,yes"
! (const
! (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
! (const_string "yes")
! (const_string "no"))))
;; True if an instruction might assign to hi or lo when reloaded.
;; This is used by the TUNE_MACC_CHAINS code.
--- 599,610 ----
(const_string "yes")
(const_string "no")))
! ;; Attribute defining whether or not we can use the branch-likely
! ;; instructions.
(define_attr "branch_likely" "no,yes"
! (if_then_else (ne (symbol_ref "GENERATE_BRANCHLIKELY") (const_int 0))
! (const_string "yes")
! (const_string "no")))
;; True if an instruction might assign to hi or lo when reloaded.
;; This is used by the TUNE_MACC_CHAINS code.
***************
*** 788,793 ****
--- 788,796 ----
;; by swapping the operands.
(define_code_iterator swapped_fcond [ge gt unge ungt])
+ ;; Equality operators.
+ (define_code_iterator equality_op [eq ne])
+
;; These code iterators allow the signed and unsigned scc operations to use
;; the same template.
(define_code_iterator any_gt [gt gtu])
***************
*** 848,853 ****
--- 851,862 ----
(unge "ule")
(ungt "ult")])
+ ;; The value of the bit when the branch is taken for branch_bit patterns.
+ ;; Comparison is always against zero so this depends on the operator.
+ (define_code_attr bbv [(eq "0") (ne "1")])
+
+ ;; This is the inverse value of bbv.
+ (define_code_attr bbinv [(eq "1") (ne "0")])
;; .........................
;;
***************
*** 856,866 ****
;; .........................
(define_delay (and (eq_attr "type" "branch")
! (eq (symbol_ref "TARGET_MIPS16") (const_int 0)))
[(eq_attr "can_delay" "yes")
(nil)
! (and (eq_attr "branch_likely" "yes")
! (eq_attr "can_delay" "yes"))])
(define_delay (eq_attr "type" "jump")
[(eq_attr "can_delay" "yes")
--- 865,883 ----
;; .........................
(define_delay (and (eq_attr "type" "branch")
! (eq (symbol_ref "TARGET_MIPS16") (const_int 0))
! (eq_attr "branch_likely" "yes"))
[(eq_attr "can_delay" "yes")
(nil)
! (eq_attr "can_delay" "yes")])
!
! ;; Branches that don't have likely variants do not annul on false.
! (define_delay (and (eq_attr "type" "branch")
! (eq (symbol_ref "TARGET_MIPS16") (const_int 0))
! (eq_attr "branch_likely" "no"))
! [(eq_attr "can_delay" "yes")
! (nil)
! (nil)])
(define_delay (eq_attr "type" "jump")
[(eq_attr "can_delay" "yes")
***************
*** 5052,5057 ****
--- 5069,5118 ----
(if_then_else (match_operand 0)
(label_ref (match_operand 1))
(pc)))])
+
+ ;; Branch if bit is set/clear.
+
+ (define_insn "*branch_bit<bbv><mode>"
+ [(set (pc)
+ (if_then_else
+ (equality_op (zero_extract:GPR
+ (match_operand:GPR 1 "register_operand" "d")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0))
+ (label_ref (match_operand 0 ""))
+ (pc)))]
+ "ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
+ {
+ return
+ mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"),
+ MIPS_BRANCH ("bbit<bbinv>", "%1,%2,%0"));
+ }
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "branch_likely" "no")])
+
+ (define_insn "*branch_bit<bbv><mode>_inverted"
+ [(set (pc)
+ (if_then_else
+ (equality_op (zero_extract:GPR
+ (match_operand:GPR 1 "register_operand" "d")
+ (const_int 1)
+ (match_operand 2 "const_int_operand" ""))
+ (const_int 0))
+ (pc)
+ (label_ref (match_operand 0 ""))))]
+ "ISA_HAS_BBIT && UINTVAL (operands[2]) < GET_MODE_BITSIZE (<MODE>mode)"
+ {
+ return
+ mips_output_conditional_branch (insn, operands,
+ MIPS_BRANCH ("bbit<bbinv>", "%1,%2,%0"),
+ MIPS_BRANCH ("bbit<bbv>", "%1,%2,%0"));
+ }
+ [(set_attr "type" "branch")
+ (set_attr "mode" "none")
+ (set_attr "branch_likely" "no")])
;;
;; ....................
Index: gcc/testsuite/gcc.target/mips/octeon-bbit-1.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.target/mips/octeon-bbit-1.c 2008-08-28 16:49:41.000000000 -0700
***************
*** 0 ****
--- 1,55 ----
+ /* { dg-do compile } */
+ /* { dg-mips-options "-O2 -march=octeon" } */
+ /* { dg-final { scan-assembler-times "\tbbit1\t" 4 } } */
+ /* { dg-final { scan-assembler-times "\tbbit0\t" 2 } } */
+ /* { dg-final { scan-assembler-not "andi\t" } } */
+
+ NOMIPS16 void
+ f1 (long long i)
+ {
+ if (i & 0x80)
+ foo ();
+ }
+
+ NOMIPS16 void
+ f2 (int i)
+ {
+ if (!(i & 0x80))
+ foo ();
+ }
+
+ NOMIPS16 void
+ f3 (int i)
+ {
+ if (i % 2)
+ foo ();
+ }
+
+ NOMIPS16 void
+ f4 (int i)
+ {
+ if (i & 1)
+ foo ();
+ }
+
+ NOMIPS16 void
+ f5 (long long i)
+ {
+ if ((i >> 3) & 1)
+ foo ();
+ }
+
+ unsigned long long r;
+
+ NOMIPS16 static inline __attribute__((always_inline)) int
+ test_bit(unsigned long long nr, const unsigned long long *addr)
+ {
+ return 1UL & (addr[nr >> 6] >> (nr & 63ULL));
+ }
+
+ NOMIPS16 void
+ f6 ()
+ {
+ if (!test_bit(0, &r))
+ g ();
+ }
Index: gcc/testsuite/gcc.target/mips/octeon-bbit-2.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.target/mips/octeon-bbit-2.c 2008-08-28 16:49:41.000000000 -0700
***************
*** 0 ****
--- 1,24 ----
+ /* { dg-do compile } */
+ /* { dg-mips-options "-O2 -march=octeon -mbranch-likely" } */
+ /* { dg-final { scan-assembler "\tbbit\[01\]\t" } } */
+ /* { dg-final { scan-assembler-not "\tbbit\[01\]l\t" } } */
+ /* { dg-final { scan-assembler "\tbnel\t" } } */
+ /* { dg-final { scan-assembler-not "\tbne\t" } } */
+
+ NOMIPS16 int
+ f (int n, int i)
+ {
+ int s = 0;
+ for (; i & 1; i++)
+ s += i;
+ return s;
+ }
+
+ NOMIPS16 int
+ g (int n, int i)
+ {
+ int s = 0;
+ for (i = 0; i < n; i++)
+ s += i;
+ return s;
+ }
Index: gcc/testsuite/gcc.target/mips/octeon-bbit-3.c
===================================================================
*** /dev/null 1970-01-01 00:00:00.000000000 +0000
--- gcc/testsuite/gcc.target/mips/octeon-bbit-3.c 2008-08-28 16:49:41.000000000 -0700
***************
*** 0 ****
--- 1,31 ----
+ /* { dg-do compile } */
+ /* { dg-mips-options "-O2 -march=octeon" } */
+ /* { dg-final { scan-assembler-times "\tbbit\[01\]\t|\tbgez\t" 2 } } */
+ /* { dg-final { scan-assembler-not "ext\t" } } */
+
+ void abort (void);
+ void exit (int);
+
+ typedef unsigned long long ulong64;
+
+ typedef struct bitfield_s {
+ ulong64 a:1;
+ ulong64 b:29;
+ ulong64 c:1;
+ ulong64 d:15;
+ ulong64 f:18;
+ } bitfield_t;
+
+ bitfield_t bar;
+
+ NOMIPS16 void
+ f ()
+ {
+ foo(&bar);
+ if (bar.a != 0x1)
+ abort ();
+ else if (!bar.c)
+ abort ();
+ else
+ exit (0);
+ }