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]

patch: fix e500 comparisons


Sigh... A customer found a comparison bug while running spec2k.  It turns
out we were actually looking at the wrong bit for some combinations
of comparisons.  The code worked because the hardware was apparently 
_also_ setting an undefined bit which we were looking at.

Interestingly enough, this worked on e500 v1, but not on v2.  I've
fixed it: hopefully, once and for all.

The patch below has been tested on actual hardware, and has been
used to build and test an entire gcc + glibc combo.  It also validates
spec2k int.

Committed to mainline, 4.0-branch, 3.4-e500-branch.

Aldy

	* config/rs6000/rs6000-protos.h: Rename output_e500_flip_eq_bit to
	output_e500_flip_gt_bit.

	* config/rs6000/rs6000.c (print_operand): case D: Print out bit 31
	as bit 31.
	(rs6000_generate_compare): Fix logic to look at the correct bits.
	(output_e500_flip_eq_bit): Rename to output_e500_flip_gt_bit.
	Look at GT bit.
	(rs6000_emit_sCOND): Rename gen_e500_flip_eq_bit to
	gen_e500_flip_gt_bit.  Rename gen_move_from_CR_eq_bit to
	gen_move_from_CR_gt_bit.

	* config/rs6000/rs6000.md ("move_from_CR_eq_bit"): Change bit
	("move_from_CR_eq_bit"): Rename to move_from_CR_gt_bit.
	(UNSPEC_MV_CR_EQ): Rename to UNSPEC_MV_CR_GT.

	* config/rs6000/spe.md ("e500_cr_ior_compare"): New.
	(E500_CR_IOR_COMPARE): New constant.

Index: config/rs6000/rs6000-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000-protos.h,v
retrieving revision 1.94
diff -c -p -r1.94 rs6000-protos.h
*** config/rs6000/rs6000-protos.h	2 Mar 2005 14:03:42 -0000	1.94
--- config/rs6000/rs6000-protos.h	8 Mar 2005 00:23:27 -0000
*************** extern enum rtx_code rs6000_reverse_cond
*** 76,82 ****
  extern void rs6000_emit_sCOND (enum rtx_code, rtx);
  extern void rs6000_emit_cbranch (enum rtx_code, rtx);
  extern char * output_cbranch (rtx, const char *, int, rtx);
! extern char * output_e500_flip_eq_bit (rtx, rtx);
  extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
  extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
  extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
--- 76,82 ----
  extern void rs6000_emit_sCOND (enum rtx_code, rtx);
  extern void rs6000_emit_cbranch (enum rtx_code, rtx);
  extern char * output_cbranch (rtx, const char *, int, rtx);
! extern char * output_e500_flip_gt_bit (rtx, rtx);
  extern rtx rs6000_emit_set_const (rtx, enum machine_mode, rtx, int);
  extern int rs6000_emit_cmove (rtx, rtx, rtx, rtx);
  extern int rs6000_emit_vector_cond_expr (rtx, rtx, rtx, rtx, rtx, rtx);
