ARM: minor DImode logical improvements

Richard Earnshaw rearnsha@arm.com
Sun Oct 31 23:33:00 GMT 1999


> 
> [ I'll be doing some minor ARM work over the next couple weeks; since I've
>   never done ARM work in the past I'd like either Nick or Richard to review
>   the patches.  ]

Cool.  Yes, I'll try to have a look at them.


> 
> This allows the scheduler to split up multi-instruction DImode logical
> operations for scheduling purposes.  Since we have splitters, there's no need
> to have output strings for the cases where we can split the instruction.

It looks fine to me.  However, could we hold off on this until we get the 
new ARM/Thumb back-end merged in; additions like this are good, but will 
make the merge more complicated unless they are applied to both.

Nick, Jeff,

I think it might be worth creating a branch so that we can commit changes 
to the new code without having to put it on the mainline just yet (ie, do 
the same as for the x86).  As things stand it is hard to generate patches 
for the new code because I don't really have a reference to work against.

Richard.

> 
> 	* arm.c (logical_binary_operator): New fucntion.
> 	* arm.h (logical_binary_operator): Declare it.
> 	(PREDICATE_CODES): Handle logical_binary_operator.
> 	* arm.md (anddi3, anddi_zesidi_di, anddi_sesdi_di): Use "#" for
> 	output constraints.  Add appropriate splitters.
> 	(anddi_notdi_di, anddi_notzesidi_di, anddi_notsesidi_di): Likewise.
> 	(iordi3, iordi_zesidi_di, iordi_sesidi_di): Likewise.
> 	(xordi3, xordi_zesidi_di, xordi_sesidi_di): Likewise.
> 
> Index: arm.c
> ===================================================================
> RCS file: /cvs/gcc/egcs/gcc/config/arm/arm.c,v
> retrieving revision 1.67
> diff -c -3 -p -r1.67 arm.c
> *** arm.c	1999/10/19 16:47:23	1.67
> --- arm.c	1999/10/22 08:34:09
> *************** shiftable_operator (x, mode)
> *** 2366,2371 ****
> --- 2366,2388 ----
>       }
>   }
>   
> + /* Return TRUE for binary logical operators.  */
> + 
> + int
> + logical_binary_operator (x, mode)
> +      rtx x;
> +      enum machine_mode mode;
> + {
> +   if (GET_MODE (x) != mode)
> +     return FALSE;
> +   else
> +     {
> +       enum rtx_code code = GET_CODE (x);
> + 
> +       return (code == IOR || code == XOR || code == AND);
> +     }
> + }
> + 
>   /* Return TRUE for shift operators. */
>   
>   int
> Index: arm.h
> ===================================================================
> RCS file: /cvs/gcc/egcs/gcc/config/arm/arm.h,v
> retrieving revision 1.48
> diff -c -3 -p -r1.48 arm.h
> *** arm.h	1999/08/27 20:36:58	1.48
> --- arm.h	1999/10/22 08:34:12
> *************** extern struct rtx_def * arm_compare_op1;
> *** 1960,1965 ****
> --- 1960,1966 ----
>     {"reg_or_int_operand", {SUBREG, REG, CONST_INT}},			\
>     {"multi_register_push", {PARALLEL}},					\
>     {"cc_register", {REG}},						\
> +   {"logical_binary_operator", {AND, IOR, XOR}},				\
>     {"dominant_cc_register", {REG}},
>   
>   
> *************** int    soft_df_operand PROTO ((Rtx, Mmod
> *** 2262,2267 ****
> --- 2263,2269 ----
>   int    index_operand PROTO ((Rtx, Mmode));
>   int    const_shift_operand PROTO ((Rtx, Mmode));
>   int    shiftable_operator PROTO ((Rtx, Mmode));
> + int    logical_binary_operator PROTO ((Rtx, Mmode));
>   int    shift_operator PROTO ((Rtx, Mmode));
>   int    equality_operator PROTO ((Rtx, Mmode));
>   int    minmax_operator PROTO ((Rtx, Mmode));
> Index: arm.md
> ===================================================================
> RCS file: /cvs/gcc/egcs/gcc/config/arm/arm.md,v
> retrieving revision 1.33
> diff -c -3 -p -r1.33 arm.md
> *** arm.md	1999/09/09 14:30:54	1.33
> --- arm.md	1999/10/22 08:34:17
> ***************
> *** 1090,1101 ****
>   
>   ;; Boolean and,ior,xor insns
>   
>   (define_insn "anddi3"
>     [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
>   	(and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
>   		(match_operand:DI 2 "s_register_operand" "r,0")))]
>     ""
> !   "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*anddi_zesidi_di"
> --- 1090,1266 ----
>   
>   ;; Boolean and,ior,xor insns
>   
> + ;; Split up double word logical operations
> + 
> + ;; Split up simple DImode logical operations.  Simply perform the logical
> + ;; operation on the upper and lower halves of the registers.
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(match_operator:DI 6 "logical_binary_operator"
> + 	  [(match_operand:DI 1 "s_register_operand" "")
> + 	   (match_operand:DI 2 "s_register_operand" "")]))]
> +   "reload_completed"
> +   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
> +    (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
> +   "
> + {
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> +   operands[5] = gen_highpart (SImode, operands[2]);
> +   operands[2] = gen_lowpart (SImode, operands[2]);
> + }")
> + 
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(not:DI (match_operand:DI 1 "s_register_operand" "")))]
> +   "reload_completed"
> +   [(set (match_dup 0) (not:SI (match_dup 1)))
> +    (set (match_dup 2) (not:SI (match_dup 3)))]
> +   "
> + {
> +   operands[2] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[3] = gen_highpart (SImode, operands[1]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> + }")
> + 
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(and:DI
> + 	  (not:DI (match_operand:DI 1 "s_register_operand" ""))
> + 	  (match_operand:DI 2 "s_register_operand" "")))]
> +   "reload_completed"
> +   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
> +    (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
> +   "
> + {
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> +   operands[5] = gen_highpart (SImode, operands[2]);
> +   operands[2] = gen_lowpart (SImode, operands[2]);
> + }")
> + 
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(match_operator:DI 6 "logical_binary_operator"
> + 	  [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
> + 	   (match_operand:DI 1 "s_register_operand" "")]))]
> +   "reload_completed"
> +   [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
> +    (set (match_dup 3) (match_op_dup:SI 6
> + 			[(ashiftrt:SI (match_dup 2) (const_int 31))
> + 			 (match_dup 4)]))]
> +   "
> + {
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> +   operands[5] = gen_highpart (SImode, operands[2]);
> +   operands[2] = gen_lowpart (SImode, operands[2]);
> + }")
> + 
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(and:DI (not:DI (sign_extend:DI
> + 			(match_operand:SI 2 "s_register_operand" "")))
> + 		(match_operand:DI 1 "s_register_operand" "")))]
> +   "reload_completed"
> +   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
> +    (set (match_dup 3) (and:SI (not:SI
> + 				(ashiftrt:SI (match_dup 2) (const_int 31)))
> + 			       (match_dup 4)))]
> +   "
> + {
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> +   operands[2] = gen_lowpart (SImode, operands[2]);
> + }")
> + 
> + ;; The zero extend of operand 2 clears the high word of the output
> + ;; operand.
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(and:DI
> + 	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
> + 	  (match_operand:DI 1 "s_register_operand" "")))]
> +   "reload_completed"
> +   [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
> +    (set (match_dup 3) (const_int 0))]
> +   "
> + {
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> + }")
> + 
> + ;; The zero extend of operand 2 means we can just copy the high part of
> + ;; operand1 into operand0.
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(ior:DI
> + 	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
> + 	  (match_operand:DI 1 "s_register_operand" "")))]
> +   "operands[0] != operands[1] && reload_completed"
> +   [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
> +    (set (match_dup 3) (match_dup 4))]
> +   "
> + {
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> + }")
> + 
> + ;; The zero extend of operand 2 means we can just copy the high part of
> + ;; operand1 into operand0.
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(xor:DI
> + 	  (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
> + 	  (match_operand:DI 1 "s_register_operand" "")))]
> +   "operands[0] != operands[1] && reload_completed"
> +   [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
> +    (set (match_dup 3) (match_dup 4))]
> +   "
> + {
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> + }")
> + 
> + ;; (not (zero_extend ...)) allows us to just copy the high word from
> + ;; operand1 to operand0.
> + (define_split
> +   [(set (match_operand:DI 0 "s_register_operand" "")
> + 	(and:DI (not:DI (zero_extend:DI
> + 			(match_operand:SI 2 "s_register_operand" "")))
> + 		(match_operand:DI 1 "s_register_operand" "")))]
> +   "operands[0] != operands[1] && reload_completed"
> +   [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
> +    (set (match_dup 3) (match_dup 4))]
> +   "
> + {
> +   operands[3] = gen_highpart (SImode, operands[0]);
> +   operands[0] = gen_lowpart (SImode, operands[0]);
> +   operands[4] = gen_highpart (SImode, operands[1]);
> +   operands[1] = gen_lowpart (SImode, operands[1]);
> +   operands[2] = gen_lowpart (SImode, operands[2]);
> + }")
> + 
>   (define_insn "anddi3"
>     [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
>   	(and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
>   		(match_operand:DI 2 "s_register_operand" "r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*anddi_zesidi_di"
> ***************
> *** 1104,1110 ****
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*anddi_sesdi_di"
> --- 1269,1275 ----
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*anddi_sesdi_di"
> ***************
> *** 1113,1119 ****
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
>   [(set_attr "length" "8")])
>   
>   (define_expand "andsi3"
> --- 1278,1284 ----
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_expand "andsi3"
> ***************
> *** 1374,1380 ****
>   	(and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
>   		(match_operand:DI 1 "s_register_operand" "0,r")))]
>     ""
> !   "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
>   [(set_attr "length" "8")])
>     
>   (define_insn "*anddi_notzesidi_di"
> --- 1539,1545 ----
>   	(and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
>   		(match_operand:DI 1 "s_register_operand" "0,r")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>     
>   (define_insn "*anddi_notzesidi_di"
> ***************
> *** 1385,1391 ****
>     ""
>     "@
>      bic%?\\t%Q0, %Q1, %2
> !    bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
>   [(set_attr "length" "4,8")])
>     
>   (define_insn "*anddi_notsesidi_di"
> --- 1550,1556 ----
>     ""
>     "@
>      bic%?\\t%Q0, %Q1, %2
> !    #"
>   [(set_attr "length" "4,8")])
>     
>   (define_insn "*anddi_notsesidi_di"
> ***************
> *** 1394,1400 ****
>   			 (match_operand:SI 2 "s_register_operand" "r,r")))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
>   [(set_attr "length" "8")])
>     
>   (define_insn "andsi_notsi_si"
> --- 1559,1565 ----
>   			 (match_operand:SI 2 "s_register_operand" "r,r")))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>     
>   (define_insn "andsi_notsi_si"
> ***************
> *** 1441,1447 ****
>   	(ior:DI (match_operand:DI 1 "s_register_operand" "%0")
>   		(match_operand:DI 2 "s_register_operand" "r")))]
>     ""
> !   "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*iordi_zesidi_di"
> --- 1606,1612 ----
>   	(ior:DI (match_operand:DI 1 "s_register_operand" "%0")
>   		(match_operand:DI 2 "s_register_operand" "r")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*iordi_zesidi_di"
> ***************
> *** 1452,1458 ****
>     ""
>     "@
>      orr%?\\t%Q0, %Q1, %2
> !    orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
>   [(set_attr "length" "4,8")])
>   
>   (define_insn "*iordi_sesidi_di"
> --- 1617,1623 ----
>     ""
>     "@
>      orr%?\\t%Q0, %Q1, %2
> !    #"
>   [(set_attr "length" "4,8")])
>   
>   (define_insn "*iordi_sesidi_di"
> ***************
> *** 1461,1467 ****
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
>   [(set_attr "length" "8")])
>   
>   (define_expand "iorsi3"
> --- 1626,1632 ----
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_expand "iorsi3"
> ***************
> *** 1528,1534 ****
>   	(xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
>   		(match_operand:DI 2 "s_register_operand" "r,0")))]
>     ""
> !   "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*xordi_zesidi_di"
> --- 1693,1699 ----
>   	(xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
>   		(match_operand:DI 2 "s_register_operand" "r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_insn "*xordi_zesidi_di"
> ***************
> *** 1539,1545 ****
>     ""
>     "@
>      eor%?\\t%Q0, %Q1, %2
> !    eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
>   [(set_attr "length" "4,8")])
>   
>   (define_insn "*xordi_sesidi_di"
> --- 1704,1710 ----
>     ""
>     "@
>      eor%?\\t%Q0, %Q1, %2
> !    #"
>   [(set_attr "length" "4,8")])
>   
>   (define_insn "*xordi_sesidi_di"
> ***************
> *** 1548,1554 ****
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
>   [(set_attr "length" "8")])
>   
>   (define_insn "xorsi3"
> --- 1713,1719 ----
>   		 (match_operand:SI 2 "s_register_operand" "r,r"))
>   		(match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_insn "xorsi3"
> ***************
> *** 2035,2041 ****
>     [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
>   	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
>   [(set_attr "length" "8")])
>   
>   (define_insn "one_cmplsi2"
> --- 2200,2206 ----
>     [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
>   	(not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
>     ""
> !   "#"
>   [(set_attr "length" "8")])
>   
>   (define_insn "one_cmplsi2"
> 
> 




More information about the Gcc-patches mailing list