This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Mips instruction hazards (part 2/4)


Following on from my last mail, this patch tries to give gcc
a better idea about where nops might be needed.  It also makes
ADJUST_INSN_LENGTH assume the worst case.

This will be somewhat pessimistic on mips1 targets since all loads will
be treated as 8 bytes long.  I don't think that's such a big deal though.
For one thing, there aren't many true mips1 targets around any more.
Even then, the difference only matters for large functions, many of
which suffer from out-of-range branches under the current code.

There was a slight snag...  In order to avoid a hardware bug,
the r4000 multiplication patterns include the mflo.  These patterns
are therefore subject to the same hazards as a normal mflo and mfhi.

Thing is, we were using the r4000 dmult pattern for mips16 as well
(even though we use the normal pattern for mult).  I've not heard
that any mips16 hardware has a bug in this area and there's no
comment in the code to suggest it has.  I checked the vr4100 manual
but couldn't see anything.

So, the patch switches mips16 to using the normal pattern and
applies the hazard only to r4000 code.

The patch fixes gcc.c-torture/compile/20001226-1.c -Os and
g++.dg/opt/longbranch1.C for mips-elf and mipsel-linux-gnu.
Tested on those targets, mips64vrel-elf and mips-sgi-irix6.5.
OK to install?

Richard


	* config/mips/mips.h (ISA_HAS_LOAD_DELAY, ISA_HAS_XFER_DELAY,
	ISA_HAS_FCMP_DELAY, ISA_HAS_HILO_INTERLOCKS): New macros.
	(PREDICATE_CODES): Add hilo_operand.
	* config/mips/mips.c (hilo_operand): New predicate.
	(mips_adjust_insn_length): Account for the number nops that might
	be needed to avoid hardware hazards.
	* config/mips/mips.md (dslot): Remove attribute.
	(hazard): New attribute.
	(can_delay): Use it.  Check for calls, branches & jumps.
	(muldi3): Use the standard dmult pattern for mips16 code.
	(muldi3_internal, muldi3_internal2): Adjust conditions accordingly.

Index: config/mips/mips.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.h,v
retrieving revision 1.251
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.251 mips.h
*** config/mips/mips.h	16 May 2003 18:57:42 -0000	1.251
--- config/mips/mips.h	18 May 2003 17:53:10 -0000
*************** #define ISA_HAS_SEB_SEH         (!TARGET
*** 967,972 ****
--- 967,990 ----
                                   && (ISA_MIPS32R2                      \
                                       ))
  
+ /* True if the result of a load is not available to the next instruction.
+    A nop will then be needed between instructions like "lw $4,..."
+    and "addiu $4,$4,1".  */
+ #define ISA_HAS_LOAD_DELAY	(mips_isa == 1				\
+ 				 && !TARGET_MIPS3900			\
+ 				 && !TARGET_MIPS16)
+ 
+ /* Likewise mtc1 and mfc1.  */
+ #define ISA_HAS_XFER_DELAY	(mips_isa <= 3)
+ 
+ /* Likewise floating-point comparisons.  */
+ #define ISA_HAS_FCMP_DELAY	(mips_isa <= 3)
+ 
+ /* True if mflo and mfhi can be immediately followed by instructions
+    which write to the HI and LO registers.  Most targets require a
+    two-instruction gap.  */
+ #define ISA_HAS_HILO_INTERLOCKS	(TARGET_MIPS5500 || TARGET_SB1)
+ 
  /* CC1_SPEC causes -mips3 and -mips4 to set -mfp64 and -mgp64; -mips1 or
     -mips2 sets -mfp32 and -mgp32.  This can be overridden by an explicit
     -mfp32, -mfp64, -mgp32 or -mgp64.  -mfp64 sets MASK_FLOAT64 in
*************** #define PREDICATE_CODES							\
*** 3396,3402 ****
  				  REG, MEM}},				\
    {"consttable_operand",	{ LABEL_REF, SYMBOL_REF, CONST_INT,	\
  				  CONST_DOUBLE, CONST }},		\
!   {"fcc_register_operand",	{ REG, SUBREG }},
  
  /* A list of predicates that do special things with modes, and so
     should not elicit warnings for VOIDmode match_operand.  */