Index: config/rs6000/rs6000.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.c,v
retrieving revision 1.791
diff -c -p -r1.791 rs6000.c
*** config/rs6000/rs6000.c	3 Mar 2005 01:03:28 -0000	1.791
--- config/rs6000/rs6000.c	8 Mar 2005 00:23:35 -0000
*************** print_operand (FILE *file, rtx x, int co
*** 9211,9218 ****
        /* Bit 1 is EQ bit.  */
        i = 4 * (REGNO (x) - CR0_REGNO) + 2;
  
!       /* If we want bit 31, write a shift count of zero, not 32.  */
!       fprintf (file, "%d", i == 31 ? 0 : i + 1);
        return;
  
      case 'E':
--- 9211,9217 ----
        /* Bit 1 is EQ bit.  */
        i = 4 * (REGNO (x) - CR0_REGNO) + 2;
  
!       fprintf (file, "%d", i);
        return;
  
      case 'E':
*************** rs6000_generate_compare (enum rtx_code c
*** 10017,10023 ****
    if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT)
        && rs6000_compare_fp_p)
      {
!       rtx cmp, or1, or2, or_result, compare_result2;
        enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
  
        if (op_mode == VOIDmode)
--- 10016,10022 ----
    if ((TARGET_E500 && !TARGET_FPRS && TARGET_HARD_FLOAT)
        && rs6000_compare_fp_p)
      {
!       rtx cmp, or_result, compare_result2;
        enum machine_mode op_mode = GET_MODE (rs6000_compare_op0);
  
        if (op_mode == VOIDmode)
*************** rs6000_generate_compare (enum rtx_code c
*** 10091,10099 ****
  	    default: abort ();
  	    }
  
- 	  or1 = gen_reg_rtx (SImode);
- 	  or2 = gen_reg_rtx (SImode);
- 	  or_result = gen_reg_rtx (CCEQmode);
  	  compare_result2 = gen_reg_rtx (CCFPmode);
  
  	  /* Do the EQ.  */
--- 10090,10095 ----
*************** rs6000_generate_compare (enum rtx_code c
*** 10112,10125 ****
  	  else abort ();
  	  emit_insn (cmp);
  
- 	  or1 = gen_rtx_GT (SImode, compare_result, const0_rtx);
- 	  or2 = gen_rtx_GT (SImode, compare_result2, const0_rtx);
- 
  	  /* OR them together.  */
! 	  cmp = gen_rtx_SET (VOIDmode, or_result,
! 			     gen_rtx_COMPARE (CCEQmode,
! 					      gen_rtx_IOR (SImode, or1, or2),
! 					      const_true_rtx));
  	  compare_result = or_result;
  	  code = EQ;
  	}
--- 10108,10117 ----
  	  else abort ();
  	  emit_insn (cmp);
  
  	  /* OR them together.  */
! 	  or_result = gen_reg_rtx (CCFPmode);
! 	  cmp = gen_e500_cr_ior_compare (or_result, compare_result,
! 					   compare_result2);
  	  compare_result = or_result;
  	  code = EQ;
  	}
*************** rs6000_emit_sCOND (enum rtx_code code, r
*** 10229,10237 ****
  	abort ();
  
        if (cond_code == NE)
! 	emit_insn (gen_e500_flip_eq_bit (t, t));
  
!       emit_insn (gen_move_from_CR_eq_bit (result, t));
        return;
      }
  
--- 10221,10229 ----
  	abort ();
  
        if (cond_code == NE)
! 	emit_insn (gen_e500_flip_gt_bit (t, t));
  
!       emit_insn (gen_move_from_CR_gt_bit (result, t));
        return;
      }
  
*************** output_cbranch (rtx op, const char *labe
*** 10412,10420 ****
    return string;
  }
  
! /* Return the string to flip the EQ bit on a CR.  */
  char *
! output_e500_flip_eq_bit (rtx dst, rtx src)
  {
    static char string[64];
    int a, b;
--- 10404,10412 ----
    return string;
  }
  
! /* Return the string to flip the GT bit on a CR.  */
  char *
! output_e500_flip_gt_bit (rtx dst, rtx src)
  {
    static char string[64];
    int a, b;
*************** output_e500_flip_eq_bit (rtx dst, rtx sr
*** 10423,10431 ****
        || GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src)))
      abort ();
  
!   /* EQ bit.  */
!   a = 4 * (REGNO (dst) - CR0_REGNO) + 2;
!   b = 4 * (REGNO (src) - CR0_REGNO) + 2;
  
    sprintf (string, "crnot %d,%d", a, b);
    return string;
--- 10415,10423 ----
        || GET_CODE (src) != REG || ! CR_REGNO_P (REGNO (src)))
      abort ();
  
!   /* GT bit.  */
!   a = 4 * (REGNO (dst) - CR0_REGNO) + 1;
!   b = 4 * (REGNO (src) - CR0_REGNO) + 1;
  
    sprintf (string, "crnot %d,%d", a, b);
    return string;
Index: config/rs6000/rs6000.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/rs6000.md,v
retrieving revision 1.352
diff -c -p -r1.352 rs6000.md
*** config/rs6000/rs6000.md	1 Mar 2005 22:23:25 -0000	1.352
--- config/rs6000/rs6000.md	8 Mar 2005 00:23:39 -0000
***************
*** 50,56 ****
     (UNSPEC_TLSGOTTPREL		28)
     (UNSPEC_TLSTLS		29)
     (UNSPEC_FIX_TRUNC_TF		30)	; fadd, rounding towards zero
