* [SH][committed] Improve treg_set_expr matching
@ 2015-09-28 14:53 Oleg Endo
2015-10-01 12:39 ` Oleg Endo
0 siblings, 1 reply; 2+ messages in thread
From: Oleg Endo @ 2015-09-28 14:53 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 944 bytes --]
Hi,
This patch has been hanging around in my queue for a while. Basically,
it uses reverse_condition to get better matching for treg_set_expr.
Tested on sh-elf 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.
Committed as r228202.
Cheers,
Oleg
gcc/ChangeLog:
PR target/54236
* config/sh/predicates.md (t_reg_operand, negt_reg_operand): Allow
and handle ne and eq codes.
* config/sh/sh.c (sh_rtx_costs): Adjust matching of tst #imm,r0 insn.
(sh_recog_treg_set_expr): Early accept negt_reg_operand. Eearly reject
CONST_INT_P. Use reverse_condition.
(sh_split_treg_set_expr): Likewise.
gcc/testsuite/ChangeLog:
PR target/54236
* gcc.target/sh/pr54236-1.c (test_09, test_10, test_11): New.
* gcc.target/sh/pr59533-1.c (test_23, test_24, test_25, test_26,
test_27): New.
* gcc.target/sh/pr54236-5.c: New.
* gcc.target/sh/pr54236-6.c: New.
[-- Attachment #2: sh_pr54236_10_3.patch --]
[-- Type: text/x-patch, Size: 13512 bytes --]
Index: gcc/config/sh/predicates.md
===================================================================
--- gcc/config/sh/predicates.md (revision 228175)
+++ gcc/config/sh/predicates.md (working copy)
@@ -1158,10 +1158,18 @@
;; A predicate describing the T bit register in any form.
(define_predicate "t_reg_operand"
- (match_code "reg,subreg,sign_extend,zero_extend")
+ (match_code "reg,subreg,sign_extend,zero_extend,ne,eq")
{
switch (GET_CODE (op))
{
+ case EQ:
+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
+ && XEXP (op, 1) == const1_rtx;
+
+ case NE:
+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
+ && XEXP (op, 1) == const0_rtx;
+
case REG:
return REGNO (op) == T_REG;
@@ -1183,13 +1191,21 @@
;; A predicate describing a negated T bit register.
(define_predicate "negt_reg_operand"
- (match_code "subreg,xor")
+ (match_code "subreg,xor,ne,eq")
{
switch (GET_CODE (op))
{
+ case EQ:
+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
+ && XEXP (op, 1) == const0_rtx;
+
+ case NE:
+ return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
+ && XEXP (op, 1) == const1_rtx;
+
case XOR:
return t_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)))
- && satisfies_constraint_M (XEXP (op, 1));
+ && XEXP (op, 1) == const1_rtx;
case SUBREG:
return negt_reg_operand (XEXP (op, 0), GET_MODE (XEXP (op, 0)));
Index: gcc/config/sh/sh.c
===================================================================
--- gcc/config/sh/sh.c (revision 228176)
+++ gcc/config/sh/sh.c (working copy)
@@ -3592,13 +3592,12 @@
case EQ:
/* An and with a constant compared against zero is
- most likely going to be a TST #imm, R0 instruction.
- Notice that this does not catch the zero_extract variants from
- the md file. */
+ most likely going to be a TST #imm, R0 instruction. */
if (XEXP (x, 1) == const0_rtx
- && (GET_CODE (XEXP (x, 0)) == AND
- || (SUBREG_P (XEXP (x, 0))
- && GET_CODE (SUBREG_REG (XEXP (x, 0))) == AND)))
+ && ((GET_CODE (XEXP (x, 0)) == AND
+ || (SUBREG_P (XEXP (x, 0))
+ && GET_CODE (SUBREG_REG (XEXP (x, 0))) == AND))
+ || GET_CODE (XEXP (x, 0)) == ZERO_EXTRACT))
{
*total = 1;
return true;
@@ -14200,7 +14199,8 @@
return false;
/* Early accept known possible operands before doing recog. */
- if (op == const0_rtx || op == const1_rtx || t_reg_operand (op, mode))
+ if (op == const0_rtx || op == const1_rtx || t_reg_operand (op, mode)
+ || negt_reg_operand (op, mode))
return true;
/* Early reject impossible operands before doing recog.
@@ -14209,8 +14209,8 @@
such as lower-subreg will bail out. Some insns such as SH4A movua are
done with UNSPEC, so must reject those, too, or else it would result
in an invalid reg -> treg move. */
- if (register_operand (op, mode) || memory_operand (op, mode)
- || sh_unspec_insn_p (op))
+ if (CONST_INT_P (op) || register_operand (op, mode)
+ || memory_operand (op, mode) || sh_unspec_insn_p (op))
return false;
if (!can_create_pseudo_p ())
@@ -14230,26 +14230,30 @@
SET_PREV_INSN (i) = NULL;
SET_NEXT_INSN (i) = NULL;
+ /* If the comparison op doesn't have a result mode, set it to SImode. */
+ machine_mode prev_op_mode = GET_MODE (op);
+ if (COMPARISON_P (op) && prev_op_mode == VOIDmode)
+ PUT_MODE (op, SImode);
+
int result = recog (PATTERN (i), i, 0);
- /* It seems there is no insn like that. Create a simple negated
- version and try again. If we hit a negated form, we'll allow that
- and append a nott sequence when splitting out the insns. Insns that
- do the split can then remove the trailing nott if they know how to
- deal with it. */
- if (result < 0 && GET_CODE (op) == EQ)
+ /* It seems there is no insn like that. Create a negated version and
+ try again. If we hit a negated form, we'll allow that and append a
+ nott sequence when splitting out the insns. Insns that do the split
+ can then remove the trailing nott if they know how to deal with it. */
+ if (result < 0 && COMPARISON_P (op))
{
- PUT_CODE (op, NE);
+ machine_mode cmp_mode = GET_MODE (XEXP (op, 0));
+ if (cmp_mode == VOIDmode)
+ cmp_mode = GET_MODE (XEXP (op, 1));
+
+ rtx_code prev_code = GET_CODE (op);
+ PUT_CODE (op, reverse_condition (GET_CODE (op)));
result = recog (PATTERN (i), i, 0);
- PUT_CODE (op, EQ);
+ PUT_CODE (op, prev_code);
}
- if (result < 0 && GET_CODE (op) == NE)
- {
- PUT_CODE (op, EQ);
- result = recog (PATTERN (i), i, 0);
- PUT_CODE (op, NE);
- }
+ PUT_MODE (op, prev_op_mode);
recog_data = prev_recog_data;
return result >= 0;
}
@@ -14350,37 +14354,43 @@
fprintf (dump_file, "\n");
}
+ /* If the insn is not found, we will try a negated form and append
+ a nott. */
+ bool append_nott = false;
+
/* We are going to invoke recog/split_insns in a re-entrant way and thus
have to capture its current state and restore it afterwards. */
recog_data_d prev_recog_data = recog_data;
- int insn_code = recog (PATTERN (i), i, 0);
-
- /* If the insn was not found, see if we matched the negated form before
- and append a nott. */
- bool append_nott = false;
-
- if (insn_code < 0 && GET_CODE (x) == EQ)
+ if (negt_reg_operand (x, GET_MODE (x)))
{
- PUT_CODE (x, NE);
- insn_code = recog (PATTERN (i), i, 0);
- if (insn_code >= 0)
- append_nott = true;
- else
- PUT_CODE (x, EQ);
+ /* This is a normal movt followed by a nott. It will be converted
+ into a movrt after initial expansion. */
+ XEXP (PATTERN (i), 1) = get_t_reg_rtx ();
+ append_nott = true;
}
- if (insn_code < 0 && GET_CODE (x) == NE)
+ else
{
- PUT_CODE (x, EQ);
- insn_code = recog (PATTERN (i), i, 0);
- if (insn_code >= 0)
- append_nott = true;
- else
- PUT_CODE (x, NE);
+ /* If the comparison op doesn't have a mode set, set it to SImode. */
+ if (COMPARISON_P (x) && GET_MODE (x) == VOIDmode)
+ PUT_MODE (x, SImode);
+
+ int insn_code = recog (PATTERN (i), i, 0);
+
+ if (insn_code < 0 && COMPARISON_P (x))
+ {
+ machine_mode cmp_mode = GET_MODE (XEXP (x, 0));
+ if (cmp_mode == VOIDmode)
+ cmp_mode = GET_MODE (XEXP (x, 1));
+
+ PUT_CODE (x, reverse_condition (GET_CODE (x)));
+ insn_code = recog (PATTERN (i), i, 0);
+ append_nott = true;
+ }
+
+ gcc_assert (insn_code >= 0);
}
- gcc_assert (insn_code >= 0);
-
/* Try to recursively split the insn. Some insns might refuse to split
any further while we are in the treg_set_expr splitting phase. They
will be emitted as part of the outer insn and then split again. */
Index: gcc/testsuite/gcc.target/sh/pr54236-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54236-1.c (revision 228175)
+++ gcc/testsuite/gcc.target/sh/pr54236-1.c (working copy)
@@ -4,8 +4,8 @@
/* { dg-do compile } */
/* { dg-options "-O1" } */
/* { dg-skip-if "" { "sh*-*-*" } { "-m5*"} { "" } } */
-/* { dg-final { scan-assembler-times "addc" 4 } } */
-/* { dg-final { scan-assembler-times "subc" 3 } } */
+/* { dg-final { scan-assembler-times "addc" 6 } } */
+/* { dg-final { scan-assembler-times "subc" 4 } } */
/* { dg-final { scan-assembler-times "sett" 5 } } */
/* { dg-final { scan-assembler-times "negc" 2 { target { ! sh2a } } } } */
@@ -86,3 +86,25 @@
/* 1x addc, 1x sett */
return (a << 1) + 1;
}
+
+unsigned int
+test_09 (unsigned int x)
+{
+ /* 1x tst, 1x addc */
+ return x - (x != 0);
+}
+
+unsigned int
+test_10 (unsigned int x)
+{
+ /* 1x tst, 1x subc */
+ return x + (x == 0);
+}
+
+unsigned int
+test_11 (unsigned int x)
+{
+ /* 1x tst, 1x addc */
+ return x + (x != 0);
+}
+
Index: gcc/testsuite/gcc.target/sh/pr54236-5.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54236-5.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54236-5.c (working copy)
@@ -0,0 +1,89 @@
+/* Check that addc and subc instructions are generated as expected in
+ combination with ifcvt. */
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-times "subc" 4 { target { ! sh2a } } } } */
+/* { dg-final { scan-assembler-times "addc" 4 { target { ! sh2a } } } } */
+/* { dg-final { scan-assembler-times "not\t" 0 { target { ! sh2a } } } } */
+
+/* { dg-final { scan-assembler-times "subc" 4 { target { sh2a } } } } */
+/* { dg-final { scan-assembler-times "addc" 4 { target { sh2a } } } } */
+/* { dg-final { scan-assembler-times "nott" 0 { target { sh2a } } } } */
+
+/* { dg-final { scan-assembler-times "tst\t" 4 } } */
+/* { dg-final { scan-assembler-times "cmp/eq" 1 } } */
+/* { dg-final { scan-assembler-times "cmp/pl" 2 } } */
+/* { dg-final { scan-assembler-times "cmp/gt" 1 } } */
+
+/* { dg-final { scan-assembler-not "movt" } } */
+/* { dg-final { scan-assembler-not "negc" } } */
+/* { dg-final { scan-assembler-not "movrt" } } */
+
+int
+test_00 (int x, int y)
+{
+ /* 1x tst, 1x subc */
+ if (y)
+ ++x;
+ return x;
+}
+
+int
+test_01 (int x, int y)
+{
+ /* 1x tst, 1x addc */
+ if (y)
+ --x;
+ return x;
+}
+
+int
+test_02 (int x, int y)
+{
+ /* 1x tst, 1x addc */
+ if (!y)
+ ++x;
+ return x;
+}
+
+int
+test_03 (int x, int y)
+{
+ /* 1x tst, 1x subc */
+ if (!y)
+ --x;
+ return x;
+}
+
+int
+test_04 (int x, int y)
+{
+ /* 1x cmp/eq, 1x addc */
+ if (y == x)
+ ++x;
+ return x;
+}
+
+int
+test_05 (int x, int y)
+{
+ /* 1x cmp/gt, 1x subc */
+ if (y < 4)
+ ++x;
+ return x;
+}
+
+int
+test_06 (int x)
+{
+ /* 1x cmp/pl, 1x addc */
+ return x > 0 ? x + 1 : x;
+}
+
+int
+test_07 (int x)
+{
+ /* 1x cmp/pl, 1x subc */
+ return x > 0 ? x - 1 : x;
+}
Index: gcc/testsuite/gcc.target/sh/pr54236-6.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54236-6.c (revision 0)
+++ gcc/testsuite/gcc.target/sh/pr54236-6.c (working copy)
@@ -0,0 +1,75 @@
+/* In this snippet, there was a missed subc case:
+ tst #1,r0
+ movt r0
+ neg r0,r0
+
+ which should be:
+ tst #1,r0
+ subc r0,r0
+*/
+
+/* { dg-do compile } */
+/* { dg-options "-O2" } */
+
+/* { dg-final { scan-assembler-times {tst #1,r0} 1 } } */
+/* { dg-final { scan-assembler-times {subc r} 1 } } */
+
+/* { dg-final { scan-assembler-not "movt|not|neg\movrt" } } */
+
+
+struct inode
+{
+ unsigned int i_gid;
+};
+
+struct iattr
+{
+ unsigned int ia_valid;
+ unsigned int ia_gid;
+};
+
+struct task_struct
+{
+ unsigned long flags;
+ unsigned int cap_effective;
+};
+
+extern int in_group_p (unsigned int);
+
+static inline struct task_struct*
+get_current (void)
+{
+ struct task_struct *current;
+ return current;
+}
+
+static inline int
+capable (int cap)
+{
+ if (((get_current()->cap_effective) & (1 << (cap))))
+ {
+ get_current()->flags |= 0x00000100;
+ return 1;
+ }
+ return 0;
+}
+
+int
+inode_change_ok (struct inode *inode, struct iattr *attr)
+{
+ int retval = -1;
+ unsigned int ia_valid = attr->ia_valid;
+
+ if (ia_valid & 512)
+ goto fine;
+
+ if ((ia_valid & 4)
+ && (!in_group_p(attr->ia_gid) && attr->ia_gid != inode->i_gid)
+ && !capable(0))
+ goto error;
+
+fine:
+ retval = 0;
+error:
+ return retval;
+}
Index: gcc/testsuite/gcc.target/sh/pr59533-1.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr59533-1.c (revision 228175)
+++ gcc/testsuite/gcc.target/sh/pr59533-1.c (working copy)
@@ -9,13 +9,13 @@
/* { dg-final { scan-assembler-times "and" 3 } } */
/* { dg-final { scan-assembler-times "extu.b" 5 } } */
-/* { dg-final { scan-assembler-times "cmp/pz" 22 { target { ! sh2a } } } } */
-/* { dg-final { scan-assembler-times "addc" 3 { target { ! sh2a } } } } */
-/* { dg-final { scan-assembler-times "subc" 12 { target { ! sh2a } } } } */
+/* { dg-final { scan-assembler-times "cmp/pz" 27 { target { ! sh2a } } } } */
+/* { dg-final { scan-assembler-times "addc" 4 { target { ! sh2a } } } } */
+/* { dg-final { scan-assembler-times "subc" 16 { target { ! sh2a } } } } */
-/* { dg-final { scan-assembler-times "cmp/pz" 20 { target { sh2a } } } } */
-/* { dg-final { scan-assembler-times "addc" 5 { target { sh2a } } } } */
-/* { dg-final { scan-assembler-times "subc" 10 { target { sh2a } } } } */
+/* { dg-final { scan-assembler-times "cmp/pz" 25 { target { sh2a } } } } */
+/* { dg-final { scan-assembler-times "addc" 6 { target { sh2a } } } } */
+/* { dg-final { scan-assembler-times "subc" 14 { target { sh2a } } } } */
/* { dg-final { scan-assembler-times "bld" 2 { target { sh2a } } } } */
int
@@ -183,3 +183,38 @@
/* 1x cmp/pz, 1x movt */
return (x >> 31) + 1;
}
+
+int
+test_23 (int x)
+{
+ /* 1x cmp/pz, 1x subc */
+ return x < 0 ? x + 1 : x;
+}
+
+unsigned int
+test_24 (unsigned int x)
+{
+ /* 1x cmp/pz, 1x subc */
+ return x & 0x80000000 ? x + 1 : x;
+}
+
+unsigned int
+test_25 (unsigned int x)
+{
+ /* 1x cmp/pz, 1x subc */
+ return x >> 31 ? x + 1 : x;
+}
+
+int
+test_26 (int x)
+{
+ /* 1x cmp/pz, 1x subc */
+ return x >> 31 ? x + 1 : x;
+}
+
+int
+test_27 (int x, int y, int z)
+{
+ /* 1x cmp/pz, 1x addc */
+ return 1 - ((x >> 4) < 0) + z;
+}
^ permalink raw reply [flat|nested] 2+ messages in thread
* Re: [SH][committed] Improve treg_set_expr matching
2015-09-28 14:53 [SH][committed] Improve treg_set_expr matching Oleg Endo
@ 2015-10-01 12:39 ` Oleg Endo
0 siblings, 0 replies; 2+ messages in thread
From: Oleg Endo @ 2015-10-01 12:39 UTC (permalink / raw)
To: gcc-patches
[-- Attachment #1: Type: text/plain, Size: 605 bytes --]
On Mon, 2015-09-28 at 23:03 +0900, Oleg Endo wrote:
> Hi,
>
> This patch has been hanging around in my queue for a while. Basically,
> it uses reverse_condition to get better matching for treg_set_expr.
> Tested on sh-elf 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.
> Committed as r228202.
Attached is a small follow up patch that fixes a typo in one of the
tests. Committed as r228332.
Cheers,
Oleg
gcc/testsuite/ChangeLog:
PR target/54236
* gcc.target/sh/pr54236-6.c: Fix assembler-not string.
[-- Attachment #2: sh_pr54236_10_3_testcase_typo.patch --]
[-- Type: text/x-patch, Size: 525 bytes --]
Index: gcc/testsuite/gcc.target/sh/pr54236-6.c
===================================================================
--- gcc/testsuite/gcc.target/sh/pr54236-6.c (revision 228244)
+++ gcc/testsuite/gcc.target/sh/pr54236-6.c (working copy)
@@ -14,7 +14,7 @@
/* { dg-final { scan-assembler-times {tst #1,r0} 1 } } */
/* { dg-final { scan-assembler-times {subc r} 1 } } */
-/* { dg-final { scan-assembler-not "movt|not|neg\movrt" } } */
+/* { dg-final { scan-assembler-not "movt|not\t|neg\t|movrt" } } */
struct inode
^ permalink raw reply [flat|nested] 2+ messages in thread
end of thread, other threads:[~2015-10-01 12:39 UTC | newest]
Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-09-28 14:53 [SH][committed] Improve treg_set_expr matching Oleg Endo
2015-10-01 12:39 ` 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).