--- 3414,3421 ----
  				  REG, MEM}},				\
    {"consttable_operand",	{ LABEL_REF, SYMBOL_REF, CONST_INT,	\
  				  CONST_DOUBLE, CONST }},		\
!   {"fcc_register_operand",	{ REG, SUBREG }},			\
!   {"hilo_operand",		{ REG }},
  
  /* A list of predicates that do special things with modes, and so
     should not elicit warnings for VOIDmode match_operand.  */
Index: config/mips/mips.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.c,v
retrieving revision 1.263
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.263 mips.c
*** config/mips/mips.c	14 May 2003 07:29:50 -0000	1.263
--- config/mips/mips.c	18 May 2003 17:53:08 -0000
*************** const_float_1_operand (op, mode)
*** 1522,1527 ****
--- 1522,1539 ----
    return REAL_VALUES_EQUAL (d, dconst1);
  }
  
+ /* Return true if OP is either the HI or LO register.  */
+ 
+ int
+ hilo_operand (op, mode)
+      rtx op;
+      enum machine_mode mode;
+ {
+   return ((mode == VOIDmode || mode == GET_MODE (op))
+ 	  && REG_P (op)
+ 	  && (REGNO (op) == HI_REGNUM || REGNO (op) == LO_REGNUM));
+ }
+ 
  /* Return nonzero if the code of this rtx pattern is EQ or NE.  */
  
  int
*************** mips_adjust_insn_length (insn, length)
*** 10221,10226 ****
--- 10233,10254 ----
        || (!TARGET_MIPS16  && (GET_CODE (insn) == JUMP_INSN
  			      || GET_CODE (insn) == CALL_INSN)))
      length += 4;
+ 
+   /* See how many nops might be needed to avoid hardware hazards.  */
+   if (INSN_CODE (insn) >= 0)
+     switch (get_attr_hazard (insn))
+       {
+       case HAZARD_NONE:
+ 	break;
+ 
+       case HAZARD_DELAY:
+ 	length += 4;
+ 	break;
+ 
+       case HAZARD_HILO:
+ 	length += 8;
+ 	break;
+       }
  
    /* All MIPS16 instructions are a measly two bytes.  */
    if (TARGET_MIPS16)
Index: config/mips/mips.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/mips/mips.md,v
retrieving revision 1.167
diff -c -d -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.167 mips.md
*** config/mips/mips.md	10 May 2003 22:59:01 -0000	1.167
--- config/mips/mips.md	18 May 2003 17:53:11 -0000
*************** (define_attr "cpu"
*** 193,209 ****
    "default,4kc,5kc,20kc,m4k,r3000,r3900,r6000,r4000,r4100,r4111,r4120,r4300,r4600,r4650,r5000,r5400,r5500,r8000,sb1,sr71000"
    (const (symbol_ref "mips_cpu_attr")))
  
! ;; Does the instruction have a mandatory delay slot?
! ;;   The 3900, is (mostly) mips1, but does not have a mandatory load delay
! ;;   slot.
! (define_attr "dslot" "no,yes"
!   (if_then_else (ior (eq_attr "type" "branch,jump,call,xfer,hilo,fcmp")
! 		     (and (eq_attr "type" "load")
! 			  (and (eq (symbol_ref "mips_isa") (const_int 1))
! 			       (and (eq (symbol_ref "mips16") (const_int 0))
!                                     (eq_attr "cpu" "!r3900")))))
! 		(const_string "yes")
! 		(const_string "no")))
  
  ;; Is it a single instruction?
  (define_attr "single_insn" "no,yes"
--- 193,225 ----
    "default,4kc,5kc,20kc,m4k,r3000,r3900,r6000,r4000,r4100,r4111,r4120,r4300,r4600,r4650,r5000,r5400,r5500,r8000,sb1,sr71000"
    (const (symbol_ref "mips_cpu_attr")))
  
