fixed optimization/13260

Joern Rennecke joern.rennecke@superh.com
Thu Dec 4 21:11:00 GMT 2003


The problem is that ifcvt uses the scc expanders, which were meant to
be used at rtl generation time.  The SH implemnets scc by first emitting
a comparison, which clobbers the T hard register, and then moving the
result into the target register.  Once we start rtl optimizations, the T
register could be life pretty much anywhere, thus it is no longer save
to use the standard rtl expansion method.
To make the scc patterns safe, I have made them fail when rtl generation
is over.  But with that change alone, ifcvt generates atrocious code, so
I've also added some code to handle equality comparisons of the T register
against integer constants - these are the only ones that ifcvt will find
in branch instructions, and they can be handled without changing the value
of the T register.

2003-12-04  J"orn Rennecke <joern.rennecke@superh.com>

	PR optimization/13260
	* sh-protos.h (sh_expand_t_scc): Declare.
	* sh.h (PREDICATE_CODES): Add cmpsi_operand.
	* sh.c (cmpsi_operand, sh_expand_t_scc): New functions.
	* sh.md (cmpsi): Use cmpsi_operand.  If T_REG is compared to
	something that is not a CONST_INT, copy it into a pseudo register.
	(subc): Fix description of new T value.
	(slt, sgt, sge, sgtu): Don't clobber T after rtl generation is over.
	(sltu, sleu, sgeu): Likewise.
	(seq, sne): Likewise. Use sh_expand_t_scc.

Index: config/sh/sh-protos.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh-protos.h,v
retrieving revision 1.50
diff -p -r1.50 sh-protos.h
*** config/sh/sh-protos.h	7 Nov 2003 17:44:57 -0000	1.50
--- config/sh/sh-protos.h	4 Dec 2003 15:32:26 -0000
*************** extern int sh_insn_length_adjustment (rt
*** 97,102 ****
--- 97,103 ----
  extern int sh_can_redirect_branch (rtx, rtx);
  extern void sh_expand_unop_v2sf (enum rtx_code, rtx, rtx);
  extern void sh_expand_binop_v2sf (enum rtx_code, rtx, rtx, rtx);
+ extern int sh_expand_t_scc (enum rtx_code code, rtx target);
  #ifdef TREE_CODE
  extern void sh_va_start (tree, rtx);
  extern rtx sh_va_arg (tree, tree);
Index: config/sh/sh.h
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.h,v
retrieving revision 1.227
diff -p -r1.227 sh.h
*** config/sh/sh.h	7 Nov 2003 17:44:57 -0000	1.227
--- config/sh/sh.h	4 Dec 2003 15:32:27 -0000
*************** extern int rtx_equal_function_value_matt
*** 3145,3150 ****
--- 3145,3151 ----
    {"arith_reg_or_0_operand", {SUBREG, REG, CONST_INT, CONST_VECTOR}},	\
    {"binary_float_operator", {PLUS, MINUS, MULT, DIV}},			\
    {"binary_logical_operator", {AND, IOR, XOR}},				\
+   {"cmpsi_operand", {SUBREG, REG, CONST_INT}},				\
    {"commutative_float_operator", {PLUS, MULT}},				\
    {"equality_comparison_operator", {EQ,NE}},				\
    {"extend_reg_operand", {SUBREG, REG, TRUNCATE}},			\
Index: config/sh/sh.c
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.c,v
retrieving revision 1.239
diff -p -r1.239 sh.c
*** config/sh/sh.c	7 Nov 2003 17:44:57 -0000	1.239
--- config/sh/sh.c	4 Dec 2003 15:32:27 -0000
*************** sh_register_operand (rtx op, enum machin
*** 8898,8903 ****
--- 8898,8912 ----
    return register_operand (op, mode);
  }
  
+ int
+ cmpsi_operand (rtx op, enum machine_mode mode)
+ {
+   if (GET_CODE (op) == REG && REGNO (op) == T_REG
+       && GET_MODE (op) == SImode)
+     return 1;
+   return arith_operand (op, mode);
+ }
+ 
  static rtx emit_load_ptr (rtx, rtx);
  
  static rtx
*************** sh_get_pr_initial_val (void)
*** 9127,9132 ****
--- 9136,9170 ----
    if (TARGET_SH1)
      return gen_rtx_UNSPEC (SImode, gen_rtvec (1, val), UNSPEC_RA);
    return val;
+ }
+ 
+ int
+ sh_expand_t_scc (enum rtx_code code, rtx target)
+ {
+   rtx result = target;
+   HOST_WIDE_INT val;
+ 
+   if (GET_CODE (sh_compare_op0) != REG || REGNO (sh_compare_op0) != T_REG
+       || GET_CODE (sh_compare_op1) != CONST_INT)
+     return 0;
+   if (GET_CODE (result) != REG)
+     result = gen_reg_rtx (SImode);
+   val = INTVAL (sh_compare_op1);
+   if ((code == EQ && val == 1) || (code == NE && val == 0))
+     emit_insn (gen_movt (result));
+   else if ((code == EQ && val == 0) || (code == NE && val == 1))
+     {
+       emit_insn (gen_rtx_CLOBBER (VOIDmode, result));
+       emit_insn (gen_subc (result, result, result));
+       emit_insn (gen_addsi3 (result, result, GEN_INT (1)));
+     }
+   else if (code == EQ || code == NE)
+     emit_insn (gen_move_insn (result, GEN_INT (code == NE)));
+   else
+     return 0;
+   if (result != target)
+     emit_move_insn (target, result);
+   return 1;
  }
  
  #include "gt-sh.h"
