* [Committed] [PATCH, loop2_invariant, 1/2] Check only one register class
@ 2014-06-30 3:46 Zhenqiang Chen
0 siblings, 0 replies; only message in thread
From: Zhenqiang Chen @ 2014-06-30 3:46 UTC (permalink / raw)
To: Jeff Law; +Cc: Steven Bosscher, gcc-patches
On 26 June 2014 05:30, Jeff Law <law@redhat.com> wrote:
> On 06/11/14 04:05, Zhenqiang Chen wrote:
>>
>> On 10 June 2014 19:06, Steven Bosscher <stevenb.gcc@gmail.com> wrote:
>>>
>>> On Tue, Jun 10, 2014 at 11:22 AM, Zhenqiang Chen wrote:
>>>>
>>>> Hi,
>>>>
>>>> For loop2-invariant pass, when flag_ira_loop_pressure is enabled,
>>>> function gain_for_invariant checks the pressures of all register
>>>> classes. This does not make sense since one invariant might impact
>>>> only one register class.
>>>>
>>>> The patch enhances functions get_inv_cost and gain_for_invariant to
>>>> check only the register pressure of the invariant if possible.
>>>
>>>
>>> This patch may work for targets with more-or-less orthogonal reg
>>> classes, but not if there is a lot of overlap between reg classes.
>>
>>
>> Yes. I need check the overlap between reg classes.
>>
>> Patch is updated to check all overlap reg classes by
>> reg_classes_intersect_p:
>
> So you need a new ChangeLog, of course :-)
>
>
>
>>
>> diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
>> index c76a2a0..6e43b49 100644
>> --- a/gcc/loop-invariant.c
>> +++ b/gcc/loop-invariant.c
>> @@ -1092,16 +1092,22 @@ get_pressure_class_and_nregs (rtx insn, int
>> *nregs)
>> }
>>
>> /* Calculates cost and number of registers needed for moving invariant
>> INV
>> - out of the loop and stores them to *COST and *REGS_NEEDED. */
>> + out of the loop and stores them to *COST and *REGS_NEEDED. *CL will
>> be
>> + the REG_CLASS of INV. Return
>> + 0: if INV is invalid.
>> + 1: if INV and its depends_on have same reg_class
>> + > 1: if INV and its depends_on have different reg_classes. */
>
> Nit/bikeshedding. I tend to prefer < 0, 0, > 0 (or -1, 0, 1) for
> tri-states. It's not a big deal though.
Thanks! Update the tri-state values to ( -1, 0, 1).
>
>> check_p = i < ira_pressure_classes_num;
>> +
>> + if ((dep_ret > 1) || ((dep_ret == 1) && (*cl != dep_cl)))
>> + {
>> + *cl = ALL_REGS;
>> + ret ++;
>
> Whitespace nit -- no space in this statement. use "ret++;"
>
> You should add a testcase if at all possible. Perhaps two, one which runs
> on an ARM variant and one for x86_64. The former because that's obviously
> what Linaro cares about, the latter for wider testing.
>
>
> Definitely add a ChangeLog entry, fix the whitespace nit & add testcase. OK
> with those fixes. Your choice on the tri-state values.
Updated with a testcase for X86-64 and committed @212135.
ChangeLog:
2014-06-30 Zhenqiang Chen <zhenqiang.chen@linaro.org>
* loop-invariant.c (get_inv_cost): Handle register class.
(gain_for_invariant): Check the register pressure of the inv
and its overlapped register class, other than all.
testsuite/ChangeLog:
2014-06-30 Zhenqiang Chen <zhenqiang.chen@linaro.org>
* ira-loop-pressure.c: New test.
diff --git a/gcc/loop-invariant.c b/gcc/loop-invariant.c
index 25e63e4..ef5c59b 100644
--- a/gcc/loop-invariant.c
+++ b/gcc/loop-invariant.c
@@ -1090,16 +1090,22 @@ get_pressure_class_and_nregs (rtx insn, int *nregs)
}
/* Calculates cost and number of registers needed for moving invariant INV
- out of the loop and stores them to *COST and *REGS_NEEDED. */
+ out of the loop and stores them to *COST and *REGS_NEEDED. *CL will be
+ the REG_CLASS of INV. Return
+ -1: if INV is invalid.
+ 0: if INV and its depends_on have same reg_class
+ 1: if INV and its depends_on have different reg_classes. */
-static void
-get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed)
+static int
+get_inv_cost (struct invariant *inv, int *comp_cost, unsigned *regs_needed,
+ enum reg_class *cl)
{
int i, acomp_cost;
unsigned aregs_needed[N_REG_CLASSES];
unsigned depno;
struct invariant *dep;
bitmap_iterator bi;
+ int ret = 1;
/* Find the representative of the class of the equivalent invariants. */
inv = invariants[inv->eqto];
@@ -1115,7 +1121,7 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
if (inv->move
|| inv->stamp == actual_stamp)
- return;
+ return -1;
inv->stamp = actual_stamp;
if (! flag_ira_loop_pressure)
@@ -1127,6 +1133,8 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
pressure_class = get_pressure_class_and_nregs (inv->insn, &nregs);
regs_needed[pressure_class] += nregs;
+ *cl = pressure_class;
+ ret = 0;
}
if (!inv->cheap_address
@@ -1167,6 +1175,8 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
EXECUTE_IF_SET_IN_BITMAP (inv->depends_on, 0, depno, bi)
{
bool check_p;
+ enum reg_class dep_cl = ALL_REGS;
+ int dep_ret;
dep = invariants[depno];
@@ -1174,7 +1184,7 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
if (dep->move)
continue;
- get_inv_cost (dep, &acomp_cost, aregs_needed);
+ dep_ret = get_inv_cost (dep, &acomp_cost, aregs_needed, &dep_cl);
if (! flag_ira_loop_pressure)
check_p = aregs_needed[0] != 0;
@@ -1184,6 +1194,12 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
if (aregs_needed[ira_pressure_classes[i]] != 0)
break;
check_p = i < ira_pressure_classes_num;
+
+ if ((dep_ret == 1) || ((dep_ret == 0) && (*cl != dep_cl)))
+ {
+ *cl = ALL_REGS;
+ ret = 1;
+ }
}
if (check_p
/* We need to check always_executed, since if the original value of
@@ -1217,6 +1233,7 @@ get_inv_cost (struct invariant *inv, int
*comp_cost, unsigned *regs_needed)
}
(*comp_cost) += acomp_cost;
}
+ return ret;
}
/* Calculates gain for eliminating invariant INV. REGS_USED is the number
@@ -1231,10 +1248,12 @@ gain_for_invariant (struct invariant *inv,
unsigned *regs_needed,
bool speed, bool call_p)
{
int comp_cost, size_cost;
+ enum reg_class cl;
+ int ret;
actual_stamp++;
- get_inv_cost (inv, &comp_cost, regs_needed);
+ ret = get_inv_cost (inv, &comp_cost, regs_needed, &cl);
if (! flag_ira_loop_pressure)
{
@@ -1243,6 +1262,11 @@ gain_for_invariant (struct invariant *inv,
unsigned *regs_needed,
- estimate_reg_pressure_cost (new_regs[0],
regs_used, speed, call_p));
}
+ else if (ret < 0)
+ return -1;
+ else if ((ret == 0) && (cl == NO_REGS))
+ /* Hoist it anyway since it does not impact register pressure. */
+ return 1;
else
{
int i;
@@ -1251,6 +1275,10 @@ gain_for_invariant (struct invariant *inv,
unsigned *regs_needed,
for (i = 0; i < ira_pressure_classes_num; i++)
{
pressure_class = ira_pressure_classes[i];
+
+ if (!reg_classes_intersect_p (pressure_class, cl))
+ continue;
+
if ((int) new_regs[pressure_class]
+ (int) regs_needed[pressure_class]
+ LOOP_DATA (curr_loop)->max_reg_pressure[pressure_class]
diff --git a/gcc/testsuite/gcc.dg/ira-loop-pressure.c
b/gcc/testsuite/gcc.dg/ira-loop-pressure.c
new file mode 100644
index 0000000..7ef4fa7
--- /dev/null
+++ b/gcc/testsuite/gcc.dg/ira-loop-pressure.c
@@ -0,0 +1,32 @@
+/* Loop2_invariants pass should distinguish register pressures of different
+ register classes. In this case, register pressue of INT is high. But
+ we can still move the FP invariant out of the loop. */
+
+/* { dg-do compile { target { x86_64-*-* && lp64 } } } */
+/* { dg-options "-O2 -fira-loop-pressure -fdump-rtl-loop2_invariant " } */
+
+float tt;
+extern void foo2 (int *, int *, int *, int *, int *, int *);
+extern int foo3 (int, int, int, int, int, int);
+int foo (int a, int b, int c, int d)
+{
+ int i = a;
+ int t1, t2, t3, t4, t5, t6;
+ t1 = t2 = t3 = t4 = t5 = t6 = 0;
+
+ for (; i > 0; i += c)
+ {
+ tt += 123456.0;
+ if (d > t1 + t2)
+ tt = 3.0;
+ foo2 (&t1, &t2, &t3, &t4, &t5, &t6);
+ t1 += t3 + t4 + a + b;
+ t2 -= t5 - t6 - c - d;
+ }
+
+ return foo3 (t1, t2, t3, t4, t5, t6);
+}
+
+/* { dg-final { scan-rtl-dump "Decided to move invariant"
"loop2_invariant" } } */
+/* { dg-final { cleanup-rtl-dump "loop2_invariant" } } */
+
^ permalink raw reply [flat|nested] only message in thread
only message in thread, other threads:[~2014-06-30 3:46 UTC | newest]
Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-30 3:46 [Committed] [PATCH, loop2_invariant, 1/2] Check only one register class Zhenqiang Chen
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).