!    (UNSPEC_MV_CR_EQ		31)	; move_from_CR_eq_bit
    ])
  
  ;;
--- 50,56 ----
     (UNSPEC_TLSGOTTPREL		28)
     (UNSPEC_TLSTLS		29)
     (UNSPEC_FIX_TRUNC_TF		30)	; fadd, rounding towards zero
!    (UNSPEC_MV_CR_GT		31)	; move_from_CR_eq_bit
    ])
  
  ;;
***************
*** 11476,11486 ****
     (set_attr "length" "8")])
  
  ;; Same as above, but get the GT bit.
! (define_insn "move_from_CR_eq_bit"
    [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
! 	(unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_EQ))]
    "TARGET_E500"
!   "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,1"
    [(set_attr "type" "mfcr")
     (set_attr "length" "8")])
  
--- 11476,11486 ----
     (set_attr "length" "8")])
  
  ;; Same as above, but get the GT bit.
! (define_insn "move_from_CR_gt_bit"
    [(set (match_operand:SI 0 "gpc_reg_operand" "=r")
! 	(unspec:SI [(match_operand 1 "cc_reg_operand" "y")] UNSPEC_MV_CR_GT))]
    "TARGET_E500"
!   "mfcr %0\;{rlinm|rlwinm} %0,%0,%D1,31,31"
    [(set_attr "type" "mfcr")
     (set_attr "length" "8")])
  
Index: config/rs6000/spe.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/rs6000/spe.md,v
retrieving revision 1.32
diff -c -p -r1.32 spe.md
*** config/rs6000/spe.md	18 Jan 2005 12:01:42 -0000	1.32
--- config/rs6000/spe.md	8 Mar 2005 00:23:40 -0000
***************
*** 29,34 ****
--- 29,35 ----
     (TSTDFGT_GPR		1009)
     (CMPDFLT_GPR		1010)
     (TSTDFLT_GPR		1011)
+    (E500_CR_IOR_COMPARE 1012)
     ])
  
  (define_insn "*negsf2_gpr"
***************
*** 2615,2628 ****
  ;; FP comparison stuff.
  
  ;; Flip the GT bit.
! (define_insn "e500_flip_eq_bit"
    [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
  	(unspec:CCFP
  	 [(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))]
    "!TARGET_FPRS && TARGET_HARD_FLOAT"
    "*
  {
!   return output_e500_flip_eq_bit (operands[0], operands[1]);
  }"
    [(set_attr "type" "cr_logical")])
  
--- 2616,2629 ----
  ;; FP comparison stuff.
  
  ;; Flip the GT bit.
! (define_insn "e500_flip_gt_bit"
    [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
  	(unspec:CCFP
  	 [(match_operand:CCFP 1 "cc_reg_operand" "y")] 999))]
    "!TARGET_FPRS && TARGET_HARD_FLOAT"
    "*
  {
!   return output_e500_flip_gt_bit (operands[0], operands[1]);
  }"
    [(set_attr "type" "cr_logical")])
  
***************
*** 2751,2753 ****
--- 2752,2764 ----
    "TARGET_HARD_FLOAT && TARGET_E500_DOUBLE && flag_unsafe_math_optimizations"
    "efdtstlt %0,%1,%2"
    [(set_attr "type" "veccmpsimple")])
+ 
+ ;; Like cceq_ior_compare, but compare the GT bits.
+ (define_insn "e500_cr_ior_compare"
+   [(set (match_operand:CCFP 0 "cc_reg_operand" "=y")
+ 	(unspec:CCFP [(match_operand 1 "cc_reg_operand" "y")
+ 		      (match_operand 2 "cc_reg_operand" "y")]
+ 		     E500_CR_IOR_COMPARE))]
+   "TARGET_E500"
+   "cror 4*%0+gt,4*%1+gt,4*%2+gt"
+   [(set_attr "type" "cr_logical")])


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