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]

[committed] frv adddi3 fixes


The frv adddi3 patterns were pretty broken as far as constant operands
are concerned.  The two main problems were:

   (a) The predicates enforced the correct range (10 bit signed immediate)
       but the constraints allowed 12-bit immediates.

   (b) The splitters used subicc/subx to handle additions by negative amounts.
       This ruled out additions by -512, even though the predicates and
       constraints accept -512.

This patch fixes (a) by using the constraint for 10-bit immediates ('J').
It fixes (b) by using addicc for the low part and addxi for the high part.

Tested on frv-elf.  Approved by Aldy, applied to mainline.

Richard


	* config/frv/frv.md (*adddi3_internal): Change name to...
	(adddi3): ...replacing the exisiting define_expand.  Combine
	alternatives.  Fix the range of the constant constraints ('J' instead
	of 'NOP').  Remove bogus operands[2] check.  Use simplify_gen_subreg
	to extract the lower and upper halves of the DImode operands.
	Always use addi3_lower and adddi3_upper, not the subdi3 forms.
	(adddi3_lower): Fix the range of the constant constraints and
	remove the bogus operands[2] check.
	(adddi3_upper): Use gpr_or_int10_operand as the predicate for
	operand 2.  Use addxi to handle constant operands.
	(subdi3_lower, subdi3_upper): Don't handle constant operands.