! ;; The type of hardware hazard associated with this instruction.
! ;; DELAY means that the next instruction cannot read the result
! ;; of this one.  HILO means that the next two instructions cannot
! ;; write to HI or LO.
! (define_attr "hazard" "none,delay,hilo"
!   (cond [(and (eq_attr "type" "load")
! 	      (ne (symbol_ref "ISA_HAS_LOAD_DELAY") (const_int 0)))
! 	 (const_string "delay")
! 
! 	 (and (eq_attr "type" "xfer")
! 	      (ne (symbol_ref "ISA_HAS_XFER_DELAY") (const_int 0)))
! 	 (const_string "delay")
! 
! 	 (and (eq_attr "type" "fcmp")
! 	      (ne (symbol_ref "ISA_HAS_FCMP_DELAY") (const_int 0)))
! 	 (const_string "delay")
! 
! 	 ;; The r4000 multiplication patterns include an mflo instruction.
! 	 (and (eq_attr "type" "imul")
! 	      (ne (symbol_ref "TARGET_MIPS4000") (const_int 0)))
! 	 (const_string "hilo")
! 
! 	 (and (eq_attr "type" "hilo")
! 	      (and (eq (symbol_ref "ISA_HAS_HILO_INTERLOCKS") (const_int 0))
! 		   (match_operand 1 "hilo_operand" "")))
! 	 (const_string "hilo")]
! 	(const_string "none")))
  
  ;; Is it a single instruction?
  (define_attr "single_insn" "no,yes"
*************** (define_attr "single_insn" "no,yes"
*** 211,218 ****
  
  ;; Can the instruction be put into a delay slot?
  (define_attr "can_delay" "no,yes"
!   (if_then_else (and (eq_attr "dslot" "no")
! 		     (eq_attr "single_insn" "yes"))
  		(const_string "yes")
  		(const_string "no")))
  
--- 227,235 ----
  
  ;; Can the instruction be put into a delay slot?
  (define_attr "can_delay" "no,yes"
!   (if_then_else (and (eq_attr "type" "!branch,call,jump")
! 		     (and (eq_attr "hazard" "none")
! 			  (eq_attr "single_insn" "yes")))
  		(const_string "yes")
  		(const_string "no")))
  
*************** (define_expand "muldi3"
*** 2274,2280 ****
  
    "
  {
!   if (GENERATE_MULT3_DI || TARGET_MIPS4000 || TARGET_MIPS16)
      emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2]));
    else
      emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2]));
--- 2291,2297 ----
  
    "
  {
!   if (GENERATE_MULT3_DI || TARGET_MIPS4000)
      emit_insn (gen_muldi3_internal2 (operands[0], operands[1], operands[2]));
    else
      emit_insn (gen_muldi3_internal (operands[0], operands[1], operands[2]));
*************** (define_insn "muldi3_internal"
*** 2287,2293 ****
  		 (match_operand:DI 2 "register_operand" "d")))
     (clobber (match_scratch:DI 3 "=h"))
     (clobber (match_scratch:DI 4 "=a"))]
!   "TARGET_64BIT && !TARGET_MIPS4000 && !TARGET_MIPS16"
    "dmult\\t%1,%2"
    [(set_attr "type"	"imul")
     (set_attr "mode"	"DI")])
--- 2304,2310 ----
  		 (match_operand:DI 2 "register_operand" "d")))
     (clobber (match_scratch:DI 3 "=h"))
     (clobber (match_scratch:DI 4 "=a"))]
!   "TARGET_64BIT && !TARGET_MIPS4000"
    "dmult\\t%1,%2"
    [(set_attr "type"	"imul")
     (set_attr "mode"	"DI")])
*************** (define_insn "muldi3_internal2"
*** 2299,2305 ****
     (clobber (match_scratch:DI 3 "=h"))
     (clobber (match_scratch:DI 4 "=l"))
     (clobber (match_scratch:DI 5 "=a"))]
!   "TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000 || TARGET_MIPS16)"
    {
      if (GENERATE_MULT3_DI)
        return "dmult\t%0,%1,%2";
--- 2316,2322 ----
     (clobber (match_scratch:DI 3 "=h"))
     (clobber (match_scratch:DI 4 "=l"))
     (clobber (match_scratch:DI 5 "=a"))]
!   "TARGET_64BIT && (GENERATE_MULT3_DI || TARGET_MIPS4000)"
    {
      if (GENERATE_MULT3_DI)
        return "dmult\t%0,%1,%2";


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]