mirror of
https://gcc.gnu.org/git/gcc.git
synced 2026-02-22 12:00:03 -05:00
Compare commits
20 Commits
trunk
...
devel/loop
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
271072ca25 | ||
|
|
da159b3057 | ||
|
|
8d64734864 | ||
|
|
399a970a9e | ||
|
|
74ccb99070 | ||
|
|
ef6f1e1356 | ||
|
|
1990086f57 | ||
|
|
3a3e129ce0 | ||
|
|
0cc1e77123 | ||
|
|
88701062f3 | ||
|
|
ce7462de86 | ||
|
|
04951a4791 | ||
|
|
68db341795 | ||
|
|
3281d212cb | ||
|
|
6a11fbc73f | ||
|
|
149d1e4ec9 | ||
|
|
1fb345c4ed | ||
|
|
694b57cbf4 | ||
|
|
401de0fee5 | ||
|
|
1fdb1e9a24 |
@@ -187,6 +187,7 @@ DEBUG_COUNTER (ira_move)
|
||||
DEBUG_COUNTER (ivopts_loop)
|
||||
DEBUG_COUNTER (lim)
|
||||
DEBUG_COUNTER (local_alloc_for_sched)
|
||||
DEBUG_COUNTER (loop_unswitch)
|
||||
DEBUG_COUNTER (match)
|
||||
DEBUG_COUNTER (merged_ipa_icf)
|
||||
DEBUG_COUNTER (phiopt_edge_range)
|
||||
|
||||
@@ -14180,9 +14180,6 @@ The maximum depth of a loop nest suitable for complete peeling.
|
||||
@item max-unswitch-insns
|
||||
The maximum number of insns of an unswitched loop.
|
||||
|
||||
@item max-unswitch-level
|
||||
The maximum number of branches unswitched in a single loop.
|
||||
|
||||
@item lim-expensive
|
||||
The minimum cost of an expensive expression in the loop invariant motion.
|
||||
|
||||
|
||||
@@ -745,10 +745,6 @@ The maximum number of instructions to consider to unroll in a loop.
|
||||
Common Joined UInteger Var(param_max_unswitch_insns) Init(50) Param Optimization
|
||||
The maximum number of insns of an unswitched loop.
|
||||
|
||||
-param=max-unswitch-level=
|
||||
Common Joined UInteger Var(param_max_unswitch_level) Init(3) Param Optimization
|
||||
The maximum number of unswitchings in a single loop.
|
||||
|
||||
-param=max-variable-expansions-in-unroller=
|
||||
Common Joined UInteger Var(param_max_variable_expansions) Init(1) Param Optimization
|
||||
If -fvariable-expansion-in-unroller is used, the maximum number of times that an individual variable will be expanded during loop unrolling.
|
||||
|
||||
56
gcc/testsuite/gcc.dg/loop-unswitch-10.c
Normal file
56
gcc/testsuite/gcc.dg/loop-unswitch-10.c
Normal file
@@ -0,0 +1,56 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
__attribute__((noipa))
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, int order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp, tmp2;
|
||||
|
||||
switch(order)
|
||||
{
|
||||
case 0:
|
||||
tmp = -8 * a[i];
|
||||
tmp2 = 2 * b[i];
|
||||
break;
|
||||
case 1:
|
||||
tmp = 3 * a[i] - 2 * b[i];
|
||||
tmp2 = 5 * b[i] - 2 * c[i];
|
||||
break;
|
||||
case 2:
|
||||
tmp = 9 * a[i] + 2 * b[i] + c[i];
|
||||
tmp2 = 4 * b[i] + 2 * c[i] + 8 * d[i];
|
||||
break;
|
||||
case 3:
|
||||
tmp = 3 * a[i] + 2 * b[i] - c[i];
|
||||
tmp2 = b[i] - 2 * c[i] + 8 * d[i];
|
||||
break;
|
||||
defaut:
|
||||
__builtin_unreachable ();
|
||||
}
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
double y = 3.4f * tmp + d[i] + tmp2;
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define N 16 * 1024
|
||||
double aa[N], bb[N], cc[N], dd[N], rr[N];
|
||||
|
||||
int main()
|
||||
{
|
||||
for (int i = 0; i < 100 * 1000; i++)
|
||||
foo (aa, bb, cc, dd, rr, N, i % 4);
|
||||
}
|
||||
|
||||
|
||||
/* Test that we actually unswitched something. */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 0" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 1" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 2" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 3" 1 "unswitch" } } */
|
||||
45
gcc/testsuite/gcc.dg/loop-unswitch-11.c
Normal file
45
gcc/testsuite/gcc.dg/loop-unswitch-11.c
Normal file
@@ -0,0 +1,45 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, int order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp, tmp2;
|
||||
|
||||
switch(order)
|
||||
{
|
||||
case 5 ... 6:
|
||||
case 9:
|
||||
tmp = -8 * a[i];
|
||||
tmp2 = 2 * b[i];
|
||||
break;
|
||||
case 11:
|
||||
tmp = 3 * a[i] - 2 * b[i];
|
||||
tmp2 = 5 * b[i] - 2 * c[i];
|
||||
break;
|
||||
case 22:
|
||||
tmp = 9 * a[i] + 2 * b[i] + c[i];
|
||||
tmp2 = 4 * b[i] + 2 * c[i] + 8 * d[i];
|
||||
break;
|
||||
case 33:
|
||||
tmp = 3 * a[i] + 2 * b[i] - c[i];
|
||||
tmp2 = b[i] - 2 * c[i] + 8 * d[i];
|
||||
break;
|
||||
defaut:
|
||||
__builtin_unreachable ();
|
||||
}
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
double y = 3.4f * tmp + d[i] + tmp2;
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* \\+ 4294967291.*order.* == 9" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 1" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 2" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 3" 1 "unswitch" } } */
|
||||
28
gcc/testsuite/gcc.dg/loop-unswitch-12.c
Normal file
28
gcc/testsuite/gcc.dg/loop-unswitch-12.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, int order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
if (order == 1)
|
||||
tmp = -8 * a[i];
|
||||
else
|
||||
tmp = -4 * b[i];
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
|
||||
if (order == 1)
|
||||
x += 2;
|
||||
|
||||
double y = 3.4f * tmp + d[i];
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 1" 1 "unswitch" } } */
|
||||
35
gcc/testsuite/gcc.dg/loop-unswitch-13.c
Normal file
35
gcc/testsuite/gcc.dg/loop-unswitch-13.c
Normal file
@@ -0,0 +1,35 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fno-thread-jumps -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, unsigned order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
switch (order)
|
||||
{
|
||||
case 0 ... 4:
|
||||
tmp = -8 * a[i];
|
||||
break;
|
||||
default:
|
||||
tmp = -4 * b[i];
|
||||
break;
|
||||
}
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
|
||||
/* This and the case 0 ... 4 condition should only be unswitched once
|
||||
since they are mutually excluded. */
|
||||
if (order >= 5)
|
||||
x += 2;
|
||||
|
||||
double y = 3.4f * tmp + d[i];
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition" 1 "unswitch" } } */
|
||||
60
gcc/testsuite/gcc.dg/loop-unswitch-14.c
Normal file
60
gcc/testsuite/gcc.dg/loop-unswitch-14.c
Normal file
@@ -0,0 +1,60 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized --param=max-unswitch-insns=1000" } */
|
||||
|
||||
int
|
||||
__attribute__((noipa))
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, int order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp, tmp2;
|
||||
|
||||
if (order <= 0)
|
||||
tmp = 123;
|
||||
|
||||
switch(order)
|
||||
{
|
||||
case 0:
|
||||
tmp += -8 * a[i];
|
||||
tmp2 = 2 * b[i];
|
||||
break;
|
||||
case 1:
|
||||
tmp = 3 * a[i] - 2 * b[i];
|
||||
tmp2 = 5 * b[i] - 2 * c[i];
|
||||
break;
|
||||
case 2:
|
||||
tmp = 9 * a[i] + 2 * b[i] + c[i];
|
||||
tmp2 = 4 * b[i] + 2 * c[i] + 8 * d[i];
|
||||
break;
|
||||
case 3:
|
||||
tmp = 3 * a[i] + 2 * b[i] - c[i];
|
||||
tmp2 = b[i] - 2 * c[i] + 8 * d[i];
|
||||
break;
|
||||
defaut:
|
||||
__builtin_unreachable ();
|
||||
}
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
double y = 3.4f * tmp + d[i] + tmp2;
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#define N 16 * 1024
|
||||
double aa[N], bb[N], cc[N], dd[N], rr[N];
|
||||
|
||||
int main()
|
||||
{
|
||||
for (int i = 0; i < 100 * 1000; i++)
|
||||
foo (aa, bb, cc, dd, rr, N, i % 4);
|
||||
}
|
||||
|
||||
|
||||
/* Test that we actually unswitched something. */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* <= 0" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 0" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 1" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 2" 1 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 3" 1 "unswitch" } } */
|
||||
15
gcc/testsuite/gcc.dg/loop-unswitch-15.c
Normal file
15
gcc/testsuite/gcc.dg/loop-unswitch-15.c
Normal file
@@ -0,0 +1,15 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
void bar();
|
||||
void baz();
|
||||
void foo (int a, int b, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (a < b)
|
||||
bar ();
|
||||
else
|
||||
baz ();
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump "Unswitching loop on condition:" "unswitch" } } */
|
||||
22
gcc/testsuite/gcc.dg/loop-unswitch-16.c
Normal file
22
gcc/testsuite/gcc.dg/loop-unswitch-16.c
Normal file
@@ -0,0 +1,22 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized --param max-unswitch-insns=100" } */
|
||||
|
||||
void bar (int);
|
||||
void foo (int a, int b, int c, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
{
|
||||
if (a > 5)
|
||||
bar (1);
|
||||
if (b < 10)
|
||||
bar (2);
|
||||
if (c != 5)
|
||||
bar (3);
|
||||
}
|
||||
}
|
||||
|
||||
/* Verify we can unswitch all permutations of the predicates. */
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition" 7 "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump "Unswitching loop on condition: a" "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump "Unswitching loop on condition: b" "unswitch" } } */
|
||||
/* { dg-final { scan-tree-dump "Unswitching loop on condition: c" "unswitch" } } */
|
||||
24
gcc/testsuite/gcc.dg/loop-unswitch-17.c
Normal file
24
gcc/testsuite/gcc.dg/loop-unswitch-17.c
Normal file
@@ -0,0 +1,24 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int foo (int a)
|
||||
{
|
||||
do
|
||||
{
|
||||
if (a == 1)
|
||||
return 0;
|
||||
switch (a)
|
||||
{
|
||||
case 1:
|
||||
return 5;
|
||||
case 2:
|
||||
return 7;
|
||||
case 3:
|
||||
return 11;
|
||||
default:;
|
||||
}
|
||||
}
|
||||
while (1);
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop" 3 "unswitch" } } */
|
||||
28
gcc/testsuite/gcc.dg/loop-unswitch-7.c
Normal file
28
gcc/testsuite/gcc.dg/loop-unswitch-7.c
Normal file
@@ -0,0 +1,28 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fno-thread-jumps -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, float order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
if (order == 1.f)
|
||||
tmp = -8 * a[i];
|
||||
else
|
||||
tmp = -4 * b[i];
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
|
||||
if (order == 1.f)
|
||||
x += 2;
|
||||
|
||||
double y = 3.4f * tmp + d[i];
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order.* == 1.0e" 1 "unswitch" } } */
|
||||
31
gcc/testsuite/gcc.dg/loop-unswitch-8.c
Normal file
31
gcc/testsuite/gcc.dg/loop-unswitch-8.c
Normal file
@@ -0,0 +1,31 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, int order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
if (order < 3)
|
||||
tmp = -8 * a[i];
|
||||
else
|
||||
tmp = -4 * b[i];
|
||||
|
||||
double x = 3 * tmp + d[i] + tmp;
|
||||
|
||||
if (5 > order)
|
||||
x += 2;
|
||||
|
||||
if (order == 12345)
|
||||
x *= 5;
|
||||
|
||||
double y = 3.4f * tmp + d[i];
|
||||
r[i] = x + y;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order" 3 "unswitch" } } */
|
||||
27
gcc/testsuite/gcc.dg/loop-unswitch-9.c
Normal file
27
gcc/testsuite/gcc.dg/loop-unswitch-9.c
Normal file
@@ -0,0 +1,27 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-options "-O2 -funswitch-loops -fdump-tree-unswitch-optimized" } */
|
||||
|
||||
int
|
||||
foo(double *a, double *b, double *c, double *d, double *r, int size, int order)
|
||||
{
|
||||
for (int i = 0; i < size; i++)
|
||||
{
|
||||
double tmp;
|
||||
|
||||
if (order == 1)
|
||||
tmp = -8 * a[i];
|
||||
else
|
||||
{
|
||||
if (order == 2)
|
||||
tmp = -4 * b[i];
|
||||
else
|
||||
tmp = a[i];
|
||||
}
|
||||
|
||||
r[i] = 3.4f * tmp + d[i];
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* { dg-final { scan-tree-dump-times "Unswitching loop on condition: order" 2 "unswitch" } } */
|
||||
39
gcc/testsuite/gcc.dg/torture/20220518-1.c
Normal file
39
gcc/testsuite/gcc.dg/torture/20220518-1.c
Normal file
@@ -0,0 +1,39 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-funswitch-loops" } */
|
||||
|
||||
enum {
|
||||
MOD_WVG_MASK_TEX_USE_INT,
|
||||
MOD_WVG_MASK_TEX_USE_RED,
|
||||
MOD_WVG_MASK_TEX_USE_BLUE,
|
||||
MOD_WVG_MASK_TEX_USE_SAT,
|
||||
MOD_WVG_MASK_TEX_USE_VAL,
|
||||
MOD_WVG_MASK_TEX_USE_ALPHA
|
||||
} foo_num;
|
||||
float *foo_org_w;
|
||||
int *foo_new_w;
|
||||
float foo_fact;
|
||||
int foo_tex_use_channel, foo_i, foo_texres_0;
|
||||
void foo()
|
||||
{
|
||||
for (; foo_num;)
|
||||
switch (foo_tex_use_channel) {
|
||||
case MOD_WVG_MASK_TEX_USE_INT:
|
||||
foo_org_w[foo_i] = foo_new_w[foo_i] * foo_texres_0;
|
||||
break;
|
||||
case MOD_WVG_MASK_TEX_USE_RED:
|
||||
foo_org_w[foo_i] = 0;
|
||||
case MOD_WVG_MASK_TEX_USE_BLUE:
|
||||
foo_org_w[foo_i] = foo_fact + foo_org_w[foo_i];
|
||||
break;
|
||||
case MOD_WVG_MASK_TEX_USE_SAT:
|
||||
foo_org_w[foo_i] = foo_fact;
|
||||
break;
|
||||
case MOD_WVG_MASK_TEX_USE_VAL:
|
||||
foo_org_w[foo_i] = 0;
|
||||
case MOD_WVG_MASK_TEX_USE_ALPHA:
|
||||
foo_org_w[foo_i] = foo_fact + foo_org_w[foo_i];
|
||||
break;
|
||||
default:
|
||||
foo_org_w[foo_i] = foo_new_w[foo_i] * foo_texres_0;
|
||||
}
|
||||
}
|
||||
14
gcc/testsuite/gcc.dg/torture/20220518-2.c
Normal file
14
gcc/testsuite/gcc.dg/torture/20220518-2.c
Normal file
@@ -0,0 +1,14 @@
|
||||
/* { dg-do compile } */
|
||||
/* { dg-additional-options "-funswitch-loops" } */
|
||||
|
||||
int Get_Spline_Val_sp_0, Get_Spline_Val_k;
|
||||
double Get_Spline_Val_p, Get_Spline_Val_se_0_0_0;
|
||||
double *Get_Spline_Val_v;
|
||||
void Get_Spline_Val() {
|
||||
int i;
|
||||
for (;;)
|
||||
if (i > Get_Spline_Val_sp_0)
|
||||
Get_Spline_Val_k = Get_Spline_Val_se_0_0_0;
|
||||
else if (Get_Spline_Val_sp_0 == 1)
|
||||
Get_Spline_Val_v[Get_Spline_Val_k] = Get_Spline_Val_p;
|
||||
}
|
||||
@@ -9038,11 +9038,16 @@ gimple_lv_add_condition_to_bb (basic_block first_head ATTRIBUTE_UNUSED,
|
||||
edge e0;
|
||||
|
||||
/* Build new conditional expr */
|
||||
gsi = gsi_last_bb (cond_bb);
|
||||
|
||||
cond_expr = force_gimple_operand_gsi_1 (&gsi, cond_expr,
|
||||
is_gimple_condexpr_for_cond,
|
||||
NULL_TREE, false,
|
||||
GSI_CONTINUE_LINKING);
|
||||
new_cond_expr = gimple_build_cond_from_tree (cond_expr,
|
||||
NULL_TREE, NULL_TREE);
|
||||
|
||||
/* Add new cond in cond_bb. */
|
||||
gsi = gsi_last_bb (cond_bb);
|
||||
gsi_insert_after (&gsi, new_cond_expr, GSI_NEW_STMT);
|
||||
|
||||
/* Adjust edges appropriately to connect new head with first head
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user