Index: config/frv/frv.md
===================================================================
RCS file: /cvs/gcc/gcc/gcc/config/frv/frv.md,v
retrieving revision 1.24
diff -c -p -F^\([(a-zA-Z0-9_]\|#define\) -r1.24 frv.md
*** config/frv/frv.md	5 Oct 2004 20:11:17 -0000	1.24
--- config/frv/frv.md	11 Oct 2004 12:07:18 -0000
*************** (define_insn "negsi2"
*** 2940,2996 ****
  ;; ::::::::::::::::::::
  
  ;; Addition
! (define_expand "adddi3"
!   [(parallel [(set (match_operand:DI 0 "integer_register_operand" "")
! 		   (plus:DI (match_operand:DI 1 "integer_register_operand" "")
! 			    (match_operand:DI 2 "gpr_or_int10_operand" "")))
! 	      (clobber (match_scratch:CC 3 ""))])]
    ""
-   "
- {
-   if (GET_CODE (operands[2]) == CONST_INT
-       && INTVAL (operands[2]) == -2048
-       && !no_new_pseudos)
-     operands[2] = force_reg (DImode, operands[2]);
- }")
- 
- (define_insn_and_split "*adddi3_internal"
-   [(set (match_operand:DI 0 "integer_register_operand" "=&e,e,e,&e,e,&e,e")
- 	(plus:DI (match_operand:DI 1 "integer_register_operand" "%e,0,e,e,0,e,0")
- 		 (match_operand:DI 2 "gpr_or_int10_operand" "e,e,0,N,N,OP,OP")))
-    (clobber (match_scratch:CC 3 "=t,t,t,t,t,t,t"))]
-   "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) != -2048"
    "#"
    "reload_completed"
    [(match_dup 4)
     (match_dup 5)]
    "
  {
!   rtx op0_high = gen_highpart (SImode, operands[0]);
!   rtx op1_high = gen_highpart (SImode, operands[1]);
!   rtx op0_low  = gen_lowpart (SImode, operands[0]);
!   rtx op1_low  = gen_lowpart (SImode, operands[1]);
!   rtx op2 = operands[2];
!   rtx op3 = operands[3];
  
!   if (GET_CODE (op2) != CONST_INT)
!     {
!       rtx op2_high = gen_highpart (SImode, operands[2]);
!       rtx op2_low  = gen_lowpart (SImode, operands[2]);
!       operands[4] = gen_adddi3_lower (op0_low, op1_low, op2_low, op3);
!       operands[5] = gen_adddi3_upper (op0_high, op1_high, op2_high, op3);
!     }
!   else if (INTVAL (op2) >= 0)
!     {
!       operands[4] = gen_adddi3_lower (op0_low, op1_low, op2, op3);
!       operands[5] = gen_adddi3_upper (op0_high, op1_high, const0_rtx, op3);
!     }
!   else
!     {
!       operands[4] = gen_subdi3_lower (op0_low, op1_low,
! 				      GEN_INT (- INTVAL (op2)), op3);
!       operands[5] = gen_subdi3_upper (op0_high, op1_high, const0_rtx, op3);
!     }
  }"
    [(set_attr "length" "8")
     (set_attr "type" "multi")])
--- 2940,2969 ----
  ;; ::::::::::::::::::::
  
  ;; Addition
! (define_insn_and_split "adddi3"
!   [(set (match_operand:DI 0 "integer_register_operand" "=&e,e")
! 	(plus:DI (match_operand:DI 1 "integer_register_operand" "%e,0")
! 		 (match_operand:DI 2 "gpr_or_int10_operand" "eJ,eJ")))
!    (clobber (match_scratch:CC 3 "=t,t"))]
    ""
    "#"
    "reload_completed"
    [(match_dup 4)
     (match_dup 5)]
    "
  {
!   rtx parts[3][2];
!   int op, part;
  
!   for (op = 0; op < 3; op++)
!     for (part = 0; part < 2; part++)
!       parts[op][part] = simplify_gen_subreg (SImode, operands[op],
! 					     DImode, part * UNITS_PER_WORD);
! 
!   operands[4] = gen_adddi3_lower (parts[0][1], parts[1][1], parts[2][1],
! 				  operands[3]);
!   operands[5] = gen_adddi3_upper (parts[0][0], parts[1][0], parts[2][0],
! 				  copy_rtx (operands[3]));
  }"
    [(set_attr "length" "8")
     (set_attr "type" "multi")])
*************** (define_insn_and_split "subdi3"
*** 3027,3076 ****
  (define_insn "adddi3_lower"
    [(set (match_operand:SI 0 "integer_register_operand" "=d")
  	(plus:SI (match_operand:SI 1 "integer_register_operand" "d")
! 		 (match_operand:SI 2 "gpr_or_int10_operand" "dOP")))
     (set (match_operand:CC 3 "icc_operand" "=t")
  	(compare:CC (plus:SI (match_dup 1)
  			     (match_dup 2))
  		    (const_int 0)))]
!   "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 0"
    "add%I2cc %1,%2,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
  (define_insn "adddi3_upper"
!   [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
! 	(plus:SI (match_operand:SI 1 "integer_register_operand" "d,d")
! 		 (plus:SI (match_operand:SI 2 "reg_or_0_operand" "d,O")
! 			  (match_operand:CC 3 "icc_operand" "t,t"))))]
    ""
!   "@
!    addx %1,%2,%0,%3
!    addx %1,%.,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
  (define_insn "subdi3_lower"
    [(set (match_operand:SI 0 "integer_register_operand" "=d")
  	(minus:SI (match_operand:SI 1 "integer_register_operand" "d")
! 		  (match_operand:SI 2 "gpr_or_int10_operand" "dOP")))
     (set (match_operand:CC 3 "icc_operand" "=t")
  	(compare:CC (plus:SI (match_dup 1)
  			     (match_dup 2))
  		    (const_int 0)))]
!   "GET_CODE (operands[2]) != CONST_INT || INTVAL (operands[2]) >= 0"
!   "sub%I2cc %1,%2,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
  (define_insn "subdi3_upper"
!   [(set (match_operand:SI 0 "integer_register_operand" "=d,d")
! 	(minus:SI (match_operand:SI 1 "integer_register_operand" "d,d")
! 		  (minus:SI (match_operand:SI 2 "reg_or_0_operand" "d,O")
! 			    (match_operand:CC 3 "icc_operand" "t,t"))))]
    ""
!   "@
!    subx %1,%2,%0,%3
!    subx %1,%.,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
--- 3000,3045 ----
  (define_insn "adddi3_lower"
    [(set (match_operand:SI 0 "integer_register_operand" "=d")
  	(plus:SI (match_operand:SI 1 "integer_register_operand" "d")
! 		 (match_operand:SI 2 "gpr_or_int10_operand" "dJ")))
     (set (match_operand:CC 3 "icc_operand" "=t")
  	(compare:CC (plus:SI (match_dup 1)
  			     (match_dup 2))
  		    (const_int 0)))]
!   ""
    "add%I2cc %1,%2,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
  (define_insn "adddi3_upper"
!   [(set (match_operand:SI 0 "integer_register_operand" "=d")
! 	(plus:SI (match_operand:SI 1 "integer_register_operand" "d")
! 		 (plus:SI (match_operand:SI 2 "gpr_or_int10_operand" "dJ")
! 			  (match_operand:CC 3 "icc_operand" "t"))))]
    ""
!   "addx%I2 %1,%2,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
  (define_insn "subdi3_lower"
    [(set (match_operand:SI 0 "integer_register_operand" "=d")
  	(minus:SI (match_operand:SI 1 "integer_register_operand" "d")
! 		  (match_operand:SI 2 "integer_register_operand" "d")))
     (set (match_operand:CC 3 "icc_operand" "=t")
  	(compare:CC (plus:SI (match_dup 1)
  			     (match_dup 2))
  		    (const_int 0)))]
!   ""
!   "subcc %1,%2,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
  (define_insn "subdi3_upper"
!   [(set (match_operand:SI 0 "integer_register_operand" "=d")
! 	(minus:SI (match_operand:SI 1 "integer_register_operand" "d")
! 		  (minus:SI (match_operand:SI 2 "integer_register_operand" "d")
! 			    (match_operand:CC 3 "icc_operand" "t"))))]
    ""
!   "subx %1,%2,%0,%3"
    [(set_attr "length" "4")
     (set_attr "type" "int")])
  
*** /dev/null	Fri Apr 23 00:21:55 2004
--- testsuite/gcc.c-torture/execute/20041011-1.c	Mon Oct 11 13:05:51 2004
***************
*** 0 ****
--- 1,60 ----
+ typedef unsigned long long ull;
+ volatile int gvol[32];
+ ull gull;
+ 
+ #define MULTI(X) \
+ 	X( 1), X( 2), X( 3), X( 4), X( 5), X( 6), X( 7), X( 8), X( 9), X(10), \
+ 	X(11), X(12), X(13), X(14), X(15), X(16), X(17), X(18), X(19), X(20), \
+ 	X(21), X(22), X(23), X(24), X(25), X(26), X(27), X(28), X(29), X(30)
+ 
+ #define DECLARE(INDEX) x##INDEX
+ #define COPYIN(INDEX) x##INDEX = gvol[INDEX]
+ #define COPYOUT(INDEX) gvol[INDEX] = x##INDEX
+ 
+ #define BUILD_TEST(NAME, N)		\
+   ull __attribute__((noinline))		\
+   NAME (int n, ull x)			\
+   {					\
+     while (n--)				\
+       {					\
+ 	int MULTI (DECLARE);		\
+ 	MULTI (COPYIN);			\
+ 	MULTI (COPYOUT);		\
+ 	x += N;				\
+       }					\
+     return x;				\
+   }
+ 
+ #define RUN_TEST(NAME, N)		\
+   if (NAME (3, ~0ULL) != N * 3 - 1)	\
+     abort ();				\
+   if (NAME (3, 0xffffffffULL)		\
+       != N * 3 + 0xffffffffULL)		\
+     abort ();
+ 
+ #define DO_TESTS(DO_TEST)	\
+   DO_TEST (t1, -2048)		\
+   DO_TEST (t2, -513)		\
+   DO_TEST (t3, -512)		\
+   DO_TEST (t4, -511)		\
+   DO_TEST (t5, -1)		\
+   DO_TEST (t6, 1)		\
+   DO_TEST (t7, 511)		\
+   DO_TEST (t8, 512)		\
+   DO_TEST (t9, 513)		\
+   DO_TEST (t10, gull)		\
+   DO_TEST (t11, -gull)
+ 
+ DO_TESTS (BUILD_TEST)
+ 
+ ull neg (ull x) { return -x; }
+ 
+ int
+ main ()
+ {
+   gull = 100;
+   DO_TESTS (RUN_TEST)
+   if (neg (gull) != -100ULL)
+     abort ();
+   exit (0);
+ }


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