This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
ia64 rotate patterns [Re: shrp]
- To: David Mosberger <davidm at hpl dot hp dot com>
- Subject: ia64 rotate patterns [Re: shrp]
- From: Richard Henderson <rth at cygnus dot com>
- Date: Mon, 25 Sep 2000 15:05:17 -0700
- Cc: gcc-patches at gcc dot gnu dot org
- References: <200009251622.JAA21767@napali.hpl.hp.com>
On Mon, Sep 25, 2000 at 09:22:34AM -0700, David Mosberger wrote:
> Would it be hard for gcc to recognize this:
>
> (w >> n) | (w << (64 - n))
>
> and translate it into the equivalent of:
>
> asm ("shrp %0=%1,%1,%2" : "=r"(result) : "r"(w), "i"(n))
We'd already had a rotate right pattern in the md file, which works fine
when N is a constant. However, combine believes the canonical form to be
rotate left, and since we did not define this pattern, we'd not do anything
when N was a constant variable.
I also defined some SImode rotate insn_and_split's for combine to chew on.
r~
* config/ia64/ia64.c (ia64_print_operand): Define 'e' as 64-n.
* config/ia64/ia64.md (rotrsi3): Allow variable rotates; don't
split until after reload.
(rotlsi3, rotldi3): New.
Index: ia64.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.c,v
retrieving revision 1.52
diff -c -p -d -r1.52 ia64.c
*** ia64.c 2000/09/25 13:03:20 1.52
--- ia64.c 2000/09/25 21:54:06
*************** ia64_print_operand_address (stream, addr
*** 3090,3095 ****
--- 3090,3096 ----
C Swap and print a comparison operator.
D Print an FP comparison operator.
E Print 32 - constant, for SImode shifts as extract.
+ e Print 64 - constant, for DImode rotates.
F A floating point constant 0.0 emitted as f0, or 1.0 emitted as f1, or
a floating point register emitted normally.
I Invert a predicate register by adding 1.
*************** ia64_print_operand (file, x, code)
*** 3152,3157 ****
--- 3153,3162 ----
case 'E':
fprintf (file, HOST_WIDE_INT_PRINT_DEC, 32 - INTVAL (x));
+ return;
+
+ case 'e':
+ fprintf (file, HOST_WIDE_INT_PRINT_DEC, 64 - INTVAL (x));
return;
case 'F':
Index: ia64.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/ia64/ia64.md,v
retrieving revision 1.49
diff -c -p -d -r1.49 ia64.md
*** ia64.md 2000/09/24 23:58:24 1.49
--- ia64.md 2000/09/25 21:54:06
***************
*** 3858,3881 ****
}")
;; Use mix4.r/shr to implement rotrsi3. We only get 32 bits of valid result
! ;; here, instead of 64 like the patterns above.
(define_expand "rotrsi3"
[(set (match_dup 3)
! (ior:DI (zero_extend:DI (match_operand:SI 1 "gr_register_operand" ""))
(ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
(set (match_dup 3)
! (lshiftrt:DI (match_dup 3)
! (match_operand:DI 2 "nonmemory_operand" "")))
! (set (match_operand:SI 0 "gr_register_operand" "") (match_dup 4))]
""
"
{
if (! shift_32bit_count_operand (operands[2], SImode))
! FAIL;
! operands[3] = gen_reg_rtx (DImode);
! operands[4] = gen_lowpart (SImode, operands[3]);
}")
;; ::::::::::::::::::::
;; ::
--- 3858,3925 ----
}")
;; Use mix4.r/shr to implement rotrsi3. We only get 32 bits of valid result
! ;; here, instead of 64 like the patterns above. Keep the pattern together
! ;; until after combine; otherwise it won't get matched often.
(define_expand "rotrsi3"
+ [(set (match_operand:SI 0 "gr_register_operand" "")
+ (rotatert:SI (match_operand:SI 1 "gr_register_operand" "")
+ (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
+ ""
+ "
+ {
+ if (GET_MODE (operands[2]) != VOIDmode)
+ {
+ rtx tmp = gen_reg_rtx (DImode);
+ emit_insn (gen_zero_extendsidi2 (tmp, operands[2]));
+ operands[2] = tmp;
+ }
+ }")
+
+ (define_insn_and_split "*rotrsi3_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=&r")
+ (rotatert:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "gr_reg_or_5bit_operand" "rM")))]
+ ""
+ "#"
+ "reload_completed"
[(set (match_dup 3)
! (ior:DI (zero_extend:DI (match_dup 1))
(ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
(set (match_dup 3)
! (lshiftrt:DI (match_dup 3) (match_dup 2)))]
! "operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));")
!
! (define_expand "rotlsi3"
! [(set (match_operand:SI 0 "gr_register_operand" "")
! (rotate:SI (match_operand:SI 1 "gr_register_operand" "")
! (match_operand:SI 2 "gr_reg_or_5bit_operand" "")))]
""
"
{
if (! shift_32bit_count_operand (operands[2], SImode))
! {
! rtx tmp = gen_reg_rtx (SImode);
! emit_insn (gen_subsi3 (tmp, GEN_INT (32), operands[2]));
! emit_insn (gen_rotrsi3 (operands[0], operands[1], tmp));
! DONE;
! }
}")
+
+ (define_insn_and_split "*rotlsi3_internal"
+ [(set (match_operand:SI 0 "gr_register_operand" "=r")
+ (rotate:SI (match_operand:SI 1 "gr_register_operand" "r")
+ (match_operand:SI 2 "shift_32bit_count_operand" "n")))]
+ ""
+ "#"
+ "reload_completed"
+ [(set (match_dup 3)
+ (ior:DI (zero_extend:DI (match_dup 1))
+ (ashift:DI (zero_extend:DI (match_dup 1)) (const_int 32))))
+ (set (match_dup 3)
+ (lshiftrt:DI (match_dup 3) (match_dup 2)))]
+ "operands[3] = gen_rtx_REG (DImode, REGNO (operands[0]));
+ operands[2] = GEN_INT (32 - INTVAL (operands[2]));")
;; ::::::::::::::::::::
;; ::
***************
*** 3967,3972 ****
--- 4011,4034 ----
"shrp %0 = %1, %1, %2"
[(set_attr "type" "I")])
+ (define_expand "rotldi3"
+ [(set (match_operand:DI 0 "gr_register_operand" "")
+ (rotate:DI (match_operand:DI 1 "gr_register_operand" "")
+ (match_operand:DI 2 "nonmemory_operand" "")))]
+ ""
+ "
+ {
+ if (! shift_count_operand (operands[2], DImode))
+ FAIL;
+ }")
+
+ (define_insn "*rotldi3_internal"
+ [(set (match_operand:DI 0 "gr_register_operand" "=r")
+ (rotate:DI (match_operand:DI 1 "gr_register_operand" "r")
+ (match_operand:DI 2 "shift_count_operand" "M")))]
+ ""
+ "shrp %0 = %1, %1, %e2"
+ [(set_attr "type" "I")])
;; ::::::::::::::::::::
;; ::