* [SH] PR 54089 - Add support for rotcr insn
@ 2012-08-19 23:03 Oleg Endo
2012-08-20 11:13 ` Kaz Kojima
2012-08-20 21:09 ` Gary Funck
0 siblings, 2 replies; 4+ messages in thread
From: Oleg Endo @ 2012-08-19 23:03 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 590 bytes --]
Hello,
This adds support for SH's rotcr insn.
Tested on rev 190459 with
make -k check RUNTESTFLAGS="--target_board=sh-sim
\{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
and no new failures.
OK?
Cheers,
Oleg
ChangeLog:
PR target/50489
* config/sh/sh.md (rotcr, *rotcr, shar, shlr): New insns and
splits.
(ashrdi3_k, lshrdi3_k): Rewrite as insn_and_split.
* config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p): New function.
* config/sh/sh-protos.h (sh_lshrsi_clobbers_t_reg_p): Declare
it.
testsuite/ChangeLog:
PR target/50489
* gcc.target/sh/pr54089-1.c: New.
[-- Attachment #2: sh_pr54089_06.patch --]
[-- Type: text/x-patch, Size: 9107 bytes --]
Index: gcc/config/sh/sh.md
===================================================================
--- gcc/config/sh/sh.md (revision 190459)
+++ gcc/config/sh/sh.md (working copy)
@@ -3827,6 +3827,100 @@
FAIL;
})
+;; The rotcr insn is used primarily in DImode right shifts (arithmetic
+;; and logical). It can also be used to implement things like
+;; bool t = a == b;
+;; int x = (y >> 1) | (t << 31);
+(define_insn "rotcr"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+ (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (const_int 1))
+ (ashift:SI (match_operand:SI 2 "t_reg_operand")
+ (const_int 31))))
+ (set (reg:SI T_REG)
+ (and:SI (match_dup 1) (const_int 1)))]
+ "TARGET_SH1"
+ "rotcr %0"
+ [(set_attr "type" "arith")])
+
+;; Simplified rotcr version for combine, which allows arbitrary shift
+;; amounts for the reg. If the shift amount is '1' rotcr can be used
+;; directly. Otherwise we have to insert a shift in between.
+(define_insn_and_split "*rotcr"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (ior:SI (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand")
+ (match_operand:SI 2 "const_int_operand"))
+ (ashift:SI (match_operand:SI 3 "t_reg_operand")
+ (const_int 31))))
+ (clobber (reg:SI T_REG))]
+ "TARGET_SH1"
+ "#"
+ "&& can_create_pseudo_p ()"
+ [(const_int 0)]
+{
+ if (INTVAL (operands[2]) > 1)
+ {
+ /* use plus_constant function ?? */
+ const int shift_count = INTVAL (operands[2]) - 1;
+ const rtx shift_count_rtx = GEN_INT (shift_count);
+ rtx shift_res = gen_reg_rtx (SImode);
+
+ rtx prev_set_t_insn = NULL_RTX;
+ rtx tmp_t_reg = NULL_RTX;
+
+ /* If we're going to emit a shift sequence that clobbers the T_REG,
+ try to find the previous insn that sets the T_REG and emit the
+ shift insn before that insn, to remove the T_REG dependency.
+ If the insn that sets the T_REG cannot be found, store the T_REG
+ in a temporary reg and restore it after the shift. */
+ if (sh_lshrsi_clobbers_t_reg_p (shift_count_rtx)
+ && ! sh_dynamicalize_shift_p (shift_count_rtx))
+ {
+ prev_set_t_insn = prev_nonnote_insn_bb (curr_insn);
+ if (! (prev_set_t_insn != NULL_RTX
+ && reg_set_p (get_t_reg_rtx (), prev_set_t_insn)
+ && ! reg_referenced_p (get_t_reg_rtx (),
+ PATTERN (prev_set_t_insn))))
+ {
+ prev_set_t_insn = NULL_RTX;
+ tmp_t_reg = gen_reg_rtx (SImode);
+ emit_insn (gen_move_insn (tmp_t_reg, get_t_reg_rtx ()));
+ }
+ }
+
+ rtx shift_rtx = gen_lshrsi3 (shift_res, operands[1], shift_count_rtx);
+ operands[1] = shift_res;
+
+ /* Emit the shift insn before the insn that sets T_REG, if possible. */
+ if (prev_set_t_insn != NULL_RTX)
+ emit_insn_before (shift_rtx, prev_set_t_insn);
+ else
+ emit_insn (shift_rtx);
+
+ /* Restore T_REG if it has been saved before. */
+ if (tmp_t_reg != NULL_RTX)
+ emit_insn (gen_cmpgtsi_t (tmp_t_reg, const0_rtx));
+ }
+
+ emit_insn (gen_rotcr (operands[0], operands[1], operands[3]));
+ DONE;
+})
+
+;; rotcr combine bridge pattern which will make combine try out more
+;; complex patterns.
+(define_insn_and_split "*rotcr"
+ [(set (match_operand:SI 0 "arith_reg_dest")
+ (ashift:SI (match_operand:SI 1 "t_reg_operand") (const_int 31)))]
+ "TARGET_SH1"
+ "#"
+ "&& 1"
+ [(set (match_dup 0) (match_dup 1))
+ (parallel [(set (match_dup 0)
+ (ior:SI (lshiftrt:SI (match_dup 0) (const_int 1))
+ (ashift:SI (match_dup 1) (const_int 31))))
+ (set (reg:SI T_REG)
+ (and:SI (match_dup 0) (const_int 1)))])])
+
;; . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
;; SImode shift left
@@ -4146,6 +4240,16 @@
FAIL;
})
+(define_insn "shar"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+ (ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (const_int 1)))
+ (set (reg:SI T_REG)
+ (and:SI (match_dup 1) (const_int 1)))]
+ "TARGET_SH1"
+ "shar %0"
+ [(set_attr "type" "arith")])
+
(define_insn "ashrsi3_k"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(ashiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
@@ -4233,16 +4337,22 @@
FAIL;
})
-;; This should be a define_insn_and_split
-(define_insn "ashrdi3_k"
+(define_insn_and_split "ashrdi3_k"
[(set (match_operand:DI 0 "arith_reg_dest" "=r")
(ashiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
(const_int 1)))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
- "shar %S0\;rotcr %R0"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx high = gen_highpart (SImode, operands[0]);
+ rtx low = gen_lowpart (SImode, operands[0]);
+ emit_insn (gen_shar (high, high));
+ emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
+ DONE;
+})
(define_insn "ashrdi3_media"
[(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
@@ -4322,6 +4432,16 @@
"shld %2,%0"
[(set_attr "type" "dyn_shift")])
+(define_insn "shlr"
+ [(set (match_operand:SI 0 "arith_reg_dest" "=r")
+ (lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
+ (const_int 1)))
+ (set (reg:SI T_REG)
+ (and:SI (match_dup 1) (const_int 1)))]
+ "TARGET_SH1"
+ "shlr %0"
+ [(set_attr "type" "arith")])
+
(define_insn "lshrsi3_m"
[(set (match_operand:SI 0 "arith_reg_dest" "=r")
(lshiftrt:SI (match_operand:SI 1 "arith_reg_operand" "0")
@@ -4384,16 +4504,22 @@
FAIL;
})
-;; This should be a define_insn_and_split
-(define_insn "lshrdi3_k"
+(define_insn_and_split "lshrdi3_k"
[(set (match_operand:DI 0 "arith_reg_dest" "=r")
(lshiftrt:DI (match_operand:DI 1 "arith_reg_operand" "0")
(const_int 1)))
(clobber (reg:SI T_REG))]
"TARGET_SH1"
- "shlr %S0\;rotcr %R0"
- [(set_attr "length" "4")
- (set_attr "type" "arith")])
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ rtx high = gen_highpart (SImode, operands[0]);
+ rtx low = gen_lowpart (SImode, operands[0]);
+ emit_insn (gen_shlr (high, high));
+ emit_insn (gen_rotcr (low, low, get_t_reg_rtx ()));
+ DONE;
+})
(define_insn "lshrdi3_media"
[(set (match_operand:DI 0 "ext_dest_operand" "=r,r")
Index: gcc/config/sh/sh-protos.h
===================================================================
--- gcc/config/sh/sh-protos.h (revision 190459)
+++ gcc/config/sh/sh-protos.h (working copy)
@@ -74,6 +74,7 @@
extern void sh_emit_compare_and_branch (rtx *, enum machine_mode);
extern void sh_emit_compare_and_set (rtx *, enum machine_mode);
extern bool sh_ashlsi_clobbers_t_reg_p (rtx);
+extern bool sh_lshrsi_clobbers_t_reg_p (rtx);
extern void gen_shifty_op (int, rtx *);
extern void gen_shifty_hi_op (int, rtx *);
extern bool expand_ashiftrt (rtx *);
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c (revision 190459)
+++ gcc/config/sh/sh.c (working copy)
@@ -2892,6 +2892,14 @@
& ASHL_CLOBBERS_T) != 0;
}
+bool
+sh_lshrsi_clobbers_t_reg_p (rtx shift_amount)
+{
+ gcc_assert (CONST_INT_P (shift_amount));
+ return (ashl_lshr_seq[INTVAL (shift_amount) & 31].clobbers_t
+ & LSHR_CLOBBERS_T) != 0;
+}
+
/* Assuming we have a value that has been sign-extended by at least one bit,
can we use the ext_shift_amounts with the last shift turned to an arithmetic shift
to shift it by N without data loss, and quicker than by other means? */
Index: gcc/testsuite/gcc.target/sh/pr54089-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54089-1.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54089-1.c (revision 0)
@@ -0,0 +1,83 @@
+/* Check that the rotcr instruction is generated. */
+/* { dg-do compile { target "sh*-*-*" } } */
+/* { dg-options "-O1" } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
+/* { dg-final { scan-assembler-times "rotcr" 11 } } */
+
+typedef char bool;
+
+long long
+test_00 (long long a)
+{
+ return a >> 1;
+}
+
+unsigned int
+test_01 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 1) | (r << 31));
+}
+
+unsigned int
+test_02 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 2) | (r << 31));
+}
+
+unsigned int
+test_03 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 3) | (r << 31));
+}
+
+unsigned int
+test_04 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 4) | (r << 31));
+}
+
+unsigned int
+test_05 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 5) | (r << 31));
+}
+
+unsigned int
+test_06 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 6) | (r << 31));
+}
+
+unsigned int
+test_07 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 7) | (r << 31));
+}
+
+unsigned int
+test_08 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 8) | (r << 31));
+}
+
+unsigned int
+test_09 (unsigned int a, int b, int c)
+{
+ bool r = b == c;
+ return ((a >> 31) | (r << 31));
+}
+
+int
+test_10 (int a, int b)
+{
+ bool r = a == b;
+ return r << 31;
+}
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [SH] PR 54089 - Add support for rotcr insn
2012-08-19 23:03 [SH] PR 54089 - Add support for rotcr insn Oleg Endo
@ 2012-08-20 11:13 ` Kaz Kojima
2012-08-20 21:09 ` Gary Funck
1 sibling, 0 replies; 4+ messages in thread
From: Kaz Kojima @ 2012-08-20 11:13 UTC (permalink / raw)
To: oleg.endo; +Cc: gcc-patches
Oleg Endo <oleg.endo@t-online.de> wrote:
> This adds support for SH's rotcr insn.
> Tested on rev 190459 with
> make -k check RUNTESTFLAGS="--target_board=sh-sim
> \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
>
> and no new failures.
> OK?
OK.
Regards,
kaz
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [SH] PR 54089 - Add support for rotcr insn
2012-08-19 23:03 [SH] PR 54089 - Add support for rotcr insn Oleg Endo
2012-08-20 11:13 ` Kaz Kojima
@ 2012-08-20 21:09 ` Gary Funck
2012-08-20 21:38 ` Oleg Endo
1 sibling, 1 reply; 4+ messages in thread
From: Gary Funck @ 2012-08-20 21:09 UTC (permalink / raw)
To: Oleg Endo; +Cc: gcc-patches
On 08/20/12 01:02:39, Oleg Endo wrote:
> Hello,
>
> This adds support for SH's rotcr insn.
> Tested on rev 190459 with
> make -k check RUNTESTFLAGS="--target_board=sh-sim
> \{-m2/-ml,-m2/-mb,-m2a/-mb,-m4/-ml,-m4/-mb,-m4a/-ml,-m4a/-mb}"
>
> and no new failures.
> OK?
>
> Cheers,
> Oleg
>
> ChangeLog:
>
> PR target/50489
Above: that should be: PR target/54089.
> * config/sh/sh.md (rotcr, *rotcr, shar, shlr): New insns and
> splits.
> (ashrdi3_k, lshrdi3_k): Rewrite as insn_and_split.
> * config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p): New function.
> * config/sh/sh-protos.h (sh_lshrsi_clobbers_t_reg_p): Declare
> it.
>
> testsuite/ChangeLog:
>
> PR target/50489
Here also.
> * gcc.target/sh/pr54089-1.c: New.
This is OK.
For a sec. I thought my long-standing bug report
got some attention. :)
- Gary
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [SH] PR 54089 - Add support for rotcr insn
2012-08-20 21:09 ` Gary Funck
@ 2012-08-20 21:38 ` Oleg Endo
0 siblings, 0 replies; 4+ messages in thread
From: Oleg Endo @ 2012-08-20 21:38 UTC (permalink / raw)
To: Gary Funck; +Cc: gcc-patches
On Mon, 2012-08-20 at 14:09 -0700, Gary Funck wrote:
> >
> > ChangeLog:
> >
> > PR target/50489
>
> Above: that should be: PR target/54089.
>
> > * config/sh/sh.md (rotcr, *rotcr, shar, shlr): New insns and
> > splits.
> > (ashrdi3_k, lshrdi3_k): Rewrite as insn_and_split.
> > * config/sh/sh.c (sh_lshrsi_clobbers_t_reg_p): New function.
> > * config/sh/sh-protos.h (sh_lshrsi_clobbers_t_reg_p): Declare
> > it.
> >
> > testsuite/ChangeLog:
> >
> > PR target/50489
>
> Here also.
>
> > * gcc.target/sh/pr54089-1.c: New.
>
> This is OK.
Thanks and sorry for the digit twister.
I've corrected it in the ChangeLog files. Is there any way to delete
the PR commit comment in bugzilla?
> For a sec. I thought my long-standing bug report
> got some attention. :)
It did, but probably not in a constructive way ;)
Cheers,
Oleg
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2012-08-20 21:38 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-08-19 23:03 [SH] PR 54089 - Add support for rotcr insn Oleg Endo
2012-08-20 11:13 ` Kaz Kojima
2012-08-20 21:09 ` Gary Funck
2012-08-20 21:38 ` Oleg Endo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).