Index: config/sh/sh.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/sh/sh.md,v
retrieving revision 1.161
diff -p -F^( -r1.161 sh.md
*** config/sh/sh.md	12 Nov 2003 14:05:42 -0000	1.161
--- config/sh/sh.md	4 Dec 2003 15:32:49 -0000
*************** (define_insn "cmpgtusi_t"
*** 705,715 ****
  
  (define_expand "cmpsi"
    [(set (reg:SI T_REG)
! 	(compare (match_operand:SI 0 "arith_operand" "")
  		 (match_operand:SI 1 "arith_operand" "")))]
    "TARGET_SH1"
    "
  {
    sh_compare_op0 = operands[0];
    sh_compare_op1 = operands[1];
    DONE;
--- 705,718 ----
  
  (define_expand "cmpsi"
    [(set (reg:SI T_REG)
! 	(compare (match_operand:SI 0 "cmpsi_operand" "")
  		 (match_operand:SI 1 "arith_operand" "")))]
    "TARGET_SH1"
    "
  {
+   if (GET_CODE (operands[0]) == REG && REGNO (operands[0]) == T_REG
+       && GET_CODE (operands[1]) != CONST_INT)
+     operands[0] = copy_to_mode_reg (SImode, operands[0]);
    sh_compare_op0 = operands[0];
    sh_compare_op1 = operands[1];
    DONE;
*************** (define_insn "subc"
*** 1167,1173 ****
  			    (match_operand:SI 2 "arith_reg_operand" "r"))
  		  (reg:SI T_REG)))
     (set (reg:SI T_REG)
! 	(gtu:SI (minus:SI (match_dup 1) (match_dup 2)) (match_dup 1)))]
    "TARGET_SH1"
    "subc	%2,%0"
    [(set_attr "type" "arith")])
--- 1170,1178 ----
  			    (match_operand:SI 2 "arith_reg_operand" "r"))
  		  (reg:SI T_REG)))
     (set (reg:SI T_REG)
! 	(gtu:SI (minus:SI (minus:SI (match_dup 1) (match_dup 2))
! 			  (reg:SI T_REG))
! 		(match_dup 1)))]
    "TARGET_SH1"
    "subc	%2,%0"
    [(set_attr "type" "arith")])
*************** (define_expand "seq"
*** 7446,7451 ****
--- 7451,7460 ----
  	}
        DONE;
      }
+   if (sh_expand_t_scc (EQ, operands[0]))
+     DONE;
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (EQ);
  }")
  
*************** (define_expand "slt"
*** 7492,7497 ****
--- 7501,7508 ----
  	}
        DONE;
      }
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (LT);
  }")
  
*************** (define_expand "sgt"
*** 7594,7599 ****
--- 7605,7612 ----
  	}
        DONE;
      }
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (GT);
  }")
  
*************** (define_expand "sge"
*** 7646,7651 ****
--- 7659,7666 ----
        DONE;
      }
  
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    if (GET_MODE_CLASS (GET_MODE (sh_compare_op0)) == MODE_FLOAT)
      {
        if (TARGET_IEEE)
*************** (define_expand "sgtu"
*** 7685,7690 ****
--- 7700,7707 ----
  				     sh_compare_op0, sh_compare_op1));
        DONE;
      }
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (GTU);
  }")
  
*************** (define_expand "sltu"
*** 7709,7714 ****
--- 7726,7733 ----
  				     sh_compare_op1, sh_compare_op0));
        DONE;
      }
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (LTU);
  }")
  
*************** (define_expand "sleu"
*** 7738,7743 ****
--- 7757,7764 ----
  
        DONE;
      }
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (LEU);
  }")
  
*************** (define_expand "sgeu"
*** 7768,7773 ****
--- 7789,7796 ----
        DONE;
      }
  
+   if (! rtx_equal_function_value_matters)
+     FAIL;
    operands[1] = prepare_scc_operands (GEU);
  }")
  
*************** (define_expand "sne"
*** 7815,7822 ****
        DONE;
      }
  
!    operands[1] = prepare_scc_operands (EQ);
!    operands[2] = gen_reg_rtx (SImode);
  }")
  
  (define_expand "sunordered"
--- 7838,7849 ----
        DONE;
      }
  
!   if (sh_expand_t_scc (NE, operands[0]))
!     DONE;
!   if (! rtx_equal_function_value_matters)
!     FAIL;
!   operands[1] = prepare_scc_operands (EQ);
!   operands[2] = gen_reg_rtx (SImode);
  }")
  
  (define_expand "sunordered"



More information about the Gcc-patches mailing list