diff options
author | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
---|---|---|
committer | upstream source tree <ports@midipix.org> | 2015-03-15 20:14:05 -0400 |
commit | 554fd8c5195424bdbcabf5de30fdc183aba391bd (patch) | |
tree | 976dc5ab7fddf506dadce60ae936f43f58787092 /gcc/testsuite/gcc.dg/tree-ssa | |
download | cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.bz2 cbb-gcc-4.6.4-554fd8c5195424bdbcabf5de30fdc183aba391bd.tar.xz |
obtained gcc-4.6.4.tar.bz2 from upstream website;upstream
verified gcc-4.6.4.tar.bz2.sig;
imported gcc-4.6.4 source tree from verified upstream tarball.
downloading a git-generated archive based on the 'upstream' tag
should provide you with a source tree that is binary identical
to the one extracted from the above tarball.
if you have obtained the source via the command 'git clone',
however, do note that line-endings of files in your working
directory might differ from line-endings of the respective
files in the upstream repository.
Diffstat (limited to 'gcc/testsuite/gcc.dg/tree-ssa')
792 files changed, 24561 insertions, 0 deletions
diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030530-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030530-2.c new file mode 100644 index 000000000..3d4ba4f91 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030530-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + + +typedef struct rs6000_stack { + int first_gp_reg_save; +} rs6000_stack_t; +extern char regs_ever_live[113]; +extern rs6000_stack_t *rs6000_stack_info (void); +void +rs6000_emit_prologue (int i, rs6000_stack_t *info) +{ + if (regs_ever_live[info->first_gp_reg_save + i] || i+info->first_gp_reg_save) + gen_rtx_REG (info->first_gp_reg_save + i); +} + +/* There should be precisely one load of first_gp_reg_save. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "first_gp_reg_save" 1 "dom2"} } */ + +/* There should be precisely one addition. If there is more than one, then + the dominator optimizations failed, most likely due to not handling + commutative operands correctly. */ +/* { dg-final { scan-tree-dump-times "\\+" 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030611-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030611-1.c new file mode 100644 index 000000000..fac91be70 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030611-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern int square (int) __attribute__ ((__const__)); +shit(int a) +{ + return square (a) + square (a); + +} + +/* There should be precisely one call to square. If there is more than one, + then the dominator optimizations failed to remove the redundant call. */ +/* { dg-final { scan-tree-dump-times "square" 1 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030703-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030703-1.c new file mode 100644 index 000000000..fa5992372 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030703-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +extern int blah[]; + +foo(int index) +{ + if (blah [(unsigned int)index] != 0) + abort (); + if (blah [(unsigned int)index] != 0) + abort (); +} + +/* There should be precisely one load of blah. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "blah" 1 "dom2"} } */ + +/* There should be exactly one IF conditional. */ +/* { dg-final { scan-tree-dump-times "if " 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030703-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030703-2.c new file mode 100644 index 000000000..4a64b90db --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030703-2.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +union tree_node; +typedef union tree_node *tree; +extern const char tree_code_type[]; + +union tree_node +{ + int code; + long pointer_alias_set; +}; + +long +get_alias_set (t) + tree t; +{ + if (tree_code_type[t->code]) + abort (); + if (t->pointer_alias_set) + { + tree __t = t; + if (tree_code_type[__t->code]) + abort (); + } +} + +/* There should be precisely one load of {t,__t}->code. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "->code" 1 "dom2"} } */ + +/* There should be precisely one load of tree_code_type. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "tree_code_type" 1 "dom2"} } */ + +/* There should be one IF conditional. If 'tree_code_type[t->code]' is + zero, then the third if() conditional is unnecessary. That should cause + the call to abort() to be removed, which in turn causes the whole second + if() to disappear. */ +/* { dg-final { scan-tree-dump-times "if " 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030708-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030708-1.c new file mode 100644 index 000000000..b3be8a939 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030708-1.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ +extern void abort (void); +struct rtx_def; +typedef struct rtx_def *rtx; +enum rtx_code +{ + CALL_INSN, + EXPR_LIST, + NOTE, + LAST = 256 +}; + +struct rtx_def +{ + + enum rtx_code code:16; +}; + +int +nonlocal_mentioned_p (x) + rtx x; +{ + if (x->code == CALL_INSN) + { + rtx const _rtx = ((x)); + if (_rtx->code != CALL_INSN + && _rtx->code != NOTE + && _rtx->code != EXPR_LIST) + abort (); + } + + blah (&x); +} + +/* There should be no casts to a short unsigned int since the entire + set of conditionals should optimize away. */ +/* { dg-final { scan-tree-dump-times "\\(short unsigned int\\)" 0 "dom2"} } */ + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030709-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030709-1.c new file mode 100644 index 000000000..686ca76a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030709-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +static int copying_arguments; + +int +foo () +{ + unsigned int regno; + if (regno < 53 && copying_arguments) + if (regno >= 53) + return 1; +} + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c new file mode 100644 index 000000000..f99598d73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030709-2.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce2" } */ + +struct rtx_def; +typedef struct rtx_def *rtx; +union tree_node; +typedef union tree_node *tree; +typedef struct mem_attrs +{ + int foo; + +} mem_attrs; +union rtunion_def +{ + mem_attrs *rtmem; +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + rtunion fld[1]; +}; +struct tree_decl +{ + rtx rtl; +}; +union tree_node +{ + struct tree_decl decl; +}; +void * +get_alias_set (t) + tree t; +{ + long set; + if (t->decl.rtl) + return (t->decl.rtl->fld[1].rtmem + ? 0 + : (((t->decl.rtl ? t->decl.rtl: (make_decl_rtl (t, 0), t->decl.rtl)))->fld[1]).rtmem); + return (void*)-1; +} + +/* There should be precisely one load of ->decl.rtl. If there is + more than, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "->decl\\.rtl" 1 "cddce2"} } */ + +/* There should be no loads of .rtmem since the complex return statement + is just "return 0". */ +/* { dg-final { scan-tree-dump-times ".rtmem" 0 "cddce2"} } */ + +/* There should be one IF statement (the complex return statement should + collapse down to a simple return 0 without any conditionals). */ +/* { dg-final { scan-tree-dump-times "if " 1 "cddce2"} } */ + +/* { dg-final { cleanup-tree-dump "cddce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030709-3.c b/gcc/testsuite/gcc.dg/tree-ssa/20030709-3.c new file mode 100644 index 000000000..4f9847852 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030709-3.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +union tree_node; +typedef union tree_node *tree; +enum tree_code +{ + TREE_VEC = 20, +}; +struct tree_common +{ + int code; +}; +struct tree_type +{ + tree binfo; +}; +union tree_node +{ + struct tree_common common; + struct tree_type type; +}; +void +record_component_aliases (type) + tree type; +{ + const tree __z = type->type.binfo; + if (type->type.binfo->common.code != TREE_VEC) + abort (); + + if (__z->common.code != TREE_VEC) + abort (); +} + +/* There should be precisely one load of type.binfo. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "type\\.binfo" 1 "dom2"} } */ + +/* There should be precisely one load of common.code. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "common\\.code" 1 "dom2"} } */ + +/* There should be one IF conditional. */ +/* { dg-final { scan-tree-dump-times "if " 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030710-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030710-1.c new file mode 100644 index 000000000..c344d48e9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030710-1.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +union tree_node; +typedef union tree_node *tree; +struct tree_vec +{ + int length; + tree a[1]; +}; +struct tree_type +{ + tree binfo; +}; +union tree_node +{ + struct tree_type type; + struct tree_vec vec; +}; +void +record_component_aliases (type) + tree type; +{ + if (type->type.binfo->vec.length) + abort (); + for (; (( + { + const tree __z = type->type.binfo; + if (type->type.binfo->vec.length) + abort (); + type->type.binfo->vec.a[4];} + )->vec.length);) + { + if (4 >= type->type.binfo->vec.length) + abort (); + blah (); + } +} + +/* The call to blah should have been eliminated. If the call is not + eliminated, then dominator optimizations failed and it'll be + impossible to delete other unnecessary code. */ +/* { dg-final { scan-tree-dump-not "blah \\(\\)" "dom2" } } */ + +/* There should be two IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 2 "dom2"} } */ + +/* There should be a single load of type.binfo. */ +/* { dg-final { scan-tree-dump-times "type\\.binfo" 1 "dom2"} } */ + +/* There should be two loads of vec.length. */ +/* { dg-final { scan-tree-dump-times "vec.length" 2 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c new file mode 100644 index 000000000..1855580d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030711-1.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +union tree_node; +typedef union tree_node *tree; +struct tree_vec +{ + int length; + tree a[1]; +}; +struct tree_type +{ + tree binfo; +}; +union tree_node +{ + struct tree_type type; + struct tree_vec vec; +}; + +void +record_component_aliases (type) + tree type; +{ + int i; + if (4 >= type->type.binfo->vec.length) + abort (); + for (; i < (( + { + const tree __t = type->type.binfo; + if (4 >= __t->vec.length) + abort (); type->type.binfo->vec.a[4];} + )->vec.length);) + { + if (4 >= type->type.binfo->vec.length) + abort (); + blah (); + } +} + +/* The call to blah can not be eliminated. */ +/* { dg-final { scan-tree-dump-times "blah \\(\\)" 1 "dom2" } } */ + +/* There should be four IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 4 "dom2"} } */ + +/* There should be two loads of type.binfo. */ +/* { dg-final { scan-tree-dump-times "type\\.binfo" 2 "dom2"} } */ + +/* There should be four loads of vec.length. */ +/* { dg-final { scan-tree-dump-times "vec.length" 4 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030711-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030711-2.c new file mode 100644 index 000000000..44dd25355 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030711-2.c @@ -0,0 +1,69 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + + +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtvec_def; +typedef struct rtvec_def *rtvec; +union tree_node; +typedef union tree_node *tree; +typedef struct mem_attrs +{ + long alias; +} +mem_attrs; +union rtunion_def +{ + mem_attrs *rtmem; +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + int code; + rtunion fld[1]; +}; +struct tree_decl +{ + rtx rtl; +}; +union tree_node +{ + struct tree_decl decl; +}; +long +get_alias_set (t,z) + tree t; + rtx z; +{ + if (t->decl.rtl && (((t->decl.rtl ? z + : (make_decl_rtl (t, 0), t->decl.rtl)))->code)) + return (((((t->decl.rtl ? z : (make_decl_rtl (t, 0), t->decl.rtl)))-> + fld[1]).rtmem) == 0 ? 0 : ((((( + { + t;} + )->decl. + rtl ? z : (make_decl_rtl (t, 0), + t->decl.rtl)))-> + fld[1]).rtmem)->alias); +} + +/* The calls to make_decl_rtl should be eliminated +/* { dg-final { scan-tree-dump-not "make_decl_rtl \\(\\)" "dom2" } } */ + +/* There should be three IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */ + +/* There should be one loads of decl.rtl. */ +/* { dg-final { scan-tree-dump-times "decl\\.rtl" 1 "dom2"} } */ + +/* There should be one load of code. */ +/* { dg-final { scan-tree-dump-times "code" 1 "dom2"} } */ + +/* There should be one load of rtmem. */ +/* { dg-final { scan-tree-dump-times "rtmem" 1 "dom2"} } */ + +/* There should be one load of alias. */ +/* { dg-final { scan-tree-dump-times "->alias" 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030711-3.c b/gcc/testsuite/gcc.dg/tree-ssa/20030711-3.c new file mode 100644 index 000000000..ec04e1754 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030711-3.c @@ -0,0 +1,61 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + + +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtvec_def; +typedef struct rtvec_def *rtvec; +union tree_node; +typedef union tree_node *tree; +typedef struct mem_attrs +{ + long alias; +} +mem_attrs; +union rtunion_def +{ + mem_attrs *rtmem; +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + int code; + rtunion fld[1]; +}; +struct tree_decl +{ + rtx rtl; +}; +union tree_node +{ + struct tree_decl decl; +}; +long +get_alias_set (t) + tree t; +{ + if (t->decl.rtl != (void *) 0) + return (((t->decl.rtl->fld[1]).rtmem) == + 0 ? 0 + : ((((t->decl. + rtl ? 0 : (make_decl_rtl (t, ((void *) 0)), + t->decl.rtl)))->fld[1]).rtmem)->alias); +} + +/* The calls to make_decl_rtl should be eliminated. */ +/* { dg-final { scan-tree-dump-not "make_decl_rtl \\(\\)" "dom2" } } */ + +/* There should be two IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 2 "dom2"} } */ + +/* There should be one load of decl.rtl. */ +/* { dg-final { scan-tree-dump-times "decl\\.rtl" 1 "dom2"} } */ + +/* There should be two loads of rtmem. */ +/* { dg-final { scan-tree-dump-times "rtmem" 2 "dom2"} } */ + +/* There should be one load of alias. */ +/* { dg-final { scan-tree-dump-times "->alias" 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c new file mode 100644 index 000000000..0225d58a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030714-1.c @@ -0,0 +1,46 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +struct rtx_def; +typedef struct rtx_def *rtx; +enum rtx_code +{ + REG, + LAST_AND_UNUSED_RTX_CODE = 256 +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + enum rtx_code code:16; + unsigned frame_related:1; +}; + +static rtx +find_base_value (src) + rtx src; +{ + rtx temp; + rtx src_0, src_2; + rtx src_1, src_3; + + if ((src_0->code == REG) && (({src_2;})->frame_related)) + return find_base_value (src_0); + if ((src_1->code == REG) && (({ src_3;})->frame_related)) + return find_base_value (src_1); + if (src_0->code == REG) + find_base_value (src_0); + if (src_1->code == REG) + find_base_value (src_1); +} + +rtx +find_base_value_wrapper (src) + rtx src; +{ + return find_base_value (src); +} + +/* There should be no casts to short unsigned int. */ +/* { dg-final { scan-tree-dump-times "\\(short unsigned int\\)" 0 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c new file mode 100644 index 000000000..cac648687 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030714-2.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + + +union tree_node; +typedef union tree_node *tree; +extern const char tree_code_type[]; +struct tree_common +{ + int code; + tree type; +}; +struct tree_exp +{ + tree operands[1]; +}; +union tree_node +{ + struct tree_common common; + struct tree_exp exp; +}; +long +get_alias_set (t) + tree t; +{ + if (tree_code_type[t->common.code] != 't' && t->common.type == 0) + return 0; + if (tree_code_type[t->common.code] != 't') + { + while (t->exp.operands[0]) + t = t->exp.operands[0]; + } +} + +/* There should be exactly three IF conditionals if we thread jumps + properly. */ +/* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c new file mode 100644 index 000000000..f884736a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030728-1.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand-details" } */ + + +union tree_node; +typedef union tree_node *tree; + +enum tree_code +{ + ARRAY_TYPE, + LAST_AND_UNUSED_TREE_CODE +}; + +struct tree_common +{ + enum tree_code code:8; +}; + + + + + +union tree_node +{ + struct tree_common common; +}; + + + + +int +objects_must_conflict_p (t1, t2) + tree t1, t2; +{ + + if ((t1->common.code == ARRAY_TYPE) != (t2 + && t2->common.code == ARRAY_TYPE)) + return 11; + + + return foo (t2 ? get_alias_set (t2) : 0); +} + +/* There should be two assignments of variables to the value zero. */ +/* { dg-final { scan-rtl-dump-times "PART.. = 0" 2 "expand"} } */ + +/* { dg-final { cleanup-rtl-dump "expand" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030729-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030729-1.c new file mode 100644 index 000000000..59b48397c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030729-1.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +union tree_node; +typedef union tree_node *tree; + + +enum tree_code +{ + SET_TYPE, + RECORD_TYPE, + LAST_AND_UNUSED_TREE_CODE +}; +extern const char tree_code_type[]; + +struct tree_common +{ + + enum tree_code code:8; +}; + + + + + +union tree_node +{ + struct tree_common common; +}; + +readonly_fields_p (type) + tree type; +{ + + if (type->common.code != RECORD_TYPE) + return; + + if (tree_code_type[type->common.code] != 't') + abort (); + + return; +} + +/* A good optimizer would realize that the cast to (unsigned int) is + useless as the earlier cast of the same value of (unsigned char) will + always produce the same result. */ +/* { dg-final { scan-tree-dump-times "\\(unsigned int\\)" 0 "dom2"} } */ + +/* There should be one load of ->common.code. We currently fail this + because we load from ->common.code using different types. */ +/* { dg-final { scan-tree-dump-times "common\.code" 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030730-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030730-1.c new file mode 100644 index 000000000..bb474ff4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030730-1.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + +extern void exit (int); +extern void *ggc_alloc (__SIZE_TYPE__); +typedef struct dw_attr_struct *dw_attr_ref; +typedef struct dw_attr_struct +{ + int dw_attr; +} +dw_attr_node; +void +foo (int attr_kind, unsigned long offset) +{ + dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node)); + attr->dw_attr = attr_kind; + if (attr != 0) + exit (0); +} + +/* There should be no IF conditionals, unless target has fno-delete-null-pointer-checks */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump "if " "dom2" { target { keeps_null_pointer_checks } } } } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030730-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030730-2.c new file mode 100644 index 000000000..1768d4523 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030730-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + +extern void exit (int); +extern void *ggc_alloc (__SIZE_TYPE__); +typedef struct dw_attr_struct *dw_attr_ref; +typedef struct dw_attr_struct +{ + int dw_attr; +} +dw_attr_node; +void +foo (int attr_kind, unsigned long offset) +{ + dw_attr_ref attr = (dw_attr_ref) ggc_alloc (sizeof (dw_attr_node)); + attr->dw_attr = attr_kind; + if (attr != ((void *)0)) + exit (0); +} + +/* There should be no IF conditionals, unless target has fno-delete-null-pointer-checks */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump "if " "dom2" { target { keeps_null_pointer_checks } } } } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030731-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030731-1.c new file mode 100644 index 000000000..a16f49dbb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030731-1.c @@ -0,0 +1,67 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtvec_def; +typedef struct rtvec_def *rtvec; +union tree_node; +typedef union tree_node *tree; +struct rtx_def +{ + int code; + int mode; + unsigned int in_struct:1; +}; +struct tree_common +{ + int code; +}; +struct tree_decl +{ + rtx rtl; +}; +union tree_node +{ + struct tree_common common; + struct tree_decl decl; +}; +rtx +store_expr (exp, target, want_value) + tree exp; + rtx target; + int want_value; +{ + if (exp->common.code == 42) + abort (); + else if (queued_subexp_p (target)) + { + blah (target->mode); + if (target->code) + abort (); + } + else + { + if (target->code && (__extension__({target;})->in_struct)); + } + + if ((target != (exp->decl.rtl + ? (exp->decl.rtl + ? exp->decl.rtl + : (make_decl_rtl (exp, 0), exp->decl.rtl)) + : 0)) + && expr_size (exp)) + ; +} + +/* All paths to the test "target != 0" occuring in the final IF statement + dereference target. Thus target can not have the value zero at that + point and the test should have been eliminated. */ +/* ??? The dominator walker (A) doesn't merge this data at joins and + (B) only looks at immediate dominators, and only queued_subexp_p + immediately dominates the comparison in question. We need something + stronger. */ +/* { dg-final { scan-tree-dump-times "target.*!= 0" 0 "dom2" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030731-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030731-2.c new file mode 100644 index 000000000..8300320c8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030731-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dce1" } */ + +void +bar (int i, int partial, int args_addr) +{ + int offset = 0; + if (args_addr == 0) + offset = 0; + if (i >= offset) + foo (); +} + +/* There should be only one IF conditional since the first does nothing + useful. */ +/* { dg-final { scan-tree-dump-times "if " 1 "dce1"} } */ +/* { dg-final { cleanup-tree-dump "dce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-1.c new file mode 100644 index 000000000..84344e36c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-1.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +struct rtx_def; +typedef struct rtx_def *rtx; + + + +union rtunion_def +{ + int rtint; +}; +typedef union rtunion_def rtunion; + + + +struct rtx_def +{ + rtunion fld[1]; + +}; + +static int *uid_cuid; +static int max_uid_cuid; + +rtx +bar (rtx r) +{ + rtx place = r; + + if (place->fld[0].rtint <= max_uid_cuid + && (place->fld[0].rtint > max_uid_cuid ? insn_cuid (place) : + uid_cuid[place->fld[0].rtint])) + return r; + + return 0; +} + +/* There should be two IF conditionals. One tests <= max_uid_cuid, the + other tets the value in uid_cuid. If either is false the jumps + are threaded to the return 0. Which in turn means the path + which combines the result of those two tests into a new test + must always be true and it is optimized appropriately. */ +/* { dg-final { scan-tree-dump-times "if " 2 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c new file mode 100644 index 000000000..fe5e859ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-10.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + + +extern const unsigned char mode_size[]; +unsigned int +subreg_highpart_offset (outermode, innermode) + int outermode, innermode; +{ + unsigned int offset = 0; + int difference = (mode_size[innermode] - mode_size[outermode]); + if (difference > 0) + { + offset += difference % (0 ? 8 : 4); + offset += difference / 4 * 4; + } + return offset; +} + +/* There should be one mask with the value 3. */ +/* { dg-final { scan-tree-dump-times " \& 3" 1 "vrp1"} } */ + +/* There should be one right shift by 2 places. */ +/* { dg-final { scan-tree-dump-times " >> 2" 1 "vrp1"} } */ + +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-11.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-11.c new file mode 100644 index 000000000..0711053bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-11.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtx_def +{ + int code; +}; +foo (reg) + rtx reg; +{ + reg->code = 42; + if (reg->code != 42) + abort (); +} + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c new file mode 100644 index 000000000..a12d71840 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-2.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-vrp -fdump-tree-dom2" } */ + +extern void abort (void); + +oof () +{ + int live_head; + int * live = &live_head; + + if (live) + bitmap_clear (live); +} + +foo(int n) +{ + int *space = (int *)__builtin_alloca (n); + + if (space == 0) + abort (); + else + bar (space); +} + + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2" } } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-3.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-3.c new file mode 100644 index 000000000..9a3c23163 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +typedef unsigned int cppchar_t; +cppchar_t +cpp_parse_escape (pstr, limit, wide) + const unsigned char **pstr; + const unsigned char *limit; + int wide; +{ + cppchar_t i = 0; + int overflow = 0; + cppchar_t mask = ~0; + + while (*pstr < limit) + { + overflow |= i ^ (i << 4 >> 4); + i = oof (); + } + if (overflow | (i != (i & mask))) + foo(); +} + +/* There should be precisely three IF statements. If there is + more than two, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "if " 3 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c new file mode 100644 index 000000000..424b5583b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-5.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +struct rtx_def; +typedef struct rtx_def *rtx; + + +struct rtx_def +{ + + int code; + unsigned int unchanging:1; + +}; +static rtx current_sym_addr; + +int +foo () +{ + if (current_sym_addr->code == 42 + && (({ + rtx _rtx = current_sym_addr; + if (((_rtx)->code) != 42) + abort (); + _rtx;} + )->unchanging)) + return 0; +} + +/* There should be precisely one load of ->code. If there is + more than, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "->code" 1 "dom2"} } */ + +/* There should be two IF statements. One for 'current_sym_addr->code == 42'. + The other one for '(EXPR)->unchanging'. */ +/* { dg-final { scan-tree-dump-times "if " 2 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-6.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-6.c new file mode 100644 index 000000000..8a6506b3d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-6.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + + +void +foo (distance, i, j) + int distance[13][13]; + int i, j; +{ + if (distance[i][j] < 0) + distance[i][0] = ((distance[i][j]) < 0 ? -(distance[i][j]) : (distance[i][j])); +} + +void +foo2 (distance, i, j) + int distance[13][13]; + int i, j; +{ + if (distance[i][j] <= 0) + distance[i][0] = ((distance[i][j]) < 0 ? -(distance[i][j]) : (distance[i][j])); +} + +void +foo3 (distance, i, j) + int distance[13][13]; + int i, j; +{ + if (distance[i][j] > 0) + distance[i][0] = ((distance[i][j]) < 0 ? -(distance[i][j]) : (distance[i][j])); +} + +void +foo4 (distance, i, j) + double distance[13][13]; + int i, j; +{ + if (distance[i][j] >= 0) + distance[i][0] = ((distance[i][j]) < 0 ? -(distance[i][j]) : (distance[i][j])); +} + +/* There should be no ABS_EXPR. */ +/* { dg-final { scan-tree-dump-times "ABS_EXPR " 0 "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c new file mode 100644 index 000000000..ed6f7c0d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-7.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void abort (void); + +union tree_node; +typedef union tree_node *tree; +struct tree_common +{ + int code; +}; +struct tree_list +{ + tree purpose; +}; +union tree_node +{ + struct tree_common common; + struct tree_list list; +}; +void +simplify_condition (cond_p) + tree *cond_p; +{ + tree decl; + tree cond = *cond_p; + if (cond->common.code != 42) + abort (); + decl = cond->list.purpose; + if (cond->common.code != 42) + abort (); + c_simplify_stmt (&decl); +} + +/* There should be exactly one IF conditional. */ +/* { dg-final { scan-tree-dump-times "if " 1 "vrp1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-8.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-8.c new file mode 100644 index 000000000..77fd3e59a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-8.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +struct die_struct; +typedef struct die_struct *dw_die_ref; +typedef struct dw_loc_list_struct *dw_loc_list_ref; +enum dw_val_class +{ + dw_val_class_loc_list, +}; +typedef struct dw_val_struct +{ + enum dw_val_class val_class; + union dw_val_struct_union + { + dw_loc_list_ref val_loc_list; + } + v; +} +dw_val_node; +typedef struct dw_attr_struct *dw_attr_ref; +typedef struct dw_attr_struct +{ + dw_val_node dw_attr_val; +} +dw_attr_node; + +extern __inline__ enum dw_val_class +AT_class (a) + dw_attr_ref a; +{ + return a->dw_attr_val.val_class; +} + +extern __inline__ dw_loc_list_ref +AT_loc_list (a) + dw_attr_ref a; +{ + if (AT_class (a) == dw_val_class_loc_list) + return a->dw_attr_val.v.val_loc_list; +} + +void +output_location_lists (die) + dw_die_ref die; +{ + dw_die_ref c; + dw_attr_ref d_attr; + if (AT_class (d_attr) == dw_val_class_loc_list) + output_loc_list (AT_loc_list (d_attr)); +} + +/* There should be exactly one IF conditional, in output_location_lists. */ +/* { dg-final { scan-tree-dump-times "if " 1 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030807-9.c b/gcc/testsuite/gcc.dg/tree-ssa/20030807-9.c new file mode 100644 index 000000000..4f0b7cbaf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030807-9.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +static void +bar () +{ + const char *label2 = (*"*.L_sfnames_b" == '*') + "*.L_sfnames_b"; + oof (label2); +} + +void +ooof () +{ + if (""[0] == 0) + foo(); +} + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030808-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030808-1.c new file mode 100644 index 000000000..27e2c7105 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030808-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-cddce2" } */ + +extern void abort (void); + +struct rtx_def; +typedef struct rtx_def *rtx; +enum rtx_code +{ + UNKNOWN, + CODE_LABEL, + NOTE, + LAST_AND_UNUSED_RTX_CODE = 256 +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + enum rtx_code code:16; +}; +void +delete_dead_jumptables () +{ + rtx insn, next; + if (insn->code == CODE_LABEL) + { + rtx const _rtx = insn; + if (_rtx->code != CODE_LABEL && _rtx->code != NOTE) + abort (); + } + ; +} + +/* There should be no loads of ->code. If any exist, then we failed to + optimize away all the IF statements and the statements feeding + their conditions. */ +/* { dg-final { scan-tree-dump-times "->code" 0 "cddce2"} } */ + +/* There should be no IF statements. */ +/* { dg-final { scan-tree-dump-times "if " 0 "cddce2"} } */ + +/* { dg-final { cleanup-tree-dump "cddce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-1.c new file mode 100644 index 000000000..aad53c339 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +com(int *blah) +{ + int z = *blah; + if (z == 256) + { + oof (z); + abort (); + } + return *blah; +} + +/* There should be precisely one load of blah. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "\\*blah" 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-2.c new file mode 100644 index 000000000..7f60b2783 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +void +foo (int value) +{ + switch (value) + { + case 42: + if (value != 42) + abort (); + case 50: + blah (); + } +} + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-3.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-3.c new file mode 100644 index 000000000..2746415e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-3.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +void +foo (int value) +{ + switch (value) + { + case 40: + case 42: + if (value != 42) + abort (); + case 50: + blah (); + } +} + +/* There should be one IF conditional. */ +/* { dg-final { scan-tree-dump-times "if " 1 "dom2"} } */ + +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-4.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-4.c new file mode 100644 index 000000000..2c2142cbc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-4.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2 -fdump-tree-optimized" } */ + +extern void abort (void); +union tree_node; +typedef union tree_node *tree; +extern const char tree_code_type[]; +struct tree_common +{ + int code; +}; +struct tree_decl +{ + long pointer_alias_set; +}; +union tree_node +{ + struct tree_common common; + struct tree_decl decl; +}; +long +blah (decl, set) + tree decl; + long set; +{ + decl->decl.pointer_alias_set = set; + if (tree_code_type[decl->common.code] != 'd') + abort (); + record_alias_subset (decl->decl.pointer_alias_set); + if (set != -1) + set = 0; + return set; +} + +/* There should be precisely one reference to pointer_alias_set. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "pointer_alias_set" 1 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ + +/* The assignment set = -1 in the ELSE clause of the last IF + statement should be removed by the final cleanup phase. */ +/* { dg-final { scan-tree-dump-times "set = -1" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-5.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-5.c new file mode 100644 index 000000000..41aa1482d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-5.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2 -fdump-tree-optimized" } */ + +extern void abort (void); +union tree_node; +typedef union tree_node *tree; +extern const char tree_code_type[]; +struct tree_common +{ + int code; +}; +struct tree_decl +{ + long pointer_alias_set; +}; +union tree_node +{ + struct tree_common common; + struct tree_decl decl; +}; +long +blah (decl, set) + tree decl; + long set; +{ + decl->decl.pointer_alias_set = oof(); + if (tree_code_type[decl->common.code] != 'd') + abort (); + record_alias_subset (decl->decl.pointer_alias_set); + if (set != -1) + set = 0; + return set; +} + +/* There should be precisely one reference to pointer_alias_set. If there is + more than one, then the dominator optimizations failed. */ +/* { dg-final { scan-tree-dump-times "pointer_alias_set" 1 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ + +/* The assignment set = -1 in the ELSE clause of the last IF + statement should be removed by the final cleanup phase. */ +/* { dg-final { scan-tree-dump-times "set = -1" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-6.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-6.c new file mode 100644 index 000000000..170526547 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-6.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +union tree_node; +typedef union tree_node *tree; +enum tree_code +{ + LAST_AND_UNUSED_TREE_CODE +}; +extern const char tree_code_type[]; +struct tree_common +{ + enum tree_code code:8; +}; +struct tree_type +{ + double alias_set; +}; +union tree_node +{ + struct tree_common common; + struct tree_type type; +}; +long +foo (t, set) + tree t; + double set; +{ + if (tree_code_type[t->common.code] != 't') + abort (); + + t->type.alias_set = set; + + if (t->common.code == 42) + return 1; + else + return 0; +} +/* There should be precisely one load of common.code. If there is + more than one, then the dominator optimizations failed. */ +/* ??? Will fail until we properly distinguish member stores. At + present the write to type.alias_set kills the previous load. */ +/* { dg-final { scan-tree-dump-times "common.code" 1 "dom2" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030814-7.c b/gcc/testsuite/gcc.dg/tree-ssa/20030814-7.c new file mode 100644 index 000000000..711bab251 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030814-7.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtvec_def; +typedef struct rtvec_def *rtvec; +union tree_node; +typedef union tree_node *tree; +struct tree_common +{ + int code; +}; +union tree_node +{ + struct tree_common common; +}; +extern tree current_function_decl; +struct cgraph_rtl_info +{ + _Bool pure_function; +}; +struct cgraph_rtl_info *cgraph_rtl_info (tree); +void +mark_constant_function (void) +{ + rtx insn; + int nonlocal_memory_referenced; + + if (current_function_decl->common.code != 42) + abort (); + + cgraph_rtl_info (current_function_decl)->pure_function = 1; +} + +/* current_function_decl should be loaded once into a temporary + and the temporary used as the argument to cgraph_rtl_info. + This if we find current_function_decl used as an argument, then + we have failed. */ +/* { dg-final { scan-tree-dump-times "\\(current_function_decl\\)" 0 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030820-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030820-1.c new file mode 100644 index 000000000..4b659ca34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030820-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* A test for unreachable blocks removal -- bind_expr whose entry is + unreachable, but it contains reachable statements. */ + +void foo(void) +{ + if (1) + { + goto bla; + } + else + { +xxx: + { +bla: + bar (); + return; + } + goto xxx; + } +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030820-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030820-2.c new file mode 100644 index 000000000..9ca9fbb59 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030820-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* A test for variables getting out of their scope in copy propagation. */ + +void foo(void) +{ + int k; + + goto forward; +back: + bla (k); + return; + +forward: + { + int i = bar (); + + k = i; + + goto back; + } +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030821-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030821-1.c new file mode 100644 index 000000000..5de503ed6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030821-1.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom1 -fdump-tree-optimized" } */ + +void foo(int k) +{ + int i = 1; + void *label; + + label = k ? &&x : &&y; + + if (k == 1) + goto *label; + + i = 0; + goto z; +z: +x: + if (i) + dont_remove (); +y: ; +} + +/* { dg-final { scan-tree-dump-times "dont_remove \\(\\)" 1 "optimized"} } */ + +/* We should have folded away the goto &x */ +/* { dg-final { scan-tree-dump-times "goto &x" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c new file mode 100644 index 000000000..e5988bd79 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030824-1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct A +{ + int a,b; +}; + +int foo (int x, int y) +{ + int i, j; + struct A a,b; + + a.a = x; + b.b = y; + j = a.a; + i = b.b; + return i + j; +} + +/* The addition should be optimized into 'y+x'. */ +/* { dg-final { scan-tree-dump-times "\[xy\]_..D. \\+ \[xy]_..D." 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c new file mode 100644 index 000000000..1234aeb34 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030824-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct A +{ + int a,b; +}; + +int foo (int x, int y) +{ + int i, j; + struct A a; + + a.a = x; + a.b = y; + j = a.a; + i = a.b; + return i + j; +} + +/* This function should be optimized into 'return y+x'. */ +/* { dg-final { scan-tree-dump-times "\[xy\]_..D. \\+ \[xy]_..D." 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030825-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030825-1.c new file mode 100644 index 000000000..de34acaec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030825-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +void bla(void); + +void +foo(int c, int d) +{ + goto skip; + +ebef: + goto xxx; + +skip: + + if (c) + { +xxx:; + if (!c) + bla (); + } + + if (d) + goto ebef; +} + +/* Bla should not be optimized away. */ +/* { dg-final { scan-tree-dump-times "bla" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030907-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030907-1.c new file mode 100644 index 000000000..a36472d39 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030907-1.c @@ -0,0 +1,30 @@ +/* PR optimization/12198 + + This was a miscompilation of a switch expressions because + the "Case Ranges" extension wasn't handled in tree-cfg.c. */ + +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +extern void abort (void); +extern void exit (int); + +int main() +{ + int i; + i = 2; + switch (i) + { + case 1 ... 5: + goto L1; + default: + abort (); + goto L1; + } + L1: + exit(0); +} + +/* The abort() call clearly is unreachable. */ +/* { dg-final { scan-tree-dump-times "abort" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030907-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030907-2.c new file mode 100644 index 000000000..47d60946e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030907-2.c @@ -0,0 +1,30 @@ +/* PR optimization/12109 + + This would ICE in tree-ssa-dce.c:process_worklist() when + the function was expecting an SSA_NAME but found a VAR_DECL. */ + +/* { dg-do compile } */ +/* { dg-options "-O -ftree-dce" } */ + +void *do_it(void * dest, const void * src); +double *create_float(void); + +void parse_rvalue(void **DataPtr) +{ + double local = 0.0; + int terms = 1; + + *DataPtr = create_float(); + + switch (terms) + { + case 1: + *((double *)*DataPtr) = local; + break; + + case 2: + do_it(*DataPtr, &local); + break; + } +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030917-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030917-1.c new file mode 100644 index 000000000..eb1f5ec7d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030917-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + +extern int board[]; + +void +findbestextension (int blah, int blah2) +{ + int defval; + defval = def_val (board[blah2]); + if (blah) + defval = 0; + foo (defval); +} + +/* The argument to "foo" should be a variable, not a constant. */ +/* { dg-final { scan-tree-dump-times "foo .defval" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030917-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030917-2.c new file mode 100644 index 000000000..2c08050c9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030917-2.c @@ -0,0 +1,40 @@ +/* This test was causing an ICE in DCE because we were allowing void * + pointers to have a memory tag, which we were copying when doing copy + propagation. Since void * can never be de-referenced, its memory tag + was never renamed. */ + +/* { dg-do compile } */ +/* { dg-options "-O -ftree-dominator-opts" } */ + +typedef __SIZE_TYPE__ size_t; +typedef union tree_node *tree; +struct operands_d +{ + tree *def_op; +}; + +void +gt_ggc_mx_operands_d (void *x_p) +{ + struct operands_d *const x = (struct operands_d *) x_p; + if ((*x).def_op != ((void *) 0)) + { + size_t i0; + do + { + const void *const a__ = ((*x).def_op); + if (a__ != ((void *) 0) && a__ != (void *) 1) + ggc_set_mark (a__); + } + while (0); + for (i0 = 0; i0 < (size_t) (1); i0++) + { + do + { + if ((void *) (*x).def_op[i0] != ((void *) 0)) + gt_ggc_mx_lang_tree_node ((*x).def_op[i0]); + } + while (0); + } + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030917-3.c b/gcc/testsuite/gcc.dg/tree-ssa/20030917-3.c new file mode 100644 index 000000000..e74bd08da --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030917-3.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +extern int printf (const char *, ...); + +main () +{ + int variable = 0; + int p = 1; + while (1) + { + if (p) + break; + variable = variable + 1; + if (variable == 10) + break; + } + printf("%d\n", variable); +} + + +/* The argument to "printf" should be a constant, not a variable. */ +/* { dg-final { scan-tree-dump-times "printf.*, 0" 1 "ccp1"} } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030918-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030918-1.c new file mode 100644 index 000000000..719ea65f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030918-1.c @@ -0,0 +1,15 @@ +/* The compiler was failing to adjust pointer dereferences into array + references after propagating &equot[0] into p. */ + +/* { dg-do compile } */ +/* { dg-options "-O -ftree-dominator-opts" } */ + +static unsigned short equot[(6 +3)]; +int +foo (num) + unsigned short num[]; +{ + unsigned short *p = &equot[0]; + *p++ = num[0]; + *p++ = num[1]; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030920-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030920-1.c new file mode 100644 index 000000000..e27764aec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030920-1.c @@ -0,0 +1,112 @@ +/* Jump threading was creating FALLTHRU edges out of blocks ending in + GOTO_EXPR. */ + +extern int frame_pointer_needed; + +struct value_data_entry +{ + unsigned int mode; + unsigned int oldest_regno; + unsigned int next_regno; +}; + +struct value_data +{ + struct value_data_entry e[53]; + unsigned int max_value_regs; +}; + +struct rtx_def +{ + unsigned int code: 16; + unsigned int mode : 8; + unsigned int jump : 1; + unsigned int call : 1; + unsigned int unchanging : 1; + unsigned int volatil : 1; + unsigned int in_struct : 1; + unsigned int used : 1; + unsigned integrated : 1; + unsigned frame_related : 1; + int fld[1]; +}; + +typedef struct rtx_def *rtx; + +enum machine_mode { VOIDmode, BImode, QImode, HImode, SImode, DImode, + TImode, OImode, PQImode, PHImode, PSImode, PDImode, QFmode, HFmode, + TQFmode, SFmode, DFmode, XFmode, TFmode, QCmode, HCmode, SCmode, + DCmode, XCmode, TCmode, CQImode, CHImode, CSImode, CDImode, CTImode, + COImode, V1DImode, V2QImode, V2HImode, V2SImode, V2DImode, V4QImode, + V4HImode, V4SImode, V4DImode, V8QImode, V8HImode, V8SImode, V8DImode, + V16QImode, V2HFmode, V2SFmode, V2DFmode, V4HFmode, V4SFmode, V4DFmode, + V8HFmode, V8SFmode, V8DFmode, V16SFmode, BLKmode, CCmode, CCGCmode, + CCGOCmode, CCNOmode, CCZmode, CCFPmode, CCFPUmode, MAX_MACHINE_MODE }; + +enum mode_class { MODE_RANDOM, MODE_INT, MODE_FLOAT, MODE_PARTIAL_INT, MODE_CC, + MODE_COMPLEX_INT, MODE_COMPLEX_FLOAT, + MODE_VECTOR_INT, MODE_VECTOR_FLOAT, + MAX_MODE_CLASS}; + +extern const unsigned char mode_size[(int) MAX_MACHINE_MODE]; +extern const enum mode_class mode_class[(int) MAX_MACHINE_MODE]; + +extern int target_flags; + +static void +copy_value (rtx dest, rtx src, struct value_data *vd) +{ + unsigned int dr = (((dest)->fld[0])); + unsigned int sr = (((src)->fld[0])); + unsigned int dn, sn; + unsigned int i; + + + + if (sr == dr) + return; + + + + if (dr == 7) + return; + + + if (frame_pointer_needed && dr == 6) + return; + + + dn = (((dr) >= 8 && (dr) <= (8 + 7)) || (((dr) >= (20 + 1) && (dr) <= ((20 + 1) + 7)) || ((dr) >= (((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) && (dr) <= ((((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) + 7))) || ((dr) >= (((20 + 1) + 7) + 1) && (dr) <= ((((20 + 1) + 7) + 1) + 7)) ? (((mode_class[(int) (((enum machine_mode) (dest)->mode))]) == MODE_COMPLEX_INT || (mode_class[(int) (((enum machine_mode) (dest)->mode))]) == MODE_COMPLEX_FLOAT) ? 2 : 1) : ((((enum machine_mode) (dest)->mode)) == TFmode ? ((target_flags & 0x00100000) ? 2 : 3) : (((enum machine_mode) (dest)->mode)) == TCmode ? ((target_flags & 0x00100000) ? 4 : 6) : (((mode_size[(int) (((enum machine_mode) (dest)->mode))]) + ((target_flags & 0x00100000) ? 8 : 4) - 1) / ((target_flags & 0x00100000) ? 8 : 4)))); + sn = (((sr) >= 8 && (sr) <= (8 + 7)) || (((sr) >= (20 + 1) && (sr) <= ((20 + 1) + 7)) || ((sr) >= (((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) && (sr) <= ((((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) + 7))) || ((sr) >= (((20 + 1) + 7) + 1) && (sr) <= ((((20 + 1) + 7) + 1) + 7)) ? (((mode_class[(int) (((enum machine_mode) (dest)->mode))]) == MODE_COMPLEX_INT || (mode_class[(int) (((enum machine_mode) (dest)->mode))]) == MODE_COMPLEX_FLOAT) ? 2 : 1) : ((((enum machine_mode) (dest)->mode)) == TFmode ? ((target_flags & 0x00100000) ? 2 : 3) : (((enum machine_mode) (dest)->mode)) == TCmode ? ((target_flags & 0x00100000) ? 4 : 6) : (((mode_size[(int) (((enum machine_mode) (dest)->mode))]) + ((target_flags & 0x00100000) ? 8 : 4) - 1) / ((target_flags & 0x00100000) ? 8 : 4)))); + if ((dr > sr && dr < sr + sn) + || (sr > dr && sr < dr + dn)) + return; + + + + + if (vd->e[sr].mode == VOIDmode) + set_value_regno (sr, vd->e[dr].mode, vd); + else if (sn < (unsigned int) (((sr) >= 8 && (sr) <= (8 + 7)) || (((sr) >= (20 + 1) && (sr) <= ((20 + 1) + 7)) || ((sr) >= (((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) && (sr) <= ((((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) + 7))) || ((sr) >= (((20 + 1) + 7) + 1) && (sr) <= ((((20 + 1) + 7) + 1) + 7)) ? (((mode_class[(int) (vd->e[sr].mode)]) == MODE_COMPLEX_INT || (mode_class[(int) (vd->e[sr].mode)]) == MODE_COMPLEX_FLOAT) ? 2 : 1) : ((vd->e[sr].mode) == TFmode ? ((target_flags & 0x00100000) ? 2 : 3) : (vd->e[sr].mode) == TCmode ? ((target_flags & 0x00100000) ? 4 : 6) : (((mode_size[(int) (vd->e[sr].mode)]) + ((target_flags & 0x00100000) ? 8 : 4) - 1) / ((target_flags & 0x00100000) ? 8 : 4)))) + && ((mode_size[(int) (vd->e[sr].mode)]) > ((target_flags & 0x00100000) ? 8 : 4) + ? 0 : 0)) + return; + + + + + else if (sn > (unsigned int) (((sr) >= 8 && (sr) <= (8 + 7)) || (((sr) >= (20 + 1) && (sr) <= ((20 + 1) + 7)) || ((sr) >= (((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) && (sr) <= ((((((((20 + 1) + 7) + 1) + 7) + 1) + 7) + 1) + 7))) || ((sr) >= (((20 + 1) + 7) + 1) && (sr) <= ((((20 + 1) + 7) + 1) + 7)) ? (((mode_class[(int) (vd->e[sr].mode)]) == MODE_COMPLEX_INT || (mode_class[(int) (vd->e[sr].mode)]) == MODE_COMPLEX_FLOAT) ? 2 : 1) : ((vd->e[sr].mode) == TFmode ? ((target_flags & 0x00100000) ? 2 : 3) : (vd->e[sr].mode) == TCmode ? ((target_flags & 0x00100000) ? 4 : 6) : (((mode_size[(int) (vd->e[sr].mode)]) + ((target_flags & 0x00100000) ? 8 : 4) - 1) / ((target_flags & 0x00100000) ? 8 : 4))))) + return; + + + + vd->e[dr].oldest_regno = vd->e[sr].oldest_regno; + + for (i = sr; vd->e[i].next_regno != (~(unsigned int) 0); i = vd->e[i].next_regno) + continue; + vd->e[i].next_regno = dr; + + + validate_value_data (vd); + +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030922-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20030922-1.c new file mode 100644 index 000000000..96db1bd1d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030922-1.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ + +extern void abort (void); + +union tree_node; +typedef union tree_node *tree; +enum tree_code +{ + BIND_EXPR, +}; +struct tree_common +{ + enum tree_code code:8; +}; +union tree_node +{ + struct tree_common common; +}; +tree +voidify_wrapper_expr (tree wrapper) +{ + switch (wrapper->common.code) + { + case BIND_EXPR: + if (wrapper->common.code != BIND_EXPR) + abort (); + } +} + + +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20030922-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20030922-2.c new file mode 100644 index 000000000..9a787bd21 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20030922-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom1" } */ + +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtx_def +{ + int bb; +}; +int *block_to_bb; +int target_bb; + +int +rgn_rank (rtx insn1, rtx insn2) +{ + if (block_to_bb[insn1->bb] != block_to_bb[insn2->bb]) + if (block_to_bb[insn2->bb] == target_bb + && block_to_bb[insn1->bb] != target_bb) + return 1; +} + +/* There should be two IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 2 "dom1" } } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031015-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031015-1.c new file mode 100644 index 000000000..102715c01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031015-1.c @@ -0,0 +1,18 @@ +/* With tree-ssa, gcc.dg/20000724-1.c failed because we missed + a VOP of x in the asm statement. */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-alias-vops" } */ + +struct s { int a; }; + +int +main(void) +{ + struct s x = { 0 }; + asm volatile ("" : : "r" (&x) : "memory"); + return 0; +} + +/* The VDEF comes from the initial assignment and the asm. */ +/* { dg-final { scan-tree-dump-times "DEF" 2 "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031021-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031021-1.c new file mode 100644 index 000000000..117cddf12 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031021-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct A +{ + int i : 8; +}; + +signed char c1, c2; +struct A a; + +int main() +{ + a.i = c1; + c2 = a.i; + return a.i; +} + +/* We should only store to a.i, not load from it. */ +/* { dg-final { scan-tree-dump-times "a.i" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031022-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031022-1.c new file mode 100644 index 000000000..27de6e90e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031022-1.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom1" } */ + +typedef struct edge_def +{ + int z; +} *edge; +typedef struct basic_block_def +{ + edge pred; +} *basic_block; +extern struct basic_block_def entry_exit_blocks[2]; +void +blah (int arf) +{ + edge e; + e = (&entry_exit_blocks[1])->pred; + for ( ; ;) + if (arf) + break; + commit_edge_insertions (); + e = (&entry_exit_blocks[1])->pred; + foo (e); +} + +/* There should be one load from entry_exit_blocks[1].pred. */ +/* { dg-final { scan-tree-dump-times "entry_exit_blocks.1..pred" 1 "dom1"} } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031031-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031031-1.c new file mode 100644 index 000000000..baca2a00a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031031-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* This program requires the SSA renamer to be run after the second DOM + pass. Test provided by Falk Hueffner as Bugzilla #12825. */ + +struct floppy_raw_cmd { + int flags, track; +} *raw_cmd, default_raw_cmd; + +void +setup_format_params (void) +{ + raw_cmd = &default_raw_cmd; + raw_cmd->track = 0; + raw_cmd->flags = 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031106-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031106-1.c new file mode 100644 index 000000000..fea5aaf08 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031106-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* Check for dead stores to an array. */ + +void foo (int testarray[]) +{ + testarray[0] = 0; + testarray[0]++; + if (testarray[0] != 1) + link_error (); +} + +/* There should be only one reference to "testarray" and one in the function header. */ +/* { dg-final { scan-tree-dump-times "testarray" 2 "optimized" } } */ + +/* There should be no link_error calls. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031106-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20031106-2.c new file mode 100644 index 000000000..73dd4ff2e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031106-2.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* Check for dead stores to a struct. */ + +struct s +{ + char d; + int a, b; + double m; +}; + +void foo (struct s* teststruct) +{ + teststruct->a = 0; + teststruct->a++; + if (teststruct->a != 1) + link_error (); +} + +/* There should be only one reference to "teststruct" and one in the function header. */ +/* { dg-final { scan-tree-dump-times "teststruct" 2 "optimized" } } */ + +/* There should be no link_error calls. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031106-3.c b/gcc/testsuite/gcc.dg/tree-ssa/20031106-3.c new file mode 100644 index 000000000..2508a2c2f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031106-3.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* Check for cprop on array elements. */ + +void foo (int testarray[]) +{ + testarray[0] = 0; + testarray[1] = 1; + testarray[0]++; + testarray[1]++; + if (testarray[0] != 1) + link_error (); + if (testarray[1] != 2) + link_error (); +} + +/* There should be no link_error calls. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031106-4.c b/gcc/testsuite/gcc.dg/tree-ssa/20031106-4.c new file mode 100644 index 000000000..d72788691 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031106-4.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* Check for cprop on fields of the same struct. */ + +struct s +{ + char d; + int a, b; + double m; +}; + + +void foo (struct s* r) +{ + r->a = 0; + r->b = 1; + r->a++; + r->b++; + if (r->a != 1) + link_error (); + if (r->b != 2) + link_error (); +} + +/* There should be no link_error calls. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031106-5.c b/gcc/testsuite/gcc.dg/tree-ssa/20031106-5.c new file mode 100644 index 000000000..b066ab6ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031106-5.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* Check for cprop on different fields of same type structs. */ + +struct s +{ + char d; + int a, b; + double m; +}; + +void foo2 (struct s* r, struct s* p) +{ + r->a = 0; + p->b = 1; + r->a++; + p->b++; + if (r->a != 1) + link_error (); + if (p->b != 2) + link_error (); +} + +/* There should be no link_error calls. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031106-6.c b/gcc/testsuite/gcc.dg/tree-ssa/20031106-6.c new file mode 100644 index 000000000..51fcd9788 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031106-6.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-tree-sra -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* Check for copyprop on structs. */ + +struct s +{ + char d; + int a, b; + double m; +}; + +struct s foo (struct s r) +{ + struct s temp_struct1; + struct s temp_struct2; + struct s temp_struct3; + temp_struct1 = r; + temp_struct2 = temp_struct1; + temp_struct3 = temp_struct2; + return temp_struct3; +} + +/* There should be no references to any of "temp_struct*" + temporaries. */ +/* { dg-final { scan-tree-dump-times "temp_struct" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031113-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031113-1.c new file mode 100644 index 000000000..865915f4f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031113-1.c @@ -0,0 +1,32 @@ +/* PR optimization/12640 + + We used to get into an infinite loop while trying to + figure out `strlen (resultString)'. This showed up as + a stack overflow while compiling tk. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +extern __SIZE_TYPE__ strlen (const char *); + +int i; + +static void +SendEventProc (char *resultString) +{ + char *p; + + resultString = ""; + while (*p == '-') + { + if (p[2] == ' ') + { + resultString = p + 3; + } + } + for (;;) + { + i = strlen (resultString) + 1; + } +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20031216-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20031216-1.c new file mode 100644 index 000000000..0e97833fe --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20031216-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +void +foo (int b) +{ + int a; + a = b + 2; + a--; + a--; + if (a != b) + link_error (); +} + +/* The comparison should be eliminated, there should be no reference + to link_error. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040121-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040121-1.c new file mode 100644 index 000000000..6225bcdc8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040121-1.c @@ -0,0 +1,28 @@ + + +/* Test that (p!=0) + (q!=0) is computed as int, + not boolean */ +/* { dg-options "-O3" } */ +/* { dg-do run } */ +extern void abort (void); +char *foo(char *p, char *q) { + int x = (p !=0) + (q != 0); + if (x==2) return "a"; else return 0; +} +extern char *bar(char*, char*) __attribute__((noinline)); +char *bar(char *first, char *last) +{ + int y; + if (!first) return last; + if (!last) return first; + if (*first == 'a') + return foo(first, last); + return 0; +} +main() { + char *p = "a", *q = "b"; + if (p) + if (bar(p,q)) + return 0; + abort(); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c new file mode 100644 index 000000000..45e44a1b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040204-1.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* + test that a condition is propagated inside an if +*/ + +void test5 (int x) +{ + extern int foo (int); + if (x == 0) + foo (x); + else if (x == 0 ) + link_error (); +} + +void test55 (int x, int y) +{ + int u; + if (x == 5 && y) + { + u = x + 22; + if (u != 27) + link_error (); + } +} + +/* There should be not link_error calls, if there is any the + optimization has failed */ +/* ??? Ug. This one may or may not fail based on how fold decides + that the && should be emitted (based on BRANCH_COST). Fix this + by teaching dom to look through && and register all components + as true. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail { ! "alpha*-*-* powerpc*-*-* cris-*-* crisv32-*-* hppa*-*-* i?86-*-* mmix-*-* mips*-*-* m68k*-*-* moxie-*-* sparc*-*-* spu-*-* x86_64-*-*" } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040209-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040209-1.c new file mode 100644 index 000000000..087715322 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040209-1.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wuninitialized" } */ + +typedef union tree_node *tree; + +struct tree_common +{ + tree chain; +}; + +struct tree_decl +{ + struct tree_common common; + tree name; +}; + + +union tree_node +{ + struct tree_common common; + struct tree_decl decl; +}; + +int pedantic; + +void +finish_struct (tree t, tree fieldlist, tree attributes) +{ + union tree_node * x; + + if (pedantic) + { + x = fieldlist; + if (x->decl.name == 0) + { + while (x) + x = x->common.chain; + foo (fieldlist); + } + } + + x = fieldlist; + if (x) + { + do + { + x = x->common.chain; + } while (x != 0); + } + + bar1 (&fieldlist); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040210-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040210-1.c new file mode 100644 index 000000000..990cb8075 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040210-1.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */ + + +void abort(void); +void exit(int); + +int x, y; + +static void __attribute__ ((noinline)) +init_xy(void) +{ + x = 3; + y = 2; +} + +void +test4(void) +{ + init_xy(); + if ((x < y ? x++ : y++) != 2) + abort (); +} + +int +main(){ + test4 (); + exit (0); +} + +/* Should have no more than two ifs left after straightening. */ +/* { dg-final { scan-tree-dump-times "if " 2 "phiopt1"} } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c new file mode 100644 index 000000000..34a592679 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040211-1.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce2" } */ + +struct rtx_def; +typedef struct rtx_def *rtx; +extern const char rtx_class[]; +union rtunion_def +{ + rtx rtx; +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + int code; + rtunion fld[1]; +}; +static int +can_move_up (rtx insn, int n_insns) +{ + while (n_insns > 0) + { + insn = (((insn)->fld[1]).rtx); + if (((rtx_class[(int) (((insn)->code))]) == 'i')) + n_insns--; + } + return n_insns <= 0; +} +int +com (rtx insn, int blah) +{ + if (!can_move_up (insn, blah)) + foo (); +} + +/* Cddce cannot remove possibly infinite loops and there is no way how to + determine whether the loop in can_move_up ends. */ +/* { dg-final { scan-tree-dump "if " "cddce2"} } */ +/* { dg-final { cleanup-tree-dump "cddce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040216-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040216-1.c new file mode 100644 index 000000000..c770340a7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040216-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dse1-details" } */ + +foo(int *z, int *y, int xx) +{ + *z = 1; + if (xx) + xx = 20; + else + xx = 30; + *z = 2; + *z = 3; + return xx; +} + +/* We should convert two COND_EXPRs into straightline code. */ +/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1"} } */ +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040302-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040302-1.c new file mode 100644 index 000000000..8b80128cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040302-1.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +/* Test for .GLOBAL_VAR not being renamed into SSA after alias analysis. + provided by Dale Johannesen in PR 14266. */ + +void foo() { bar (); } +main () { foo (); } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c new file mode 100644 index 000000000..8e9f61da6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040305-1.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce2 -fdump-tree-forwprop1-details" } */ + +int abarney[2]; +int afred[1]; + +void foo(int edx, int eax) +{ + if (eax == 100) + { + if (edx == 1) + { + abarney[0] = 5; + abarney[1] = 6; + } + } + if (eax == 100) + { + if (-- edx == 0) + afred[0] = 2; + } +} + + +/* Verify that we did a forward propagation. */ +/* { dg-final { scan-tree-dump-times "Replaced" 1 "forwprop1"} } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ + +/* After cddce we should have two IF statements remaining as the other + two tests can be threaded. */ +/* { dg-final { scan-tree-dump-times "if " 2 "cddce2"} } */ +/* { dg-final { cleanup-tree-dump "cddce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040313-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040313-1.c new file mode 100644 index 000000000..0ad144c03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040313-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +/* Test provided by Volker Reichelt in PR 14553. The redundant PHI + node elimination pass was not using the right API functions to + propagate pointers, which resulted in dereferenced pointers that + did not have memory tags associated with them. */ + +void foo(int* p) +{ + int i; + for (i=1; i>0; --i, ++p) + *p=0; +} + +void bar(int* p) { foo(p); } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040319-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040319-1.c new file mode 100644 index 000000000..d6e544971 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040319-1.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +/* Test derived from PR 14643. When a function has no addressable + variables but 2 or more pointers have conflicting memory tags, they + were not being processed by the type based alias analyzer, + resulting in optimizations removing a non-redundant load. */ + +extern void abort (void); + +struct bar { int count; int *arr;}; + +void foo (struct bar *b) +{ + b->count = 0; + *(b->arr) = 2; + if (b->count == 0) /* b->count can't be assumed to be 0 here. */ + abort (); +} + +main () +{ + struct bar x; + x.arr = &x.count; + foo (&x); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040324-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040324-1.c new file mode 100644 index 000000000..be718aba6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040324-1.c @@ -0,0 +1,34 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +/* Ensure that BIT_FIELD_REFs gets the appropriate VUSE. + Contributed by Paolo Bonzini <bonzini@gnu.org>. + + This testcase actually never triggered in the CVS repo, but it did + in my local tree and it seems worth testing. In this test, the if's + are folded to BIT_FIELD_REFs but the VUSEs were erroneously left out. + Therefore, DOM did not see that i was modified between the two ifs + and optimized away the second if. */ + +extern void abort (void); +extern void exit (int); + +struct x +{ + unsigned b:1; + unsigned c:1; +}; + +struct x i = { 1, 1 }; + +int +main () +{ + i.b = 1; + if (i.b == 1 && i.c == 0) + exit (0); + i.c = 0; + if (i.b == 1 && i.c == 0) + exit (0); + abort (); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040326-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040326-1.c new file mode 100644 index 000000000..4be6049e9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040326-1.c @@ -0,0 +1,32 @@ +/* { dg-options "-O2 -fno-inline-functions" } */ +/* { dg-do run } */ +/* When there are no call-clobbered variables, we should still create + a .GLOBAL_VAR to model the side effects of functions. Without it, + we were moving the call to Faref() inside the second call to + Faset(). */ +extern void abort (void); +extern void exit (int); + +main () +{ + int table, c, elt; + int tem = Faref (table, elt); + Faset (table, elt, c); + Faset (table, c, tem);/* tem cannot be replaced with Faref (table, elt) */ + exit (0); +} + +int j = 0; + +int __attribute__ ((noinline)) Faref (table, elt) +{ + j = 1; + return 0; +} + +int __attribute__ ((noinline)) Faset (table, elt, c) +{ + if (j != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040326-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20040326-2.c new file mode 100644 index 000000000..b1bed75da --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040326-2.c @@ -0,0 +1,64 @@ +/* { dg-options "-O2 -fno-inline-functions" } */ +/* { dg-do run } */ + +/* Gimplification problem exposed by zsh. All the side-effects in + function arguments and in the called expression should happen + before the actual function call. */ +extern void abort (void); +int A; + +typedef void (*fnptr) (void); +fnptr *F; + +void +foo (int x) +{ + if (A == x) + abort (); +} + +void +bar (int x, int y) +{ + if (x == 5 || y != 3) + abort (); +} + +void +boz (void) +{ + abort (); +} + +void +baz (void) +{ + if (*F != boz) + abort (); +} + +fnptr B[2] = { baz, boz }; + +main () +{ + int b, c; + + /* The gimplifier was emitting A++ after the call to foo. */ + A = 5; + foo (A++); + + /* The increment to 'b' and 'c' must happen before the call. However, + the first argument to bar() must be the original value of 'b', while + the second argument must be the new value of 'c'. */ + b = 4; + c = 2; + bar (b++, ++c); + + /* This call via function pointer *F should go to baz, but F should + be incremented before the actual call (i.e., right before the + call F should be pointing to boz). */ + F = &B[0]; + (*F++) (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040408-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040408-1.c new file mode 100644 index 000000000..6578be543 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040408-1.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +/* Make sure that when a variable with an NMT is marked for renaming + that the NMT's aliases are also marked for renaming. */ + +static int eiisnan (short unsigned int *x) +{ + int i; + + if( x[i] != 0 ) + return(1); +} + +static int eiisinf (unsigned short *x) +{ + if (eiisnan (x)) + return (0); + + if ((x[1] & 0x7fff) == 0x7fff) + return (1); +} + +static void toe64(short unsigned int *a, short unsigned int *b) +{ + register unsigned short *p, *q; + unsigned short i; + + q = b + 4; + + if (eiisinf (a)); + + for( i=0; i<4; i++ ) + *q-- = *p++; +} + +static int asctoeg(short unsigned int *y, int oprec) +{ + unsigned short yy[13]; + char *s; + + while( *s == ' ' ) + ++s; + + toe64( yy, y ); +} + +long double _strtold (char *s, char **se) +{ + long double x; + asctoeg( (unsigned short *)&x, 64 ); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040430-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040430-1.c new file mode 100644 index 000000000..4bc1f85ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040430-1.c @@ -0,0 +1,26 @@ +/* PR middle-end/14470. Similar to + gcc.c-torture/execute/20040313-1.c, but with a compile time test to + make sure the second if() is removed. */ +/* Update: We now remove both ifs. Whee. */ + +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + +extern void abort(void); + +int main() +{ + int t[1025] = { 1024 }, d; + + d = 0; + d = t[d]++; + if (t[0] != 1025) + abort(); + if (d != 1024) + abort(); + return 0; +} + +/* { dg-final { scan-tree-dump-times "if " 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040513-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040513-1.c new file mode 100644 index 000000000..bc65b979d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040513-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-forwprop1" } */ +void bar (void); + +void +foo (unsigned int a) +{ + if ((a >> 5) & 1) + bar (); +} + + + +/* There should be no casts to a _Bool since we can use the temporary + holding (a>>5)&1 directly. */ +/* { dg-final { scan-tree-dump-times "\\(_Bool\\)" 0 "forwprop1"} } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040513-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20040513-2.c new file mode 100644 index 000000000..a3edf9b80 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040513-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom2" } */ +int link_error(void); +int s(void); + +int t(int i) +{ + _Bool g = i == 4; + int h = g; + _Bool j = h; + int k = j; + _Bool l = k == 0; + _Bool o = !l; + int m = o; + + if (m) + if (i != 4) + return link_error(); + return 0; +} + +/* There should be no link_error calls, if there is any, the + optimization has failed */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c new file mode 100644 index 000000000..4c2835075 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040514-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */ + +int t( int i) +{ + int j; + if(i ==0) + { + j = 1; + goto end; + } + j = 0; +end: + return j; +} + +/* Should have no ifs left after straightening. */ +/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1"} } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040514-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20040514-2.c new file mode 100644 index 000000000..d518cacd0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040514-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-phiopt1" } */ +int +foo2 (distance, i, j) + int distance; + int i, j; +{ + int t = distance; + if (t <= 0) + t = ((t) >= 0 ? (t) : -(t)); + return t; +} + +/* There should be one ABS_EXPR and no conditionals. */ +/* { dg-final { scan-tree-dump-times "ABS_EXPR " 1 "phiopt1"} } */ +/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1"} } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c new file mode 100644 index 000000000..99b27ce02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040517-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-alias-vops" } */ +extern void abort (void); +int a; + +extern void __attribute__ ((malloc)) *foo (); + +void bar (void) +{ + a = 1; + foo (); + if (a) + abort (); +} + +/* We used to treat malloc functions like pure and const functions, but + malloc functions may clobber global memory. Only the function result + does not alias any other pointer. + Hence, we must have a VDEF for a before and after the call to foo(). */ +/* { dg-final { scan-tree-dump-times "VDEF" 2 "alias"} } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c new file mode 100644 index 000000000..315a5ebf8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040518-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */ +int f(int a, int b) +{ + int c = b; + if (a != b) + c = a; + return c; +} + +/* Should have no ifs left after straightening. */ +/* { dg-final { scan-tree-dump-times "if " 0 "phiopt1"} } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040518-2.c b/gcc/testsuite/gcc.dg/tree-ssa/20040518-2.c new file mode 100644 index 000000000..62f66232d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040518-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-phiopt1-details" } */ + +int t( int i) +{ + int j; + if(i>=0) + j = i; + else + j = -i; + return j; +} + +/* We should convert one COND_EXPRs into straightline code with ABS. */ +/* { dg-final { scan-tree-dump-times "straightline" 1 "phiopt1"} } */ +/* { dg-final { scan-tree-dump-times "ABS_EXPR" 1 "phiopt1"} } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c new file mode 100644 index 000000000..5bb7a4d7f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040615-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom1" } */ + +void bar1 (void); +void bar2 (void); + +void +foo (unsigned int a, unsigned int b) +{ + if (a >= b) + bar1 (); + else if (b <= a) + bar2 (); +} + +/* { dg-final { scan-tree-dump-times "bar2" 0 "dom1" } } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040624-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040624-1.c new file mode 100644 index 000000000..eb8e21095 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040624-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dom1" } */ + +void bar1 (void); +void bar2 (void); + +void +foo (unsigned int a, unsigned int b) +{ + if (a >= b) + bar1 (); + else if (a <= b) + bar2 (); +} + +/* The second conditional is redundant since we know it must be + true (to reach the second condition we know a < b via the first + conditional. */ + +/* { dg-final { scan-tree-dump-times "if " 1 "dom1" } } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c new file mode 100644 index 000000000..ad96198a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040703-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2" } */ + +float foo(float x) +{ + x += 1; + x -= 1; + return x; +} + +/* We should *not* fold the arithmetic. */ +/* { dg-final { scan-tree-dump-times "0\\.0" 0 "dom2"} } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040713-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040713-1.c new file mode 100644 index 000000000..78919d040 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040713-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ + +/* Extracted from PR 16443. Contributed by Volker Reichelt. + Scanning of __asm__ operands wasn't considering call-clobbered + variables discovered before the aliasing pass. This was causing a + crash in verify_ssa() because 'p' was not being given an SSA_NAME. */ + +void foo(char *p) +{ + __asm__ ("" ::: "memory"); +} + +void bar() +{ + static char *p; + foo(p); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040721-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040721-1.c new file mode 100644 index 000000000..1a6e36df8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040721-1.c @@ -0,0 +1,29 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +/* Test to check whether global variables are being + constant propagated. */ + +extern void link_error (void); + +int G; + +void +foo (int i) +{ + if (i > 0) + G = 3; + else + G = 3; + + if (G != 3) + link_error (); +} + +int +main () +{ + foo (0); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040729-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040729-1.c new file mode 100644 index 000000000..ef94096fa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040729-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dce2" } */ + +foo () +{ + volatile int *p; + volatile int x; + + p = &x; + *p = 3; + return *p + 1; +} + +/* The assignment to 'p' is dead and should be removed. But the + compiler was mistakenly thinking that the statement had volatile + operands. But 'p' itself is not volatile and taking the address of + a volatile does not constitute a volatile operand. */ +/* { dg-final { scan-tree-dump-times "&x" 0 "dce2"} } */ +/* { dg-final { cleanup-tree-dump "dce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20040911-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20040911-1.c new file mode 100644 index 000000000..f17e98aed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20040911-1.c @@ -0,0 +1,22 @@ +/* Verify that points-to information is handled properly for PTR + OFFSET + pointer arithmetics. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-alias-vops" } */ + +char buf[4], *q; +int foo (int i) +{ + char c, *p; + q = &c; + p = buf; + if (i) + p = p + 3; + else + p = p + 2; + *p = 6; + c = 8; + return *p; +} + +/* { dg-final { scan-tree-dump-not "VUSE <c" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20041002-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20041002-1.c new file mode 100644 index 000000000..9a07877fb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20041002-1.c @@ -0,0 +1,24 @@ +/* PR tree-optimization/16632 + fold() failed to see the following "if" statements never trigger. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ssa" } */ + +int +foo (int i) +{ + if ((i | 3) == 1) + return 1; + return 0; +} + +int +bar (int i) +{ + if ((i & 4) == 2) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "if" 0 "ssa" } } */ +/* { dg-final { cleanup-tree-dump "ssa" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20041008-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20041008-1.c new file mode 100644 index 000000000..ca24427b6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20041008-1.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +struct A { + int x; + int y; +}; + +baz (struct A *a) +{ + a->x = 3; + a->y = 2; +} + +foo (int i) +{ + struct A a; + + /* Make sure we can't scalarize 'a'. */ + baz (&a); + + if (i > 10) + a.x = i; + else + a.x = i; + + /* Copy propagation should prove that this predicate is always false. */ + if (a.x != i) + link_error (); + + return a.x; +} + +main () +{ + foo (30); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c new file mode 100644 index 000000000..600794954 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20041122-1.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fstrict-aliasing -fdump-tree-fre" } */ + +__extension__ typedef __SIZE_TYPE__ size_t; +extern void *xmalloc (size_t) __attribute__ ((__malloc__)); +struct edge_def +{ + struct basic_block_def *dest; + int flags; +}; +typedef struct edge_def *edge; +struct basic_block_def +{ + int flags; +}; +typedef struct basic_block_def *basic_block; +extern int n_basic_blocks; +extern edge frob (); +basic_block * +find_unreachable_blocks (void) +{ + basic_block *tos, *worklist; + tos = worklist = xmalloc (sizeof (basic_block) * n_basic_blocks); + edge e = frob(); + if (!(e->dest->flags & 4)) + { + e->dest->flags |= 4; + *tos++ = e->dest; + } + return worklist; +} + +/* If the aliasing code does its job properly, then we should be + able to determine that modifying e->dest->flags does not + modify e or e->dest if we can assert strict-aliasing rules. + The net result is that we only need one load of e->dest. */ +/* { dg-final { scan-tree-dump-times "->dest" 1 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050128-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050128-1.c new file mode 100644 index 000000000..7197ec8b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050128-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +int +foo (int align) +{ + int off = 0 % align; + return off ? align - off : 0; +} + +/* We should have optimized away the mod operator before we gimpleized + the code. */ +/* { dg-final { scan-tree-dump-times "%" 0 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050215-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050215-1.c new file mode 100644 index 000000000..b9bb3a749 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050215-1.c @@ -0,0 +1,14 @@ +/* PR middle-end/19857 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int i; +int foo (void) +{ + return i & ~(unsigned int) 3; +} + +/* Make sure the optimizers don't introduce overflow where one + did not exist in the original. */ +/* { dg-final { scan-tree-dump-times "-0+4" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050314-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050314-1.c new file mode 100644 index 000000000..2ba1ee047 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050314-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-lim-details" } */ + +float a[100]; + +int foo(void); +float sinf (float); + +void xxx (void) +{ + int i, k = foo (); + + for (i = 0; i < 100; i++) + a[k] += sinf (i); +} + +/* Store motion may be applied to the assignment to a[k], since sinf + cannot read nor write the memory. */ + +/* { dg-final { scan-tree-dump-times "Moving statement" 1 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050412-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050412-1.c new file mode 100644 index 000000000..9c172d769 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050412-1.c @@ -0,0 +1,16 @@ +/* PR tree-optimization/14627 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + +int b; +void foo (int a) { + if (a) + a = 3; + b = a; +} + +/* Make sure we do not have an assignment a = 0 in the resulting + optimized dump. */ +/* { dg-final { scan-tree-dump-times "a.* = 0;" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c new file mode 100644 index 000000000..8dc4c7e5b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20050719-1.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void) __attribute__ ((__nothrow__)) __attribute__ +((__noreturn__)); +extern void exit (int __status) __attribute__ ((__nothrow__)) +__attribute__ ((__noreturn__)); + +struct bootLoader { + int x; +}; + +void +zap(struct bootLoader *bootLoader) +{ + /* The expression on the RHS of the assignment is *not* a + dereference of pointer 'bootLoader'. It is merely used as an + offset calculation. VRP was erroneously removing the if() + because it thought that 'bootLoader' was always dereferenced. */ + int *boot = &bootLoader->x; + + if (bootLoader) + { + useboot (boot); + } +} + +int +useboot (void *boot) +{ + abort (); +} + +main() +{ + zap (0); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20070302-1.c b/gcc/testsuite/gcc.dg/tree-ssa/20070302-1.c new file mode 100644 index 000000000..4b148f23d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20070302-1.c @@ -0,0 +1,45 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +struct A +{ + int x; + float y; +}; + +volatile float X, Y; + +int __attribute__ ((__noinline__)) +baz (struct A *z, struct A *y) +{ + z->x = (int) X; + z->y = Y; + y->x = (int) X; + y->y = Y; +} + + +struct A B; + +float foo (int i) +{ + struct A *p, x, y, z; + + p = (i > 10) ? &x : &z; + x.y = 3.0; + p->x += baz (&z, &y); + X = z.y; + Y = p->y; + + /* This predicate should always evaluate to false. The call to + baz() is not a clobbering site for x.y. The operand scanner was + considering it a clobbering site for x.y because x.y is in the + alias set of a call-clobbered memory tag. */ + if (x.y != 3.0) + link_error (); +} + +main(int argc, char **argv) +{ + foo (argc); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20070815.c b/gcc/testsuite/gcc.dg/tree-ssa/20070815.c new file mode 100644 index 000000000..fa0e69f7c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20070815.c @@ -0,0 +1,60 @@ +/* { dg-do compile } */ +/* { dg-options "-O -w" } */ + +/* This code snippet from glibc 2.3.5 was causing an ICE during + optimization because we were failing to update the SSA form for + stale name tags. These are tags that are associated with SSA pointers + that have been removed from the IL. This was causing the SSA + verifier to fail before we had a chance to run the cleanup pass that + finally removes all the remaining PHI nodes for the stale name tag. */ +struct _IO_wide_data +{ +}; +struct _IO_FILE { +}; +typedef struct _IO_FILE _IO_FILE; +struct _IO_jump_t +{ +}; +struct _IO_FILE_plus +{ + _IO_FILE file; +}; +extern const struct _IO_jump_t _IO_file_jumps_maybe_mmap ; +extern const struct _IO_jump_t _IO_wfile_jumps; +extern const struct _IO_jump_t _IO_wfile_jumps_maybe_mmap ; + +_IO_new_fdopen (fd, mode) + const char *mode; +{ + int read_write; + int posix_mode = 0; + struct locked_FILE + { + struct _IO_FILE_plus fp; + struct _IO_wide_data wd; + } *new_f; + int fd_flags; + int use_mmap = 0; + { + } + { + switch (*++mode) + { + case '\0': + use_mmap = 1; + } + } + if (((fd_flags & 0003) == 00 && !(read_write & 8)) + || ((fd_flags & 0003) == 01 && !(read_write & 4))) + { + } + if ((posix_mode & 02000) && !(fd_flags & 02000)) + return ((void *)0); + _IO_no_init (&new_f->fp.file, 0, 0, &new_f->wd, + (use_mmap && (read_write & 8)) + ? &_IO_wfile_jumps_maybe_mmap : + &_IO_wfile_jumps); + (use_mmap && (read_write & 8)) ? &_IO_file_jumps_maybe_mmap : + _IO_file_init (&new_f->fp); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/20080530.c b/gcc/testsuite/gcc.dg/tree-ssa/20080530.c new file mode 100644 index 000000000..bf222fee1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/20080530.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-einline" } */ + +void bar (char *); +int i; + +static void +foo (void) +{ + char *p = __builtin_alloca (i); + bar (p); +} + +int +baz (void) +{ + foo (); /* foo() should not be inlined here because it calls alloca */ + return 6; +} + +/* { dg-final { scan-tree-dump-times "Inlining foo into baz" 0 "einline"} } */ +/* { dg-final { cleanup-tree-dump "einline" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c new file mode 100644 index 000000000..03956100a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-10.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct { + int i; + int x[2]; + int j; +} a; + +int foo(int i) +{ + a.i = 1; + a.j = 2; + a.x[i] = 0; + return a.i + a.j; +} + +/* { dg-final { scan-tree-dump "return 3;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c new file mode 100644 index 000000000..d4ce34bd8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-11.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct param { int *a; }; +void foo(struct param *p); +int bar(void) +{ + int a[32]; + struct param p; + a[0] = 1; + a[1] = 1; + p.a = &a[0]; + foo(&p); + return a[0] + *p.a; +} + +/* We need to have both: a load from "a[0]" and a load from "*p.a", + the latter can be an ssa temporary. */ +/* { dg-final { scan-tree-dump "= a.0.;" "optimized" } } */ +/* { dg-final { scan-tree-dump "= \\*\[pD\]" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c new file mode 100644 index 000000000..b1fb7997f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-12.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-alias-vops" } */ + +struct { + int i; + int x[128]; + int j; +} a; + +int foo(int i) +{ + a.x[i] = 0; + return a.x[i]; +} + +/* { dg-final { scan-tree-dump "VDEF" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-13.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-13.c new file mode 100644 index 000000000..ae7cc8214 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-13.c @@ -0,0 +1,33 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + + +struct a +{ + char a1; +}; + +int *aa; + +void g(int *a) +{ + aa = a; + *a = 2; +} + +int t(int i, struct a *b) +{ + g(&i); + b->a1 = 1; + i = 2; + if (b->a1 != 1) + link_failure (); +} +int main(void) +{ + struct a b; + t(1, &b); + return 0; +} + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-14.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-14.c new file mode 100644 index 000000000..a1216b7d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-14.c @@ -0,0 +1,20 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +struct s +{ + long long a:12; + long long b:12; + long long c:40; +}; + +struct s s, *p = &s; + +int +main () +{ + p->a = 1; + s.a = 0; + s.b = 0; + return p->a + s.b; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-16.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-16.c new file mode 100644 index 000000000..c71486c26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-16.c @@ -0,0 +1,29 @@ +/* { dg-do run } */ + +extern void abort (void); + +struct X { + int a; + struct Y { + int b[4]; + } b; + struct Y c; +} m; + +struct X n; + +foo (int i) +{ + struct Y *p = (i > 10) ? &m.b : &n.c; + p->b[2] = 10; + m.b.b[3] = 6; + n.c.b[2] = 3; + return p->b[2] + n.c.b[2] + m.b.b[3]; +} + +main() +{ + if (foo (3) != 12) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-17.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-17.c new file mode 100644 index 000000000..48e72ffee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-17.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-early-inlining -fdump-tree-ccp2" } */ + +int *p; +int inline bar(void) { return 0; } +int foo(int x) +{ + int i; + int *q; + if (bar()) + q = &i; + else + q = p; + return *q + *p; +} + +/* { dg-final { scan-tree-dump-not "NOTE: no flow-sensitive alias info for" "ccp2" } } */ +/* { dg-final { cleanup-tree-dump "ccp2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-18.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-18.c new file mode 100644 index 000000000..e86acbc19 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-18.c @@ -0,0 +1,90 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-details -fdump-tree-optimized" } */ + +struct A { + int i; + int j; + float x; +}; +struct B { + struct A a; + int k; +}; + +int g; + +int test0 (struct A *p, struct A *q) +{ + p->i = 0; + q->j = -1; + return p->i; +} + +int test1 (struct A *p, struct B *q) +{ + p->i = 1; + q->k = -1; + return p->i; +} + +int test2 (struct A *p, struct B *q) +{ + p->i = 2; + q->a.i = -1; + return p->i; +} + +int test3 (struct A *p, struct B *q) +{ + p->i = 3; + q->a.j = -1; + return p->i; +} + +int test4 (struct A *p) +{ + g = 4; + p->i = -1; + return g; +} + +int test5 (struct A *p) +{ + p->i = 5; + g = -1; + return p->i; +} + +int test6 (struct A *p, int *q) +{ + p->i = 6; + *q = -1; + return p->i; +} + +int test7 (struct A *p, int *q) +{ + p->j = 7; + *q = -1; + return p->j; +} + +int test8 (struct A *p, int *q) +{ + *q = 8; + p->x = -1; + return *q; +} + +/* { dg-final { scan-tree-dump "with 0" "fre" } } */ +/* { dg-final { scan-tree-dump "with 1" "fre" } } */ +/* { dg-final { scan-tree-dump "with 3" "fre" } } */ +/* { dg-final { scan-tree-dump "with 4" "fre" } } */ +/* { dg-final { scan-tree-dump "with 5" "fre" } } */ +/* { dg-final { scan-tree-dump "with 8" "fre" } } */ +/* { dg-final { scan-tree-dump-not "return 2;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return 6;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return 7;" "optimized" } } */ +/* { dg-final { scan-tree-dump-not "return -1;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-19.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-19.c new file mode 100644 index 000000000..7b3689049 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-19.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-alias-vops" } */ + +const static int a; + +int __attribute__((noinline)) +foo(int i) +{ + const int *q; + int b; + if (i) + q = &a; + else + q = &b; + b = 1; + /* We should not prune a from the points-to set of q. */ + return *q; +} + +extern void abort (void); +int main() +{ + if (foo(1) != 0) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "q_. = { a b }" "alias" } } */ +/* { dg-final { scan-tree-dump "q_., points-to vars: { a b }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-2.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-2.c new file mode 100644 index 000000000..ecd0fdc9f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-2.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target { nonpic } } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +static int a; +int f; +void bar (void) __attribute__((noinline)); +void bar (void) +{ + f = 9; +} + +void link_error (); + +int foo() +{ + int b, c; + a = 5; + b = a; + bar (); + b = b + a; + if (b != 10) + link_error (); + return b; +} + +/* We should have removed the link_error on the tree level as GCC can tell that + a is not touched by the calling bar at all. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-20.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-20.c new file mode 100644 index 000000000..7991c52fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-20.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */ + +struct S { float f; int i; }; +struct R { int x; int i; }; + +/* Strict-aliasing rules say that int and float do not alias. */ +int bar(struct S *s, int *i) +{ + *i = 0; + s->f = 1.0; + return *i; +} + +/* Strict-aliasing rules say that S and R do not alias. */ +int foo(struct S *s, struct R *r) +{ + r->i = 0; + s->i = 1; + return r->i; +} + +/* { dg-final { scan-tree-dump-times "return 0;" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-3.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-3.c new file mode 100644 index 000000000..3d8587da8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct { + int i; + int j; + int x[2]; +} a; + +int foo(void) +{ + a.i = 1; + a.j = 0; + a.x[0] = 0; + return a.i + a.j; +} + +/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c new file mode 100644 index 000000000..e0394327d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-4.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct { + int i; + struct { + int x[2]; + } b; +} a; + +int foo(void) +{ + a.i = 1; + a.b.x[0] = 0; + a.b.x[1] = 1; + return a.i + a.b.x[0]; +} + +/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c new file mode 100644 index 000000000..f1faae52c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-5.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct { + int i; + struct { + struct { + int i; + } x[2]; + } b; +} a; + +int foo(void) +{ + a.i = 1; + a.b.x[0].i = 0; + a.b.x[1].i = 1; + return a.i + a.b.x[0].i; +} + +/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c new file mode 100644 index 000000000..bcc011898 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-6.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct param { int *a; }; +void foo(struct param *p); +int bar(void) +{ + int a[2]; + struct param p; + a[0] = 1; + a[1] = 1; + p.a = &a[0]; + foo(&p); + return a[0] + *p.a; +} + +/* We need to have both: a load from "a[0]" and a load from "*p.a", + the latter can be an ssa temporary. */ +/* { dg-final { scan-tree-dump "= a.0.;" "optimized" } } */ +/* { dg-final { scan-tree-dump "= \\*\[pD\]" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c new file mode 100644 index 000000000..7ef604be2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-7.c @@ -0,0 +1,17 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +void abort(void); +int main() +{ + int a[2]; + int *p = a; + int i; + a[0] = 1; + a[1] = 2; + for (i=0; i<2; ++i) + if (p[i] != i+1) + abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c new file mode 100644 index 000000000..7c825f965 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-8.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +void abort(void); +int main() +{ + int a[2]; + int i = 1; + a[0] = 1; + a[1] = 2; + if (*(a + i) != 2) + abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c b/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c new file mode 100644 index 000000000..0a20e0543 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/alias-9.c @@ -0,0 +1,15 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +void abort(void); +int main() +{ + int a[32]; + int i = 1; + a[0] = 1; + a[1] = 2; + if (*(a + i) != 2) + abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c b/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c new file mode 100644 index 000000000..1a5385740 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/andor-1.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +unsigned int test1(unsigned int a) +{ + return (a & 1) | 1; +} + +int test2(int b) +{ + return (b & 1) | 1; +} + +unsigned int test3(unsigned int c) +{ + return (c | 1) & 1; +} + +int test4(int d) +{ + return (d | 1) & 1; +} + +unsigned int test5(unsigned int e) +{ + return (e | 4) & 6; +} + +int test6(int f) +{ + return (f | 4) & 6; +} + +unsigned int test7(unsigned int g) +{ + return (g & -2) | 1; +} + +int test8(int h) +{ + return (h & -2) | 1; +} + +unsigned int test9(unsigned int i) +{ + return (i & 3) | 1; +} + +int test10(int j) +{ + return (j & 3) | 1; +} + +/* { dg-final { scan-tree-dump-times "a \& 1 \\| 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "b \& 1 \\| 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "\\(c \\| 1\\) \& 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "\\(d \\| 1\\) \& 1" 0 "original" } } */ +/* { dg-final { scan-tree-dump-times "e \& 2 \\| 4" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "f \& 2 \\| 4" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "g \\| 1" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "h \\| 1" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "i \& 2 \\| 1" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "j \& 2 \\| 1" 1 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/andor-2.c b/gcc/testsuite/gcc.dg/tree-ssa/andor-2.c new file mode 100644 index 000000000..cdc00b7a4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/andor-2.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +int test1(int a, int b) +{ + return (a & b) | b; +} + +int test2(int c, int d) +{ + return (c & d) | c; +} + +int test3(int e, int f) +{ + return e | (e & f); +} + +int test4(int g, int h) +{ + return g | (h & g); +} + +int test5(int i, int j) +{ + return (i | j) & j; +} + +int test6(int k, int l) +{ + return (k | l) & k; +} + +int test7(int m, int n) +{ + return m & (m | n); +} + +int test8(int o, int p) +{ + return o & (p | o); +} + +/* { dg-final { scan-tree-dump-times "return b;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return c;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return e;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return g;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return j;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return k;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return m;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return o;" 1 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asm-1.c b/gcc/testsuite/gcc.dg/tree-ssa/asm-1.c new file mode 100644 index 000000000..64026287c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/asm-1.c @@ -0,0 +1,17 @@ +/* Make sure that gcc understands that an in/out operand is a use as well + as a def. */ + +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +void f() +{ + int i = 42; + int j = 63; + + asm ("": "=m"(i), "+r"(j) : "m"(i)); +} + +/* { dg-final { scan-tree-dump-times "42" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "63" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c b/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c new file mode 100644 index 000000000..c67b9b53f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/asm-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#ifdef __hppa__ +#define REGISTER "1" +#else +#define REGISTER "0" +#endif + +void baz(void) +{ + register int xyzzy asm(REGISTER) = 1; + asm volatile ("" : : "r"(xyzzy)); +} + +/* { dg-final { scan-tree-dump-times "asm\[^\\r\\n\]*xyzzy" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c b/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c new file mode 100644 index 000000000..5ed282e49 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/asm-3.c @@ -0,0 +1,36 @@ +/* PR 17739 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +#ifdef __hppa__ +#define REGISTER "1" +#else +#ifdef __moxie__ +#define REGISTER "8" +#else +#define REGISTER "0" +#endif +#endif + +static inline int source(void) +{ + register int hardreg __asm__(REGISTER); + asm("" : "=r"(hardreg)); + return hardreg; +} + +void test(void) +{ + int t = source(); + foo(t); + bar(t); +} + +/* Hardreg should appear exactly 3 times -- declaration, asm stmt, + and copy out. */ +/* { dg-final { scan-tree-dump-times "hardreg" 3 "optimized" } } */ + +/* In particular, hardreg should *not* appear in the call to bar. */ +/* { dg-final { scan-tree-dump-times "bar \[(\]t_.\[)\]" 1 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/asmgoto-1.c b/gcc/testsuite/gcc.dg/tree-ssa/asmgoto-1.c new file mode 100644 index 000000000..9dd549906 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/asmgoto-1.c @@ -0,0 +1,95 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -w -fdump-tree-optimized" } */ + +extern void XYZZY (void); +typedef unsigned long __kernel_size_t; +typedef __kernel_size_t size_t; +typedef unsigned gfp_t; +struct per_cpu_pageset { } __attribute__ ((__aligned__ ((1 << (6))))); +struct zone { struct per_cpu_pageset *pageset[64]; } +zone_flags_t; typedef struct pglist_data { struct zone node_zones[4]; } pg_data_t; +extern struct pglist_data *first_online_pgdat (void); +extern struct zone *next_zone (struct zone *zone); +extern volatile int per_cpu__x86_cpu_to_node_map[]; +struct kmem_cache { int size; }; +extern struct kmem_cache kmalloc_caches[(12 + 2)]; +struct tracepoint { void **funcs; } __attribute__ ((aligned (32))); +extern struct tracepoint __tracepoint_kmalloc_node; +void *__kmalloc_node (size_t size, gfp_t flags, int node); + +static inline int +cpu_to_node (int cpu) +{ + return per_cpu__x86_cpu_to_node_map[cpu]; +} + +static inline void +trace_kmalloc_node (unsigned long call_site, const void *ptr, + size_t bytes_req, size_t bytes_alloc, gfp_t gfp_flags, + int node) +{ + asm goto ("" : : : : trace_label); + if (0) + { + void **it_func; + trace_label: + asm ("" : "=r"(it_func) : "0"(&__tracepoint_kmalloc_node.funcs)); + } +}; + +static inline __attribute__ ((always_inline)) int +kmalloc_index (size_t size) +{ + if (size <= 64) + return 6; + return -1; +} + +static inline __attribute__ ((always_inline)) struct kmem_cache * +kmalloc_slab (size_t size) +{ + int index = kmalloc_index (size); + if (index == 0) + return ((void *) 0); + return &kmalloc_caches[index]; +} + +static inline __attribute__ ((always_inline)) void * +kmalloc_node (size_t size, gfp_t flags, int node) +{ + void *ret; + if (__builtin_constant_p (size) && size <= (2 * ((1UL) << 12)) + && !(flags & ((gfp_t) 0x01u))) + { + struct kmem_cache *s = kmalloc_slab (size); + if (!s) + return ((void *) 16); + trace_kmalloc_node (({ __here:(unsigned long) &&__here;}), + ret, size, s->size, flags, node); + } + return __kmalloc_node (size, flags, node); +} + +int +process_zones (int cpu) +{ + struct zone *zone, *dzone; + int node = cpu_to_node (cpu); + for (zone = (first_online_pgdat ())->node_zones; + zone; zone = next_zone (zone)) + { + ((zone)->pageset[(cpu)]) = + kmalloc_node (sizeof (struct per_cpu_pageset), + (((gfp_t) 0x10u) | ((gfp_t) 0x40u) | ((gfp_t) 0x80u)), + node); + if (!((zone)->pageset[(cpu)])) + goto bad; + } + return 0; +bad: + XYZZY (); + return -12; +} + +/* { dg-final { scan-tree-dump-times "XYZZY" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c new file mode 100644 index 000000000..d6e121ae0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + if (x != 0) + return 1; + return 0; +} + +/* There should be no != 0 which is produced by the front-end as + bool_var != 0 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "!= 0" 0 "optimized"} } */ + +/* There should be no adde for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "adde" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c new file mode 100644 index 000000000..d7bf20da8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-10.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + return (x != 1); +} + +/* There should be no != 1 which is produced by the front-end as + bool_var != 1 is the same as !bool_var. */ +/* { dg-final { scan-tree-dump-times "!= 1" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "!x" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c new file mode 100644 index 000000000..8d88b7e87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-11.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + return (x == 0); +} + +/* There should be no == 0 which is produced by the front-end as + bool_var == 0 is the same as !bool_var. */ +/* { dg-final { scan-tree-dump-times "== 0" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "!x" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c new file mode 100644 index 000000000..0f88b0965 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + int y; + if (x) + y = 1; + else + y = 0; + return y; +} + +/* There should be no != 0 which is produced by the front-end as + bool_var != 0 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "!= 0" 0 "optimized"} } */ + +/* There should be no adde for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "adde" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-3.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-3.c new file mode 100644 index 000000000..8fa2a57c4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + int y; + if (!x) + y = 0; + else + y = 1; + return y; +} + +/* There should be no == 0. Though PHI-OPT or invert_truth does not + fold its tree forwprop is able to clean up the mess. */ +/* { dg-final { scan-tree-dump-times "== 0" 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-4.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-4.c new file mode 100644 index 000000000..b06182e2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-4.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + return (x != 0); +} + +/* There should be no != 0 which is produced by the front-end as + bool_var != 0 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "!= 0" 0 "optimized"} } */ + +/* There should be no adde for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "adde" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-5.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-5.c new file mode 100644 index 000000000..e33ce9c73 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-5.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + if (x == 1) + return 1; + return 0; +} + +/* There should be no == 1 which is produced by the front-end as + bool_var == 1 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "== 1" 0 "optimized"} } */ + +/* There should be no adde for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "adde" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-6.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-6.c new file mode 100644 index 000000000..cc77591c9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-6.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + int y; + if (x) + y = 1; + else + y = 0; + return y; +} + +/* There should be no == 1 which is produced by the front-end as + bool_var == 1 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "== 1" 0 "optimized"} } */ + +/* There should be no adde for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "adde" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-7.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-7.c new file mode 100644 index 000000000..b79871064 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-7.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + int y; + if (x != 1) + y = 0; + else + y = 1; + return y; +} + +/* There should be no != 1. Fold changes x != 1 to ! x. */ +/* { dg-final { scan-tree-dump-times "!= 1" 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-8.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-8.c new file mode 100644 index 000000000..527525270 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-8.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(_Bool x) +{ + return (x == 1); +} + +/* There should be no == 1 which is produced by the front-end as + bool_var == 1 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "== 1" 0 "optimized"} } */ + +/* There should be no adde for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "adde" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bool-9.c b/gcc/testsuite/gcc.dg/tree-ssa/bool-9.c new file mode 100644 index 000000000..2660b2580 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bool-9.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +_Bool f1(_Bool x) +{ + return !!x; +} + +/* There should be no != 0 which is produced by the front-end as + bool_var != 0 is the same as bool_var. */ +/* { dg-final { scan-tree-dump-times "!= 0" 0 "optimized"} } */ + +/* There should be no subfe for powerpc. Check if we actually optimized + away the comparison. */ +/* { dg-final { scan-assembler-times "subfe" 0 { target powerpc*-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c new file mode 100644 index 000000000..42d4b0dd8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +f (int i, float j) +{ + if (__builtin_expect (i > 0 && j, 0)) + g (); +} + +/* { dg-final { scan-tree-dump-times {builtin_expect[^\n]*, 0\);\n[^\n]*if} 2 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c new file mode 100644 index 000000000..ff175b975 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +f (int i, float j) +{ + if (__builtin_expect (i > 0 || j, 0)) + ; + else + g (); +} + +/* { dg-final { scan-tree-dump-times {builtin_expect[^\n]*, 0\);\n[^\n]*if} 2 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c new file mode 100644 index 000000000..8fcc4e2bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +f (int i, float j) +{ + if (__builtin_expect (i > 0 && j, 0)) + a (); + else + b (); +} + +/* { dg-final { scan-tree-dump-times {builtin_expect[^\n]*, 0\);\n[^\n]*if} 2 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c new file mode 100644 index 000000000..1fecf1b98 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +f (int i, float j) +{ + if (__builtin_expect (i > 0 || j, 0)) + a (); + else + b (); +} + +/* { dg-final { scan-tree-dump-times {builtin_expect[^\n]*, 0\);\n[^\n]*if} 2 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c new file mode 100644 index 000000000..ed53b287b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-expect-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop" } */ + +f (int i, float j) +{ + if (__builtin_expect (i > 0 && __builtin_expect (j != 0, 1), 0)) + a (); + else + b (); +} + +/* { dg-final { scan-tree-dump-times { if } 2 "forwprop1"} } */ +/* { dg-final { scan-tree-dump {builtin_expect[^\n]*, 0\);\n[^\n]*if} "forwprop1"} } */ +/* { dg-final { scan-tree-dump {builtin_expect[^\n]*, 1\);\n[^\n]*if} "forwprop1"} } */ +/* { dg-final { cleanup-tree-dump "forwprop?" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-fprintf-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-fprintf-1.c new file mode 100644 index 000000000..b08e1242b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-fprintf-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +typedef struct { int i; } FILE; +FILE *fp; +extern int fprintf (FILE *, const char *, ...); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9; + +void test (void) +{ + vi0 = 0; + fprintf (fp, "hello"); + vi1 = 0; + fprintf (fp, "hello\n"); + vi2 = 0; + fprintf (fp, "a"); + vi3 = 0; + fprintf (fp, ""); + vi4 = 0; + fprintf (fp, "%s", "hello"); + vi5 = 0; + fprintf (fp, "%s", "hello\n"); + vi6 = 0; + fprintf (fp, "%s", "a"); + vi7 = 0; + fprintf (fp, "%c", 'x'); + vi8 = 0; + fprintf (fp, "%d%d", vi0, vi1); + vi9 = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*fwrite.*\"hello\".*1, 5, fp.*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*fwrite.*\"hello\\\\n\".*1, 6, fp.*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*fputc.*fp.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*fwrite.*\"hello\".*1, 5, fp.*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*fwrite.*\"hello\\\\n\".*1, 6, fp.*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*fputc.*fp.*vi7" "fab"} } */ +/* { dg-final { scan-tree-dump "vi7.*fputc.*fp.*vi8" "fab"} } */ +/* { dg-final { scan-tree-dump "vi8.*fprintf.*fp.*\"%d%d\".*vi9" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-fprintf-chk-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-fprintf-chk-1.c new file mode 100644 index 000000000..93e38cb9a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-fprintf-chk-1.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +typedef struct { int i; } FILE; +FILE *fp; +extern int __fprintf_chk (FILE *, int, const char *, ...); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9; + +void test (void) +{ + vi0 = 0; + __fprintf_chk (fp, 1, "hello"); + vi1 = 0; + __fprintf_chk (fp, 1, "hello\n"); + vi2 = 0; + __fprintf_chk (fp, 1, "a"); + vi3 = 0; + __fprintf_chk (fp, 1, ""); + vi4 = 0; + __fprintf_chk (fp, 1, "%s", "hello"); + vi5 = 0; + __fprintf_chk (fp, 1, "%s", "hello\n"); + vi6 = 0; + __fprintf_chk (fp, 1, "%s", "a"); + vi7 = 0; + __fprintf_chk (fp, 1, "%c", 'x'); + vi8 = 0; + __fprintf_chk (fp, 1, "%d%d", vi0, vi1); + vi9 = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*fwrite.*\"hello\".*1, 5, fp.*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*fwrite.*\"hello\\\\n\".*1, 6, fp.*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*fputc.*fp.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*fwrite.*\"hello\".*1, 5, fp.*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*fwrite.*\"hello\\\\n\".*1, 6, fp.*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*fputc.*fp.*vi7" "fab"} } */ +/* { dg-final { scan-tree-dump "vi7.*fputc.*fp.*vi8" "fab"} } */ +/* { dg-final { scan-tree-dump "vi8.*__fprintf_chk.*fp.*1.*\"%d%d\".*vi9" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-free.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-free.c new file mode 100644 index 000000000..67dd07140 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-free.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void bar (void *); +void foo(unsigned n) +{ + void *p = __builtin_malloc (n); + if (p) + { + bar (p); + __builtin_free (p); + p = 0; + } + __builtin_free (p); +} + +/* We should remove the redundant call to free. */ + +/* { dg-final { scan-tree-dump-times "free" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-printf-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-printf-1.c new file mode 100644 index 000000000..a78d0880c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-printf-1.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +extern int printf (const char *, ...); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9, via; + +void test (void) +{ + vi0 = 0; + printf ("hello"); + vi1 = 0; + printf ("hello\n"); + vi2 = 0; + printf ("a"); + vi3 = 0; + printf (""); + vi4 = 0; + printf ("%s", "hello"); + vi5 = 0; + printf ("%s", "hello\n"); + vi6 = 0; + printf ("%s", "a"); + vi7 = 0; + printf ("%s", ""); + vi8 = 0; + printf ("%c", 'x'); + vi9 = 0; + printf ("%s\n", "hello\n"); + via = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*printf.*\"hello\".*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*puts.*\"hello\".*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*putchar.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*printf.*\"hello\".*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*puts.*\"hello\".*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*putchar.*vi7" "fab"} } */ +/* { dg-final { scan-tree-dump "vi7 ={v} 0\[^\(\)\]*vi8 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi8.*putchar.*vi9" "fab"} } */ +/* { dg-final { scan-tree-dump "vi9.*puts.*\"hello\\\\n\".*via" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-printf-chk-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-printf-chk-1.c new file mode 100644 index 000000000..2f85b28ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-printf-chk-1.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +extern int __printf_chk (int, const char *, ...); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9, via; + +void test (void) +{ + vi0 = 0; + __printf_chk (1, "hello"); + vi1 = 0; + __printf_chk (1, "hello\n"); + vi2 = 0; + __printf_chk (1, "a"); + vi3 = 0; + __printf_chk (1, ""); + vi4 = 0; + __printf_chk (1, "%s", "hello"); + vi5 = 0; + __printf_chk (1, "%s", "hello\n"); + vi6 = 0; + __printf_chk (1, "%s", "a"); + vi7 = 0; + __printf_chk (1, "%s", ""); + vi8 = 0; + __printf_chk (1, "%c", 'x'); + vi9 = 0; + __printf_chk (1, "%s\n", "hello\n"); + via = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*__printf_chk.*1.*\"hello\".*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*puts.*\"hello\".*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*putchar.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*__printf_chk.*1.*\"hello\".*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*puts.*\"hello\".*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*putchar.*vi7" "fab"} } */ +/* { dg-final { scan-tree-dump "vi7 ={v} 0\[^\(\)\]*vi8 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi8.*putchar.*vi9" "fab"} } */ +/* { dg-final { scan-tree-dump "vi9.*puts.*\"hello\\\\n\".*via" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-vfprintf-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vfprintf-1.c new file mode 100644 index 000000000..1083f13bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vfprintf-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +#include <stdarg.h> + +typedef struct { int i; } FILE; +FILE *fp; +extern int vfprintf (FILE *, const char *, va_list); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9, via; + +void +test (va_list ap1, va_list ap2, va_list ap3, va_list ap4, va_list ap5, + va_list ap6, va_list ap7) +{ + vi0 = 0; + vfprintf (fp, "hello", ap1); + vi1 = 0; + vfprintf (fp, "hello\n", ap2); + vi2 = 0; + vfprintf (fp, "a", ap3); + vi3 = 0; + vfprintf (fp, "", ap4); + vi4 = 0; + vfprintf (fp, "%s", ap5); + vi5 = 0; + vfprintf (fp, "%c", ap6); + vi6 = 0; + vfprintf (fp, "%s\n", ap7); + vi7 = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*fwrite.*\"hello\".*1, 5, fp.*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*fwrite.*\"hello\\\\n\".*1, 6, fp.*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*fputc.*fp.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*vfprintf.*\"%s\".*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*vfprintf.*\"%c\".*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*vfprintf.*\"%s\\\\n\".*vi7" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-vfprintf-chk-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vfprintf-chk-1.c new file mode 100644 index 000000000..ce767d1a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vfprintf-chk-1.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +#include <stdarg.h> + +typedef struct { int i; } FILE; +FILE *fp; +extern int __vfprintf_chk (FILE *, int, const char *, va_list); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9, via; + +void +test (va_list ap1, va_list ap2, va_list ap3, va_list ap4, va_list ap5, + va_list ap6, va_list ap7) +{ + vi0 = 0; + __vfprintf_chk (fp, 1, "hello", ap1); + vi1 = 0; + __vfprintf_chk (fp, 1, "hello\n", ap2); + vi2 = 0; + __vfprintf_chk (fp, 1, "a", ap3); + vi3 = 0; + __vfprintf_chk (fp, 1, "", ap4); + vi4 = 0; + __vfprintf_chk (fp, 1, "%s", ap5); + vi5 = 0; + __vfprintf_chk (fp, 1, "%c", ap6); + vi6 = 0; + __vfprintf_chk (fp, 1, "%s\n", ap7); + vi7 = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*fwrite.*\"hello\".*1, 5, fp.*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*fwrite.*\"hello\\\\n\".*1, 6, fp.*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*fputc.*fp.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*__vfprintf_chk.*fp.*1.*\"%s\".*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*__vfprintf_chk.*fp.*1.*\"%c\".*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*__vfprintf_chk.*fp.*1.*\"%s\\\\n\".*vi7" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-vprintf-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vprintf-1.c new file mode 100644 index 000000000..416ee5b54 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vprintf-1.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +#include <stdarg.h> + +extern int vprintf (const char *, va_list); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9, via; + +void +test (va_list ap1, va_list ap2, va_list ap3, va_list ap4, va_list ap5, + va_list ap6, va_list ap7) +{ + vi0 = 0; + vprintf ("hello", ap1); + vi1 = 0; + vprintf ("hello\n", ap2); + vi2 = 0; + vprintf ("a", ap3); + vi3 = 0; + vprintf ("", ap4); + vi4 = 0; + vprintf ("%s", ap5); + vi5 = 0; + vprintf ("%c", ap6); + vi6 = 0; + vprintf ("%s\n", ap7); + vi7 = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*vprintf.*\"hello\".*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*puts.*\"hello\".*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*putchar.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*vprintf.*\"%s\".*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*vprintf.*\"%c\".*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*vprintf.*\"%s\\\\n\".*vi7" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/builtin-vprintf-chk-1.c b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vprintf-chk-1.c new file mode 100644 index 000000000..567a3dfd1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/builtin-vprintf-chk-1.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fab" } */ + +#include <stdarg.h> + +extern int __vprintf_chk (int, const char *, va_list); +volatile int vi0, vi1, vi2, vi3, vi4, vi5, vi6, vi7, vi8, vi9, via; + +void +test (va_list ap1, va_list ap2, va_list ap3, va_list ap4, va_list ap5, + va_list ap6, va_list ap7) +{ + vi0 = 0; + __vprintf_chk (1, "hello", ap1); + vi1 = 0; + __vprintf_chk (1, "hello\n", ap2); + vi2 = 0; + __vprintf_chk (1, "a", ap3); + vi3 = 0; + __vprintf_chk (1, "", ap4); + vi4 = 0; + __vprintf_chk (1, "%s", ap5); + vi5 = 0; + __vprintf_chk (1, "%c", ap6); + vi6 = 0; + __vprintf_chk (1, "%s\n", ap7); + vi7 = 0; +} + +/* { dg-final { scan-tree-dump "vi0.*__vprintf_chk.*1.*\"hello\".*vi1" "fab"} } */ +/* { dg-final { scan-tree-dump "vi1.*puts.*\"hello\".*vi2" "fab"} } */ +/* { dg-final { scan-tree-dump "vi2.*putchar.*vi3" "fab"} } */ +/* { dg-final { scan-tree-dump "vi3 ={v} 0\[^\(\)\]*vi4 ={v} 0" "fab"} } */ +/* { dg-final { scan-tree-dump "vi4.*__vprintf_chk.*1.*\"%s\".*vi5" "fab"} } */ +/* { dg-final { scan-tree-dump "vi5.*__vprintf_chk.*1.*\"%c\".*vi6" "fab"} } */ +/* { dg-final { scan-tree-dump "vi6.*__vprintf_chk.*1.*\"%s\\\\n\".*vi7" "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cfgcleanup-1.c b/gcc/testsuite/gcc.dg/tree-ssa/cfgcleanup-1.c new file mode 100644 index 000000000..e86a6484e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cfgcleanup-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dce1" } */ +void +cleanup (int a, int b) +{ + if (a) + if (b) + a = 1; + else + b = 1; + else if (a) + a = 1; + else + b = 1; + return; +} +/* Dce should get rid of the initializers and cfgcleanup should elliminate ifs */ +/* { dg-final { scan-tree-dump-times "if " 0 "dce1"} } */ +/* { dg-final { cleanup-tree-dump "dce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/col-1.c b/gcc/testsuite/gcc.dg/tree-ssa/col-1.c new file mode 100644 index 000000000..5838134ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/col-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple-details-lineno" } */ + +void foo (int, int); + +int +m(int x) +{ + int c, a; + a = (c = 5) + 16 + x * 2 ; + foo (c, a); +} + +/* { dg-final { scan-tree-dump-times "10:9.*c = 5" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "10:14.*c . 16" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "10:4.*a =" 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/complex-1.c b/gcc/testsuite/gcc.dg/tree-ssa/complex-1.c new file mode 100644 index 000000000..7c76467f4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/complex-1.c @@ -0,0 +1,13 @@ +/* Verify that we don't libcall for complex * real. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -O -fdump-tree-optimized" } */ + +typedef _Complex float C; + +C foo(C x, float y) +{ + return x * y; +} + +/* { dg-final { scan-tree-dump-times "__mul" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/complex-2.c b/gcc/testsuite/gcc.dg/tree-ssa/complex-2.c new file mode 100644 index 000000000..d2d42b93d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/complex-2.c @@ -0,0 +1,13 @@ +/* Verify that we don't libcall for complex / real. */ +/* { dg-do compile } */ +/* { dg-options "-std=c99 -O -fdump-tree-optimized" } */ + +typedef _Complex float C; + +C foo(C x, float y) +{ + return x / y; +} + +/* { dg-final { scan-tree-dump-times "__div" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/complex-3.c b/gcc/testsuite/gcc.dg/tree-ssa/complex-3.c new file mode 100644 index 000000000..5f4b110c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/complex-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +typedef _Complex float COMPLEX_FLOAT; +float real_part(COMPLEX_FLOAT a) +{ + return *(float*)(&a); +} + +float real_part_2(COMPLEX_FLOAT a) +{ + return ((float*)(&a))[0]; +} + + +float imag_part(COMPLEX_FLOAT a) +{ + return ((float*)(&a))[1]; +} + +/* Test that the above gets optimized to REALPART_EXPR and IMAGPART_EXPR + respectively. */ + +/* { dg-final { scan-tree-dump-times "REALPART_EXPR" 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "IMAGPART_EXPR" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/complex-4.c b/gcc/testsuite/gcc.dg/tree-ssa/complex-4.c new file mode 100644 index 000000000..fa2ad5816 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/complex-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int g(_Complex int*); +int f(void) +{ + _Complex int t = 0; + int i, j; + __real__ t += 2; + __imag__ t += 2; + return g(&t); +} + +/* { dg-final { scan-tree-dump-times "__complex__" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/complex-5.c b/gcc/testsuite/gcc.dg/tree-ssa/complex-5.c new file mode 100644 index 000000000..dec394a5f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/complex-5.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-tree-dce -fdump-tree-optimized" } */ +_Complex int t = 0; +int f(void) +{ + t = 0; + __real__ t = 2; + __imag__ t = 2; +} + +/* { dg-final { scan-tree-dump-times "__complex__" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/copy-headers.c b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers.c new file mode 100644 index 000000000..474633eab --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/copy-headers.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ch-details" } */ + +extern int foo (int); + +void bla (void) +{ + int i, n = foo (0); + + for (i = 0; i < n; i++) + foo (i); +} + +/* There should be a header duplicated. */ +/* { dg-final { scan-tree-dump-times "Duplicating header" 1 "ch"} } */ +/* { dg-final { cleanup-tree-dump "ch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c b/gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c new file mode 100644 index 000000000..ec1d28fe3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cswtch-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-switchconv" } */ + +typedef enum { a = 5, b = 6, c = 7, d = 8, e = 9 } X; + +int h1 (X x) +{ + switch (x) { + case a: + case b: + case c: + case d: + case e: + return 1; + default: + return 0; + } +} + +/* { dg-final { scan-tree-dump-times "CSWTCH" 0 "switchconv" } } */ +/* { dg-final { cleanup-tree-dump "switchconv" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/cswtch.c b/gcc/testsuite/gcc.dg/tree-ssa/cswtch.c new file mode 100644 index 000000000..06710f217 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/cswtch.c @@ -0,0 +1,81 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-switchconv" } */ +/* { dg-do run } */ + +extern void abort (void); + +static int X, Y; + +int check(int param) +{ + int a = 0; + int b = 1; + + switch (param) + { + case -2: + a = 0; + b = -1; + break; + case 1: + case 2: + a = 8; + b = 6; + break; + case 3: + a = 9; + b = 5; + break; + case 6: + a = 10; + b = 4; + break; + default: + a = 16; + b = 1; + } + + X = a; + Y = b; + return 0; +} + +void assertions(int a, int b) +{ + if (X != a || Y != b) + abort(); + + return; +} + +int main () +{ + check (-10); + assertions (16, 1); + + check (-2); + assertions (0, -1); + + check(1); + assertions (8, 6); + + check(2); + assertions (8, 6); + + check(3); + assertions (9, 5); + + check(5); + assertions (16, 1); + + check(6); + assertions (10, 4); + + check(12); + assertions (16, 1); + + return 0; +} + +/* { dg-final { scan-tree-dump "Switch converted" "switchconv" } } */ +/* { dg-final { cleanup-tree-dump "switchconv" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dce-1.c b/gcc/testsuite/gcc.dg/tree-ssa/dce-1.c new file mode 100644 index 000000000..12612e546 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/dce-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce1" } */ +int foo (int b, int j) +{ + if (b) + { + int i; + for (i = 0; i<1000; ++i) + ; + j = 0; + } + return j; +} +/* Check that empty loop is eliminated in this case. We should no longer have + the exit condition after the loop. */ +/* { dg-final { scan-tree-dump-not "999" "cddce1"} } */ +/* { dg-final { scan-tree-dump-not "1000" "cddce1"} } */ +/* { dg-final { cleanup-tree-dump "cddce1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/divide-1.c b/gcc/testsuite/gcc.dg/tree-ssa/divide-1.c new file mode 100644 index 000000000..66bc3745b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/divide-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */ + +int f(int a) +{ + return (-a)/10; +} + + +/* { dg-final { scan-tree-dump-times "-a" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "a_..D. / -10" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/divide-2.c b/gcc/testsuite/gcc.dg/tree-ssa/divide-2.c new file mode 100644 index 000000000..6cd86b21f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/divide-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */ + +int f(int a) +{ + return 10/-a; +} + + +/* { dg-final { scan-tree-dump-times "10 / -a" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "-10 / a" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/divide-3.c b/gcc/testsuite/gcc.dg/tree-ssa/divide-3.c new file mode 100644 index 000000000..12fa09b95 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/divide-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */ + +int f(int a) +{ + return -(a/10); +} + +/* { dg-final { scan-tree-dump-times "a_\[0-9()D\]* / 10" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "a_..D. / -10" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/divide-4.c b/gcc/testsuite/gcc.dg/tree-ssa/divide-4.c new file mode 100644 index 000000000..734acad69 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/divide-4.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fstrict-overflow -fdump-tree-optimized" } */ + +int f(int a) +{ + return -(-a/10); +} + +/* { dg-final { scan-tree-dump-times "-a" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "a_..D. / 10" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/dump-1.c b/gcc/testsuite/gcc.dg/tree-ssa/dump-1.c new file mode 100644 index 000000000..382f3231b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/dump-1.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-profile-details" } */ + +int f(void) +{ + return 0; +} + +/* { dg-final { cleanup-tree-dump "profile" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/flatten-1.c b/gcc/testsuite/gcc.dg/tree-ssa/flatten-1.c new file mode 100644 index 000000000..2eb41e5b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/flatten-1.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options -O2 } */ + +/* Basic tests for flatten attribute, check we end up + with only the flattened function bodies. */ + +static int foobar(int i); +static int bar(int i); + +int __attribute__((flatten)) leaf0a(int i) +{ + return bar(i); +} +int __attribute__((flatten)) leaf0b(int i) +{ + return foobar(i); +} +int __attribute__((flatten)) leaf1(int i) +{ + return bar(foobar(i)); +} +int __attribute__((flatten)) leaf2(int i) +{ + int j; + j = foobar(i); + return bar(j); +} + +static int foobar(int i) +{ + return i-1; +} +static int bar(int i) +{ + return i + foobar(i); +} + + +static int gloobar(int i) +{ + return i*5+1; +} +static int floobar(int i) +{ + return gloobar(i); +} +int __attribute__((flatten)) leaf3(int i) +{ + int j; + j = floobar(i); + j += floobar(i); + return j; +} + +/* { dg-final { scan-assembler-not "bar\[: \t\n\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/flatten-2.c b/gcc/testsuite/gcc.dg/tree-ssa/flatten-2.c new file mode 100644 index 000000000..ffed23cf4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/flatten-2.c @@ -0,0 +1,85 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-early-inlining" } */ + +extern void do_something_usefull(); +/* Check that we finish compiling even if instructed to + flatten a cyclic callgraph. Verify we correctly + flatten with another function marked flatten in the + callgraph. + + Main inline is cureful about indirect calls giving + precedence to breaking cycle at indirect call sites. + Early inliner can't do similar analysis, so we need + to disable it if we want cycles to be broken consistently. */ + +void __attribute__((flatten)) direct(void) +{ + direct(); +} + + +void __attribute__((flatten)) indirect(void); +static void indirect1(void) +{ + indirect(); +} +void __attribute__((flatten)) indirect(void) +{ + indirect1(); +} + + +void __attribute__((flatten)) doubleindirect(void); +static void doubleindirect2(void) +{ + doubleindirect(); + do_something_usefull (); +} +static void doubleindirect1(void) +{ + doubleindirect2(); +} +void __attribute__((flatten)) doubleindirect(void) +{ + doubleindirect1(); +} + + +static void subcycle1(void); +static void subcycle2(void) +{ + subcycle1(); + do_something_usefull (); +} +static void subcycle1(void) +{ + subcycle2(); +} +void __attribute__((flatten)) subcycle(void) +{ + subcycle1(); +} + + +static void doublesubcycle1(void); +static void doublesubcycle2(void); +static void doublesubcycle3(void) +{ + doublesubcycle1(); + do_something_usefull (); +} +static void doublesubcycle2(void) +{ + doublesubcycle3(); +} +static void doublesubcycle1(void) +{ + doublesubcycle2(); +} +void __attribute__((flatten)) doublesubcycle(void) +{ + doublesubcycle1(); +} + +/* { dg-final { scan-assembler "cycle\[123\]\[: \t\n\]" } } */ +/* { dg-final { scan-assembler-not "indirect\[12\]\[: \t\n\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/flatten-3.c b/gcc/testsuite/gcc.dg/tree-ssa/flatten-3.c new file mode 100644 index 000000000..a1edb910e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/flatten-3.c @@ -0,0 +1,79 @@ +/* { dg-do compile } */ +/* { dg-options -O2 } */ + +extern void do_something_usefull(); +/* Check that we finish compiling even if instructed to + flatten a cyclic callgraph. Verify we correctly + flatten with another function marked flatten in the + callgraph. */ + +void __attribute__((flatten)) direct(void) +{ + direct(); +} + + +void __attribute__((flatten)) indirect(void); +static void indirect1(void) +{ + indirect(); +} +void __attribute__((flatten)) indirect(void) +{ + indirect1(); +} + + +void __attribute__((flatten)) doubleindirect(void); +static void doubleindirect2(void) +{ + doubleindirect(); + do_something_usefull (); +} +static void doubleindirect1(void) +{ + doubleindirect2(); +} +void __attribute__((flatten)) doubleindirect(void) +{ + doubleindirect1(); +} + + +static void subcycle1(void); +static void subcycle2(void) +{ + subcycle1(); + do_something_usefull (); +} +static void subcycle1(void) +{ + subcycle2(); +} +void __attribute__((flatten)) subcycle(void) +{ + subcycle1(); +} + + +static void doublesubcycle1(void); +static void doublesubcycle2(void); +static void doublesubcycle3(void) +{ + doublesubcycle1(); + do_something_usefull (); +} +static void doublesubcycle2(void) +{ + doublesubcycle3(); +} +static void doublesubcycle1(void) +{ + doublesubcycle2(); +} +void __attribute__((flatten)) doublesubcycle(void) +{ + doublesubcycle1(); +} + +/* { dg-final { scan-assembler "cycle\[123\]\[: \t\n\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c b/gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c new file mode 100644 index 000000000..a3c6a2ece --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldaddr-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-original" } */ +#include <stddef.h> + +char *a; +int foo(char *b) +{ + return a+5+(ptrdiff_t)b == (ptrdiff_t)b+a; +} + +/* Folding should have determined that the two addresses were + not identical and thus collapsed the function into a trivial + "return 0". */ +/* { dg-final { scan-tree-dump-times "return 0" 1 "original" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c b/gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c new file mode 100644 index 000000000..08b827c1d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldcast-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-original" } */ + +typedef int ssize_t __attribute__((mode(pointer))); +ssize_t foo (ssize_t x) +{ + return (ssize_t)(char *)x; +} + +char *bar (char *x) +{ + return (char *)(ssize_t)x; +} + +/* { dg-final { scan-tree-dump-times "return x;" 2 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-1.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-1.c new file mode 100644 index 000000000..10414a2a5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +void bar (unsigned int); + +void +foo (void) +{ + char buf[1] = { 3 }; + const char *p = buf; + const char **q = &p; + unsigned int ch; + switch (**q) + { + case 1: ch = 5; break; + case 2: ch = 4; break; + case 3: ch = 3; break; + case 4: ch = 2; break; + case 5: ch = 1; break; + default: ch = 0; break; + } + bar (ch); +} +/* The switch should be switch converted and later constant propagated. */ +/* { dg-final { scan-tree-dump-not "CSWTCH" "optimized"} } */ +/* { dg-final { scan-tree-dump-not "switch" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-2.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-2.c new file mode 100644 index 000000000..0eff197bf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-2.c @@ -0,0 +1,58 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ch" } */ +typedef union tree_node *tree; +enum tree_code +{ + OFFSET_TYPE, ENUMERAL_TYPE, BOOLEAN_TYPE, POINTER_TYPE, FIXED_POINT_TYPE, +}; +struct tree_base +{ + unsigned public_flag:1; +}; +struct tree_decl_with_vis +{ + unsigned comdat_flag:1; +}; +union tree_node +{ + struct tree_base base; + struct tree_decl_with_vis decl_with_vis; +}; +enum tree_index +{ + TI_LONG_DOUBLE_PTR_TYPE, TI_INTEGER_PTR_TYPE, TI_VOID_TYPE, TI_PTR_TYPE, + TI_VA_LIST_FPR_COUNTER_FIELD, TI_BOOLEAN_TYPE, TI_FILEPTR_TYPE, + TI_CURRENT_TARGET_PRAGMA, TI_CURRENT_OPTIMIZE_PRAGMA, TI_MAX +}; +extern tree global_trees[TI_MAX]; +emit_support_tinfos (void) +{ + static tree *const fundamentals[] = { + &global_trees[TI_VOID_TYPE], &global_trees[TI_BOOLEAN_TYPE], + }; + int ix; + for (ix = 0; fundamentals[ix]; ix++) + { + { + tree tinfo; + { + ((void) (!(((tinfo)->base.public_flag) && !(__extension__ ( + { + __typeof + (tinfo) + __t + = + (tinfo); + __t;} + )->decl_with_vis. + comdat_flag)) ? + fancy_abort ("../../gcc/cp/rtti.c", 1529, + __FUNCTION__), 0 : 0)); + } + } + } +} +/* We should copy loop header to fundamentals[0] and then fold it way into + known value. */ +/* { dg-final { scan-tree-dump-not "fundamentals.0" "ch"} } */ +/* { dg-final { cleanup-tree-dump "ch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-3.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-3.c new file mode 100644 index 000000000..613236207 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-3.c @@ -0,0 +1,76 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +typedef const union tree_node *const_tree; +typedef struct +{ +} +double_int; +double_int double_int_zext (double_int, unsigned); +enum tree_code +{ ERROR_MARK, IDENTIFIER_NODE, TREE_LIST, BLOCK, ENUMERAL_TYPE, BOOLEAN_TYPE, + INTEGER_TYPE, ARRAY_TYPE, INTEGER_CST, VAR_DECL, PARM_DECL, RESULT_DECL, + }; +enum tree_code_class +{ tcc_exceptional, tcc_constant, tcc_type, tcc_declaration, tcc_reference, }; +struct tree_base +{ + __extension__ enum tree_code code:16; + unsigned unsigned_flag:1; +}; +struct tree_type +{ + unsigned int precision:10; + union tree_type_symtab + { + } symtab; +}; +union tree_node +{ + struct tree_base base; + struct tree_type type; +}; +const enum tree_code_class tree_code_type[] = +{ tcc_exceptional, 1, 0, 0, 0, 0, 2, }; + +int_fits_type_p (const_tree c, const_tree type) +{ + double_int dc, dd; + { + if (((enum tree_code) (type)->base.code) == INTEGER_TYPE && (( + { + __typeof + (type) __t + = (type); + if + (tree_code_type + [(int) + (((enum + tree_code) + (__t)-> + base. + code))] + != + (tcc_type)) + tree_class_check_failed + (__t, + __FUNCTION__); + __t;})-> + base. + unsigned_flag)) + dd = double_int_zext (dd, (( + { + __typeof (type) __t = (type); + if (tree_code_type + [(int) + (((enum tree_code) (__t)->base. + code))] != + (tcc_type)) + tree_class_check_failed (__t, + __FUNCTION__); + __t;} + )->type.precision)); +} +} +/* The switch should be switch converted and later constant propagated. */ +/* { dg-final { scan-tree-dump-not "tree_code_type" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c new file mode 100644 index 000000000..b416d371e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp2" } */ + +struct a {int a,b;}; +const static struct a a; +static int b[10]; +int c; +test() +{ + return a.a+b[c]; +} +/* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */ +/* { dg-final { cleanup-tree-dump "ccp2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldconst-5.c b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-5.c new file mode 100644 index 000000000..1dad931ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldconst-5.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + + +static const char a[5]="t"; +static const int b[5]={1,2}; +static const struct a {int a : 6; int b : 6;} c = {5,9}; +test() +{ + return a[2]+b[1]+b[3]+c.b; +} +/* { dg-final { scan-tree-dump "return 11;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/foldstring-1.c b/gcc/testsuite/gcc.dg/tree-ssa/foldstring-1.c new file mode 100644 index 000000000..fa64ae14c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/foldstring-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-fre" } */ + +void +arf () +{ + if (""[0] == 0) + blah (); +} +/* { dg-final { scan-tree-dump-times "= 0;" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c new file mode 100644 index 000000000..7b07d7f48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +/* We should be able to optimize this to b->t[i] = 1 during + early optimizations. */ + +struct a +{ + int t[10]; +}; + +void f(struct a * b, __SIZE_TYPE__ i) +{ + int *c = b->t; + c[i] = 1; +} + +/* { dg-final { scan-tree-dump-times "t\\\[i.*\\\].* = 1;" 1 "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-10.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-10.c new file mode 100644 index 000000000..b46b8ece8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-10.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +int b; +unsigned a; + +static inline int *g(void) +{ + a = 1; + return (int*)&a; +} +void test2(void) +{ + b = *g(); +} + +/* The indirect load should be replaced by a load from a and a + conversion to int. FRE should then be able to replace + the rhs of the store to b by 1. */ + +/* { dg-final { scan-tree-dump "Replaced\[^\\n\]*with 1" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-11.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-11.c new file mode 100644 index 000000000..73051ae96 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-11.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +int f(int *p, int n) +{ + int (*a)[n] = (int (*)[n])p; + int *q = &(*a)[0]; + return q[1]; +} + +int g(int *p, int n) +{ + int (*a)[n] = (int (*)[n])p; + int *q = &(*a)[2]; + return q[-1]; +} + +/* { dg-final { scan-tree-dump-times "= \\\(\\\*a_..\\\)\\\[1\\\];" 2 "forwprop1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c new file mode 100644 index 000000000..1c5ea02ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-12.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +struct X { int a[256]; }; + +int foo(struct X *p, __SIZE_TYPE__ i) +{ + int *q = &p->a[0]; + int *q2 = (int *)((void *)q + i*4 + 32); + return *q2; +} + +int bar(struct X *p, int i) +{ + return *((int *)p + i + 8); +} + +/* We should have propagated the base array address through the + address arithmetic into the memory access as an array access. */ + +/* { dg-final { scan-tree-dump-times "->a\\\[D\\\." 2 "forwprop1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c new file mode 100644 index 000000000..2aefb9ace --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-2.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +/* We should be able to optimize this to b->t[i] = 1 during + early optimizations. */ + +struct a +{ + char t[10]; +}; + +struct a *b; + +void f(__SIZE_TYPE__ i) +{ + char *c = b->t; + c[i] = 1; +} + +/* { dg-final { scan-tree-dump-times "t\\\[i.*\\\].* = 1;" 1 "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop?" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-3.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-3.c new file mode 100644 index 000000000..dbb6e420e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1" } */ + +struct bar { + int a[2]; +}; + +int foo(struct bar *x) +{ + int *p = &x->a[0]; + int *q = &x->a[1]; + if (p < q) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump "Replaced .p_. < q_.. with .1." "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-4.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-4.c new file mode 100644 index 000000000..7eabd1a7b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +/* We should be able to fold the comparison at least with the + first forwprop pass, if not a ccp pass before. */ + +extern void link_error (void); +void foo() +{ + int i; + char *p = (char *)&i; + long *q = (long *)p; + if (q == 0) + link_error (); +} + +/* { dg-final { scan-tree-dump-not "link_error" "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c new file mode 100644 index 000000000..033c60dae --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-5.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized -w" } */ +/* { dg-options "-O1 -fdump-tree-optimized -w -msse" { target { i?86-*-* x86_64-*-* } } } */ + +#define vector __attribute__((vector_size(16) )) +struct VecClass +{ + vector float v; +}; + +vector float foo( vector float v ) +{ + vector float x = v; + x = x + x; + struct VecClass disappear = *(struct VecClass*)&x; + return disappear.v; +} + +/* { dg-final { scan-tree-dump-times "disappear" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-6.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-6.c new file mode 100644 index 000000000..54e51097e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-6.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-forwprop1 -W -Wall" } */ +#if (__SIZEOF_INT__ == __SIZEOF_FLOAT__) +typedef int intflt; +#elif (__SIZEOF_LONG__ == __SIZEOF_FLOAT__) +typedef long intflt; +#else +#error Add target support here for type that will union float size +#endif + +intflt b; +void f(void) +{ + float a; + a = 1; + b = *(intflt*)&a; /* { dg-warning "aliasing" } */ +} + +/* We should be able to convert the cast to a VCE in forwprop1, + even if there is an aliasing violation. + ??? While this would be useful and nice to our users in this + particular situation before doing this transformation we have to + assure that a is killed by a dominating store via type float for + it to be valid. Then we might as well handle the situation by + value-numbering, removing the load alltogether. */ +/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 1 "forwprop1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c new file mode 100644 index 000000000..0d2bac521 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-7.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-forwprop1 -W -Wall" } */ + +int i; +int foo(void) +{ + volatile int *p = (volatile int *)&i; + return *p + *p; +} + +/* We should not convert the cast to a VCE in forwprop1 as we have a + volatile reference. */ + +/* { dg-final { scan-tree-dump-times "VIEW_CONVERT_EXPR" 0 "forwprop1"} } */ +/* { dg-final { scan-tree-dump-times "={v}" 2 "forwprop1"} } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c new file mode 100644 index 000000000..fc7429724 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-8.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-forwprop1 -W -Wall" } */ + + +struct X { int a[5]; }; +int foo(struct X *q) +{ + int (*pointer)[5] = &q->a; + return (*pointer)[0]; +} + + +/* We should have propragated &q->a into (*pointer). */ +/* { dg-final { scan-tree-dump-times "pointer" 0 "forwprop1"} } */ +/* { dg-final { scan-tree-dump "\\\[0\\\]" "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/forwprop-9.c b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-9.c new file mode 100644 index 000000000..cc583e293 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/forwprop-9.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-fre -W -Wall -fno-early-inlining" } */ + +int b; +unsigned a; +static inline int *g(void) +{ + a = 1; + return (int*)&a; +} +void f(void) +{ + b = *g(); +} + +/* We should have converted the assignments to two = 1. FRE does this. */ + +/* { dg-final { scan-tree-dump-times " = 1" 2 "optimized"} } */ +/* { dg-final { scan-tree-dump-not " = a;" "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/fre-vce-1.c b/gcc/testsuite/gcc.dg/tree-ssa/fre-vce-1.c new file mode 100644 index 000000000..599d1f1ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/fre-vce-1.c @@ -0,0 +1,37 @@ +/* { dg-options "-O2 -fdump-tree-fre -w" } */ +/* { dg-options "-O2 -fdump-tree-fre -w -msse" { target { i?86-*-* x86_64-*-* } } } */ +/* { dg-do compile } */ +#define vector __attribute__((vector_size(sizeof(int)*4) )) +struct s { vector int i; }; +vector float f(struct s *sv) +{ + sv->i = (vector int){1, 2, 3, 4}; + return (vector float)sv->i; +} + + +vector float f1(struct s *sv, vector int a) +{ + sv->i = a; + return (vector float)sv->i; +} + +struct s1 { int i; }; + +void g(struct s1 *, float); +void a1 (struct s1 sv) +{ + sv.i = 1; + g(&sv, *(float*)&sv.i); +} + + +void a2 (struct s1 sv, int i) +{ + sv.i = i; + g(&sv, *(float*)&sv.i); +} + +/* { dg-final { scan-tree-dump-times "sv_\[0-9\]\\\(D\\\)->i" 2 "fre" } } */ +/* { dg-final { scan-tree-dump-times "sv.i" 2 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c new file mode 100644 index 000000000..91a3f56a6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11.c @@ -0,0 +1,34 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fwrapv -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fwrapv -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 16 + +char ic[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; +char ib[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + +int main () +{ + int i; + char ia[N]; + + for (i = 0; i < N; i++) + { + ia[i] = ib[i] + ic[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ia[i] != ib[i] + ic[i]) + abort (); + } + + return 0; +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c new file mode 100644 index 000000000..69eb6303f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11a.c @@ -0,0 +1,42 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 16 + +#if __INT_MAX__ == 32767 +typedef char half_word; +#elif __LONG_MAX__ == 2147483647 +typedef short half_word; +#else +typedef int half_word; +#endif + +half_word ic[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; +half_word ib[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + +int main () +{ + int i; + half_word ia[N]; + + for (i = 0; i < N; i++) + { + ia[i] = ib[i] & ic[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ia[i] != (ib[i] & ic[i])) + abort (); + } + + return 0; +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11b.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11b.c new file mode 100644 index 000000000..33788134e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11b.c @@ -0,0 +1,34 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 16 + +int main () +{ + int i; + char ia[N]; + char ic[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + char ib[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + + /* Not vectorizable, multiplication */ + for (i = 0; i < N; i++) + { + ia[i] = ib[i] * ic[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ia[i] != (char) (ib[i] * ic[i])) + abort (); + } + + return 0; +} + + +/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11c.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11c.c new file mode 100644 index 000000000..ec71c62a7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-11c.c @@ -0,0 +1,40 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=3 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 16 + +#if LONG_MAX == 2147483647 +typedef short half_word; +#else +typedef int half_word; +#endif + +int main () +{ + int i; + half_word ia[N]; + half_word ic[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + half_word ib[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + + /* Not worthwhile, only 2 parts per int */ + for (i = 0; i < N; i++) + { + ia[i] = ib[i] + ic[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ia[i] != ib[i] + ic[i]) + abort (); + } + + return 0; +} + + +/* { dg-final { scan-tree-dump-times "vectorized 0 loops" 1 "vect" } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c new file mode 100644 index 000000000..d74ebaf27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-2.c @@ -0,0 +1,41 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 16 + +#if __INT_MAX__ == 32767 +typedef char half_word; +#elif __LONG_MAX__ == 2147483647 +typedef short half_word; +#else +typedef int half_word; +#endif + +half_word cb[N] = {0,3,6,9,12,15,18,21,24,27,30,33,36,39,42,45}; + +int main () +{ + half_word ca[N]; + int i; + + for (i = 0; i < N; i++) + { + ca[i] = cb[i]; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ca[i] != cb[i]) + abort (); + } + + return 0; +} + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c new file mode 100644 index 000000000..b2796c1b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-25.c @@ -0,0 +1,59 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 128 + +#if __LONG_MAX__ == 2147483647 +typedef short half_word; +#else +typedef int half_word; +#endif + +int main_1 (int n, int *p) +{ + int i; + half_word ib[N]; + half_word ia[N]; + int k; + + for (i = 0; i < N; i++) + { + ia[i] = n; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ia[i] != n) + abort (); + } + + k = *p; + for (i = 0; i < N; i++) + { + ib[i] = k; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ib[i] != k) + abort (); + } + + return 0; +} + +static volatile int n = 1; + +int main (void) +{ + return main_1 (n + 2, (int *) &n); +} + +/* { dg-final { scan-tree-dump-times "vectorized 2 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c new file mode 100644 index 000000000..954e24c92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-26.c @@ -0,0 +1,35 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 128 + +/* unaligned store. */ + +int main () +{ + int i; + char ia[N+1]; + + for (i = 1; i <= N; i++) + { + ia[i] = 5; + } + + /* check results: */ + for (i = 1; i <= N; i++) + { + if (ia[i] != 5) + abort (); + } + + return 0; +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c new file mode 100644 index 000000000..abe07cae7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-28.c @@ -0,0 +1,43 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 128 +#define OFF 3 + +/* unaligned store. */ + +int main_1 (int off) +{ + int i; + char ia[N+OFF]; + + for (i = 0; i < N; i++) + { + ia[i+off] = 5; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (ia[i+off] != 5) + abort (); + } + + return 0; +} + +static volatile int off = 1; + +int main (void) +{ + return main_1 (off); +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Alignment of access forced using peeling" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c new file mode 100644 index 000000000..0a862ab89 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-32.c @@ -0,0 +1,34 @@ +/* { dg-do run { target vect_cmdline_needed } } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats" } */ +/* { dg-options "-O2 -ftree-vectorize -ftree-vectorizer-verbose=4 -fdump-tree-vect-stats -mno-sse" { target { i?86-*-* x86_64-*-* } } } */ + +#include <stdlib.h> + +#define N 16 + +int main () +{ + struct { + char ca[N]; + } s; + int i; + + for (i = 0; i < N; i++) + { + s.ca[i] = 5; + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (s.ca[i] != 5) + abort (); + } + + return 0; +} + + +/* { dg-final { scan-tree-dump-times "vectorized 1 loops" 1 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Vectorizing an unaligned access" 0 "vect" { target { ! avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vect" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-33.c b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-33.c new file mode 100644 index 000000000..8cd12da3d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/gen-vect-33.c @@ -0,0 +1,14 @@ +/* Compiler generates 64-bit stores of zero for this on some targets. + Check there is no problem for such case. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +void +foo (float *dest, int xcount, int ycount) +{ + int x, y; + + for (y = 0; y < ycount; y++) + for (x = 0; x < xcount; x++) + dest[x + y] = (float) 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c new file mode 100644 index 000000000..e7b13b540 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-1.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize -fdump-tree-ifcvt-stats" { target *-*-* } } */ + +#include <stdarg.h> + +#define N 16 +#define MAX 42 + +int A[N] = {36,39,42,45,43,32,21,12,23,34,45,56,67,78,89,11}; + +extern void abort(void); + +int main1 () +{ + int i, j; + + for (i = 0; i < N; i++) + { + j = A[i]; + A[i] = ( j >= MAX ? MAX : 0); + } + + /* check results: */ + for (i = 0; i < N; i++) + { + if (A[i] > MAX) + abort (); + } + + return 0; +} + + + +/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */ +/* { dg-final { cleanup-tree-dump "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-2.c new file mode 100644 index 000000000..f37a4d336 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-20040816-2.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize -fdump-tree-ifcvt-stats" { target *-*-* } } */ + +void foo(const int * __restrict__ zr_in, + const int * __restrict__ zi_in, + const int * __restrict__ zk_in, + int * __restrict__ zr_out, + int * __restrict__ zi_out, + int * __restrict__ zk_out, + int cr, int ci) +{ + unsigned int pi; + int tmp_r, tmp_i, tmp_k; +#if __SIZEOF_INT__ >= 4 + for (pi = 0; pi < (512)*(512); pi++) { +#else + for (pi = 0; pi < (32)*(32); pi++) { +#endif + int zr = zr_in[pi]; + int zi = zi_in[pi]; + int zk = zk_in[pi]; + + if (zr*zr + zi*zi >= 4) { + tmp_r = zr; + tmp_i = zi; + tmp_k = zk; + } else { + tmp_r = (zr*zr - zi*zi + cr); + tmp_i = (2 * zr * zi + ci); + tmp_k = zk + 1; + } + zr_out[pi] = tmp_r; + zi_out[pi] = tmp_i; + zk_out[pi] = tmp_k; + } +} + + +/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */ +/* { dg-final { cleanup-tree-dump "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-3.c new file mode 100644 index 000000000..e853ec4df --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-3.c @@ -0,0 +1,12 @@ +/* PR 20994 */ +/* { dg-do compile } */ +int foo(double* p, double* q) +{ + int i=0; + + for (; q!=p; ++q) + if (*q) + ++i; + + return i; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-4.c new file mode 100644 index 000000000..beb1a0e60 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-4.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize -fdump-tree-ifcvt-stats" { target *-*-* } } */ + +struct ht +{ + void * (*alloc_subobject) (int); +}; +typedef struct cpp_reader cpp_reader; +typedef struct cpp_token cpp_token; +typedef struct cpp_macro cpp_macro; +enum cpp_ttype +{ + CPP_PASTE, +}; +struct cpp_token { + __extension__ enum cpp_ttype type : 8; +} cpp_comment_table; +struct cpp_macro { + union cpp_macro_u + { + cpp_token * tokens; + } exp; + unsigned int count; +}; +struct cpp_reader +{ + struct ht *hash_table; +}; +create_iso_definition (cpp_reader *pfile, cpp_macro *macro) +{ + unsigned int num_extra_tokens = 0; + { + cpp_token *tokns = + (cpp_token *) pfile->hash_table->alloc_subobject (sizeof (cpp_token) + * macro->count); + { + cpp_token *normal_dest = tokns; + cpp_token *extra_dest = tokns + macro->count - num_extra_tokens; + unsigned int i; + for (i = 0; i < macro->count; i++) + { + if (macro->exp.tokens[i].type == CPP_PASTE) + *extra_dest++ = macro->exp.tokens[i]; + else + *normal_dest++ = macro->exp.tokens[i]; + } + } + } +} + +/* This cannot be if-converted because the stores are to aggregate types. */ +/* { dg-final { scan-tree-dump-times "Applying if-conversion" 0 "ifcvt" } } */ +/* { dg-final { cleanup-tree-dump "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-5.c new file mode 100644 index 000000000..a9cc8168e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-5.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize -fdump-tree-ifcvt-stats" { target *-*-* } } */ + +void +dct_unquantize_h263_inter_c (short *block, int n, int qscale, int nCoeffs) +{ + int i, level, qmul, qadd; + + qadd = (qscale - 1) | 1; + qmul = qscale << 1; + + for (i = 0; i <= nCoeffs; i++) + { + level = block[i]; + if (level < 0) + level = level * qmul - qadd; + else + level = level * qmul + qadd; + block[i] = level; + } +} + +/* { dg-final { scan-tree-dump-times "Applying if-conversion" 1 "ifcvt" } } */ +/* { dg-final { cleanup-tree-dump "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-6.c new file mode 100644 index 000000000..a9c5db387 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-6.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize" { target *-*-* } } */ + +static int x; +foo (int n, int *A) +{ + int i; + for (i = 0; i < n; i++) + { + if (A[i]) + x = 2; + if (A[i + 1]) + x = 1; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-7.c new file mode 100644 index 000000000..4d26dc765 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-7.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize" { target *-*-* } } */ + +typedef struct eqn_d +{ + int *coef; +} *eqn; +typedef struct omega_pb_d +{ + eqn subs; +} *omega_pb; + +omega_pb omega_solve_problem (omega_pb); + +omega_pb +omega_solve_geq (omega_pb pb, int n) +{ + int i, e; + int j = 0; + + for (e = n - 1; e >= 0; e--) + if (pb->subs[e].coef[i] != pb->subs[e].coef[j]) + { + pb->subs[e].coef[i] = j; + pb->subs[e].coef[j] = i; + } + + return omega_solve_problem (pb); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr44710.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr44710.c new file mode 100644 index 000000000..d4a1be8f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr44710.c @@ -0,0 +1,44 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O2 -ftree-vectorize" { target *-*-* } } */ + +#include <stdio.h> +#include <stdlib.h> + +#define N 64 +float arr[N]; + +__attribute__ ((noinline)) +int foo (unsigned int n, float *min) +{ + unsigned int pos = 1; + unsigned int i; + float limit = N+N; + + for (i = 0; i < N; i++) + if (arr[i] < limit) + { + pos = i + 1; + limit = arr[i]; + } + + *min = limit; + return pos; +} + +int main (void) +{ + int i, pos; + float min; + + for (i = 0; i < N; i++) + arr[i] = (float)(i); + + arr[2] = -5.8; + + pos = foo (N, &min); + if (pos != 3 || min != arr[2]) + abort (); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr47271.c b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr47271.c new file mode 100644 index 000000000..bf3607946 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ifc-pr47271.c @@ -0,0 +1,49 @@ +/* { dg-options "-O3" } */ +/* { dg-do run } */ + +extern void abort (void); + +void func (void) +{ + int i; + int nops; + char *codestr = + "|\000\000Ee\000\000Z\001\000d\000\000Z\002\000d\025\000Z\003\000" + "\t\t\t\t\t\t\t\t\t\t\t\td\026\000Z\004\000d\005\000\204\000\000Z" + "\005\000e\006\000e\a\000j\005\000e\b\000d\006\000\204\002\000\203" + "\001\000Z\t\000d\a\000\204\000\000Z\n\000d\b\000\204\000\000Z\v\000d" + "\t\000\204\000\000Z\f\000d\n\000\204\000\000Z\r\000e\016\000e\017\000d" + "\v\000\203\001\000d\f\000d\r\000\203\001\001Z\020\000e\016\000e\017" + "\000d\016\000\203\001\000d\f\000d\017\000\203\001\001Z\021\000e\016" + "\000e\017\000d\020\000\203\001\000d\f\000d\021\000\203\001\001Z\022" + "\000e\016\000e\017\000d\022\000\203\001\000d\f\000d\023\000\203\001" + "\001Z\023\000d\024\000S"; + int codelen = 209; + int addrmap[500]; + + for (i=0, nops=0 ; i<codelen ; i += ((codestr[i] >= 90) ? 3 : 1)) + { + addrmap[i] = i - nops; + if (codestr[i] == 9) + nops++; + } + + if (addrmap[0] != 0 + || addrmap[3] != 3 + || addrmap[4] != 4 + || addrmap[7] != 7 + || addrmap[10] != 10 + || addrmap[13] != 13 + || addrmap[16] != 16 + || addrmap[19] != 19 + || addrmap[22] != 22 + || addrmap[23] != 22 + || addrmap[24] != 22) + abort (); +} + +int main () +{ + func (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-1.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-1.c new file mode 100644 index 000000000..030181404 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-1.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + +typedef struct { + double min; + double max; +} interval; +inline interval add(interval x, interval y) __attribute__((always_inline)); +inline interval add(interval x, interval y) +{ + interval r; + r.min = x.min + y.min; + r.max = x.max + y.max; + return r; +} +interval foo (interval a, interval b, interval c) +{ + return add (a, add (b, c)); +} + + +/* { dg-final { scan-tree-dump-times "\\(struct interval\\)" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-2.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-2.c new file mode 100644 index 000000000..72b61c369 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-2.c @@ -0,0 +1,17 @@ +/* { dg-do link } */ +/* { dg-options "-O" } */ + +/* When optimized we expect the call to foo () in bar to be inlined + and the call to link_error optimized away. */ + +extern void link_error (void); +inline int __attribute__((always_inline)) foo(void) { return 0; } + +int main() +{ + int (*fn)(void) = foo; + if (fn()) + link_error (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c new file mode 100644 index 000000000..ff140ed54 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-3.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-einline" } */ +/* { dg-add-options bind_pic_locally } */ + +extern void inlined (); +void inline_me_too (void); +void inline_through_me (void (*ptr)(void)); +void +inline_me (void) +{ + inlined(); +} + +void main(void) +{ + inline_through_me (inline_me); + inline_through_me (inline_me_too); +} +void +inline_through_me (void (*ptr)(void)) +{ + ptr(); +} + +void +inline_me_too (void) +{ + inlined(); +} +/* { dg-final { scan-tree-dump-times "Inlining inline_me " 1 "einline"} } */ +/* { dg-final { scan-tree-dump-times "Inlining inline_me_too " 1 "einline"} } */ +/* { dg-final { cleanup-tree-dump "einline" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-4.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-4.c new file mode 100644 index 000000000..1e700ef02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-4.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-einline" } */ +/* { dg-add-options bind_pic_locally } */ + +extern int rand(void); + +int get_data_for (int id) +{ + return rand(); +} + +int my_id; + +int main() +{ + int res = get_data_for (my_id); + switch (res) + { + case 0: + return 666; + default: + return -1; + } +} + +/* { dg-final { scan-tree-dump "Inlining get_data_for into main" "einline" } } */ +/* { dg-final { cleanup-tree-dump "einline" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-5.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-5.c new file mode 100644 index 000000000..1a6faf4c5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-5.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -fdump-tree-optimized" } */ +struct a {int a,b,c,d,e,f;}; + +do_inc (struct a *a) +{ + a->a=a->b; + a->b=a->c; + a->c=a->d; + a->e=a->f; +} + +test(struct a *a) +{ + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); +} +/* { dg-final { scan-tree-dump-times "do_inc" 12 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-6.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-6.c new file mode 100644 index 000000000..ae6c41f5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-6.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -fdump-tree-optimized" } */ +struct a {int a,b,c,d,e,f,g,h,i,j;}; + +do_inc (struct a *a) +{ + a->a=1; + a->b=2; + a->c=3; + a->e=4; + a->f=5; + a->g=5; + a->h=5; + a->i=5; + a->j=5; +} + +test(struct a *a) +{ + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); + do_inc (a); + do_something (a); +} +/* { dg-final { scan-tree-dump-times "do_inc" 12 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline-7.c b/gcc/testsuite/gcc.dg/tree-ssa/inline-7.c new file mode 100644 index 000000000..16c3c86bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline-7.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-einline" } */ + +void foo0(); +inline void bar0() { foo0(); } +void foobar() { bar0(); bar0(); bar0(); } + +/* { dg-final { scan-tree-dump "Iterations: 1" "einline" } } */ +/* { dg-final { cleanup-tree-dump "einline" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline_asm-1.c b/gcc/testsuite/gcc.dg/tree-ssa/inline_asm-1.c new file mode 100644 index 000000000..0c84ed3fa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline_asm-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-alias-vops" } */ +/* Test to make sure that inline-asm causes a VDEF and that we call test_function twice. */ + +char test_function(void ) __attribute__((__pure__)); +char f(char *a) +{ + char b = test_function(); + asm("":"=m"(*a):"r"(b)); + b = test_function(); + return b; +} + +/* test_function should be called twice as the inline-asm changes memory. */ +/* { dg-final { scan-tree-dump-times "test_function" 2 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +/* There should a VDEF for the inline-asm. */ +/* { dg-final { scan-tree-dump-times "VDEF" 1 "alias"} } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/inline_asm-2.c b/gcc/testsuite/gcc.dg/tree-ssa/inline_asm-2.c new file mode 100644 index 000000000..6b347c41e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/inline_asm-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-alias-vops" } */ +/* Test to make sure that inline-asm causes a VDEF. */ + + +void link_error(); +void f(char *a) +{ + int *a1 = (int *)a; + if (*a == 0) + asm("":"=m"(*a1)); + if (*a == 0) + link_error (); +} + +/* There should a VDEF for the inline-asm and one for the link_error. */ +/* { dg-final { scan-tree-dump-times "VDEF" 2 "alias"} } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-cp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-cp-1.c new file mode 100644 index 000000000..7918eb756 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-cp-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-optimized -fno-inline" } */ +/* { dg-add-options bind_pic_locally } */ + +int +very_long_function(int a) +{ + return very_long_function (a)/4; +} +main() +{ + very_long_function (1); +} +/* One appereance for dump, one self recursive call and one call from main. */ +/* { dg-final { scan-tree-dump-times "very_long_function.constprop.0 \\(\\)" 3 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-reference-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-reference-1.c new file mode 100644 index 000000000..c15a8b609 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-reference-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static int conststaticvariable; + +int f(void) +{ + return conststaticvariable; +} + +/* There should be no reference to conststaticvariable as we should have + inlined the 0 as IPA reference should have marked the variable as a const + as it is not set in the IR. */ +/* { dg-final { scan-tree-dump-times "conststaticvariable" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-1.c new file mode 100644 index 000000000..a31e8ea7a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-fnsplit" } */ +int test2(a) +{ + if (a<100) + return 1; + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + do_something_big (); + return 0; +} + +test() +{ + test2(10); + test2(20); +} +/* { dg-final { scan-tree-dump-times "Splitting function" 1 "fnsplit"} } */ +/* { dg-final { cleanup-tree-dump "fnsplit" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-2.c new file mode 100644 index 000000000..bbde73d6c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-2.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-fnsplit" } */ +int b; +int c; +int d; +split_me(int a) +{ + int t = 0; + if (d>4) + return; + do + { + long_function (t); + long_function (t); + long_function (t); + long_function (t); + long_function (t); + long_function (t); + make_me_irregular: + long_function (t); + long_function (t); + long_function (t); + long_function (t); + long_function (t); + t=b; + } + while (t); + if (c) + goto make_me_irregular; +} + +main() +{ + split_me (1); + split_me (2); + split_me (3); + split_me (4); + split_me (5); +} +/* { dg-final { scan-tree-dump-times "Splitting function" 1 "fnsplit"} } */ +/* { dg-final { cleanup-tree-dump "fnsplit" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c new file mode 100644 index 000000000..05a37f810 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-3.c @@ -0,0 +1,21 @@ +int baz (void); +static int +foo (int x) +{ + if (__builtin_expect (x <= 0, 0)) + { + __builtin_printf ("foo\n"); + __builtin_printf ("foo\n"); + __builtin_printf ("foo\n"); + __builtin_abort (); + } + return 6; +} + +int a,b,c; + +int +bar (int x) +{ + return foo (a) + foo (b) + foo (c); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-4.c new file mode 100644 index 000000000..9d5864bad --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-4.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-fnsplit" } */ +int make_me_big (void); +void abort (void); + +int +split_me (int a) +{ + if (__builtin_expect(a<10, 1)) + { + abort (); + } + else + { + make_me_big (); + make_me_big (); + make_me_big (); + make_me_big (); + return a+1; + } +} + +int +test(void) +{ + return split_me (0)+split_me(1)+split_me(2); +} +/* { dg-final { scan-tree-dump-times "Splitting function" 1 "fnsplit"} } */ +/* { dg-final { cleanup-tree-dump "fnsplit" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c new file mode 100644 index 000000000..bf0714902 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ipa-split-5.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-fnsplit -fdump-tree-optimized" } */ + +struct a {int a,b;}; +struct a make_me_big (int a); +struct a split_me (int a) +{ + struct a retval; + if (__builtin_expect (a!=0,1)) + { + retval.a = 0; + retval.b = 0; + return retval; + } + else + { + struct a retval = make_me_big (a); + retval = make_me_big (a); + retval = make_me_big (a); + retval = make_me_big (a); + retval = make_me_big (a); + retval = make_me_big (a); + return retval; + } +} +int val; +test() +{ + split_me (val); + split_me (val); + split_me (val); + split_me (val); +} +/* { dg-final { scan-tree-dump-times "Splitting function" 1 "fnsplit"} } */ +/* { dg-final { cleanup-tree-dump "fnsplit" } } */ +/* { dg-final { scan-tree-dump "part" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_1.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_1.c new file mode 100644 index 000000000..60baa4bd3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_1.c @@ -0,0 +1,18 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts" } */ +#define TYPE char* + +/* Testing that only one induction variable is selected after IVOPT on + the given target instead of 3. */ +void foo (int i_width, TYPE dst, TYPE src1, TYPE src2) +{ + int x; + for( x = 0; x < i_width; x++ ) + { + dst[x] = ( src1[x] + src2[x] + 1 ) >> 1; + } +} + + +/* { dg-final { scan-tree-dump-times "PHI <ivtmp" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_2.c new file mode 100644 index 000000000..ba87b502c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_2.c @@ -0,0 +1,17 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts" } */ + +#define TYPE char* + +/* Testing on the given target, only one iv candidate instead of 3. */ +void foo (int i_width, TYPE dst, TYPE src1, TYPE src2) +{ + int x; + for( x = 0; x < i_width; x++ ) + { + *dst++ = ( *src1++ + *src2++ + 1 ) >> 1; + } +} + +/* { dg-final { scan-tree-dump-times "PHI <ivtmp" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_3.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_3.c new file mode 100644 index 000000000..ae4185a7a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_3.c @@ -0,0 +1,20 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts" } */ + +#define TYPE char* + +/* Make sure only 1 iv candidate is selected after IVOPT. */ +void foo (int i_width, char* dst, char* src1, char* src2) +{ + int x; + for( x = 0; x < i_width; x++ ) + { + *((TYPE)dst) = ( *((TYPE)src1) + *((TYPE)src2) + 1 ) >> 1; + dst+=sizeof(TYPE); + src1+=sizeof(TYPE); + src2+=sizeof(TYPE); + } +} + +/* { dg-final { scan-tree-dump-times "PHI <ivtmp" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_4.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_4.c new file mode 100644 index 000000000..570664c92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_4.c @@ -0,0 +1,19 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts" } */ + +#ifndef TYPE +#define TYPE char* +#endif + +/* Make sure only 1 iv candidate is selected. */ +void foo (int i_width, TYPE dst, TYPE src1, TYPE src2) +{ + TYPE dstn= dst + i_width; + for( ; dst < dstn; ) + { + *dst++ = ( *src1++ + *src2++ + 1 ) >> 1; + } +} + +/* { dg-final { scan-tree-dump-times "PHI <ivtmp" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_1.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_1.c new file mode 100644 index 000000000..076f5118e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_1.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ + +#ifndef TYPE +#define TYPE char* +#endif + +int a[400]; + +/* Testing inferred loop iteration from array -- exit test can be replaced. */ +void foo (int i_width, TYPE dst, TYPE src1, TYPE src2) +{ + TYPE dstn= dst + i_width; + TYPE dst0 = dst; + unsigned long long i = 0; + for( ; dst <= dstn; ) + { + dst0[i] = ( src1[i] + src2[i] + 1 +a[i]) >> 1; + dst++; + i += 16; + } +} + +/* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c new file mode 100644 index 000000000..4b7e197dd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_infer_2.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ + +#ifndef TYPE +#define TYPE char* +#endif + +extern int a[]; + +/* Can not infer loop iteration from array -- exit test can not be replaced. */ +void foo (int i_width, TYPE dst, TYPE src1, TYPE src2) +{ + TYPE dstn= dst + i_width; + TYPE dst0 = dst; + unsigned long long i = 0; + for( ; dst <= dstn; ) + { + dst0[i] = ( src1[i] + src2[i] + 1 +a[i]) >> 1; + dst++; + i += 16; + } +} + +/* { dg-final { scan-tree-dump-times "Replacing" 0 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1.c new file mode 100644 index 000000000..4e19dfd01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_1.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ + +/* The test 'if (p2 > p_limit2)' can be replaced, so iv p2 can be + * eliminated. */ +long foo(long* p, long* p2, int N1, int N2) +{ + int i = 0; + long* p_limit = p + N1; + long* p_limit2 = p2 + N2; + long s = 0; + while (p <= p_limit) + { + p++; + p2++; + if (p2 > p_limit2) + break; + s += (*p); + } + return s; +} + +/* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2.c new file mode 100644 index 000000000..5e38df67b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_2.c @@ -0,0 +1,25 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ + +/* Exit tests 'i < N1' and 'p2 > p_limit2' can be replaced, so + * two ivs i and p2 can be eliminate. */ +long foo(long* p, long* p2, int N1, int N2) +{ + int i = 0; + long* p_limit2 = p2 + N2; + long s = 0; + while (i < N1) + { + p++; + p2++; + i++; + if (p2 > p_limit2) + break; + s += (*p); + } + + return s; +} + +/* { dg-final { scan-tree-dump-times "Replacing" 2 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c new file mode 100644 index 000000000..dc78a43f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_3.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ + +/* iv p2 can be eliminated. */ +long foo(long* p, long* p2, int N1, int N2) +{ + unsigned long i = 0; + long* p_limit2 = p2 + N2; + long s = 0; + while (i < N1) + { + p2++; + i++; + if (p2 > p_limit2) + break; + s += p[i]; + } + return s; +} + +/* { dg-final { scan-tree-dump-times "Replacing" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_4.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_4.c new file mode 100644 index 000000000..d2aa78d61 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopt_mult_4.c @@ -0,0 +1,25 @@ + +/* { dg-do compile { target {{ i?86-*-* x86_64-*-* } && lp64 } } } */ +/* { dg-options "-O2 -m64 -fdump-tree-ivopts-details" } */ + +/* iv i's step 16 so its period is smaller than the max iterations + * i.e. replacing if (p2 > p_limit2) with testing of i may result in + * overflow. */ +long foo(long* p, long* p2, int N1, int N2) +{ + unsigned long i = 0; + long* p_limit2 = p2 + N2; + long s = 0; + while (i < N1) + { + p2++; + i += 16; + if (p2 > p_limit2) + break; + s += p[i]; + } + return s; +} + +/* { dg-final { scan-tree-dump-times "Replacing" 0 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-1.c new file mode 100644 index 000000000..44f1b628f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ + +/* Not all platforms support TImode integers. */ +#if (defined(__LP64__) && !defined(__hppa__)) || defined(__SPU__) +typedef int TItype __attribute__ ((mode (TI))); +#else +typedef long TItype; +#endif + +TItype last_data_offset ; +int store; +char *data; + +f () +{ + + TItype data_offset = last_data_offset; + char *p; + + for (p = data; *p; p++) + { + data_offset++; + g (data_offset); + store = data_offset + 1; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-2.c new file mode 100644 index 000000000..369f082e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ivopts-details" } */ + +long last_data_offset; +int store; +char *data; + +f () +{ + + long data_offset = last_data_offset; + char *p; + + for (p = data; *p; p++) + { + data_offset++; + g (data_offset); + store = data_offset + 1; + } +} + +/* We should only have two IVs. */ +/* { dg-final { scan-tree-dump-not "\\n candidates \\d+, \\d+,\[^\\n\]*\\n\[^\\n\]*\\nFinal cost" "ivopts" } } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-3.c new file mode 100644 index 000000000..202ad1f4e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-3.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ivopts-details" } */ + +void main (void) +{ + int i; + for (i = 0; i < 10; i++) + f2 (); +} + +/* { dg-final { scan-tree-dump-times "!= 0" 5 "ivopts" } } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ivopts-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-4.c new file mode 100644 index 000000000..908015239 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ivopts-4.c @@ -0,0 +1,8 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ +void foo(int *p, long i, int j) +{ + do { + p[i]++; + } while (i += j); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-1.c new file mode 100644 index 000000000..43c104665 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-1.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +void foo (int * __restrict__ ia, + int * __restrict__ ib, + int * __restrict__ oxa, + int * __restrict__ oxb, + int * __restrict__ oya, + int * __restrict__ oyb) +{ + int i; + long int mya[52]; + long int myb[52]; + + for (i=0; i < 52; i++) + { + mya[i] = ia[i] * oxa[i] + ib[i] * oxb[i]; + myb[i] = -ia[i] * oxb[i] + ib[i] * oxa[i]; + oya[i] = mya[i] >> 10; + oyb[i] = myb[i] >> 10; + } + + /* This loop was distributed, but it is not anymore due to the cost + model changes: the result of a distribution would look like this: + + | for (i=0; i < 52; i++) + | oya[i] = ia[i] * oxa[i] + ib[i] * oxb[i] >> 10; + | + | for (i=0; i < 52; i++) + | oyb[i] = -ia[i] * oxb[i] + ib[i] * oxa[i] >> 10; + + and in this the array IA is read in both tasks. For maximizing + the cache reuse, ldist does not distributes this loop anymore. + */ +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-10.c new file mode 100644 index 000000000..0790c18a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-10.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + int a[1000], b[1000], c[1000]; + + for (i = 1; i < 1000; i ++) + { + a[i] = c[i]; /* S1 */ + b[i] = a[i-1]+1; /* S2 */ + } + /* Dependences: + S1->S2 (flow, level 1) + + One partition as A is used in both S1 and S2. + */ + + return a[1000-2] + b[1000-1] + c[1000-2]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c new file mode 100644 index 000000000..88651e7b7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-11.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +void foo (int * __restrict__ ia, + int * __restrict__ ib, + int * __restrict__ oxa, + int * __restrict__ oxb, + int * __restrict__ oya, + int * __restrict__ oyb) +{ + int i; + long int mya[52]; + long int myb[52]; + + for (i=0; i < 52; i++) + { + mya[i] = ia[i] * oxa[i] + ib[i] * oxb[i]; + myb[i] = -ia[i] * oxb[i] + ib[i] * oxa[i]; + oya[i] = 0; + oyb[i] = myb[i] >> 10; + } + + /* This loop should be distributed, and the result should look like + this: + | memset (oya, 0, 208); + | for (i=0; i < 52; i++) + | oyb[i] = -ia[i] * oxb[i] + ib[i] * oxa[i] >> 10; + */ +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" } } */ +/* { dg-final { scan-tree-dump-times "generated memset zero" 1 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c new file mode 100644 index 000000000..1e555fe26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-12.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int foo (int * __restrict__ ia, + int * __restrict__ ib, + int * __restrict__ oxa, + int * __restrict__ oxb) +{ + int i; + int oya[52], oyb[52]; + + for (i=0; i < 52; i++) + { + oya[i] = (ia[i] * oxa[i]) >> 10; + oyb[i] = (ib[i] * oxb[i]) >> 10; + } + + return oya[22] + oyb[21]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c new file mode 100644 index 000000000..984156954 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-13.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */ + +float * __restrict__ x; +float * __restrict__ y; + +float foo (int n) +{ + int i; + float tmp = 0.0; + for (i = 0; i < n; ++i) + { + x[i] = 0.0; + tmp += y[i]; + } + return tmp; +} + +/* We should apply loop distribution. */ + +/* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c new file mode 100644 index 000000000..700599f1c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-14.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-strict-aliasing -ftree-loop-distribution -fdump-tree-ldist-details" } */ + +struct desc { + int i; + void * __restrict__ data; + int j; +} a, b; + +float foo (int n) +{ + int i; + float * __restrict__ x, * __restrict__ y, tmp = 0.0; + x = (float * __restrict__)a.data; + y = (float * __restrict__)b.data; + for (i = 0; i < n; ++i) + { + x[i] = 0.0; + tmp += y[i]; + } + return tmp; +} + +/* We should apply loop distribution. */ + +/* { dg-final { scan-tree-dump "Loop 1 distributed: split to 2 loops" "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-15.c new file mode 100644 index 000000000..7ce3b956b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-15.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-ldist-details" } */ + +int x[1000]; + +void foo (int n) +{ + int i; + + for (i = 0; i < n; ++i) + { + x[2*i] = 0; + x[2*i + 1] = 1; + } +} + +/* We should not apply loop distribution as it is not beneficial from + a data locality point of view. Also it is not possible to generate + a memset (0) as the write has a stride of 2. */ + +/* { dg-final { scan-tree-dump-not "distributed: split to" "ldist" } } */ +/* { dg-final { scan-tree-dump-not "__builtin_memset" "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c new file mode 100644 index 000000000..61e8e56d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-16.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-ldist-details" } */ + +int x[1000]; + +void foo (int n) +{ + int i; + + for (i = 0; i < n; ++i) + { + x[i] = 0; + x[2*i + 1] = 1; + } +} + +/* We should apply loop distribution and generate a memset (0). */ + +/* { dg-final { scan-tree-dump "distributed: split to 2" "ldist" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_memset" 2 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c new file mode 100644 index 000000000..a831d3c1b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-17.c @@ -0,0 +1,50 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */ + +typedef int mad_fixed_t; +struct mad_pcm +{ + unsigned int samplerate; + unsigned short channels; + unsigned short length; + mad_fixed_t samples[2][1152]; +}; +struct mad_synth +{ + mad_fixed_t filter[2][2][2][16][8]; + unsigned int phase; + struct mad_pcm pcm; +}; +void mad_synth_mute (struct mad_synth *synth); +void +mad_synth_mute (struct mad_synth *synth) +{ + unsigned int ch; + unsigned int s; + unsigned int v; + + ch = 0U; + while (ch < 2U) + { + s = 0U; + while (s < 16U) + { + v = 0U; + while (v < 8U) + { + synth->filter[ch][1][1][s][v] = 0; + synth->filter[ch][1][0][s][v] = 0; + synth->filter[ch][0][1][s][v] = 0; + synth->filter[ch][0][0][s][v] = 0; + v++; + } + s++; + } + ch++; + } + return; +} + +/* { dg-final { scan-tree-dump "distributed: split to 4" "ldist" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_memset" 8 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-1a.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-1a.c new file mode 100644 index 000000000..623aacfdb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-1a.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int foo (int * __restrict__ ia, + int * __restrict__ ib, + int * __restrict__ oxa, + int * __restrict__ oxb) +{ + int i; + int oya[52], oyb[52]; + + for (i=0; i < 52; i++) + { + oya[i] = (ia[i] * oxa[i] + ib[i] * oxb[i]) >> 10; + oyb[i] = (-ia[i] * oxb[i] + ib[i] * oxa[i]) >> 10; + } + + return oya[22] + oyb[21]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-2.c new file mode 100644 index 000000000..de98ccc4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-2.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +void foo (int * __restrict__ a, + int * __restrict__ b, + int * __restrict__ c) +{ + int i; + + for (i=1; i < 10; i++) + { + a[i] += c[i]; + b[i] = a[i - 1] + 1; + } + + /* This loop is not distributed because the cost of spliting it: + + | for (i=1; i < N; i++) + | a[i] += c[i]; + | + | for (i=1; i < N; i++) + | b[i] = a[i - 1] + 1; + + is higher due to data in array A that is written and then read in + another task. The cost model should forbid the transformation in + this case. + */ +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-3.c new file mode 100644 index 000000000..40adfe1a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-3.c @@ -0,0 +1,34 @@ +/* { dg-do compile { target int32plus } } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + int a[10000], b[10000], c[10000], d[10000]; + + a[0] = k; a[3] = k*2; + c[1] = k+1; + for (i = 2; i < (10000-1); i ++) + { + a[i] = k * i; /* S1 */ + b[i] = a[i-2] + k; /* S2 */ + c[i] = b[i] + a[i+1]; /* S3 */ + d[i] = c[i-1] + k + i; /* S4 */ + } + /* + Dependences: + S1 -> S2 (flow, level 1) + S1 -> S3 (anti, level 1) + S2 -> S3 (flow, level 0) + S3 -> S4 (flow, level 1) + + There are three partitions: {S1, S3}, {S2} and {S4}. + + The cost model should fuse together all the partitions, as they + are reusing the same data, ending on a single partition. + */ + return a[10000-2] + b[10000-1] + c[10000-2] + d[10000-2]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 3 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c new file mode 100644 index 000000000..a744fea02 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-4.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + unsigned int j; + int a[100], b[100][100]; + + a[0] = k; + for (i = 1; i < 100; i ++) + { + for (j = 0; j < 100; j++) + { + a[j] = k * i; + b[i][j] = a[j-1] + k; + } + } + + return b[100-1][0]; +} + +/* We used to distribute also innermost loops, but these could produce + too much code in the outer loop, degrading performance of scalar + code. So this test was XFAILed because the cost model of the stand + alone distribution pass has evolved. Now it passes. */ +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" { target ilp32 } } } */ +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" { target lp64 } } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-5.c new file mode 100644 index 000000000..9a03dc171 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-5.c @@ -0,0 +1,33 @@ +/* { dg-do compile { target int32plus } } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + unsigned int j; + int a[100][100], b[100][100], c[100][100], d[100][100]; + + a[0][0] = k; + for (i = 1; i < 100; i ++) + for (j = 1; j < (100-1); j++) + { + a[i][j] = k * i; /* S1 */ + b[i][j] = a[i][j-1] + k; /* S2 */ + c[i][j] = b[i][j] + a[i][j+1]; /* S3 */ + d[i][j] = c[i][j] + k + i; /* S4 */ + } + /* Dependences: + S1->S2 (flow, level 2) + S1->S3 (anti, level 2) + S2->S3 (flow, level 0) + S3->S4 (flow, level 0) + */ + + return a[100-1][100-1] + b[100-1][100-1] + c[100-1][100-1] + d[100-1][100-1]; +} + +/* FIXME: This is XFAILed because of a data dependence analysis + problem: the dependence test fails with a "don't know" relation. */ + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 1 "ldist" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c new file mode 100644 index 000000000..7a38c8683 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-6.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + int a[1000], b[1000], c[1000], d[1000]; + + for (i = 2; i < (1000-1); i ++) { + a[i] = k * i; /* S1 */ + b[i] = a[i-2] + k; /* S2 */ + c[i] = b[i-1] + a[i+1]; /* S3 */ + d[i] = c[i-1] + k + i; /* S4 */ + } + /* Dependences: + S1->S2 (flow, level 1) + S2->S3 (flow, level 1) + S3->S1 (anti, level 1) + S3->S4 (flow, level 1) + + There are two partitions: {S1, S2, S3} and {S4}. + + {S1, S2, S3} have to be in the same partition because: + - S1 (i) has to be executed before S2 (i+2), as S1 produces a[i] that is then consumed 2 iterations later by S2. + - S2 (i) has to be executed before S3 (i+1), as S2 produces b[i] that is then consumed one iteration later by S3, + - S3 (i) has to be executed before S1 (i+1), as a[i+1] has to execute before the update to a[i], + + {S4} is the consumer partition: it consumes the values from array "c" produced in S3. + + The cost model should fuse all the tasks together as the cost of + fetching data from caches is too high. + */ + + return a[1000-2] + b[1000-1] + c[1000-2] + d[1000-2]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-7.c new file mode 100644 index 000000000..124fcdedd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-7.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i, z; + int a[1000], b[1000], c[1000], d[1000]; + + for (i = 2; i < (1000-1); i ++) { + z = a[i+1]; /* S1 */ + a[i] = k * i; /* S2 */ + b[i] = a[i-2] + k; /* S3 */ + c[i] = b[i-1] + z; /* S4 */ + d[i] = c[i-1] + b[i+1] + k + i; /* S5 */ + } + /* Dependences: + S1->S2 (anti, level 1) + S1->S4 (flow, level 1, scalar) + S2->S3 (flow, level 1) + S3->S4 (flow, level 1) + S4->S5 (flow, level 1) + S5->S3 (anti, level 1) + + There is a single partition: {S1, S2, S3, S4, S5}, because of the + scalar dependence z between the two partitions {S1, S2} and {S3, S4, S5}. + */ + + return a[1000-2] + b[1000-1] + c[1000-2] + d[1000-2]; +} + +/* { dg-final { scan-tree-dump-times "distributed" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-8.c new file mode 100644 index 000000000..4a8e06600 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-8.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + int a[1000], b[1000], c[1000], d[1000]; + + for (i = 2; i < (1000-1); i ++) + { + a[i] = k * i; /* S1 */ + b[i] = a[i+1] + k; /* S2 */ + c[i] = a[i-1] + b[i-1] + d[i-1]; /* S3 */ + d[i] = a[i-1] + b[i+1] + k + i; /* S4 */ + } + /* Dependences: + S1->S2 (anti, level 1) + S1->S3 (flow, level 1) + S1->S4 (flow, level 1) + S2->S3 (flow, level 1) + S2->S4 (anti, level 1) + S4->S3 (flow, level 1) + + Two partitions: {S1, S2, S4} produce information that is consumed in {S3}. + + So that means that the current cost model will also fuse these + two partitions into a single one for avoiding cache misses. + */ + + return a[1000-2] + b[1000-1] + c[1000-2] + d[1000-2]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-9.c new file mode 100644 index 000000000..ee8d023de --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-9.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-all" } */ + +int loop1 (int k) +{ + unsigned int i; + int a[1000], b[1000]; + + for (i = 1; i < (1000-1); i ++) { + a[i] = a[i+1] + a[i-1]; /* S1 */ + b[i] = a[i-1] + k; /* S2 */ + } + /* + Dependences: + S1->S2 (flow, level 1) + S1->S1 (anti, level 1) + S1->S1 (flow, level 1) + + One partition, because of the cost of cache misses. + */ + + return a[1000-2] + b[1000-1]; +} + +/* { dg-final { scan-tree-dump-times "distributed: split to 2 loops" 0 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c b/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c new file mode 100644 index 000000000..f0d07cc17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ldist-pr45948.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution -fdump-tree-ldist-details" } */ + +extern void bar(int); + +void +foo (int i, int n) +{ + int a[30]; + int b[30]; + for (; i < n; i++) + a[i] = b[i] = 0; + + while (1) + if (b[0]) + bar (a[i - 1]); +} + +/* We should apply loop distribution and generate 2 memset (0). */ + +/* { dg-final { scan-tree-dump "distributed: split to 2" "ldist" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_memset" 4 "ldist" } } */ +/* { dg-final { cleanup-tree-dump "ldist" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/leaf.c b/gcc/testsuite/gcc.dg/tree-ssa/leaf.c new file mode 100644 index 000000000..936523a93 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/leaf.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +static int local_static; +void __attribute__ ((leaf)) leaf_call (void); + +int +clobber_it (void) +{ + return local_static++; +} +int +test (void) +{ + local_static = 9; + leaf_call (); + return local_static; +} +/* { dg-final { scan-tree-dump-times "return 9" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre1.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre1.c new file mode 100644 index 000000000..ce78f02c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int foo(int *a, int argc) +{ + int c; + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = *a; + if (argc) + { + a = &c; + } + e = *a; + return d + e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre10.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre10.c new file mode 100644 index 000000000..4147a702a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre10.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +struct tree_common +{ + int code; +}; +union tree_node +{ + struct tree_common common; +}; +typedef union tree_node *tree; + +extern tree test (tree, int, int); +extern tree foo (void); +extern void abort (void) __attribute__ ((__noreturn__)); + +/* Redundant loads of expr->common.code */ +tree +test (tree expr, int t, int D17630) +{ + int __i; + +L0: + if (expr->common.code != 142) goto L23; else goto L2; + +L2: + __i = 0; + goto L10; + +L10: + __i = __i + 1; + if (D17630 != __i) goto L8; else goto L19; + +L8: + if (t) goto L15; else goto L10; + +L15: + expr = foo (); + if (expr->common.code != 142) goto L23; else goto L0; + +L19: + abort (); + +L23: + return expr; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre11.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre11.c new file mode 100644 index 000000000..eb6089c4b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre11.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats -fno-tree-cselim" } */ +int *t; +int g(int); +int f(int tt) +{ + int *t1 = t; + if (*t1) + *t1 = 2; + return g(*t1); +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c new file mode 100644 index 000000000..94a3d00bd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre12.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +type *t; +int g(int); +int f(int tt) +{ + type *t1 = t; + if ((*t1)[0]) + (*t1)[0] = 2; + return g((*t1)[0]); +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c new file mode 100644 index 000000000..420ad7162 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre13.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int t[2]; +int g(int); +int f(int tt) +{ + if (t[0]) + t[0] = 2; + return g(t[0]); +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c new file mode 100644 index 000000000..11bfd0060 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre14.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int foo(type *a, int argc) +{ + type c = {0, 1}; + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[0]; + if (argc) + { + a = &c; + } + e = (*a)[0]; + return d + e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c new file mode 100644 index 000000000..b04c7621b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre15.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int foo(type *a, int argc, int t) +{ + type c = {0, 1}; + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[t]; + if (argc) + { + a = &c; + } + e = (*a)[t]; + return d + e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c new file mode 100644 index 000000000..193ae52d5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre16.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int foo(type *a, int argc) +{ + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[0]; + if (argc) + a++; + e = (*a)[0]; + return d + e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c new file mode 100644 index 000000000..ec0f6ec2f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre17.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int foo(type *a, int argc) +{ + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[argc]; + if (argc) + a++; + e = (*a)[argc]; + return d + e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c new file mode 100644 index 000000000..21a1d0670 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre18.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int main(type *a, int argc) +{ + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[argc]; + if (argc) + argc++; + e = (*a)[argc]; + return d + e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c new file mode 100644 index 000000000..0ad8988f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre19.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int foo(type *a, int argc) +{ + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[argc]; + if (!d) + argc++; + e = (*a)[argc]; + return e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre2.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre2.c new file mode 100644 index 000000000..8d6557a9e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int main(int *a, int argc) +{ + int b; + int i; + int d, e; + + /* Should be able to hoist this out of the loop. */ + for (i = 0; i < argc; i++) + { + e = *a; + } + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c new file mode 100644 index 000000000..92a235325 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre20.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int foo(type *a, int argc) +{ + int d, e; + + /* Should be able to eliminate the second load of *a along the main path. */ + d = (*a)[argc]; + if (!d) + a++; + e = (*a)[argc]; + return e; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c new file mode 100644 index 000000000..77caef6de --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre21.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int main(type *a, int argc) +{ + int b; + int i; + int d, e; + + /* Should be able to hoist this out of the loop. */ + for (i = 0; i < argc; i++) + { + e = (*a)[0]; + } + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c new file mode 100644 index 000000000..3c03c9b12 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre22.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef int type[2]; +int main(type *a, int argc) +{ + int b; + int i; + int d, e; + + /* Should be able to hoist this out of the loop. */ + for (i = 0; i < argc; i++) + { + e = (*a)[argc]; + } + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre23.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre23.c new file mode 100644 index 000000000..2273accba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre23.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +struct { + int a; + int large[100]; +} x; + +int foo(int argc) +{ + int b; + int c; + int i; + int d, e; + + for (i = 0; i < argc; i++) + { + e = x.a; + x.a = 9; + } + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre24.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre24.c new file mode 100644 index 000000000..31fcc9f8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre24.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +int a; + +int foo(int argc) +{ + int b; + int c; + int i; + int d, e; + + for (i = 0; i < argc; i++) + { + e = a; + a = 9; + } + return d + e; +} + +/* We will move the load of a out of the loop. */ + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre25.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre25.c new file mode 100644 index 000000000..aaf09313e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre25.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +struct X { int i; }; +int foo(struct X *a, int argc) +{ + int b; + int c; + int i; + int d, e; + + for (i = 0; i < argc; i++) + { + e = a->i; + a->i = 9; + } + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre3.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre3.c new file mode 100644 index 000000000..4bda8f644 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre3.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int foo(int **a,int argc) +{ + int b; + int d, e; + + if (argc) + { + d = *(*a); + } + else + { + + } + /* Should be able to eliminate one of the *(*a)'s along the if path + by pushing it into the else path. We will also eliminate + one of the *a's. */ + e = *(*a); + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre4.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre4.c new file mode 100644 index 000000000..1e2660317 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre4.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int main(int *a, int argc) +{ + int b; + int c; + int i; + int d, e; + + for (i = 0; i < argc; i++) + { + e = *a; + *a = 9; + } + return d + e; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre5.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre5.c new file mode 100644 index 000000000..475050a6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre5.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int p; +int r; + +__attribute__ ((noinline)) +static int a(void) +{ + return p; +} +int foo(int argc) +{ + int q; + q = a(); + + /* We should be able to move the call to a into the if path. + in a perfect world, we'd actually decide that it can't touch + r, and not recompute it at all!. */ + if (argc) + r = 9; + return q + a(); +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c new file mode 100644 index 000000000..e6130bbe7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre6.c @@ -0,0 +1,80 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats -fdump-tree-fre" } */ +#include <stddef.h> + +union tree_node; +typedef union tree_node *tree; + +struct tree_common +{ + tree chain; +}; + +struct tree_list +{ + struct tree_common common; + tree value; +}; + +union tree_node + +{ + struct tree_common common; + struct tree_list list; +}; + +extern void abort (void) __attribute__((noreturn)); + +void __attribute__((noinline)) +foo (void) +{ + abort (); +} + +/* There are some reloaded loads of *cell, and cell->common.chain on various + branches. */ +void __attribute__((noinline)) +remove_useless_vars (tree *unexpanded_var_list, int dump_file) +{ + tree var, *cell; + int c = 0; + for (cell = unexpanded_var_list; *cell; ) + { + var = (*cell)->list.value; + if (var) + { + if (dump_file) + foo (); + + *cell = ((*cell)->common.chain); + continue; + } + + cell = &((*cell)->common.chain); + } +} +extern void *malloc (__SIZE_TYPE__) __attribute__ ((malloc)); + +int +main (void) +{ + int i; + tree unexpanded_var_list, last = (tree) 0; + + for (i = 0; i < 2; i++) + { + unexpanded_var_list = malloc (sizeof (struct tree_list)); + unexpanded_var_list->list.value = (tree) (ptrdiff_t) (i & 1); + unexpanded_var_list->common.chain = last; + last = unexpanded_var_list; + } + + remove_useless_vars (&unexpanded_var_list, 0); + return 0; +} + +/* { dg-final { scan-tree-dump-not "= unexpanded_var_list;" "fre" } } */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { scan-tree-dump-times "Insertions: 2" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre7.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre7.c new file mode 100644 index 000000000..6f68f3ae2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre7.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +/* We can't eliminate the *p load here in any sane way, as eshup8 may + change it. */ +void +enormlz (x) + unsigned short x[]; +{ + register unsigned short *p; + p = &x[2]; + while ((*p & 0xff00) == 0) + { + eshup8 (x); + } +} +/* { dg-final { scan-tree-dump-not "Eliminated:" "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loadpre8.c b/gcc/testsuite/gcc.dg/tree-ssa/loadpre8.c new file mode 100644 index 000000000..056c3fd63 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loadpre8.c @@ -0,0 +1,97 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +typedef union tree_node *tree; +struct tree_common +{ + tree chain; +} +VEC_constructor_elt_base; +struct tree_ssa_name +{ + tree var; +}; +union tree_node +{ + struct tree_common common; + struct tree_ssa_name ssa_name; +}; +struct edge_def +{ + struct basic_block_def *dest; +}; +typedef struct edge_def *edge; +typedef struct VEC_edge_base +{ +} +VEC_edge_base; +__attribute__ ((noinline)) static edge +VEC_edge_base_index (const VEC_edge_base * vec_, unsigned ix_) +{ +} +typedef struct VEC_edge_gc +{ + VEC_edge_base base; +} +VEC_edge_gc; +struct basic_block_def +{ + VEC_edge_gc *succs; +}; +typedef struct basic_block_def *basic_block; +typedef struct +{ + unsigned index; + VEC_edge_gc **container; +} +edge_iterator; +__inline__ VEC_edge_gc * +ei_container (edge_iterator i) +{ + return *i.container; +} +__inline__ edge_iterator +ei_start_1 (VEC_edge_gc ** ev) +{ + edge_iterator i; + i.container = ev; + return i; +} +__attribute__ ((noinline)) static ei_next (edge_iterator * i) +{ +} +static __inline__ edge +ei_edge (edge_iterator i) +{ + return (edge) (VEC_edge_base_index ((((ei_container (i))) ? &((ei_container (i)))->base : 0), (i.index))); +} +static __inline__ unsigned char +ei_cond (edge_iterator ei, edge * p) +{ + *p = ei_edge (ei); +} +typedef tree *def_operand_p; +extern tree *get_phi_result_ptr (tree); +static __inline__ tree +get_def_from_ptr (def_operand_p def) +{ +} +__attribute__ ((noinline)) static tree +phi_nodes (basic_block bb) +{ +} + +/* We can eliminate a load of the SRA'd variable edge_iterator.container */ +rewrite_add_phi_arguments (basic_block bb) +{ + edge e; + edge_iterator ei; + for ((ei) = ei_start_1 (&((bb->succs))); ei_cond ((ei), &(e)); + ei_next (&(ei))) + { + tree phi; + for (phi = phi_nodes (e->dest); phi; phi = (((phi))->common.chain)) + get_reaching_def ((get_def_from_ptr (get_phi_result_ptr (phi)))->ssa_name.var); + } +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c b/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c new file mode 100644 index 000000000..afb7ca4b0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/local-pure-const.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-local-pure-const1" } */ +/* { dg-add-options bind_pic_locally } */ + +t(int a, int b, int c) +{ + int *p; + if (a) + p = &a; + else + p = &c; + return *p; +} +/* { dg-final { scan-tree-dump-times "local memory is OK" 1 "local-pure-const1"} } */ +/* { dg-final { scan-tree-dump-times "found to be const" 1 "local-pure-const1"} } */ +/* { dg-final { cleanup-tree-dump "local-pure-const1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-1.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-1.c new file mode 100644 index 000000000..a84304857 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-1.c @@ -0,0 +1,53 @@ +/* { dg-do compile } */ +/* -mlongcall will cause us to place &foo in the CTR register. */ +/* { dg-skip-if "" { powerpc*-*-* } { "-mlongcall" } { "" } } */ +/* { dg-options "-O1 -ftree-loop-ivcanon -funroll-loops -fdump-tree-ivcanon-details -fdump-tree-cunroll-details -fdump-tree-optimized" } */ + +/* On 31-bit S/390 the function address will be stored (once) in the literal pool, + so scan-assembler-times "foo" will return 1 even if the loop is fully unrolled. + -msmall-exec avoids this by enabling a call instruction with immediate operand. */ +/* { dg-options "-O1 -ftree-loop-ivcanon -funroll-loops -fdump-tree-ivcanon-details -fdump-tree-cunroll-details -fdump-tree-optimized -msmall-exec" { target s390-*-* } } */ + +/* On Darwin, we call extern functions via a stub in PIC mode which is default and + the stub is named after the function. To avoid this we use -static to go out + of PIC mode. */ +/* { dg-options "-O1 -ftree-loop-ivcanon -funroll-loops -fdump-tree-ivcanon-details -fdump-tree-cunroll-details -fdump-tree-optimized -static" { target *-*-darwin* } } */ + +/* On MIPS, disable generating hints (R_MIPS_JALR) for PIC calls. In addition + to the load from the GOT this also contains the name of the funtion so for + each call the function name would appear twice. */ +/* { dg-options "-O1 -ftree-loop-ivcanon -funroll-loops -fdump-tree-ivcanon-details -fdump-tree-cunroll-details -fdump-tree-optimized -mno-relax-pic-calls" { target mips*-*-* } } */ + +void xxx(void) +{ + int x = 45; + + while (x >>= 1) + foo (); +} + +/* We should be able to find out that the loop iterates four times and unroll it completely. */ + +/* { dg-final { scan-tree-dump-times "Added canonical iv to loop 1, 4 iterations" 1 "ivcanon"} } */ +/* { dg-final { cleanup-tree-dump "ivcanon" } } */ +/* { dg-final { scan-tree-dump-times "Unrolled loop 1 completely" 1 "cunroll"} } */ +/* { dg-final { cleanup-tree-dump "cunroll" } } */ +/* { dg-final { scan-tree-dump-times "foo" 5 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + +/* Because hppa, ia64 and Windows targets include an external declaration + for foo as well as the calls we need to look for something more specific + than just foo in order to count only the calls and not the declaration. */ +/* The SH targets always use separate instructions to load the address + and to do the actual call - bsr is only generated by link time + relaxation. */ +/* CRIS keeps the address in a register. */ +/* m68k sometimes puts the address in a register, depending on CPU and PIC. */ + +/* { dg-final { scan-assembler-times "foo" 5 { xfail hppa*-*-* ia64*-*-* sh*-*-* cris-*-* crisv32-*-* fido-*-* m68k-*-* i?86-*-mingw* i?86-*-cygwin* } } } */ +/* { dg-final { scan-assembler-times "foo,%r" 5 { target hppa*-*-* } } } */ +/* { dg-final { scan-assembler-times "= foo" 5 { target ia64*-*-* } } } */ +/* { dg-final { scan-assembler-times "call\[ \t\]*_foo" 5 { target i?86-*-mingw* i?86-*-cygwin* } } } */ +/* { dg-final { scan-assembler-times "jsr|bsrf|blink\ttr?,r18" 5 { target sh*-*-* } } } */ +/* { dg-final { scan-assembler-times "Jsr \\\$r" 5 { target cris-*-* } } } */ +/* { dg-final { scan-assembler-times "\[jb\]sr" 5 { target fido-*-* m68k-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c new file mode 100644 index 000000000..c8d118e37 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-10.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-require-effective-target int32plus } */ + +int bar (void); + +void foo (void) +{ + unsigned i, j, n; + + for (i = 0; i < 100000; i++) + ; + + n = bar (); + for (i = 0; i < n; i++) + ; + + for (i = 0; i < n; i++) + for (j = 0; j < n; j++) + ; + + /* These should not be removed. */ + for (i = 0; i < 10000; i++) + bar (); + + for (i = 0; i != n; i += 2) + ; +} + +/* { dg-final { scan-tree-dump-times "if " 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "bar " 2 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-11.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-11.c new file mode 100644 index 000000000..d6c656f31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-11.c @@ -0,0 +1,28 @@ +/* A test for final value replacement and higher-order ivs, + see PR 22442. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +void bar (unsigned); + +void foo (void) +{ + unsigned i, a; + + for (i = 0; i < 5; i++) + a = i * i; + + bar (a); +} + +/* Final value of a gets replaced. */ + +/* { dg-final { scan-tree-dump-times "\\(16\\)" 1 "optimized" } } */ + +/* And the empty loop is removed. */ + +/* { dg-final { scan-tree-dump-times "if " 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-14.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-14.c new file mode 100644 index 000000000..987c7dea8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-14.c @@ -0,0 +1,19 @@ +/* A test for final value replacement. */ + +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(void); + +int bla(void) +{ + int i, j = foo (); + + for (i = 0; i < 100; i++, j++) + foo (); + + /* Should be replaced with return j0 + 100; */ + return j; +} + +/* { dg-final { scan-tree-dump-times "\\+ 100" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c new file mode 100644 index 000000000..aa0747b6e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-15.c @@ -0,0 +1,27 @@ +/* A test for # of iterations analysis (signed counter cannot wrap) and final + value replacement. */ + +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo(void); + +int bla(void) +{ + int i, n = foo (), j; + + j = 0; + /* The loop should be removed completely. */ + for (i = 1; i <= n; i++) + j += n; + + /* Should be replaced with return n * n; */ + return j; +} + +/* Since the loop is removed, there should be no addition. */ +/* { dg-final { scan-tree-dump-times "\\+" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "n_. \\* n_." 1 "optimized" } } */ + +/* The if from the loop header copying remains in the code. */ +/* { dg-final { scan-tree-dump-times "if " 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-16.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-16.c new file mode 100644 index 000000000..50fa33330 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-16.c @@ -0,0 +1,24 @@ +/* A test for # of iterations estimation. We know that the loop is executed + at most 100 times, thus the (32-bit) induction variables do not overflow, + and we may use 64-bit variable to represent them. */ + +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-do compile { target x86_64-*-* } } */ + +unsigned a[100]; + +void foo(unsigned n) +{ + unsigned i; + + for (i = 0; i < n; i++) + a[i] = 4 * i; +} + +/* Check that the memory reference was replaced with MEM, and that there is no + multiplication. */ + +/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c new file mode 100644 index 000000000..d2903cef2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-17.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-sccp-details" } */ + +/* To determine the number of iterations in this loop we need to fold + p_4 + 4B > p_4 + 8B to false. This transformation has caused + troubles in the past due to overflow issues. */ + +int foo (int *p) +{ + int i = 0, *x; + + for (x = p; x < p + 2; x++) + i++; + + return i; +} + +/* { dg-final { scan-tree-dump "set_nb_iterations_in_loop = 1" "sccp" } } */ +/* { dg-final { cleanup-tree-dump "sccp" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-18.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-18.c new file mode 100644 index 000000000..ca75db941 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-18.c @@ -0,0 +1,24 @@ +/* A test for # of iterations estimation. We know that I does not overflow, + thus we can perform strength reduction (even though the 32-bit variable + i is first extended to 64-bit type). */ + +/* { dg-options "-O2 -fdump-tree-optimized" } */ +/* { dg-do compile { target x86_64-*-* } } */ + +unsigned bar(void); + +void foo(unsigned *p, unsigned n) +{ + unsigned i; + + for (i = 0; i < n; i++) + p[i] = bar (); +} + +/* Check that the memory reference was replaced with MEM, and that there is no + multiplication. */ + +/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c new file mode 100644 index 000000000..80f2e601e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-19.c @@ -0,0 +1,28 @@ +/* This tests strength reduction and choice of induction variables. The targets + for this testcase are quite limited, as with different set of available + addressing modes, the results may be quite different. + + The testcase comes from PR 29256 (and originally, the stream benchmark). */ + +/* { dg-do compile { target { i?86-*-* || { x86_64-*-* || powerpc_hard_double } } } } */ +/* { dg-require-effective-target nonpic } */ +/* { dg-options "-O3 -fno-prefetch-loop-arrays -fdump-tree-optimized" } */ + +# define N 2000000 +double a[N],c[N]; +void tuned_STREAM_Copy() +{ + int j; + for (j=0; j<N; j++) + c[j] = a[j]; +} + +/* Check that the memory references are based on &a and &c, with appropriate + offsets. Ideally, we would want each of them to appear once in the output. + However, due to a bug in jump threading, we end up peeling one iteration from + the loop, which creates an additional occurence. */ + +/* { dg-final { scan-tree-dump-times "MEM.(base: &|symbol: )a," 2 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MEM.(base: &|symbol: )c," 2 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c new file mode 100644 index 000000000..342682778 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-2.c @@ -0,0 +1,44 @@ +/* A test for strength reduction and induction variable elimination. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ +/* { dg-require-effective-target size32plus } */ + +/* Size of this structure should be sufficiently weird so that no memory + addressing mode applies. */ + +struct bla +{ + char x[187]; + int y; + char z[253]; +} arr_base[100]; + +void xxx(void) +{ + int iter; + + for (iter = 0; iter < 100; iter++) + arr_base[iter].y = 17 * iter; +} + +/* Access to arr_base[iter].y should be strength reduced, i.e., there should + be no multiplication. */ + +/* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ + +/* 17 * iter should be strength reduced. */ + +/* { dg-final { scan-tree-dump-times " \\* 17" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\+ 17" 1 "optimized" } } */ + +/* The induction variable comparison with 99 should be eliminated + and replaced by comparison of one of the newly created ivs. */ + +/* { dg-final { scan-tree-dump-times "iter" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= 99" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "< 100" 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-20.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-20.c new file mode 100644 index 000000000..24524a02b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-20.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/29516 */ + +/* { dg-do compile { target fpic } } */ +/* { dg-options "-O -ftree-vrp -fPIC -fdump-tree-ivopts" } */ + +typedef struct gfc_se { int pre; } gfc_se; +typedef struct gfc_ss_info { int dim[7]; } gfc_ss_info; +int gfc_rank_cst[7 + 1]; +gfc_conv_array_transpose (gfc_se * se) { + int dest, src, dest_index, src_index; + gfc_ss_info *dest_info; + int n; + for (n = 0; n < 2; n++) { + dest_info->dim[n] = n; + src_index = gfc_rank_cst[1 - n]; + a (se->pre, b (dest, dest_index), c (src, src_index)); + } +} + +/* Ivopts should not produce multiplication by a pointer constant. */ + +/* { dg-final { scan-tree-dump-times "\\* \[0-9\]*B;" 0 "ivopts" } } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-21.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-21.c new file mode 100644 index 000000000..f53407d9b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-21.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/30322 */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +extern void op( int, int); +void foo(int f0, int f1, int e0, int e1) +{ + int i0, i1; + + for (i1 = f1; i1 <= e1; ++i1) + for (i0 = f0; i0 <= e0; ++i0) + op(i0, i1); +} + +/* { dg-final { scan-tree-dump-times "~" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-22.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-22.c new file mode 100644 index 000000000..fa7da712b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-22.c @@ -0,0 +1,17 @@ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int a[100]; + +void test (int n) +{ + int i; + + for (i = 0; i < n; i += 3) + a[i] = i; +} + +/* We used to replace the exit test "i < n" by "i != ((n-1)/3) * 3 + 1". Although + correct, this transformation is obviously harmful. */ + +/* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-23.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-23.c new file mode 100644 index 000000000..a16dc5f03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-23.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -funroll-loops -fdump-tree-cunroll-details" } */ + +void bla(int); + +void foo(void) +{ + int i; + + /* This loop used to appear to be too large for unrolling. */ + for (i = 0; i < 4; i++) + { + bla (i); + bla (2*i); + bla (3*i); + bla (4*i); + bla (5*i); + bla (6*i); + bla (7*i); + bla (8*i); + } +} + +/* { dg-final { scan-tree-dump-times "Unrolled loop 1 completely" 1 "cunroll" } } */ + +/* { dg-final { cleanup-tree-dump "cunroll" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-24.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-24.c new file mode 100644 index 000000000..5632b0679 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-24.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fstrict-overflow -fdump-tree-optimized" } */ + +void foo(int a, int b) +{ for(;a!=b;a+=4); } + +void foo2(int a, int b) +{ for(;a<b;a+=4); } + +void foo3(int*a, int* b) +{ for(;a<b;a++); } + +void foo4(int*a, int*b) +{ for(;a!=b;a++); } + +/* { dg-final { scan-tree-dump-not "if" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-25.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-25.c new file mode 100644 index 000000000..479ed81d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-25.c @@ -0,0 +1,129 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-profile" } */ + +int foo(void); +void bla(void); +void bar(void); + +void test1 (void) +{ + unsigned i; + + /* Only one loop should be found here. */ + i = 0; + while (1) + { + i++; + if (i == 100) + break; + + if (foo ()) + bla (); + else + bar (); + } +} + +void test2 (void) +{ + unsigned i, j; + + /* Two loops should be found, in this case. */ + i = j = 0; + while (1) + { + j++; + foo (); + if (j < 100) + continue; + + i++; + j = 0; + if (i == 100) + break; + } +} + +void test3 (void) +{ + unsigned i, j, k; + + /* Three loops. */ + i = j = k = 0; + while (1) + { + j++; + foo (); + if (j < 100) + continue; + + j = 0; + k++; + if (k < 100) + continue; + + k = 0; + i++; + if (i == 100) + break; + } +} + +void test4 (void) +{ + unsigned i, j, k; + + /* Two loops with a nested subloop. */ + i = j = 0; + while (1) + { + j++; + foo (); + for (k = 0; k < 100; k++) + foo (); + + if (j < 100) + continue; + + i++; + j = 0; + if (i == 100) + break; + } +} + + +void test5 (void) +{ + unsigned i, j; + + /* Both subloop and non-subloop back edges. */ + i = j = 0; + while (1) + { + j++; + foo (); + if (j < 100) + continue; + j = 0; + + i++; + if (i == 100) + break; + + if (foo ()) + bla (); + else + bar (); + } +} + +/* { dg-final { scan-tree-dump-times "Disambiguating loop" 5 "profile" } } */ +/* For the following xfail marks, see PR35629. */ +/* { dg-final { scan-tree-dump-times "Found latch edge" 5 "profile" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "Merged latch edges" 2 "profile" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "4 loops found" 2 "profile" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "3 loops found" 2 "profile" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "2 loops found" 1 "profile" { xfail *-*-* } } } */ + +/* { dg-final { cleanup-tree-dump "profile" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-26.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-26.c new file mode 100644 index 000000000..f8bc8e010 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-26.c @@ -0,0 +1,29 @@ +/* PR 30730, PR 26900, number of iterations analysis should be able to + determine number of iterations of the following loops unconditionally. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fstrict-overflow -fdump-tree-optimized-blocks" } */ + +unsigned foo(unsigned int n) +{ + unsigned x = 0;; + + while (n > 10) + { + n -= 2; + x++; + } + + return x; +} + +int foo0(int i0, int i1) +{ + int i, j = 0; + for (i=i0; i<=i1+1; ++i) + ++j; + return j; +} + +/* { dg-final { scan-tree-dump-times "if" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-28.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-28.c new file mode 100644 index 000000000..77d0c47dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-28.c @@ -0,0 +1,24 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -fdump-tree-optimized -fdump-tree-aprefetch --param max-unrolled-insns=1000" } */ + +char x[100000]; + +void foo(int n) +{ + int i; + + for (i = 0; i < n; i++) + x[i] = (char) i; +} + +/* There should be 64 MEMs in the unrolled loop and one more in the copy of the loop + for the rest of the iterations. */ + +/* { dg-final { scan-tree-dump-times "MEM" 65 "optimized" } } */ + +/* There should be no i_a = i_b assignments. */ +/* { dg-final { scan-tree-dump-times "i_.*= i_\[0-9\]*;" 0 "aprefetch" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c new file mode 100644 index 000000000..c900dbf9b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-29.c @@ -0,0 +1,21 @@ +/* PR 31885 */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct s { + int *blah; +}; + +static struct s array[] = { { 0 } }; + +void +foo (struct s *p) +{ + struct s *q = &array[1]; + while (p < q) + p++; +} + +/* { dg-final { scan-tree-dump-not "if" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c new file mode 100644 index 000000000..9868c078d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-3.c @@ -0,0 +1,30 @@ +/* A test for strength reduction and induction variable elimination. + Target is restricted to x86 type architectures, so that we may + assume something about memory addressing modes. */ + +/* { dg-do compile { target { { i?86-*-* x86_64-*-* } && nonpic } } } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int arr_base[100]; + +int foo(int); + +void xxx(void) +{ + long iter; + + for (iter = 0; iter < 100; iter++) + arr_base[iter] = foo (iter); +} + +/* Access to arr_base[iter].y should not be strength reduced, since + we have a memory mode including multiplication by 4. */ + +/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "step:" 1 "optimized" } } */ + +/* And original induction variable should be preserved. */ + +/* { dg-final { scan-tree-dump-times "int iter" 1 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-30.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-30.c new file mode 100644 index 000000000..14d58e598 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-30.c @@ -0,0 +1,14 @@ +/* PR 25371 */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +void +slow_close(int n) +{ + int i; + double *mm; + for (i=0;i<2*n;i++) + for (i=0;i<2*n;i++) + *(mm+i*2*n+i) = 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-31.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-31.c new file mode 100644 index 000000000..4f226374b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-31.c @@ -0,0 +1,21 @@ +/* PR 32283 */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +short a[(2048)]; +short foo (int len, int v) +{ + int i; + for (i = 0; i < len; i++) { + a[i] = v; + } + return a[0]; +} + +/* When we do not have addressing mode including multiplication, + the memory access should be strength-reduced. */ +/* { dg-final { scan-tree-dump-times " \\+ 2" 1 "optimized" { target arm*-*-* } } } */ +/* { dg-final { scan-tree-dump-times " \\+ 2" 1 "optimized" { target { ia64-*-* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump-times " \\+ 2" 2 "optimized" { target { ia64-*-* && lp64 } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-32.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-32.c new file mode 100644 index 000000000..3a92a08f8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-32.c @@ -0,0 +1,46 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim-details" } */ + +int x; +int a[100]; + +struct a +{ + int X; + int Y; +}; + +void bla(void); + +void test1(void) +{ + unsigned i; + + /* We should perform store motion here. */ + for (x = 0; x < 100; x++) + a[x] = x; +} + +void test2(void) +{ + unsigned i; + + /* But not here. */ + for (x = 0; x < 100; x++) + bla (); +} + +void test3(struct a *A) +{ + unsigned i; + + /* But we should here (using base + offset analysis). */ + for (i = 0; i < 100; i++) + { + A[5].X += i; + A[5].Y += i; + } +} + +/* { dg-final { scan-tree-dump-times "Executing store motion of" 3 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-33.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-33.c new file mode 100644 index 000000000..3ee4e3ce0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-33.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim-details" } */ + +int x; +int a[100]; + +struct a +{ + int X; + int Y; +}; + +struct a arr[100]; + +void test4(unsigned b) +{ + unsigned i; + + /* And here. */ + for (i = 0; i < 100; i++) + { + arr[b+8].X += i; + arr[b+9].X += i; + } +} + +void test5(struct a *A, unsigned b) +{ + unsigned i; + + /* And here as well. */ + for (i = 0; i < 100; i++) + { + A[b].X += i; + A[b+1].Y += i; + } +} + +/* { dg-final { scan-tree-dump-times "Executing store motion of" 4 "lim1" { xfail lp64 } } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-34.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-34.c new file mode 100644 index 000000000..5da804f8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-34.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim-details" } */ + +int r[6]; + +void f (int n) +{ + while (-- n) + { + r [0] += r [5]; + r [1] += r [0]; + r [2] += r [1]; + r [3] += r [2]; + r [4] += r [3]; + r [5] += r [4]; + } +} + + +/* { dg-final { scan-tree-dump-times "Executing store motion of r" 6 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-35.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-35.c new file mode 100644 index 000000000..4716e9625 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-35.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim-details" } */ + +int x; +int a[100]; + +struct a +{ + int X; + int Y; +}; + +struct a arr[100]; + +void test1(int b) +{ + unsigned i; + + /* And here. */ + for (i = 0; i < 100; i++) + { + arr[b+8].X += i; + arr[b+9].X += i; + } +} + +void test2(struct a *A, int b) +{ + unsigned i; + + /* And here as well. */ + for (i = 0; i < 100; i++) + { + A[b].X += i; + A[b+1].Y += i; + } +} + +void test3(unsigned long b) +{ + unsigned i; + + /* And here. */ + for (i = 0; i < 100; i++) + { + arr[b+8].X += i; + arr[b+9].X += i; + } +} + +void test4(struct a *A, unsigned long b) +{ + unsigned i; + + /* And here as well. */ + for (i = 0; i < 100; i++) + { + A[b].X += i; + A[b+1].Y += i; + } +} +/* long index not hoisted for avr target PR 36561 */ +/* { dg-final { scan-tree-dump-times "Executing store motion of" 8 "lim1" { xfail { "avr-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "Executing store motion of" 6 "lim1" { target { "avr-*-*" } } } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-36.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-36.c new file mode 100644 index 000000000..9e9173765 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-36.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dce2" } */ + +struct X { float array[2]; }; + +struct X a,b; + +float foobar () { + float s = 0; + unsigned int d; + struct X c; + for (d=0; d<2; ++d) + c.array[d] = a.array[d] * b.array[d]; + for (d=0; d<2; ++d) + s+=c.array[d]; + return s; +} + +/* The temporary structure should have been promoted to registers + by FRE after the loops have been unrolled by the early unrolling pass. */ +/* { dg-final { scan-tree-dump-not "c\.array" "dce2" } } */ +/* { dg-final { cleanup-tree-dump "dce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-37.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-37.c new file mode 100644 index 000000000..46b26bb87 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-37.c @@ -0,0 +1,27 @@ +/* { dg-do link } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +extern void link_error (void); +static const int my_array [3] = { 4, 5, 6 }; + +void f0 (void) +{ + int j, sum = 0; + for (j = 0; j < 3; j ++) + sum += my_array [j]; + if (15 != sum) + link_error (); +} + +int f1 (int a []) +{ + int j, sum = 0; + for (j = 0; j < 3; j ++) + sum += a [j] + my_array [j]; + return sum; +} + +int main() { } + +/* { dg-final { scan-tree-dump-not "my_array" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-4.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-4.c new file mode 100644 index 000000000..a6c8c8fd3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-4.c @@ -0,0 +1,46 @@ +/* A test for strength reduction and induction variable elimination. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ +/* { dg-require-effective-target size32plus } */ + +/* Size of this structure should be sufficiently weird so that no memory + addressing mode applies. */ + +struct bla +{ + char x[187]; + int y; + char z[253]; +} arr_base[100]; + +int foo(void); + +void xxx(void) +{ + int iter; + + for (iter = 0; iter < 100; iter++) + arr_base[iter].y = foo (); +} + +/* Access to arr_base[iter].y should be strength reduced. Depending on + whether we have an addressing mode of type [base + offset], one of the + following forms might get chosen: + + -- induction variable with base &arr_base[0].y, the memory access of + form *iv = ... + -- induction variable with base 0, the memory access of form + *(iv + &arr_base[0].y) = ... + + In any case, we should not have any multiplication. */ + +/* { dg-final { scan-tree-dump-times " \\* \[^\\n\\r\]*=" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^\\n\\r\]*= \\* " 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "MEM" 1 "optimized" } } */ + +/* And the original induction variable should be eliminated. */ + +/* { dg-final { scan-tree-dump-times "iter" 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-5.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-5.c new file mode 100644 index 000000000..a8db74afe --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-5.c @@ -0,0 +1,30 @@ +/* A test for induction variable merging. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +void foo(long); + +void xxx(void) +{ + long iter, jter; + + for (iter = 0, jter = 2; iter < 100; iter++, jter++) + { + foo (iter); + foo (jter); + } +} + +/* Only iter variable should remain. */ + +/* { dg-final { scan-tree-dump-times "int iter" 1 "optimized" } } */ + +/* And jter shouldn't be an induction variable anymore (no PHI node). */ +/* { dg-final { scan-tree-dump-times "jter_\[0-9\]* = PHI" 0 "optimized" } } */ + +/* And the use of jter should be replaced by iter + 2 */ + +/* { dg-final { scan-tree-dump-times " \\+ 2" 1 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-6.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-6.c new file mode 100644 index 000000000..992f671e4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-6.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -funswitch-loops -fdump-tree-unswitch-details -fdump-tree-optimized" } */ + +int ch; +int a[100]; + +void xxx(void) +{ + int i; + + for (i = 0; i < 100; i++) + { + if (ch) + a[i] = ch; + else + a[i] = i; + } +} + +/* Loop should be unswitched. */ + +/* { dg-final { scan-tree-dump-times "Unswitching loop" 1 "unswitch" } } */ +/* { dg-final { cleanup-tree-dump "unswitch" } } */ + +/* In effect there should be exactly three conditional jumps in the final program. */ + +/* { dg-final { scan-tree-dump-times "else" 3 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-7.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-7.c new file mode 100644 index 000000000..ab4a5026f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-7.c @@ -0,0 +1,35 @@ +/* PR tree-optimization/19828 */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-lim-details" } */ + +int cst_fun1 (int) __attribute__((__const__)); +int cst_fun2 (int) __attribute__((__const__)); +int pure_fun1 (int) __attribute__((__pure__)); +int pure_fun2 (int) __attribute__((__pure__)); +int foo (void); + +int xxx (void) +{ + int i, k = foo (), x = 0; + + for (i = 0; i < 100; i++) + { + x += cst_fun1 (k); + x += pure_fun1 (k); + + if (k) + { + x += cst_fun2 (k); + x += pure_fun2 (k); + } + } + + return x; +} + +/* Calls to cst_fun1 and pure_fun1 may be moved out of the loop. + Calls to cst_fun2 and pure_fun2 should not be, since calling + with k = 0 may be invalid. */ + +/* { dg-final { scan-tree-dump-times "Moving statement" 2 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-8.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-8.c new file mode 100644 index 000000000..de439c719 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-8.c @@ -0,0 +1,25 @@ +/* A test for strength reduction of ivs with nonconstant step. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int bar (void); + +int a[100]; + +void xxx (void) +{ + int iter, step = bar (); + + for (iter = 0; iter < 10; iter++) + a[iter * step] = bar (); +} + +/* The array access should be strength reduced. But to determine the value of + the step, we need to calculate step * sizeof (int), thus we need to be + a bit careful about which multiplications we disallow. */ + +/* { dg-final { scan-tree-dump-times "step \\* \[^0-9\]" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "\[^0-9\] \\* step" 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/loop-9.c b/gcc/testsuite/gcc.dg/tree-ssa/loop-9.c new file mode 100644 index 000000000..c4b47c054 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/loop-9.c @@ -0,0 +1,24 @@ +/* Without TARGET_MEM_REFs, dom creates code like + + i1 = 4 * i; + *(p + i1) = i; + *(p + i1 + 4) = i + + causing us to have unnecessary multiplication by 4 in the + result. */ + +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +void foo (int *p) +{ + int i; + + for (i = 0; i < 100; i++) + { + p[i] = i; + p[i + 1] = i; + } +} + +/* { dg-final { scan-assembler-times "lea\\t" 0 { target i?86-*-* x86_64-*-* } } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/negate.c b/gcc/testsuite/gcc.dg/tree-ssa/negate.c new file mode 100644 index 000000000..12e2cdf71 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/negate.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +int f (int a, int b) +{ + int x = -a; + int y = b - x; + return y; +} + +/* We tested for reassociation to -(a + b) on the following which + isn't a transform that makes things cheaper. With reassoc + no longer applying to types with undefined overflow we lost + this transform. + +int g (int a, int b) +{ + int x = -a; + int y = x - b; + return y; +} + +*/ + +/* There should be an addition now. */ +/* { dg-final { scan-tree-dump-times "\\+" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-1.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-1.c new file mode 100644 index 000000000..b29516936 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(int a, int b, int c) +{ + if (c == 0) goto temp; + if (a == 0) + return 0; +temp: + if (a == b) + return a; + return a; +} + +/* There should be no ifs as the PHI arguments, we did not + optimize this before because PHI-OPT did not look at + PHIs which have more than two arguments. */ +/* { dg-final { scan-tree-dump-times "if" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c new file mode 100644 index 000000000..415c11777 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +_Bool f1(_Bool a, _Bool b) +{ + if (a) + { + if (b) + return 1; + else + return 0; + } + return 0; +} + + +/* There should be only one if, the outer one; the inner one + should have been changed to straight line code with the + value of b (except that we don't fold ! (b != 0) into b + which can be fixed in a different patch). */ +/* { dg-final { scan-tree-dump-times "if" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-3.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-3.c new file mode 100644 index 000000000..54970ad80 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(int a, int b) +{ + if (a == 0) + return 0; + if (a != b) + return a; + return a; +} + +/* There should be no ifs as the PHI arguments, we did not + optimize this before because PHI-OPT did not look at + PHIs which have more than two arguments. */ +/* { dg-final { scan-tree-dump-times "if" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c new file mode 100644 index 000000000..efd9228b6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-4.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +_Bool t(); +_Bool t1(); + +_Bool f1() +{ + return t() && t1(); +} + +/* There should be only one if, the outer one; the inner one + should have been changed to straight line code with the + value of b (except that we don't fold ! (b != 0) into b + which means that we miss a sib calling opportunity). */ +/* { dg-final { scan-tree-dump-times "if " 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c new file mode 100644 index 000000000..7a930dd45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/phi-opt-5.c @@ -0,0 +1,59 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ffinite-math-only -fdump-tree-phiopt1" } */ + +float repl1 (float varx) +{ + if (varx < 0.0) + return 0.0; + else if (varx > 1.0) + return 1.0; + else + return varx; +} + +/* Should be turned to + + varx_4 = MIN_EXPR <1.0e+0, varx_2>; + varx_5 = MAX_EXPR <varx_4, 0.0>; */ + +/* { dg-final { scan-tree-dump "varx.*MIN_EXPR.*1\\.0" "phiopt1"} } */ +/* { dg-final { scan-tree-dump "varx.*MAX_EXPR.*0\\.0" "phiopt1"} } */ + +float repl2 (float vary) +{ + if (vary > 1.0) + return 1.0; + else if (vary < 0.0) + return 0.0; + else + return vary; +} + +/* Should be turned to + + vary_4 = MAX_EXPR <0.0, vary_2>; + vary_5 = MIN_EXPR <vary_4, 1.0e+0>; */ + +/* { dg-final { scan-tree-dump "vary.*MAX_EXPR.*0\\.0" "phiopt1"} } */ +/* { dg-final { scan-tree-dump "vary.*MIN_EXPR.*1\\.0" "phiopt1"} } */ + +float repl3 (float varz, float vara, float varb) +{ + if (varz > vara) + return vara; + else if (varz < varb) + return varb; + else + return varz; +} + +/* Should be turned to + + if (varz_2 > vara_3) goto <L4>; else goto <L1>; + +<L1>:; + vara_6 = MAX_EXPR <varb_5, varz_2>; */ + +/* { dg-final { scan-tree-dump "if .*varz" "phiopt1"} } */ +/* { dg-final { scan-tree-dump "vara.*MAX_EXPR" "phiopt1"} } */ +/* { dg-final { cleanup-tree-dump "phiopt1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr13146.c b/gcc/testsuite/gcc.dg/tree-ssa/pr13146.c new file mode 100644 index 000000000..b55645767 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr13146.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */ + +struct A +{ + int i; +}; +struct B +{ + struct A a; + int j; +}; + +int foo (struct A *p, struct B *q) +{ + p->i = 0; + q->j = 1; + return p->i; +} + +/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c new file mode 100644 index 000000000..0287a25cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14341.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ +/* { dg-require-effective-target int32plus } */ + +void fn_call (int); +int h(int, int); +void t() +{ + int i; + int x; + for( i = 0; i < 100000000; i++ ){ + fn_call (i < 100000000); + } +} + +/* { dg-final { scan-tree-dump-times "fn_call \\(1\\)" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14490-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-1.c new file mode 100644 index 000000000..b69bb70d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */ +int g(int x) +{ + return (x - 10) < 0; +} +/* There should be only x <= 9 and no x - 10. */ +/* { dg-final { scan-tree-dump-times "<= 9" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "\\+ -10" 0 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14490-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-2.c new file mode 100644 index 000000000..925442bb4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-2.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple -fwrapv" } */ +int g(int x) +{ + return (x - 10) < 0; +} +/* There should be no x >= 9 and one x - 10. */ +/* { dg-final { scan-tree-dump-times "<= 9" 0 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "\\+ -10" 1 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14490-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-3.c new file mode 100644 index 000000000..bf63d3afc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-3.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */ +int g(int x) +{ + return (x + 10) < 0; +} +/* There should be only x < -10 and no x + 10. */ +/* { dg-final { scan-tree-dump-times "< -10" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "\\+ 10" 0 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14490-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-4.c new file mode 100644 index 000000000..90a49bbdd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14490-4.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple -fwrapv" } */ +int g(int x) +{ + return (x + 10) < 0; +} +/* There should be no x < -10 and one x + 10. */ +/* { dg-final { scan-tree-dump-times "< -10" 0 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "\\+ 10" 1 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14814.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14814.c new file mode 100644 index 000000000..eb3605515 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14814.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-sra -fdump-tree-forwprop2" } */ + +struct YY { + double e[3]; }; + +static inline double *y(struct YY* this_1) { return &this_1->e[1]; } + +struct XX { + struct YY v; + }; + +static inline struct YY direction (const struct XX* this_1) { return this_1->v;} + +int foo(const struct XX* r) { + struct YY t = direction(r); + if (*y(&t) < 0.000001) return 0; + return 1; +} + +/* { dg-final { scan-tree-dump-times "&" 0 "forwprop2" } } */ +/* { dg-final { cleanup-tree-dump "forwprop2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c b/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c new file mode 100644 index 000000000..cc6e0158b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr14841.c @@ -0,0 +1,29 @@ +/* PR tree-optimization/14841 + Make sure that we can fold a possible nested reference into a + constant aggregate. */ + +/* { dg-do link } */ +/* { dg-options "-O" } */ + +struct car { + int speed; + int tire_pressure[4]; +}; + +static const struct car cars[] = { + { 75, { 10, 20, 30, 40 } }, + { 35, { 12, 34, 56, 78 } }, + { 40, { 19, 28, 37, 46 } } +}; + +extern void link_error (void); + +void +foo (void) +{ + if (cars[1].tire_pressure[2] != 56) + link_error (); +} + +int main () { return 0; } + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15349.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15349.c new file mode 100644 index 000000000..9f15d727f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15349.c @@ -0,0 +1,26 @@ +/* PR 15349. Merge two PHI nodes. */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-mergephi" } */ + +int +foo (int a, int b) +{ + int t; + + if (b) + { + if (a) + t = 3; + else + t = 5; + + a = 0; + } + else + t = 7; + + return t; +} + +/* { dg-final { scan-tree-dump-times "PHI" 1 "mergephi2"} } */ +/* { dg-final { cleanup-tree-dump "mergephi\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c new file mode 100644 index 000000000..68f14adad --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-1.c @@ -0,0 +1,25 @@ +/* { dg-do link } */ + +void link_error (); + +int main () +{ + struct { int b[2]; } x; + int b[2]; + if (&b[1] != &b[1]) + link_error (); + if (&b[0] != b) + link_error (); + if (b == &b[2]) + link_error (); + if (b != b) + link_error (); + if (&x.b[1] == &x.b[0]) + link_error (); + if (x.b != &x.b[0]) + link_error (); + if (&x.b[1] == x.b) + link_error (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c new file mode 100644 index 000000000..df68bfeba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-2.c @@ -0,0 +1,13 @@ +/* { dg-do link } */ +/* { dg-options "" } */ + +void link_error (); +struct a {}; +int main () +{ + struct a b[2]; + if (&b[0] != &b[1]) + link_error (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c new file mode 100644 index 000000000..2fd03e2e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-3.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +int f(int i, unsigned j) +{ + int b[2]; + if (&b[i] == &b[j]) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "i == j" 0 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c new file mode 100644 index 000000000..82be2e33a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-4.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +int f(int i, int j) +{ + int b[2][2]; + if (&b[1][i] == &b[0][j]) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "i == j" 0 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c new file mode 100644 index 000000000..06ce523a7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr15791-5.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +int foo(int i, int j) +{ + char g[16]; + if (&g[i] == &g[j]) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "i == j" 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr16721.c b/gcc/testsuite/gcc.dg/tree-ssa/pr16721.c new file mode 100644 index 000000000..eec753405 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr16721.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-strict-aliasing -fdump-tree-optimized" } */ + +struct data { + volatile unsigned long *addr; +} *p; + +int test() +{ + *p->addr; + return 0; +} + +/* The load from p->addr should not disappear. */ +/* { dg-final { scan-tree-dump-times "\->addr" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c new file mode 100644 index 000000000..853fe70c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr17141-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +struct A { int i; }; +int +foo(struct A *locp, int str) +{ + int T355, *T356; + T356 = &locp->i; + *T356 = str; + return locp->i; +} + +/* We should have propagated &locp->i into its dereference. */ + +/* { dg-final { scan-tree-dump "locp_\[^\\n\]* =" "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr17141-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr17141-2.c new file mode 100644 index 000000000..37782cafe --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr17141-2.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + + +void abort (void); +struct a +{ + int i; +} *a; +int f(void) +{ + int *ii = &a->i; + void *l; + a->i = 1; + if (*ii) + l = &&l1; + else + l = &&l2; + goto *l; +l1: + return 0; +l2: + abort (); +} + + +/* { dg-final { scan-tree-dump-times "&" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "abort" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr17598.c b/gcc/testsuite/gcc.dg/tree-ssa/pr17598.c new file mode 100644 index 000000000..ac912a2b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr17598.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +struct f +{ + int i; + int j; +}; + +struct g +{ + int i; + struct f j; + struct f *k; +}; + +int foo(struct f *x, struct f *y) +{ + return &x->j == &y->j; /* x == y */ +} + +struct f y; +int bar(struct f *x) +{ + return &x->j == &y.j; /* x == &y */ +} + +struct g yy; +int foobar(struct g *x) +{ + return &x->j.i == &yy.j.i; /* x == &yy */ +} +int foobar2(struct g *x) +{ + return &x->k->i == &yy.k->i; /* x->k == yy.k */ +} + +/* { dg-final { scan-tree-dump-times "x == y" 1 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "x == &y" 2 "gimple" } } */ +/* { dg-final { scan-tree-dump "x->k" "gimple" } } */ +/* { dg-final { scan-tree-dump "yy.k" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr18133-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr18133-1.c new file mode 100644 index 000000000..f225f662d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr18133-1.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized-blocks" } */ + +void foo (void) +{ +void *p; +p = &&L0; +goto *p; +L0: +return; +} + +/* The goto &L0 should have been optimized away during CFG + cleanups. */ +/* { dg-final { scan-tree-dump-times "goto &L0" 0 "optimized" } } */ + +/* There should not be any abnormal edges as DOM removed the + computed goto. */ + +/* { dg-final { scan-tree-dump-times "ab" 0 "optimized" } } */ + +/* And verify that we have fixed the fallthru flag as well. + After DOM we will have two fallthru edges (e->0, 0->1), + but in the dump files we mention the 0->1 two times. So + scan for 3 instances of "fallthru". */ + +/* { dg-final { scan-tree-dump-times "fallthru" 3 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr18133-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr18133-2.c new file mode 100644 index 000000000..9d04ded45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr18133-2.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized-blocks" } */ + +int c, d; + +int +bar (int a) +{ + void *p; + int b; + + if (a!=0) + { + b = 3; + p = &&L0; + } + else + { + b = 5; + p = &&L1; + } + + goto *p; + + L0: + c = b; + return 1; + + L1: + d = b; + return 0; +} + +/* The both paths to the block containing the goto *p should + have been threaded, thus eliminating the need for the goto *p. */ + +/* { dg-final { scan-tree-dump-times "goto p" 0 "optimized" } } */ + +/* There should not be any abnormal edges as DOM removed the + computed goto. */ + +/* { dg-final { scan-tree-dump-times "ab" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c b/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c new file mode 100644 index 000000000..783d598a0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr18134.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int foo (int a) +{ +void *p; +if (a!=0) + p = &&L0; +else + p = &&L1; +goto *p; +L0: +return 1; +L1: +return 0; +} + +/* Everything should have been cleaned up leaving a simple + return statement. */ +/* { dg-final { scan-tree-dump-times "= a_..D. != 0" 1 "optimized" } } */ + +/* There should not be any abnormal edges as DOM removed the + computed gotos. */ + +/* { dg-final { scan-tree-dump-times "ab" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19055-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19055-2.c new file mode 100644 index 000000000..739d69c0e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19055-2.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ +int f1(int a,int b,int c,int d) +{ + return ((a&d)|(b&c)) ^ (b&c); +} + +int f2(int a,int b,int c,int d) +{ + return (b&c) ^ ((a&d)|(b&c)); +} + +int f3(int a,int b,int c,int d) +{ + return ((b&c)|(a&d)) ^ (b&c); +} + +int f4(int a,int b,int c,int d) +{ + return (b&c) ^ ((b&c)|(a&d)); +} + +/* There should be no ^, 4 ~ and 12 &. */ +/* { dg-final { scan-tree-dump-times "\\^" 0 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "~" 4 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "&" 12 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19055.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19055.c new file mode 100644 index 000000000..055a96c1c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19055.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ +int f1(int a,int b) +{ + return (a|b) ^ b; +} +int f2(int a,int b) +{ + return (b|a) ^ b; +} +int f3(int a,int b) +{ + return b^(a|b); +} +int f4(int a,int b) +{ + return b^(b|a); +} +/* There should be no ^, 4 ~ and 4 &. */ +/* { dg-final { scan-tree-dump-times "\\^" 0 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "~" 4 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "&" 4 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c new file mode 100644 index 000000000..906132c69 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-1.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wunsafe-loop-optimizations" } */ +extern void g(void); + +void +f (unsigned n) +{ + unsigned k; + for(k = 0;k <= n;k++) /* { dg-warning "cannot optimize.*infinite loops" } */ + g(); + + for(k = 0;k <= n;k += 4) /* { dg-warning "cannot optimize.*overflow" } */ + g(); + + /* We used to get warning for this loop. However, since then # of iterations + analysis improved, and we can now prove that this loop does not verflow. + This is because the only case when it would overflow is if n = ~0 (since + ~0 is divisible by 5), and this cannot be the case, since when we got + here, the previous loop exited, thus there exists k > n. */ + for(k = 5;k <= n;k += 5) + g(); + + /* So we need the following loop, instead. */ + for(k = 4;k <= n;k += 5) /* { dg-warning "cannot optimize.*overflow" } */ + g(); + + for(k = 15;k >= n;k--) /* { dg-warning "cannot optimize.*infinite" } */ + g(); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19210-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-2.c new file mode 100644 index 000000000..9116e97ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19210-2.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -funsafe-loop-optimizations -Wunsafe-loop-optimizations" } */ +extern void g(void); + +void +f (unsigned n) +{ + unsigned k; + for(k = 0;k <= n;k++) /* { dg-warning "assuming.*not infinite" } */ + g(); + + for(k = 5;k <= n;k += 4) /* { dg-warning "assuming.*not overflow" } */ + g(); + + /* We used to get warning for this loop. However, since then # of iterations + analysis improved, and we can now prove that this loop does not verflow. + This is because the only case when it would overflow is if n = ~0 (since + ~0 is divisible by 5), and this cannot be the case, since when we got + here, the previous loop exited, thus there exists k > n. */ + for(k = 5;k <= n;k += 5) + g(); + + for(k = 4;k <= n;k += 5) /* { dg-warning "assuming.*not overflow" } */ + g(); + + for(k = 15;k >= n;k--) /* { dg-warning "assuming.*not infinite" } */ + g(); + +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19431.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19431.c new file mode 100644 index 000000000..1c87acbdd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19431.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +/* We want this optimized as +<bb 2>: + if (k != 0) goto <L2>; else goto <L3>; + +<L3>:; + i1 = j1; + +<L2>:; + return i1; + + This requires that i1 and j1 are changed into registers after they + no longer have their address taken. */ + +int f(int k, int i1, int j1) +{ + int *f1; + if(k) + f1 = &i1; + else + f1 = &j1; + return *f1; +} + +/* { dg-final { scan-tree-dump "i1_. = PHI <i1_\[^,\]*, j1_\[^>\]*>" "optimized" } } */ +/* { dg-final { scan-tree-dump "return i1_.;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19590.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19590.c new file mode 100644 index 000000000..1be1119da --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19590.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ivopts" } */ + +void vnum_test8(int *data) +{ + int i; + int stop = data[3]; + int m = data[4]; + int n = m; + for (i=1; i<stop; i++) { + int k = data[2]; + data[k] = 2; + data[0] = m - n; + k = data[1]; + m = m + k; + n = n + k; + } +} + +/* Using the SCEV analysis, this loop should be transformed to: + + | void vnum_result8(int *data) + |{ + | int i; + | int stop = data[3]; + | for (i=1; i<stop; i++) { + | int k = data[2]; + | data[k] = 2; + | data[0] = 0; + | } + |} + +*/ + +/* { dg-final { scan-tree-dump-times "= 0;" 1 "ivopts"} } */ +/* { dg-final { scan-tree-dump-times "= 2;" 1 "ivopts"} } */ +/* { dg-final { cleanup-tree-dump "ivopts" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr19633.c b/gcc/testsuite/gcc.dg/tree-ssa/pr19633.c new file mode 100644 index 000000000..01c7eec31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr19633.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-ssa-vops" } */ +struct S +{ + int w, x, y, z; +}; +struct T +{ + int r; + struct S s; +}; +void bar (struct S, int); +void +foo (int a, struct T b) +{ + struct S x; + struct S *c = &x; + if (a) + c = &b.s; + bar (*c, a); +} + +/* Make sure that .GLOBAL_VAR is not created when there are no + clobbering calls. */ +/* { dg-final { scan-tree-dump-times "GLOBAL_VAR" 0 "ssa"} } */ +/* { dg-final { cleanup-tree-dump "ssa" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20139.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20139.c new file mode 100644 index 000000000..016ad004e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20139.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/20139 + This testcase is derived from gcc.dg/20020720-1.c. Here we check + that the optimization happens at tree level. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +extern double fabs (double); +extern void link_error (void); + +void +foo (double x) +{ + double p, q; + + p = fabs (x); + q = 0.0; + if (p < q) + link_error (); +} + +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20470.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20470.c new file mode 100644 index 000000000..b0d7492de --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20470.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +/* PR tree-optimization/20470: + Missing fold to abs(x) when x == MINUS_EXPR. */ +#define abs(x) ((x) >= 0 ? (x) : -(x)) + +int i,j,k; +void f1() +{ + i = abs(j-k); +} + +/* { dg-final { scan-tree-dump-times "ABS_EXPR" 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20490.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20490.c new file mode 100644 index 000000000..8edc35e8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20490.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ftree-pre" } */ +static int a; +static int b; + +typedef int gint; + +int blah () +{ + gint x = a; + gint y = b; + + x *= (x < 0) ? -1 : 0; + y *= (y < 0) ? -1 : 0; + + return (y * x); + +} + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c new file mode 100644 index 000000000..1c3dbf9fd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20657.c @@ -0,0 +1,18 @@ +/* PR tree-optimization/20657 + VRP did not pick up a conditional equivalence from the first "if" + statement, which was needed to eliminate the second "if" statement. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */ + +int +foo (int a) +{ + if (a == 0) + if (a == 0) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c new file mode 100644 index 000000000..3ddf48e6f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20701.c @@ -0,0 +1,41 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining" } */ + +typedef struct { + int code; +} *rtx; + +static inline void *zero () +{ + return 0; +} +static inline int three () +{ + return 3; +} + +int +can_combine_p (rtx insn, rtx elt) +{ + rtx set; + + set = zero (); + if (insn->code == three ()) + set = insn; + else + { + set = elt; + if (set == zero ()) + return 0; + } + + if (set == zero ()) + return 1; + + return 0; +} + +/* Target with fno-delete-null-pointer-checks should not fold checks */ +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 0" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 0" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c new file mode 100644 index 000000000..ce62fa3f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20702.c @@ -0,0 +1,31 @@ +/* PR tree-optimization/20702 + VRP did not insert ASSERT_EXPRs into dominator dominator children + of a basic block ending with COND_EXPR unless the children are also + immediate successors of the basic block. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */ + +extern void bar (int); + +int +foo (int *p, int b) +{ + int a; + + if (b) + bar (123); + else + bar (321); + + a = *p; + if (p == 0) + return 0; + + return a; +} + +/* Target with fno-delete-null-pointer-checks should not fold checks */ +/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20739.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20739.c new file mode 100644 index 000000000..c1e7b58e3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20739.c @@ -0,0 +1,24 @@ +/* PR middle-end/20739 */ + +/* dg-do compile */ +/* dg-options "-O" */ + +/* We used to fail to compile this because gimplification dropped the + conversion that added the const qualifier to the sub-expression + involving baz, and then immediately noticed and reported its + absence. */ + +typedef struct +{ + char chars[5]; +} +baz_t; + +extern baz_t * baz; + +extern void foo (baz_t); +int +bar (const baz_t * ls) +{ + foo (ls == 0 ? *(&baz[0]) : *ls); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20742.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20742.c new file mode 100644 index 000000000..21d6eb63c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20742.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +#define TEN(x) x x x x x x x x x x +#define THOUSAND(x) TEN (TEN (TEN (x))) + +int +foo (int x, int y) +{ + register int a = y + 57; + register int b = y + 31; + + while (x-- > 0) + { + THOUSAND (a += b; b -= a;) + } + return a + b; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20913.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20913.c new file mode 100644 index 000000000..fb5461a26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20913.c @@ -0,0 +1,34 @@ +/* PR tree-optimization/20913 + COPY-PROP did not fold COND_EXPR, blocking some copy propagation + opportunities. */ + +/* { dg-do link } */ +/* { dg-options "-O2 -fno-tree-dominator-opts" } */ + +int +foo (int a, int b, int c, int d) +{ + int x, y; + + b = a; + if (a == b) + x = c; + else + { + link_error (); + x = d; + } + + if (x == c) + return a; + else + { + link_error (); + return b; + } +} + +main() +{ + foo (1, 2, 3, 4); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr20933.c b/gcc/testsuite/gcc.dg/tree-ssa/pr20933.c new file mode 100644 index 000000000..d32d6003e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr20933.c @@ -0,0 +1,70 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern __SIZE_TYPE__ strlen (__const char *__s) + __attribute__ ((__nothrow__)) __attribute__ ((__pure__)) __attribute__ ((__nonnull__ (1))); +extern char *strcpy (char *__restrict __dest, __const char *__restrict __src) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); +extern char *getenv (__const char *__name) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); +extern int access (__const char *__name, int __type) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))); +extern void * xmalloc (__SIZE_TYPE__) __attribute__ ((__malloc__)); + +static __inline__ const char * +try (const char *dir, const char *base) +{ + if (base != 0) + return base; + if (dir != 0 + && access (dir, 4 | 2 | 1) == 0) + return dir; + return 0; +} + +static const char tmp[] = { '/', 't', 'm', 'p', 0 }; +static const char usrtmp[] = +{ '/', 'u', 's', 'r', '/', 't', 'm', 'p', 0 }; +static const char vartmp[] = +{ '/', 'v', 'a', 'r', '/', 't', 'm', 'p', 0 }; + +static char *memoized_tmpdir; +char * +choose_tmpdir (void) +{ + const char *base = 0; + char *tmpdir; + unsigned int len; + + if (memoized_tmpdir) + return memoized_tmpdir; + + base = try (getenv ("TMPDIR"), base); + base = try (getenv ("TMP"), base); + base = try (getenv ("TEMP"), base); + + + base = try ("/tmp", base); + + + + base = try (vartmp, base); + base = try (usrtmp, base); + base = try (tmp, base); + + + if (base == 0) + base = "."; + + + + len = strlen (base); + tmpdir = xmalloc (len + 2); + strcpy (tmpdir, base); + /* Alias analysis was associating read-only memory tags to pointers + that are not read-only. We would then not issue any V_MAY_DEF in + this store. */ + tmpdir[len] = '/'; + tmpdir[len+1] = '\0'; + + memoized_tmpdir = tmpdir; + return tmpdir; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c new file mode 100644 index 000000000..84280b39c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21001.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/21001 + VRP did not insert ASSERT_EXPRs when the variable tested in a + COND_EXPR is a single-use variable. By propagating the definition + of the single-use variable into the COND_EXPR, we can get useful + range infomation out of the conditional. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */ + +int +foo (int a) +{ + int b = a != 0; + if (b) + if (a != 0) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c new file mode 100644 index 000000000..de2595aee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21029.c @@ -0,0 +1,118 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fwrapv" } */ + +/* PR tree-optimization/21029 + + f() used to get optimized to an infinite loop by tree-vrp, because + j is assumed to be non-negative. Even though the conversion from + unsigned to signed has unspecified results if the expression value + is not representable in the signed type, the compiler itself (e.g., + the Ada front end) depends on wrap-around behavior. */ + +unsigned int f(void) { + unsigned char i = 123; + signed char j; + + do + if ((j = (signed char) i) < 0) + break; + else + i++; + while (1); + + return i; +} + +/* Now let's torture it a bit further. Narrowing conversions need + similar treatment. */ + +unsigned int f1 (void) { + unsigned short i = 123; + signed char j; + + do + if ((j = (signed char) i) < 0) + break; + else + i++; + while (1); + + return i; +} + +/* And so do widening conversions. */ + +unsigned int f2 (void) { + unsigned char i = 123; + signed short j; + + do + if ((j = (signed short) (signed char) i) < 0) + break; + else + i++; + while (1); + + return i; +} + +/* Check same-sign truncations with an increment that turns into + decrements. */ + +unsigned int f3 (void) { + signed short i = 5; + signed char j; + + do + if ((j = (signed char) i) < 0) + break; + else + i += 255; + while (1); + + return i; +} + +/* Check that the truncation above doesn't confuse the result of the + test after a widening conversion. */ + +unsigned int f4 (void) { + signed short i = -123; + signed int j; + + do + if ((j = (signed int) (signed char) i) > 0) + break; + else + i += 255; + while (1); + + return i; +} + +/* Even if we omit the widening truncation, the narrowing truncation + is implementation-defined. */ + +unsigned int f5 (void) { + signed long i = -123; + signed char j; + + do + if ((j = (signed char) i) > 0) + break; + else + i += 255; + while (1); + + return i; +} + +int main (void) { + f (); + f1 (); + f2 (); + f3 (); + f4 (); + f5 (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c new file mode 100644 index 000000000..df200d564 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21031.c @@ -0,0 +1,20 @@ +/* PR tree-optimization/21031 + + Make sure that a != 0 is propagated into the "if" statement. */ + +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-forwprop1-details" } */ + +int +foo (int a) +{ + int b = a != 0; + unsigned char c = b; + if (c) + return 1; + else + return 0; +} + +/* { dg-final { scan-tree-dump-times "Replaced" 2 "forwprop1"} } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c new file mode 100644 index 000000000..f924d26cc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21086.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-dce1" } */ + +int +foo (int *p) +{ + int a = *p; + int b = p != 0; + + *p = b; + + if (b) + return a; + else + return 0; +} + +/* Target with fno-delete-null-pointer-checks should not fold checks */ +/* { dg-final { scan-tree-dump "Folding predicate " "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-not "b_. =" "dce1" { target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump "b_. =" "dce1" { target { avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "dce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c new file mode 100644 index 000000000..8e32e4217 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21090.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int g, h; + +int +foo (int a) +{ + int *p; + + if (a) + p = &g; + else + p = &h; + + if (p != 0) + return 1; + else + return 0; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21171.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21171.c new file mode 100644 index 000000000..9f7278378 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21171.c @@ -0,0 +1,29 @@ +/* PR 21171. Ivopts should not rewrite references to volatile memory. */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +typedef unsigned int u_int32_t; +typedef unsigned char u_int8_t; + +#define AIC_VECTORS 32 + +typedef volatile struct AT91RM9200_regs { + u_int32_t SVR[AIC_VECTORS]; +} AT91RM9200_regs_t; + +#define CPUReg ((AT91RM9200_regs_t*)0xFFF00000) + +extern const u_int32_t __IntTable[AIC_VECTORS]; + +int main() +{ + int c; + + for (c = 0; c < AIC_VECTORS; c++) + CPUReg->SVR[c] = __IntTable[c]; + + return 0; +} + +/* { dg-final { scan-tree-dump-times "SVR" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21294.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21294.c new file mode 100644 index 000000000..567e6366a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21294.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/21294 + VRP did not notice that an address of the form &p->i is nonnull + when p is known to be nonnull. In this testcase, noticing that + allows us to eliminate the second "if" statement. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */ + +struct f { + int i; +}; + +int +foo (struct f *p) +{ + if (p != 0) + if (&p->i != 0) + return 123; + return 0; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c new file mode 100644 index 000000000..8dd75ccc5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21332.c @@ -0,0 +1,28 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +// this testcase fails also on amd64: + +extern void abort (void); + +int f () +{ + return -1; +} + +int main () +{ + int b, c, i; + + b = 0; + c = f (); + if (c <= 0) + { + c = -c; + for (i = 0; i < c; i++) + b = 1; + if (!b) + abort (); + } + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c new file mode 100644 index 000000000..4a2c82143 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21417.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dom2-details" } */ + +struct tree_common +{ + int code; +}; +union tree_node +{ + struct tree_common common; +}; +typedef union tree_node *tree; + +extern tree test (tree, int, int); +extern tree foo (void); +extern void abort (void) __attribute__ ((__noreturn__)); + +tree +test (tree expr, int t, int D17630) +{ + int __i; + +L0: + if (expr->common.code != 142) goto L23; else goto L2; + +L2: + __i = 0; + goto L10; + +L10: + __i = __i + 1; + if (D17630 != __i) goto L8; else goto L19; + +L8: + if (t) goto L15; else goto L10; + +L15: + expr = foo (); + if (expr->common.code != 142) goto L23; else goto L0; + +L19: + abort (); + +L23: + return expr; +} + + +/* We should thread the backedge to the top of the loop; ie we only + execute the if (expr->common.code != 142) test once per loop + iteration. */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 1 "dom2" } } */ +/* { dg-final { cleanup-tree-dump "dom2" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c new file mode 100644 index 000000000..01777f6e6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21458.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void g (void); +extern void bar (int); + +int +foo (int a) +{ + int i; + + for (i = 1; i < 100; i++) + { + if (i) + g (); + } +} + +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21463.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21463.c new file mode 100644 index 000000000..3f63cdd8e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21463.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-phiprop-details" } */ + +struct f +{ + int i; +}; + +int g(int i, int c, struct f *ff, int g) +{ + int *t; + if (c) + t = &i; + else + t = &ff->i; + return *t; +} + +/* { dg-final { scan-tree-dump-times "Inserting PHI for result of load" 1 "phiprop" } } */ +/* { dg-final { cleanup-tree-dump "phiprop" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c new file mode 100644 index 000000000..34f4a01db --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21559.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + +static int blocksize = 4096; + +int bar (int); + +void foo (void) +{ + int toread; + int bytes; + static char eof_reached = 0; + + toread = blocksize; + bytes = 1; + + while (toread != 0) + { + bytes = bar (toread); + if (bytes <= 0) + { + if (bytes < 0) + continue; + break; + } + toread -= bytes; + } + + if (bytes == 0) + eof_reached = 1; +} + + +/* First, we should simplify the bits < 0 test within the loop. */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ + +/* Second, we should thread the edge out of the loop via the break + statement. We also realize that the final bytes == 0 test is useless, + and thread over it. */ +/* { dg-final { scan-tree-dump-times "Threaded jump" 3 "vrp1" } } */ + +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21563.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21563.c new file mode 100644 index 000000000..8e6c57850 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21563.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/21563 + Make sure VRP folds the second "if" statement. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-vrp1-details" } */ + +int +foo (int a) +{ + if (a > 1) + if (a == 0) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate" 1 "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21574.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21574.c new file mode 100644 index 000000000..fc33d74e9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21574.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +int +foo (int *p) +{ + *p = 0; + return *p; +} + +/* The store to *p should be propagated to the load statement. */ +/* { dg-final { scan-tree-dump "Replaced \\\*p_.\\\(D\\\) with 0" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21582.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21582.c new file mode 100644 index 000000000..0f5dc9ec1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21582.c @@ -0,0 +1,28 @@ +/* { dg-do link } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +static inline void do_thing(char *s, int *p, char *q) +{ + /* This should be folded away. */ + if (s == 0 || q == 0) + link_error (); + + /* This should not be folded as 'p' is not marked nonnull. */ + if (p) + *p = 3; +} + +void __attribute__((nonnull (1, 3))) do_other_thing(char *s, int *p, char *q) +{ + do_thing(s, p, q); +} + +int i; + +main() +{ + do_other_thing ("xxx", &i, "yyy"); +} + +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*" 0 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c new file mode 100644 index 000000000..c1a48c04b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21658.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/21658 + CCP did not propagate an ADDR_EXPR far enough, preventing the "if" + statement below from being folded. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-ccp1-details" } */ + +void link_error (void); + +void +f (void) +{ + int a[10]; + int *p = &a[5]; + int *q = p - 1; + if (q != &a[4]) + link_error (); +} + +/* { dg-final { scan-tree-dump-times "Folded into: if " 1 "ccp1"} } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c new file mode 100644 index 000000000..c95714ab9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21829.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int test(int v) +{ + int x = 0; + int u; + for (u=0;u<2;u++) + { + if (u>v) + { + if (u%2==1) + x++; + } + } + return x; +} + +/* This should be unrolled and optimized into conditional set of return value "v < 0". */ + +/* { dg-final { scan-tree-dump-not "if \\(" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c new file mode 100644 index 000000000..decbcaf3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21959.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +unsigned char c[0xFF]; +void f(void) +{ + unsigned char i; + c[128] = 128; + i = 0; + while (1) + { + /* This predicate should not be folded out. */ + if (((signed char) i) < 0) break; + c[i] = ' '; + i++; + } +} + +/* { dg-final { scan-tree-dump-times "Folding predicate " 0 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr21985.c b/gcc/testsuite/gcc.dg/tree-ssa/pr21985.c new file mode 100644 index 000000000..19ad0f113 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr21985.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct +{ + struct + { + int a; + int b; + } a[100]; +} a; + +typedef __SIZE_TYPE__ size_t; +void foo(size_t); +size_t *bar (void); + +int +main (void) +{ + size_t *b = bar (); + + /* This should be folded. */ + foo (&a.a[50].a - &a.a[33].b); + foo ((size_t) &a.a[50].b - (size_t) &a); + + /* And this should not. */ + foo ((size_t) &b - (size_t) b); + return 0; +} + +/* Two of the calls to foo should be folded to just foo(constant). */ + +/* { dg-final { scan-tree-dump-times "foo \\(\[0-9\]*\\)" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22018.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22018.c new file mode 100644 index 000000000..d4d332c2f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22018.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options -O2 } */ + +void abort (void); +void g(int); +void f(int l) +{ + unsigned i; + for (i = 0; i < l; i++) + { + int y = i; + /* VRP was wrongfully computing z's range to be [0, 0] instead + of [-INF, 0]. */ + int z = y*-32; + g(z); + } +} + +void g(int i) +{ + static int x = 0; + if (i == 0) + x ++; + if (x > 1) + abort (); +} + +int main(void) +{ + f(3); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22026.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22026.c new file mode 100644 index 000000000..7e6914d9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22026.c @@ -0,0 +1,49 @@ +/* PR tree-optimization/22026 + VRP used think that ~[0,0] + ~[0,0] = ~[0,0], which is wrong. The + same applies to subtraction and unsigned multiplication. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int +plus (int x, int y) +{ + if (x != 0) + if (y != 0) + { + int z = x + y; + if (z != 0) + return 1; + } + return 0; +} + +int +minus (int x, int y) +{ + if (x != 0) + if (y != 0) + { + int z = x - y; + if (z != 0) + return 1; + } + return 0; +} + +int +mult (unsigned x, unsigned y) +{ + if (x != 0) + if (y != 0) + { + unsigned z = x * y; + if (z != 0) + return 1; + } + return 0; +} + +/* None of the predicates can be folded in these functions. */ +/* { dg-final { scan-tree-dump-times "Folding predicate" 0 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c new file mode 100644 index 000000000..73bda118f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22051-1.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + +void *arf (); +int +foo() +{ + void *p = arf (); + + if ((void (*)(void))p != 0) + return 1; + else + return 2; +} + +/* The cast to a function pointer type must remain after all optimizations + are complete so that function pointer canonicalization works on those + targets which require it. */ +/* { dg-final { scan-tree-dump-times "= \\(void \\(\\*<.*>\\) \\(void\\)\\) p_" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22051-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22051-2.c new file mode 100644 index 000000000..bcbbb73c6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22051-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -w" } */ + + + + +void *arf (); +int +foo() +{ + void (*q)(void); + int r = q; + + if (r != 0) + return 1; + else + return 2; +} + +/* The cast to an int type must remain after all optimizations are complete + so that we do not try to canonicalize a function pointer for the + comparison when no such canonicalization is wanted. */ +/* { dg-final { scan-tree-dump-times "r_. = \\(int\\) q" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22117.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22117.c new file mode 100644 index 000000000..d265d5e2c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22117.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/22117 + VRP used think that &p[q] is nonzero even though p and q are both + known to be zero after entering the first two "if" statements. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +void +foo (int *p, int q) +{ + if (p == 0) + { + if (q == 0) + { + int *r = &p[q]; + if (r != 0) + link_error (); + } + } +} + +/* { dg-final { scan-tree-dump-times "Folding predicate r_.* != 0B to 0" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22171.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22171.c new file mode 100644 index 000000000..6a26c56d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22171.c @@ -0,0 +1,28 @@ +/* { dg-options "-O2" } */ + +static unsigned int old_serial_port_irq[10]; + +static struct uart_8250_port { + volatile unsigned int slock; + unsigned int irq; +} serial8250_ports[10]; + +static __inline__ __attribute__((always_inline)) int irq_canonicalize(int irq) +{ + return ((irq == 2) ? 9 : irq); +} + +void serial8250_isa_init_ports(void) +{ + struct uart_8250_port *up; + int i; + + for (i = 0, up = serial8250_ports; i < 10; i++, up++) + up->irq = irq_canonicalize(old_serial_port_irq[i]); +} + +int main(void) +{ + serial8250_isa_init_ports(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22230.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22230.c new file mode 100644 index 000000000..4d6534909 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22230.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -ftree-vrp" } */ + +/* PR tree-optimization/22230 + + The meet of the ranges in "i*i" was not computed correctly, leading + gcc to believe that a was equal to 0 after the loop. */ + +extern void abort (void) __attribute__((noreturn)); + +int main (void) +{ + long a, i; + + for (i = 0; i < 5; i++) + a = i * i; + if (a != 16) + abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22236.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22236.c new file mode 100644 index 000000000..1986c2f0c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22236.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -fno-tree-vrp -fwrapv" } */ + +/* PR tree-optimization/22236 + + Avoid conversion of (signed char) {(uchar)1, +, (uchar)1}_x when + it is not possible to prove that the scev does not wrap. + + In this PR, a sequence 1, 2, ..., 255 has to be converted to + signed char, but this would wrap: 1, 2, ..., 127, -128, ... The + result should not be a linear scev {(schar)1, +, (schar)1}_x. + The conversion should be kept: (schar) {(uchar)1, +, (uchar)1}_x. + */ + +void abort(void); + +static inline void +foo (signed char a) +{ + int b = a - 0x7F; + if (b > 1) + abort(); +} + +int main() +{ + unsigned char b; + for(b = 0; b < 0xFF; b++) + foo (b); + + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22321.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22321.c new file mode 100644 index 000000000..64a94ab2d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22321.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-tree-vrp -fno-tree-copy-prop -fno-tree-ccp -fdump-tree-optimized" } */ + + +volatile int x; + +int main () +{ + volatile int *vip; + vip = &x; + volatile int *cvip; + cvip = vip; + + if (vip != cvip) return -1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr22591.c b/gcc/testsuite/gcc.dg/tree-ssa/pr22591.c new file mode 100644 index 000000000..f1f5ec849 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr22591.c @@ -0,0 +1,56 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +void abort (); + +typedef struct _Node +{ + struct _Node *next, *prev; +} Node; + +void __attribute__ ((noinline)) append (Node * q, Node * p) +{ + p->next = q; + p->prev = q; + q->next = p; + q->prev = p; +} + +inline void +swap (Node ** a, Node ** b) +{ + Node *tmp = *a; + *a = *b; + *b = tmp; +} + +/* Miscompilation seems to happen here. If one removes the if condition + (which should be true) the program works fine. */ +void +ListSwap (Node * x, Node * y) +{ + Node *tmp; + if (x->next) + { + swap (&x->next, &y->next); + swap (&x->prev, &y->prev); + x->next->prev = x->prev->next = x; + y->next->prev = y->prev->next = y; + } +} + +int +main () +{ + Node A, A1, B, B1; + + append (&A, &A1); + append (&B, &B1); + + ListSwap (&A, &B); + + if (&A != A.next->prev) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23048.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23048.c new file mode 100644 index 000000000..7dc67ea29 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23048.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-vectorize" } */ + +void f(unsigned char *mem) +{ + int i; + + for(i=0;i<4;i++) { + while(mem[i]==0) ; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23086.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23086.c new file mode 100644 index 000000000..206b92de1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23086.c @@ -0,0 +1,35 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +extern void link_error (void); +extern void abort (void); + +int *t; +int __attribute__((noinline)) g(int *a) +{ + t = a; + *a = 2; +} + +void __attribute__((noinline)) f(int *a) +{ + int b; + b = 1; + g(&b); + b = 2; + *a = 1; + if (b != 2) + link_error(); +} + +int main(void) +{ + int t; + f(&t); + if (t != 1) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-not "link_error" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23109.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23109.c new file mode 100644 index 000000000..39add724e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23109.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -funsafe-math-optimizations -ftrapping-math -fdump-tree-recip -fdump-tree-lim" } */ +/* { dg-warning "-fassociative-math disabled" "" { target *-*-* } 1 } */ + +double F[2] = { 0., 0. }, e = 0.; + +int main() +{ + int i; + double E, W, P, d; + + /* make sure the program crashes on FP exception */ + unsigned short int Mask; + + W = 1.; + d = 2.*e; + E = 1. - d; + + for( i=0; i < 2; i++ ) + if( d > 0.01 ) + { + P = ( W < E ) ? (W - E)/d : (E - W)/d; + F[i] += P; + } + + return 0; +} + +/* LIM only performs the transformation in the no-trapping-math case. In + the future we will do it for trapping-math as well in recip, check that + this is not wrongly optimized. */ +/* { dg-final { scan-tree-dump-not "reciptmp" "lim1" } } */ +/* { dg-final { scan-tree-dump-not "reciptmp" "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23115.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23115.c new file mode 100644 index 000000000..61408e47a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23115.c @@ -0,0 +1,33 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-vectorize" } */ + +extern void abort (void); + +#define MIN2(a,b) (((a)<(b)) ? (a) : (b)) +#define MAX2(a,b) (((a)>(b)) ? (a) : (b)) + +double p[2] = { 4., 5. }; + +int main() +{ + long j; + double R, n, x; +#if __SIZEOF_DOUBLE__ >= 8 + n = 1.e300; + x = -1.e300; +#else + n = 1.e30; + x = -1.e30; +#endif + for( j=0; j < 2; j++ ) + { + x = MAX2(x,p[j]); + n = MIN2(n,p[j]); + } + R = x-n; + + if( R < 0.1 ) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23192.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23192.c new file mode 100644 index 000000000..2a606a5c2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23192.c @@ -0,0 +1,23 @@ +/* { dg-options "-O2" } */ +/* { dg-do run } */ + +struct S { int i; } s; + +void f (struct S *q) +{ + int a, *p; + p = &a; + if (q) + p = &q->i; + *p = 1; +} + +void abort (void); + +int main (void) +{ + f (&s); + if (s.i != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23234.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23234.c new file mode 100644 index 000000000..3a3869815 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23234.c @@ -0,0 +1,58 @@ +/* The problem in this PR was mostly finding a suitable place to insert + the reciprocals of the function arguments. This test case tries to + test three possible ways of how this may go wrong. */ +/* { dg-options "-O2 -ffast-math" } */ +/* { dg-do compile } */ + +/* The original test case. */ +double +f1 (double a, double b, double c) +{ + double y0; + double y1; + + if (a == 0.0) + { + y0 = -c / b; + return y0; + } + y0 = c / b; + y1 = a / b; + return y0 * y1; +} + +/* Labels may end up in the middle of a block. Also bad. */ +double +f2 (double a, double b, double c) +{ + double y0; + double y1; + +a_label: +another_label: + if (a == 0.0) + { + y0 = -c / b; + return y0; + } + y0 = c / b; + y1 = a / b; + return y0 * y1; +} + +/* Uses must still be dominated by their defs. */ +double +f3 (double a, double b, double c) +{ + double y0; + double y1; + + y0 = -c / b; + if (a == 0.0) + { + return y0; + } + y0 = c / b; + y1 = a / b; + return y0 * y1; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23294.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23294.c new file mode 100644 index 000000000..ed890fa55 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23294.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int f1(int a) +{ + return a*6-a; +} + +int f2(int a) +{ + return a*4+a; +} + +int f3(int a) +{ + return 2*a + 3*a; +} + +int f4(int a, int b) +{ + return 2*a + 6*b; +} + +int f5(int a, int b) +{ + return 2*a - 6*b; +} + +int f6(int a, int b) +{ + return 6*a - 2*b; +} + +/* { dg-final { scan-tree-dump-times "a_..D. \\\* 5" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\\* 2" 3 "optimized" } } */ +/* { dg-final { scan-tree-dump-not "\\\* 6" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23382.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23382.c new file mode 100644 index 000000000..fd74af8d6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23382.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-details" } */ +struct a +{ + int length; + int a1[256]; +}; + +void *malloc(__SIZE_TYPE__ size) __attribute__((malloc)); + +int f(void) +{ + struct a *a = malloc(sizeof(struct a)); + return a->length; +} +/* { dg-final { scan-tree-dump-times "Variable: HEAP" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23386.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23386.c new file mode 100644 index 000000000..d322f995b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23386.c @@ -0,0 +1,24 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int f[100]; +int g[100]; +unsigned char +f1 (int a, int b) +{ + __SIZE_TYPE__ ix; + if (a) + return 1; + for (ix = 4; ix--;) + if (f[ix] != g[ix]) + return 0; + return 1; +} + +int main(void) +{ + if (!f1 (0, 2)) + __builtin_abort(); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23391.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23391.c new file mode 100644 index 000000000..a5effbb15 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23391.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +void +foo (int N) +{ + int C; + double R; + + R = 0.0; + do + { + R += 0.001; + C = (int) (R * N); + if (-R * N <= R * N) + { + C++; + } + } + while (C < 0); + + return; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c new file mode 100644 index 000000000..1d30ac751 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23401.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +struct f +{ + struct { + int i; + } ff[10]; +}; + +struct f g; +int ffff(int i) +{ + int t1 = 0; + int i1 = g.ff[t1].i; + int i2 = g.ff[i].i; + return i1 + i2; +} + +/* We should not use extra temporaries apart from for i1 + i2. */ + +/* { dg-final { scan-tree-dump-times "int" 5 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23433.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23433.c new file mode 100644 index 000000000..464d4b542 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23433.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +double transport_sumexp(int numexp) +{ + int k,j; + double xk1 = 1.0; + for(k=1; k<=numexp;k++) + for(j=1;j<=3;j++) + xk1 += 1.0; + return xk1; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23434.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23434.c new file mode 100644 index 000000000..a21b95566 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23434.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +cblas_csyr2k (int N, void *A, int lda, float *B, int ldb, float *C, int k) +{ + int i, j; + for (;; k ++) + { + for (i = 0; i < N; i ++) + { + float t = ((float * ) A) [i]; + for (j = i; j < N; j ++) + { + C [i + j] = B [ldb] * ((float *) A) [k]; + C [lda] = 0 ; + } + } + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23455.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23455.c new file mode 100644 index 000000000..766dc2b33 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23455.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +unsigned long outcnt; +extern void flush_outbuf(void); + +void +bi_windup(unsigned int *outbuf, unsigned int bi_buf) +{ + unsigned long t1 = outcnt; + outbuf[t1] = bi_buf; + + unsigned long t2 = outcnt; + if (t2 == 16384) + flush_outbuf(); + + unsigned long t3 = outcnt; + outbuf[t3] = bi_buf; +} +/* We should eliminate one load of outcnt, which will in turn let us eliminate + one multiply of outcnt which will in turn let us eliminate + one add involving outcnt and outbuf. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "pre" {target { ! avr-*-* } } } } */ +/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "pre" {target { avr-*-* } } } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23546.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23546.c new file mode 100644 index 000000000..06324dfcb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23546.c @@ -0,0 +1,10 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ +typedef int m64 __attribute__ ((__vector_size__ (8))); + +void mmxCombineMaskU (m64 * mask, int width) +{ + while (--width >= 0) + *mask++ = (m64) 0LL; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c new file mode 100644 index 000000000..538139676 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23744.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-vrp1" } */ + +int g (int i, int j) +{ + int t = 0; + int i1; + + if (i == j) + t = 3; + for (i1 = 0; i1 < 10000; i1++) h(); + if (t != 5) + return 0; + else + return 1; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23777.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23777.c new file mode 100644 index 000000000..c2ad9b707 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23777.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +extern void f(char *const *); +void g (char **o) +{ + static const char *const multilib_exclusions_raw[] = { 0 }; + const char *const *q = multilib_exclusions_raw; + + f (o); + while (*q++) + f (o); +} + +/* The last DCE pass is able to remove the load from + multilib_exclusions_raw. */ + +/* { dg-final { scan-tree-dump-not "multilib_exclusions_raw" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c new file mode 100644 index 000000000..08916e4e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-1.c @@ -0,0 +1,32 @@ +/* PR middle-end/23848 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void bar1 (char *, int); +void foo1 (int size) +{ + char temp[size]; + temp[size-1] = '\0'; + bar1 (temp, size); +} + +void bar2 (char *, char *, char *, char *, int); +void foo2 (int size) +{ + char temp[size]; + temp[size-1] = '\0'; + { + char temp2[size]; + { + char temp3[size]; + { + char temp4[size]; + bar2 (temp, temp2, temp3, temp4, size); + } + } + } +} + +/* { dg-final { scan-tree-dump-not "__builtin_stack_save" "optimized"} } */ +/* { dg-final { scan-tree-dump-not "__builtin_stack_restore" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c new file mode 100644 index 000000000..c9691469d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-2.c @@ -0,0 +1,25 @@ +/* PR middle-end/23848 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void bar (char *, char *, char *, char *, int); +void foo (int size) +{ + char temp[size]; + temp[size-1] = '\0'; + { + char temp2[size]; + { + char temp3[size]; + { + char temp4[size]; + bar (temp, temp2, temp3, temp4, size); + } + } + bar (temp, temp2, (char *) 0, (char *) 0, size); + } +} + +/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c new file mode 100644 index 000000000..d2555049b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-3.c @@ -0,0 +1,28 @@ +/* PR middle-end/23848 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void bar (int, char *, char *, char *, char *, int); +void foo (int size) +{ + int i; + for (i = 0; i < size; i++) + { + char temp[size]; + temp[size-1] = '\0'; + { + char temp2[size]; + { + char temp3[size]; + { + char temp4[size]; + bar (i, temp, temp2, temp3, temp4, size); + } + } + } + } +} + +/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c new file mode 100644 index 000000000..66b21b81e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr23848-4.c @@ -0,0 +1,25 @@ +/* PR middle-end/23848 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void bar (char *, char *, char *, char *, int); +void foo (int size) +{ + char temp[size]; + temp[size-1] = '\0'; + { + char temp2[size]; + { + char temp3[size]; + { + char temp4[size]; + bar (temp, temp2, temp3, temp4, size); + } + } + __asm __volatile ("" : : "r" (&temp[0]), "r" (&temp2[0]) : "memory"); + } +} + +/* { dg-final { scan-tree-dump-times "__builtin_stack_save" 1 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "__builtin_stack_restore" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24117.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24117.c new file mode 100644 index 000000000..ffa5dd04c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24117.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef struct { + int x; + int z; +} Foo_t; + +char *xm; +void bar(void); + +void foo(void) +{ + Foo_t x; + x.x = 1; + x.z = 2; + xm = (char *)&x; + bar(); + /* We can't propagate x.z past bar, so this link_error should still be there. */ + if (x.z != 2) + link_error (); +} +/* { dg-final { scan-tree-dump-times "link_error" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24287.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24287.c new file mode 100644 index 000000000..c264fbcb2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24287.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int g1(int); +int h(int *a, int *b)__attribute__((pure)); +void link_error(); + +/* The calls to link_error should be eliminated, since nothing escapes to + non-pure functions. */ +int g(void) +{ + int t = 0, t1 = 2; + /* ??? That's not true. The pointers escape to the integer return + value which we do not track in PTA. */ + int t2 = h(&t, &t1); + if (t != 0) + link_error (); + if (t1 != 2) + link_error (); + /* ??? And it would finally escape here even if we did. */ + g1(t2); + if (t != 0) + link_error (); + if (t1 != 2) + link_error (); + return t2 == 2; +} +/* We are allowed to optimize the first two link_error calls. */ +/* { dg-final { scan-tree-dump-times "link_error" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24627.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24627.c new file mode 100644 index 000000000..c065eef84 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24627.c @@ -0,0 +1,67 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ +/* { dg-require-effective-target int32plus } */ + +extern void abort (void); +typedef unsigned int u_int32; + +typedef struct { + union {u_int32 Xl_ui;} Ul_i; + union {u_int32 Xl_uf;} Ul_f; +} l_fp; + +void +dolfptoa (short ndec) +{ + l_fp work, ftmp; + + work.Ul_i.Xl_ui = 0; + work.Ul_f.Xl_uf = 0x535f3d8; + + while (ndec > 0) + { + u_int32 lo_tmp; + u_int32 hi_tmp; + + ndec--; + work.Ul_i.Xl_ui = 0; + work.Ul_i.Xl_ui <<= 1; + if ((work.Ul_f.Xl_uf) & 0x80000000) + (work.Ul_i.Xl_ui) |= 0x1; + (work.Ul_f.Xl_uf) <<= 1; + + ftmp = work; + (work.Ul_i.Xl_ui) <<= 1; + if ((work.Ul_f.Xl_uf) & 0x80000000) + (work.Ul_i.Xl_ui) |= 0x1; + (work.Ul_f.Xl_uf) <<= 1; + + (work.Ul_i.Xl_ui) <<= 1; + if ((work.Ul_f.Xl_uf) & 0x80000000) + (work.Ul_i.Xl_ui) |= 0x1; + (work.Ul_f.Xl_uf) <<= 1; + + lo_tmp = ((work.Ul_f.Xl_uf) & 0xffff) + ((ftmp.Ul_f.Xl_uf) & 0xffff); + hi_tmp = (((work.Ul_f.Xl_uf) >> 16) & 0xffff) + + (((ftmp.Ul_f.Xl_uf) >> 16) & 0xffff); + + if (lo_tmp & 0x10000) + hi_tmp++; + + (work.Ul_f.Xl_uf) = ((hi_tmp & 0xffff) << 16) | (lo_tmp & 0xffff); + (work.Ul_i.Xl_ui) += (ftmp.Ul_i.Xl_ui); + + if (hi_tmp & 0x10000) + (work.Ul_i.Xl_ui)++; + + + if (!(work.Ul_i.Xl_ui < 10)) + abort (); + } +} + +int main() +{ + dolfptoa(6); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24670.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24670.c new file mode 100644 index 000000000..a5ff800d9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24670.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +__inline__ void +shift128Right (int count, long long int *z1Ptr) +{ + long long int z1; + if (count == 0); + else if (count < 64); + else + z1 = (count < 64) ? count : 0; + *z1Ptr = z1; +} + +float128_rem () +{ + signed int expDiff; + long long int aSig1; + long long int sigMean1; + if (-64 < expDiff) + shift128Right (-expDiff, &aSig1); + add128 (&sigMean1); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24689.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24689.c new file mode 100644 index 000000000..4fe74b658 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24689.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +extern void bar (unsigned int); + +int +foo (void) +{ + char buf[1] = { 3 }; + const char *p = buf; + const char **q = &p; + unsigned int ch; + switch (**q) + { + case 1: ch = 5; break; + default: ch = 0; break; + } + + bar (ch); + return ch; +} + +/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr2480.c b/gcc/testsuite/gcc.dg/tree-ssa/pr2480.c new file mode 100644 index 000000000..d7f7af4d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr2480.c @@ -0,0 +1,53 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +/* We have enough cascading at -O2 to cover the missed control-dependence + in SCCVN (which considers the link_error calls to clobber the structs). */ + +struct example +{ + char a; + int b; + char c; +} *ex1; + +extern void link_error(void); + +void +bar (void) +{ + ex1->a = 1; + ex1->b = 2; + ex1->c = 3; + + if (ex1->a != 1) + link_error (); + if (ex1->b != 2) + link_error (); + if (ex1->c != 3) + link_error (); + +} + +void +foo (struct example *ex2) +{ + ex2->a = 1; + ex2->b = 2; + ex2->c = 3; + + if (ex2->a != 1) + link_error (); + if (ex2->b != 2) + link_error (); + if (ex2->c != 3) + link_error (); + +} + +int main (void) +{ + bar (); + foo (ex1); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24840.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24840.c new file mode 100644 index 000000000..736dafdec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24840.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +typedef struct +{ + int tag, y; +} Object; + +void Err_Handler () __attribute__ ((__noreturn__)); + +int +P_Error (int argc, Object * argv) +{ + if (((argv[1]).tag >> 1) != 11) + Wrong_Type (argv[1], 11); + Err_Handler (argv[0], argv[1], argc - 2, argv + 2); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr24990-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr24990-1.c new file mode 100644 index 000000000..a518df025 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr24990-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +int f(int x) +{ + return ((~x) != 0); +} +int f1(int x) +{ + return ((~x) == 0); +} + +/* There should be no != 0 which is produced by the front-end as + ~x != 0 is the same as x != -1 (or ~0). Likewise for ==. */ +/* { dg-final { scan-tree-dump-times "!= 0" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "!= -1" 1 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "== 0" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "== -1" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr25382.c b/gcc/testsuite/gcc.dg/tree-ssa/pr25382.c new file mode 100644 index 000000000..daff68ee9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr25382.c @@ -0,0 +1,19 @@ +/* PR tree-optimization/25382 + VRP used to ignore BIT_AND_EXPRs for the purpose of distilling ranges. + Check that VRP now gets ranges from BIT_AND_EXPRs. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-ccp -fdump-tree-vrp1" } */ + +int +foo (int a) +{ + int b = a & 0xff; + if (b > 300) + return 2; + else + return 1; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr25485.c b/gcc/testsuite/gcc.dg/tree-ssa/pr25485.c new file mode 100644 index 000000000..93f583cc3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr25485.c @@ -0,0 +1,17 @@ +/* PR tree-optimization/25485 + VRP did not fold TRUTH_AND_EXPR. Make sure it does now. */ + +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int +foo (int a, int b) +{ + if (a > 50) + return 19; + if (a > 63 && b < 50) + return 17; + return 31; +} + +/* { dg-final { scan-tree-dump-times "if" 1 "vrp1"} } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr25501.c b/gcc/testsuite/gcc.dg/tree-ssa/pr25501.c new file mode 100644 index 000000000..d63a5274e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr25501.c @@ -0,0 +1,36 @@ +/* PR tree-optimization/25501 + The PHI merge pass used to try to merge PHI nodes that cannot + actually merged, causing a segfault later. Make sure that does not + happen any more. */ + +/* { dg-options "-O1 -fdump-tree-mergephi" } */ + +int +foo (int a) +{ + int b; + int c; + int d; + + if (a == 2) + b = 3; + else + b = 5; + + c = 7; + + d = 11; + + for (;;) + { + if (d == 5) + break; + + d = b; + } + + return 13; +} + +/* { dg-final { scan-tree-dump-times "Removing basic block" 0 "mergephi1"} } */ +/* { dg-final { cleanup-tree-dump "mergephi\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr25734.c b/gcc/testsuite/gcc.dg/tree-ssa/pr25734.c new file mode 100644 index 000000000..a71c7f01a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr25734.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ + +struct list_head { + struct list_head *next; +}; +static inline __attribute__((always_inline)) void list_del_init(struct +list_head *entry) +{ + __list_del(entry->next); + (entry)->next = (entry); +}; +struct dentry { + void *d_fsdata; +}; +struct sysfs_dirent { + struct list_head s_sibling; + struct list_head s_children; +}; +const char *sysfs_get_name(struct sysfs_dirent *); +void sysfs_hash_and_remove(struct dentry * dir, const char * name) +{ + struct sysfs_dirent * sd; + struct sysfs_dirent * parent_sd = dir->d_fsdata; + for (sd = (struct sysfs_dirent *)((&parent_sd->s_children)->next); + &sd->s_sibling != (&parent_sd->s_children); + sd = (struct sysfs_dirent *)sd->s_sibling.next) { + if (!__builtin_strcmp(sysfs_get_name(sd), name)) + { + list_del_init(&sd->s_sibling); + break; + } + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr26180.c b/gcc/testsuite/gcc.dg/tree-ssa/pr26180.c new file mode 100644 index 000000000..13c302dea --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr26180.c @@ -0,0 +1,44 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target int32plus } */ + +void abort(void); +int bar(int x, int y) +{ + int x1, y1; + int x2, y2; + unsigned int x3, y3, w; + int z = 1; + + x1 = (x < (1 << 30)); + y1 = (y < (1 << 30)); + if (x1) + if (y1) { + x2 = ((x > 0)? (x): -(x)); + y2 = ((y > 0)? (y): -(y)); + + x3 = x2; + y3 = y2; + w = x3 * y3; + + if (w >= (1 << 30)) { + z = 1; + } else { + z = -1; + } + } + + return z; +} + + +int main() +{ + int x, y, z; + x = 536870912; /* 2^29 */ + y = 2; + z = bar(x, y); + if (z != 1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr26421.c b/gcc/testsuite/gcc.dg/tree-ssa/pr26421.c new file mode 100644 index 000000000..70f123158 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr26421.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef struct { + int i; + int j; + int k; +} Foo; + +void bar(Foo*); +int foo(void) +{ + Foo a; + a.i = 1; + bar(&a); + return a.i; +} + +/* Verify the call clobbers all of a. */ + +/* { dg-final { scan-tree-dump-not "return 1;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr26899.c b/gcc/testsuite/gcc.dg/tree-ssa/pr26899.c new file mode 100644 index 000000000..2e9941060 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr26899.c @@ -0,0 +1,10 @@ +/* { dg-options "-fstrict-overflow -fdump-tree-gimple" } */ + +int foo (int i, int j) +{ + return (i < j + 1) || (j > i - 1); +} + +/* { dg-final { scan-tree-dump "j >= i" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27236.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27236.c new file mode 100644 index 000000000..389b65206 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27236.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static inline int inline_read(volatile int *mem) +{ + return *mem; +} +__attribute__ ((noinline)) +int foo_read(volatile int *mem) +{ + return inline_read(mem); +} +unsigned int foo(volatile int *mem) +{ + foo_read(mem); + return foo_read(mem); +} + +/* { dg-final { scan-tree-dump-times "foo_read" 5 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27498.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27498.c new file mode 100644 index 000000000..75d3d4bac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27498.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +void zconfdump(void) +{ + char *p, *p2; + for (p2 = p; p2; ) + { + char __a0, __a1, __a2; + __a0 = ((__const char *) ("\"\\"))[0]; + if (__a0) + return; + } +} + +/* { dg-final { scan-tree-dump-not "goto" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27781.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27781.c new file mode 100644 index 000000000..233c93dac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27781.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-require-weak-override "" } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void __attribute__((weak)) func(void) +{ + /* no code */ +} + +int main() +{ + func(); + return 0; +} + +/* { dg-final { scan-tree-dump "func \\(\\);" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27799.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27799.c new file mode 100644 index 000000000..de09a40e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27799.c @@ -0,0 +1,26 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +struct X { double m; int x; }; +struct Y { int y; short d; }; +struct YY { int y; short d; char c; }; + +extern void link_error (void); + +int foo(struct X *x, struct Y *y) +{ + x->x = 0; + y->y = 1; + if (x->x != 0) + link_error (); +} + +int foo_no(struct X *x, struct YY *y) +{ + x->x = 0; + y->y = 1; + if (x->x != 0) + link_error (); +} + +int main() {} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c new file mode 100644 index 000000000..c7da3bd5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr27810.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +int bar (int); + +int qqq (int a) +{ + int result; + result = bar (a); + return result; +} + +/* We should not use an extra temporary for the result of the + function call. */ + +/* { dg-final { scan-tree-dump-times "int" 3 "gimple" } } */ +/* { dg-final { scan-tree-dump-times "int D\\\." 1 "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr28410.c b/gcc/testsuite/gcc.dg/tree-ssa/pr28410.c new file mode 100644 index 000000000..adc49b15c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr28410.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort(void); +struct Bar { int p; }; +struct Foo { struct Bar *p; }; +struct Bar p0 = { 0 }; +struct Bar p1 = { 1 }; +void bar(struct Foo *f) +{ + f->p = &p0; +} +int foo(struct Foo *f) +{ + f->p->p = 1; + bar(f); + return f->p->p; +} +int main() +{ + struct Foo f; + f.p = &p1; + if (foo(&f) != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c b/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c new file mode 100644 index 000000000..50b3bfd56 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr30375.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse" } */ + +typedef struct _s { + int a; + int b; + int c; + int d; +} s; + +extern void g(s*); +extern void f(void); + +void test_signed_msg_encoding(void) +{ + s signInfo = { sizeof(signInfo), 0 }; + + signInfo.b = 1; + signInfo.c = 0; + g(&signInfo); + signInfo.d = 0; + f(); +} + +/* { dg-final { scan-tree-dump-times "signInfo = {}" 1 "dse1" } } */ +/* { dg-final { cleanup-tree-dump "dse*" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr30978.c b/gcc/testsuite/gcc.dg/tree-ssa/pr30978.c new file mode 100644 index 000000000..3329383cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr30978.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int foo(int a) +{ + unsigned int b = a > 0; + char c = b; + _Bool d = c == 0; + int e = !d; + return e; +} + +/* { dg-final { scan-tree-dump "e_. = a_..D. > 0;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr31261.c b/gcc/testsuite/gcc.dg/tree-ssa/pr31261.c new file mode 100644 index 000000000..42bd2a21e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr31261.c @@ -0,0 +1,40 @@ +/* PR tree-optimization/31261 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-original" } */ + +unsigned int +f1 (unsigned int a) +{ + return (8 - (a & 7)) & 7; +} + +long int +f2 (long int b) +{ + return (16 + (b & 7)) & 15; +} + +char +f3 (char c) +{ + return -(c & 63) & 31; +} + +int +f4 (int d) +{ + return (12 - (d & 15)) & 7; +} + +int +f5 (int e) +{ + return (12 - (e & 7)) & 15; +} + +/* { dg-final { scan-tree-dump-times "return -a \& 7;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return b \& 7;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return \\(char\\) -\\(unsigned char\\) c \& 31;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return \\(int\\) \\(12 - \\(unsigned int\\) d\\) \& 7;" 1 "original" } } */ +/* { dg-final { scan-tree-dump-times "return 12 - \\(e \& 7\\) \& 15;" 1 "original" } } */ +/* { dg-final { cleanup-tree-dump "original" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr31521.c b/gcc/testsuite/gcc.dg/tree-ssa/pr31521.c new file mode 100644 index 000000000..4f54cc077 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr31521.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +void fail(void) __attribute__((noreturn)); +int bar(int); + +int foo(int x) { + int i; + int s = 0; + + if (x <= 0) fail(); + for (i = 0; i < x; ++i) { + /* This division by 4 should be replaced with >> 2. */ + s += bar(i/4); + } + return s; +} + +/* { dg-final { scan-tree-dump-times " = i_.* >> 2" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr31966.c b/gcc/testsuite/gcc.dg/tree-ssa/pr31966.c new file mode 100644 index 000000000..a18f9d041 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr31966.c @@ -0,0 +1,50 @@ +/* Contributed by Jack Lloyd <lloyd@randombit.net> */ + +/* { dg-options "-O2 -ftree-vectorize" } */ +/* { dg-options "-O2 -ftree-vectorize -march=nocona" { target { i?86-*-* x86_64-*-* } } } */ + +typedef unsigned long long word; + +const unsigned int MP_WORD_BITS = 64; +const word MP_WORD_MASK = ~((word)0); +const word MP_WORD_TOP_BIT = (word)1 << (8*sizeof(word) - 1); + +extern void abort (void); + +word do_div(word n1, word n0, word d) +{ + word high = n1 % d, quotient = 0; + unsigned int j; + + for(j = 0; j != MP_WORD_BITS; ++j) + { + word high_top_bit = (high & MP_WORD_TOP_BIT); + + high <<= 1; + high |= (n0 >> (MP_WORD_BITS-1-j)) & 1; + quotient <<= 1; + + if(high_top_bit || high >= d) + { + high -= d; + quotient |= 1; + } + } + + return quotient; +} + +int main() +{ + word result; + + result = do_div(0x0000000000200000ll, + 0x0000000000000000ll, + 0x86E53497CE000000ll); + + + if (result != 0x3CBA83) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c new file mode 100644 index 000000000..58a62662b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32044.c @@ -0,0 +1,54 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int foo (int n) +{ + while (n >= 45) + n -= 45; + + return n; +} + +int bar (int n) +{ + while (n >= 64) + n -= 64; + + return n; +} + +int bla (int n) +{ + int i = 0; + + while (n >= 45) + { + i++; + n -= 45; + } + + return i; +} + +int baz (int n) +{ + int i = 0; + + while (n >= 64) + { + i++; + n -= 64; + } + + return i; +} + +/* The loops computing division/modulo by 64 should be eliminated */ +/* { dg-final { scan-tree-dump-times "if" 6 "optimized" } } */ + +/* There should be no division/modulo in the final dump (division and modulo + by 64 are done using bit operations). */ +/* { dg-final { scan-tree-dump-times "/" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "%" 0 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32367.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32367.c new file mode 100644 index 000000000..1b153b65e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32367.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +int BinomialCoefficientsInited = 0; +int BinomialCoefficients[17 * 35]; +double Evaluate_TPat (void) +{ + unsigned short n, k; + if (BinomialCoefficientsInited == 0) + { + int *ptr = BinomialCoefficients; + for (n = 1; n <= 33; ++n) + { + for (k = 1; k < n; ++k) + ++ptr; + *ptr = 1; + } + } +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32461-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32461-1.c new file mode 100644 index 000000000..6e069886d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32461-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef struct +{ + unsigned exp[256]; +} +expbap_t; + +void +a52_bit_allocate (expbap_t * expbap) +{ + int i; + unsigned *exp = expbap->exp; + char *bap; + + while (i < 3 || exp[i] > exp[i - 1]); + + do { + if (exp[i + 1] == exp[i]) + bap[i] = 0; + i++; + } while (i < 20); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32461-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32461-2.c new file mode 100644 index 000000000..81ee6ae95 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32461-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef struct +{ + unsigned char exp[256]; +} +expbap_t; + +void +a52_bit_allocate (expbap_t * expbap) +{ + int i; + unsigned char *exp = expbap->exp; + int lowcomp; + + do + { + if (exp[i + 1] == exp[i] - 2) + lowcomp = 384; + else if (lowcomp && (exp[i + 1] > exp[i])) + lowcomp -= 64; + i++; + } + while ((i < 3) || ((i < 7) && (exp[i] > exp[i - 1]))); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32540-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32540-1.c new file mode 100644 index 000000000..f5a444806 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32540-1.c @@ -0,0 +1,36 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -ftree-pre" } */ + +int f(void); +void acceptloop_th(int *t) { + int options = 0; + if (f()) options |= 0x1 << 1; + if (f()) options |= 0x1 << 2; + if (f()) options |= 0x1 << 3; + if (f()) options |= 0x1 << 4; + if (f()) options |= 0x1 << 5; + if (f()) options |= 0x1 << 6; + if (f()) options |= 0x1 << 7; + if (f()) options |= 0x1 << 8; + if (f()) options |= 0x1 << 9; + if (f()) options |= 0x1 << 10; + if (f()) options |= 0x1 << 11; + if (f()) options |= 0x1 << 12; + if (f()) options |= 0x1 << 13; + if (f()) options |= 0x1 << 14; + if (f()) options |= 0x1 << 15; +#if(__SIZEOF_INT__ >= 4) + if (f()) options |= 0x1 << 16; + if (f()) options |= 0x1 << 17; + if (f()) options |= 0x1 << 18; + if (f()) options |= 0x1 << 19; + if (f()) options |= 0x1 << 20; + if (f()) options |= 0x1 << 21; + if (f()) options |= 0x1 << 22; + if (f()) options |= 0x1 << 23; + if (f()) options |= 0x1 << 24; + if (f()) options |= 0x1 << 25; + if (f()) options |= 0x1 << 26; +#endif + if (f()) *t = options; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32540-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32540-2.c new file mode 100644 index 000000000..f7fa38de1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32540-2.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -ftree-pre" } */ + +int f(void); +void acceptloop_th(int *t, int options) { + if (f()) options |= 0x1 << 0; + if (f()) options |= 0x1 << 1; + if (f()) options |= 0x1 << 2; + if (f()) options |= 0x1 << 3; + if (f()) options |= 0x1 << 4; + if (f()) options |= 0x1 << 5; + if (f()) options |= 0x1 << 6; + if (f()) options |= 0x1 << 7; + if (f()) options |= 0x1 << 8; + if (f()) options |= 0x1 << 9; + if (f()) options |= 0x1 << 10; + if (f()) options |= 0x1 << 11; + if (f()) options |= 0x1 << 12; + if (f()) options |= 0x1 << 13; + if (f()) options |= 0x1 << 14; + if (f()) options |= 0x1 << 15; +#if(__SIZEOF_INT__ >= 4) + if (f()) options |= 0x1 << 16; + if (f()) options |= 0x1 << 17; + if (f()) options |= 0x1 << 18; + if (f()) options |= 0x1 << 19; + if (f()) options |= 0x1 << 20; + if (f()) options |= 0x1 << 21; + if (f()) options |= 0x1 << 22; + if (f()) options |= 0x1 << 23; + if (f()) options |= 0x1 << 24; + if (f()) options |= 0x1 << 25; + if (f()) options |= 0x1 << 26; +#endif + if (f()) *t = options; +} + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32681.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32681.c new file mode 100644 index 000000000..235234244 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32681.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -ffast-math -ftree-vectorize" } */ +/* { dg-options "-O3 -ffast-math -ftree-vectorize -march=nocona" { target { i?86-*-* x86_64-*-* } } } */ + +int aa_renderpalette (int p) +{ + int y = 42; + int i; + + for (i = 0; i < 256; i++) + { + if (y > 255) + y = 255; + if (y < 0) + y = 0; + + if (p) + y = (y < p ? 0 : (y > p) * 255 / (255 - 2 * p)); + } + return y; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32821.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32821.c new file mode 100644 index 000000000..219573940 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32821.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vectorize -fdump-tree-ifcvt-details" } */ + +void +main1 (int *arr, int n, int a, int b) +{ + int i; + for (i = 0; i < n; i++) + { + int m = arr[i]; + arr[i] = (m < a ? m - a : b); + } +} + +/* { dg-final { cleanup-tree-dump "ifcvt" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32901.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32901.c new file mode 100644 index 000000000..c0ba060e1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32901.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-gimple" } */ + +struct foo { + unsigned a1: 1; + unsigned a2: 3; + unsigned : 4; +}; + +extern struct foo thefoo, theotherfoo; + +void setup_foo(void) +{ + const struct foo init = { + .a1 = 1, + .a2 = 5, + }; + volatile const struct foo volinit = { + .a1 = 0, + .a2 = 6 + }; + thefoo = init; + theotherfoo = volinit; +} + +/* { dg-final { scan-tree-dump-times "thefoo.* = {}" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "thefoo.* = 1" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "thefoo.* = 5" 1 "gimple"} } */ +/* { dg-final { scan-tree-dump-times "theotherfoo = volinit" 1 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr32964.c b/gcc/testsuite/gcc.dg/tree-ssa/pr32964.c new file mode 100644 index 000000000..18e73f939 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr32964.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +union A +{ + float a; +}; + +float t(float a) +{ + union A a1, a2, a3; + int i; + + a1.a = a; + for(i = 0; i<100; i++) + { + a2 = a1; + a2.a += a; + a1 = a2; + } + a3 = a1; + return a3.a; +} + +/* { dg-final { scan-tree-dump-times "union" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr33172.c b/gcc/testsuite/gcc.dg/tree-ssa/pr33172.c new file mode 100644 index 000000000..17a40d4a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr33172.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct abc { + void (*abc_call)(void); +}; + +/* + * Use only any one of the three definitions below at a time: + * + * 1. nothing optimized away. Good. + * 2. call_func() _not_ optimized away, but struct xyz is. gcc disappoints. + * 3. both call_func() and struct xyz optimized away. Nice. + */ + +/* 1 */ +/*extern int do_register(struct abc *xyz);*/ + +/* 2 */ +static inline int do_register(struct abc *xyz) +{ + return 0; +} + +/* 3 */ +/*#define do_register(xyz) do { (void)(xyz); } while (0)*/ + +static void call_func(void) +{ +} + +static struct abc xyz = { + .abc_call = call_func, +}; + +void func(void) +{ + do_register(&xyz); +} + +/* { dg-final { scan-tree-dump-not "call_func" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c b/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c new file mode 100644 index 000000000..32a3aad9c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr33723.c @@ -0,0 +1,72 @@ +/* PR tree-optimization/33723 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +typedef union +{ + struct + { + int f1, f2, f3, f4, f5, f6, f7, f8; + long int f9, f10; + int f11; + } f; + char s[4]; + long int a; +} T; + +void +foo1 (void) +{ + T t; + t = (T) { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; + test (&t); +} + +void +bar1 (void) +{ + T t = { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; + test (&t); +} + +void +baz1 (void) +{ + T t; + t = (const T) { { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 } }; + test (&t); +} + +void +foo2 (void) +{ + T t; + t = (T) { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } }; + test (&t); +} + +void +bar2 (void) +{ + T t = { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } }; + test (&t); +} + +void +baz2 (void) +{ + T t; + t = (const T) { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } }; + test (&t); +} + +void +baz3 (void) +{ + T t; + t = (const T) (T) { { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 } }; + test (&t); +} + +/* { dg-final { scan-tree-dump-not "t = D" "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr33920.c b/gcc/testsuite/gcc.dg/tree-ssa/pr33920.c new file mode 100644 index 000000000..e6a9e7118 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr33920.c @@ -0,0 +1,52 @@ +/* Testcase by Martin Michlmayr <tbm@cyrius.com> */ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +typedef __PTRDIFF_TYPE__ intptr_t; +typedef union lispunion *object; +struct character +{ + long e; +}; +extern struct symbol Cnil_body; +extern struct symbol Ct_body; +struct vector +{ + object *v_self; +}; +union lispunion +{ + struct vector v; +}; +void init_code () +{ + object V659; + object _x, _y; + object V643; + intptr_t V648; + unsigned char V653; + object V651; + object V654; + object V658; + +T1240: +if (V648 >= (intptr_t)V651) + goto T1243; + V653 = ((char *) V654->v.v_self)[V648]; + V659 = (object) V654 + V653; +T1261: + V658 = + (object) + V659 ? (object) & Ct_body : (object) & Cnil_body; + if (V658 == (object) & Cnil_body) + goto T1249; + goto T1224; +T1249: + V648 = (intptr_t) V648 + 1; + goto T1240; +T1243: + V643 = (object) & Cnil_body; +T1224: + _y = V643; + number_plus (_x, _y); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr33922.c b/gcc/testsuite/gcc.dg/tree-ssa/pr33922.c new file mode 100644 index 000000000..7429eb161 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr33922.c @@ -0,0 +1,79 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -ftree-pre" } */ + +typedef enum +{ + ST_TiemanStyle, +} +BrailleDisplay; +static int pendingCommand; +static int currentModifiers; +typedef struct +{ + int (*updateKeys) (BrailleDisplay * brl, int *keyPressed); +} +ProtocolOperations; +static const ProtocolOperations *protocol; +brl_readCommand (BrailleDisplay * brl) +{ + unsigned long int keys; + int command; + int keyPressed; + unsigned char routingKeys[200]; + int routingKeyCount; + signed char rightVerticalSensor; + if (pendingCommand != (-1)) + { + return command; + } + if (!protocol->updateKeys (brl, &keyPressed)) + { + if (rightVerticalSensor >= 0) + keys |= 1; + if ((routingKeyCount == 0) && keys) + { + if (currentModifiers) + { + doChord:switch (keys); + } + else + { + doCharacter: + command = 0X2200; + if (keys & 0X01UL) + command |= 0001; + if (keys & 0X02UL) + command |= 0002; + if (keys & 0X04UL) + command |= 0004; + if (keys & 0X08UL) + command |= 0010; + if (keys & 0X10UL) + command |= 0020; + if (keys & 0X20UL) + command |= 0040; + if (currentModifiers & (0X0010 | 0X0200)) + command |= 0100; + if (currentModifiers & 0X0040) + command |= 0200; + if (currentModifiers & 0X0100) + command |= 0X020000; + if (currentModifiers & 0X0400) + command |= 0X080000; + if (currentModifiers & 0X0800) + command |= 0X040000; + } + unsigned char key1 = routingKeys[0]; + if (key1 == 0) + { + } + if (key1 == 1) + if (keys) + { + currentModifiers |= 0X0010; + goto doCharacter; + } + } + } + return command; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34146-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34146-2.c new file mode 100644 index 000000000..31007b07f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34146-2.c @@ -0,0 +1,53 @@ +/* PR c/34146 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +struct A +{ + int f1, f2, f3; +}; + +struct B +{ + struct A g1, g2; +}; + +struct C +{ + struct B h1, h2; +}; + +typedef union +{ + struct C c; + char s[4]; + long int a; +} T; + +void +foo (void) +{ + T t = (T) { { { { 0, 0, 0 }, { 0, 0, 0 } }, { { 0, 0, 0 }, { 0, 0, 0 } } } }; + test (&t); +} + +void +bar (void) +{ + T t = (T) { { { { 0, 0, 0 }, (struct A) { 0, 0, 0 } }, + (struct B) { (struct A) { 0, 0, 0 }, { 0, 0, 0 } } } }; + test (&t); +} + +void +baz (void) +{ + T t = (T) { { { { 0, 0, 0 }, (struct A) { 1, 1, 1 } }, + (struct B) { (struct A) { 0, 0, 0 }, { 1, 1, 1 } } } }; + test (&t); +} + +/* { dg-final { scan-tree-dump-not "t = D" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "t\.c\.h\[12\] = D" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "\.g\[12\] = D" "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34146.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34146.c new file mode 100644 index 000000000..99fdeb5ed --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34146.c @@ -0,0 +1,53 @@ +/* PR c/34146 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-gimple" } */ + +struct A +{ + int f1, f2, f3; +}; + +struct B +{ + struct A g1, g2; +}; + +struct C +{ + struct B h1, h2; +}; + +typedef union +{ + struct C c; + char s[4]; + long int a; +} T; + +void +foo (void) +{ + T t = { { { { 0, 0, 0 }, { 0, 0, 0 } }, { { 0, 0, 0 }, { 0, 0, 0 } } } }; + test (&t); +} + +void +bar (void) +{ + T t = { { { { 0, 0, 0 }, (struct A) { 0, 0, 0 } }, + (struct B) { (struct A) { 0, 0, 0 }, { 0, 0, 0 } } } }; + test (&t); +} + +void +baz (void) +{ + T t = { { { { 0, 0, 0 }, (struct A) { 1, 1, 1 } }, + (struct B) { (struct A) { 0, 0, 0 }, { 1, 1, 1 } } } }; + test (&t); +} + +/* { dg-final { scan-tree-dump-not "t = D" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "t\.c\.h\[12\] = D" "gimple"} } */ +/* { dg-final { scan-tree-dump-not "\.g\[12\] = D" "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34244.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34244.c new file mode 100644 index 000000000..262c92f1f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34244.c @@ -0,0 +1,65 @@ +/* PR tree-optimization/34244 */ +/* { dg-do run } */ +/* { dg-options "-O2 " } */ + +int __attribute__((noinline)) GetParent(void) +{ + static int count = 0; + count++; + switch (count) + { + case 1: + case 3: + case 4: + return 1; + default: + return 0; + } +} +int __attribute__((noinline)) FindCommonAncestor(int aNode1, int aNode2) +{ + if (aNode1 && aNode2) { + int offset = 0; + int anc1 = aNode1; + for (;;) { + ++offset; + int parent = GetParent(); + if (!parent) + break; + anc1 = parent; + } + int anc2 = aNode2; + for (;;) { + --offset; + int parent = GetParent(); + if (!parent) + break; + anc2 = parent; + } + if (anc1 == anc2) { + anc1 = aNode1; + anc2 = aNode2; + while (offset > 0) { + anc1 = GetParent(); + --offset; + } + while (offset < 0) { + anc2 = GetParent(); + ++offset; + } + while (anc1 != anc2) { + anc1 = GetParent(); + anc2 = GetParent(); + } + return anc1; + } + } + return 0; +} +extern void abort (void); +int main() +{ + if (FindCommonAncestor (1, 1) != 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34635-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34635-1.c new file mode 100644 index 000000000..5afc6db27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34635-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +void foo(int x[]) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + { + x[i] = x[i+j]; + x[i] = x[i+j]; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr34635.c b/gcc/testsuite/gcc.dg/tree-ssa/pr34635.c new file mode 100644 index 000000000..5b4253cc4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr34635.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ + +void foo(int x[]) +{ + int i, j; + + for (i = 0; i < 2; i++) + for (j = 0; j < 2; j++) + { + x[i] = x[i*j]; + x[i] = x[i*j]; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c b/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c new file mode 100644 index 000000000..8601cabec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr35286.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int g2; +struct A { + int a; int b; +}g1; +int foo(int a, int b) +{ + if (a > 0) + { + g1.a = a+ b; + } + else + g1.a = b; + + g2 = a+b; + + return g1.a; +} +/* We will eliminate the g1.a from the return statement as fully redundant, + and remove one calculation of a + b. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr35287.c b/gcc/testsuite/gcc.dg/tree-ssa/pr35287.c new file mode 100644 index 000000000..1e9766280 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr35287.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int *gp; +int foo(int p) +{ + int t = 0; + if (p) + t = *gp + 1; + + return (*gp + t); +} + +/* We will eliminate one load of gp and one indirect load of *gp. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c new file mode 100644 index 000000000..7294c07b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36181.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target pthread } */ +/* { dg-options "-O3 -ftree-parallelize-loops=2" } */ + +int foo () +{ + int i, sum = 0, data[1024]; + + for(i = 0; i<1024; i++) + sum += data[i]; + + return sum; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36326.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36326.c new file mode 100644 index 000000000..0611f7d84 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36326.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +union X { int i; double x; }; + +int foo (union X *p) +{ + union X x = *p; + return x.x; +} + +/* { dg-final { scan-tree-dump-not "x.0" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36881.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36881.c new file mode 100644 index 000000000..742dd9ddb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36881.c @@ -0,0 +1,23 @@ +/* PR tree-optimization/36881 */ +/* { dg-do compile { target fpic } } */ +/* { dg-options "-O2 -fpic -fdump-tree-switchconv-all" } */ + +const char *foo (int i) +{ + const char *p; + switch (i) + { + case 0: + case 6: p = ""; break; + case 1: + case 7: p = "abc"; break; + case 2: + case 8: p = "def"; break; + default: p = "ghi"; break; + } + return p; +} + +/* { dg-final { scan-assembler-not "CSWTCH" } } */ +/* { dg-final { scan-tree-dump "need runtime relocations" "switchconv" } } */ +/* { dg-final { cleanup-tree-dump "switchconv" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c b/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c new file mode 100644 index 000000000..8fa2ed2ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr36908.c @@ -0,0 +1,65 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution" } */ +#define NULL ((void *)0) + +__extension__ typedef __SIZE_TYPE__ size_t; +extern void *foo(size_t nelem, size_t elsize); +extern void bar (char*, ...); + +typedef struct alt_state *alt_state_t; +typedef struct state *state_t; + +struct alt_state +{ + alt_state_t next_alt_state; +}; + +static alt_state_t first_free_alt_state = NULL; + +static void +free_alt_state (alt_state_t alt_state) +{ + if (alt_state == NULL) + return; + alt_state->next_alt_state = first_free_alt_state; + first_free_alt_state = alt_state; +} + +/* The function frees list started with node ALT_STATE_LIST. */ +static void +free_alt_states (alt_state_t alt_states_list) +{ + alt_state_t curr_alt_state; + alt_state_t next_alt_state; + + for (curr_alt_state = alt_states_list; + curr_alt_state != NULL; + curr_alt_state = next_alt_state) + { + next_alt_state = curr_alt_state->next_alt_state; + free_alt_state (curr_alt_state); + } +} + +int +main (void) +{ + int i; + alt_state_t state, act_state; + + act_state = state = foo (1, sizeof (struct alt_state)); + for (i = 0; i < 2; i ++) + { + act_state->next_alt_state = foo (1, sizeof (struct alt_state)); + act_state = act_state->next_alt_state; + } + + free_alt_states (state); + + for (act_state = first_free_alt_state; + act_state != NULL; + act_state = act_state->next_alt_state) + bar ("going from %p to %p\n", act_state, act_state->next_alt_state); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c b/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c new file mode 100644 index 000000000..f31c5940b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr37508.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +struct foo1 { + int i:1; +}; +struct foo2 { + unsigned i:1; +}; + +int test1 (struct foo1 *x) +{ + if (x->i == 0) + return 1; + else if (x->i == -1) + return 1; + return 0; +} + +int test2 (struct foo2 *x) +{ + if (x->i == 0) + return 1; + else if (x->i == -1) + return 1; + return 0; +} + +int test3 (struct foo1 *x) +{ + if (x->i == 0) + return 1; + else if (x->i == 1) + return 1; + return 0; +} + +int test4 (struct foo2 *x) +{ + if (x->i == 0) + return 1; + else if (x->i == 1) + return 1; + return 0; +} + +/* { dg-final { scan-tree-dump-times "Folding" 4 "vrp1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c new file mode 100644 index 000000000..fac6cd3b8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38250.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution" } */ + +__extension__ typedef __SIZE_TYPE__ size_t; +typedef struct { + long dat[2]; +} gsl_complex_long_double; +typedef struct { + size_t size; + size_t stride; + long *data; +} gsl_vector_complex_long_double; + +void gsl_vector_complex_long_double_set_zero (gsl_vector_complex_long_double * v) +{ + long * const data = v->data; + const size_t n = v->size; + const size_t stride = v->stride; + const gsl_complex_long_double zero = { { 0,0} } ; + size_t i; + for (i = 0; i < n; i++) + *(gsl_complex_long_double *) (data + 2 * i * stride) = zero; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38385.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38385.c new file mode 100644 index 000000000..a49c93e26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38385.c @@ -0,0 +1,124 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution" } */ + +struct rtx_def +{ + int a; +}; + +typedef struct rtx_def *rtx; + +struct rd { + int alternative_enabled_p[100]; + rtx operand[100]; + int n_operands; +}; + +rtx this_insn; +int n_reloads; +int n_replacements; +int n_earlyclobbers; +int replace_reloads; +int hard_regs_live_known; +short* static_reload_reg_p; +struct rd recog_data; + +int +find_reloads (rtx insn, int replace, int ind_levels, int live_known, + short *reload_reg_p) +{ + int i, j; + int noperands = replace; + + int no_input_reloads = 0; + int n_alternatives = replace; + char this_alternative_match_win[30]; + char this_alternative_win[30]; + char this_alternative_earlyclobber[30]; + int this_alternative_matches[30]; + int goal_alternative[30]; + int this_alternative_number; + + char goal_alternative_match_win[30]; + char goal_alternative_win[30]; + int best; + + int operand_mode[30]; + int retval = 0; + + for (this_alternative_number = 0; + this_alternative_number < n_alternatives; + this_alternative_number++) + { + + int losers = 0; + int bad = 0; + + if (!recog_data.alternative_enabled_p[this_alternative_number]) + { + int i; + + for (i = 0; i < recog_data.n_operands; i++) + ; + + continue; + } + + for (i = 0; i < noperands; i++) + if (this_alternative_earlyclobber[i] + && (this_alternative_win[i] || this_alternative_match_win[i])) + { + if (j != noperands) + { + losers++; + + for (j = 0; j < noperands; j++) + if (this_alternative_matches[j] == i + && this_alternative_match_win[j]) + { + this_alternative_win[j] = 0; + this_alternative_match_win[j] = 0; + losers++; + } + } + } + + if (losers == 0) + { + for (i = 0; i < noperands; i++) + { + goal_alternative_win[i] = 0; + goal_alternative_match_win[i] = 0; + } + + goto finish; + } + + if (! bad && best > losers) + { + for (i = 0; i < noperands; i++) + { + goal_alternative[i] = 0; + goal_alternative_win[i] = 0; + } + } + } + + + finish: + + for (i = 0; i < noperands; i++) + if (! goal_alternative_win[i]) + { + rtx op = recog_data.operand[i]; + int mode = operand_mode[i]; + + if (((ix86_preferred_reload_class ((op), (goal_alternative[i])) == 2) + || no_input_reloads) + && mode != 0) + {} + } + + return retval; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38533.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38533.c new file mode 100644 index 000000000..e78722760 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38533.c @@ -0,0 +1,30 @@ +/* PR middle-end/38533 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +#define A asm volatile ("" : "=r" (f) : "0" (0)); e |= f; +#define B A A A A A A A A A A A +#define C B B B B B B B B B B B + +int +foo (void) +{ + int e = 0, f; + C C B B B B B A A A A A A + return e; +} + +int +main (void) +{ + if (foo ()) + __builtin_abort (); + return 0; +} + +/* Verify that reassoc hasn't increased register pressure too much + by moving all bitwise ors after the last __asm__. There should + be exactly 2 (first) __asm__ stmts with no intervening stmts, + all others should have some bitwise or in between. */ +/* { dg-final { scan-tree-dump-times "__asm__\[^;\n]*;\n *__asm__" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38699.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38699.c new file mode 100644 index 000000000..6845324e4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38699.c @@ -0,0 +1,76 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -fdump-tree-optimized" } */ +/* + * License: GPL + * Copyright: (c) 2007 by Till Harbaum <till@harbaum.org> + * Copyright: (c) 2008 Wolfgang Moser, http://d81.de + */ + +/* #include <avr/wdt.h> */ +/* some declarations from the include above for ATMega8 */ +#define _SFR_IO8(io_addr) (*(volatile unsigned char *)((io_addr) + 0x20)) +#define TOV0 0 +#define TCNT0 _SFR_IO8(0x32) +#define TIFR _SFR_IO8(0x38) +#define DDRC _SFR_IO8(0x14) +#define DDRD _SFR_IO8(0x11) +#define PORTC _SFR_IO8(0x15) +#define PORTD _SFR_IO8(0x12) + +static void delay_wait_us( unsigned char timeout ) { + __asm__ __volatile__ ("wdr"); + + TCNT0 = timeout; + TIFR |= (1 << (TOV0)); + + /* wait until counter overflows */ + while(!(TIFR & (1 << (TOV0)))); +} + +static void delay_wait_us_ms( unsigned char timeout ) { + delay_wait_us( timeout * 1000 ); +} + + +void makeUseOfTimerWait( unsigned char val ) { + delay_wait_us( 10 ); + DDRC |= 0x10; + delay_wait_us( 10 ); + DDRD |= 0x20; + + delay_wait_us( 20 ); + PORTC &= ~0x10; + delay_wait_us( 10 ); + PORTD &= ~0x20; + + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + delay_wait_us_ms( 5 ); + + PORTC |= val & 0x10; + delay_wait_us( 10 ); + PORTD |= val & 0x20; + + delay_wait_us( 10 ); +} +/* We should not inline the delay loops. */ +/* { dg-final { scan-tree-dump "delay_wait_us" "optimized"} } */ +/* { dg-final { scan-tree-dump "delay_wait_us_ms" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38895.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38895.c new file mode 100644 index 000000000..0a96e5334 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38895.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fstrict-aliasing -fdump-tree-optimized" } */ + +struct A { + int i; + int j; +}; +struct B { + struct A a1; + struct A a2; +}; +struct C { + struct A a1; + struct B b; +}; +int foo(struct C *c, struct B *b) +{ + c->a1.i = 1; + b->a1.i = 0; + return c->a1.i; +} + +/* { dg-final { scan-tree-dump "return 1;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr38997.c b/gcc/testsuite/gcc.dg/tree-ssa/pr38997.c new file mode 100644 index 000000000..211203c9c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr38997.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution" } */ + +int a[8][8]; +int b[8]; + +void +foo (int i) +{ + int j; + for (j = 0; j < 8; j++) + { + a[i][j] = 0; + b[j] = j; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr39007.c b/gcc/testsuite/gcc.dg/tree-ssa/pr39007.c new file mode 100644 index 000000000..94b24436d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr39007.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-loop-distribution" } */ + +void +foo (int *__restrict__ p, int *__restrict__ q, int count) +{ + int i; + for (i = 0; i < count; i++) + { + *p++ = 0; + *q++ = 0; + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c b/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c new file mode 100644 index 000000000..22e2b629e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr40087.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-O1 " } */ + +extern void abort (void); + +static void __attribute__((always_inline)) +reverse(int *first, int *last) +{ + if (first == last--) + return; + while (first != last) + { + int t = *first; + *first = *last; + *last = t; + if (++first == last--) + break; + } +} + +int main() +{ + int seq[] = { 1, 2, 3, 4, 5, 6, 7, 8 }; + + reverse(seq, seq + 8); + if (seq[3] != 5 || seq[4] != 4) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr41469-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr41469-1.c new file mode 100644 index 000000000..cee2c0822 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr41469-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fexceptions -fdump-tree-optimized" } */ + +void af (void *a); + +void +bf (void) +{ + int i = 1; + char v[i]; + af (v); +} + +/* { dg-final { scan-tree-dump-not "__builtin_stack_save" "optimized"} } */ +/* { dg-final { scan-tree-dump-not "__builtin_stack_restore" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr41497.c b/gcc/testsuite/gcc.dg/tree-ssa/pr41497.c new file mode 100644 index 000000000..e66ee8464 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr41497.c @@ -0,0 +1,27 @@ +/* { dg-do run } */ +/* { dg-options "-Os" } */ + +extern void abort (void); + +unsigned int a; +int b, c; + +void +foo (void) +{ + b = 0; + do { + for (a = -13; a == 0; a = (unsigned short)a) + c = 1; + b++; + } while (b == 0); +} + +int +main () +{ + foo (); + if (a != -13) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr42327.c b/gcc/testsuite/gcc.dg/tree-ssa/pr42327.c new file mode 100644 index 000000000..c0d3811b2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr42327.c @@ -0,0 +1,7 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fcheck-data-deps" } */ + +void foo(char *str) +{ + while (*str != 0) *str++ = 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c b/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c new file mode 100644 index 000000000..52f21fe1b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr42585.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct _fat_ptr +{ + unsigned char *curr; + unsigned char *base; + unsigned char *last_plus_one; +}; +int Cyc_string_ungetc (int ignore, struct _fat_ptr *sptr); +int +Cyc_string_ungetc (int ignore, struct _fat_ptr *sptr) +{ + struct _fat_ptr *_T0; + struct _fat_ptr *_T1; + struct _fat_ptr _T2; + int _T3; + struct _fat_ptr _ans; + int _change; + + { + _T0 = sptr; + _T1 = sptr; + _T2 = *sptr; + _T3 = -1; + _ans = _T2; + _change = -1; + _ans.curr += 4294967295U; + *sptr = _ans; + return (0); + } +} + +/* The local aggregates . */ +/* Whether the structs are totally scalarized or not depends on the + MOVE_RATIO macro defintion in the back end. The scalarization will + not take place when using small values for MOVE_RATIO. */ +/* { dg-final { scan-tree-dump-times "struct _fat_ptr _ans" 0 "optimized" { target { ! "powerpc*-*-* arm-*-* sh*-*-* s390*-*-*" } } } } */ +/* { dg-final { scan-tree-dump-times "struct _fat_ptr _T2" 0 "optimized" { target { ! "powerpc*-*-* arm-*-* sh*-*-* s390*-*-*" } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr42640.c b/gcc/testsuite/gcc.dg/tree-ssa/pr42640.c new file mode 100644 index 000000000..70807c091 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr42640.c @@ -0,0 +1,58 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -ftree-loop-distribution" } */ + +/* Checks if loop distribution works correctly if the subscript used + is assigned to a loop invariant value. */ + +extern void abort (void); +struct S { int a; int b; int c; }; + +int get_rr_node_index (int i) +{ + return i; +} + +struct S nodes[8]; +struct S *rr_node = nodes; +volatile int io_rat = 2; +void +doit (int i, int j) +{ + int s_node, p_node, inode, ipad, iloop; + + for (ipad = 0; ipad < io_rat; ipad++) + { + p_node = get_rr_node_index (ipad+2); + inode = get_rr_node_index (ipad); + + for (iloop = 1; iloop <= 2; iloop++) + { + rr_node[inode].a = i; + rr_node[inode].b = j; + rr_node[inode].c = ipad; + inode = p_node; + } + } +} + +int +main () +{ + int i; + + doit (1, 2); + + if (rr_node[0].a != rr_node[1].a + || rr_node[2].a != rr_node[3].a + || rr_node[1].a != 1 + || rr_node[0].b != rr_node[1].b + || rr_node[2].b != rr_node[3].b + || rr_node[1].b != 2 + || rr_node[0].c != 0 + || rr_node[1].c != 1 + || rr_node[2].c != 0 + || rr_node[3].c != 1) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr42893.c b/gcc/testsuite/gcc.dg/tree-ssa/pr42893.c new file mode 100644 index 000000000..b3fbd7654 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr42893.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -fdump-tree-optimized" } */ + +struct frame_info; +void tui_registers_changed_hook (void); +extern struct frame_info *deprecated_selected_frame; +int tui_refreshing_registers = 0; +void +tui_registers_changed_hook (void) +{ + struct frame_info *fi; + fi = deprecated_selected_frame; + if (fi) + + { + if (tui_refreshing_registers == 0) + + { + tui_refreshing_registers = 1; + tui_refreshing_registers = 0; + } + } + return; +} + +/* No references to tui_refreshing_registers should remain. */ +/* { dg-final { scan-tree-dump-not "tui_refreshing_registers" "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44133.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44133.c new file mode 100644 index 000000000..d3d0fe3a9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr44133.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wall" } */ + +struct S { int i, j; }; + +int foo (int l) +{ + struct S s; + s.j = l - 22; + return s.i + s.j; /* { dg-warning ".s\.i. is used uninitialized" } */ +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c new file mode 100644 index 000000000..a98d3cecc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr44258.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-esra-details" } */ + +struct blah +{ + char a[4]; +}; + +struct str +{ + struct blah b1; + char x; +}; + +struct val +{ + char y; + struct blah b2; +}; + +union U +{ + struct str str; + struct val val; +}; + + +extern struct blah e_b1, e_b2; +extern union U *e_u; + +int foo (int b) +{ + union U u; + + u.str.b1 = e_b1; + u.val.b2 = e_b2; + u.str.b1.a[3] = 0; + + *e_u = u; +} + +/* { dg-final { scan-tree-dump-times "Created a replacement" 0 "esra"} } */ +/* { dg-final { cleanup-tree-dump "esra" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44306.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44306.c new file mode 100644 index 000000000..1ea04ce3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr44306.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O3 -ftree-vectorize" { target *-*-* } } */ + +extern const int quant_coef8[6][8][8]; +extern const int dequant_coef8[6][8][8]; +int LevelScale8x8Luma_Intra[6][8][8]; +int LevelScale8x8Luma_Inter[6][8][8]; +int InvLevelScale8x8Luma_Intra[6][8][8]; +int InvLevelScale8x8Luma_Inter[6][8][8]; +short UseDefaultScalingMatrix8x8Flag[2]; +void CalculateQuant8Param() +{ + int i, j, k, temp; + int present[2]; + for(k=0; j<8; j++) + for(i=0; i<8; i++) + { + temp = (i<<3)+j; + if((!present[0]) || UseDefaultScalingMatrix8x8Flag[0]) + { + LevelScale8x8Luma_Intra[k][j][i] = (quant_coef8[k][j][i]<<4); + InvLevelScale8x8Luma_Intra[k][j][i] = dequant_coef8[k][j][i]; + } + if((!present[1]) || UseDefaultScalingMatrix8x8Flag[1]) + { + LevelScale8x8Luma_Inter[k][j][i] = (quant_coef8[k][j][i]<<4); + InvLevelScale8x8Luma_Inter[k][j][i] = dequant_coef8[k][j][i]; + } + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44423.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44423.c new file mode 100644 index 000000000..6232d6496 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr44423.c @@ -0,0 +1,47 @@ +/* { dg-do compile { target x86_64-*-* } } */ +/* { dg-options "-O2 -fdump-tree-esra-details" } */ + +#include "xmmintrin.h" + +typedef __m128 v4sf; // vector of 4 floats (SSE1) + +#define ARRSZ 1024 + +typedef union { + float f[4]; + v4sf v; +} V4SF; + +struct COLOUR { + float r,g,b; +}; + +void func (float *pre1, float pre2, struct COLOUR *a, V4SF *lpic) + { + V4SF va; + int y; + va.f[0]=a->r;va.f[1]=a->g;va.f[2]=a->b;va.f[3]=0.f; + for (y=0; y<20; ++y) + { + float att = pre1[y]*pre2; + v4sf tmpatt=_mm_load1_ps(&att); + tmpatt=_mm_mul_ps(tmpatt,va.v); + lpic[y].v=_mm_add_ps(tmpatt,lpic[y].v); + } + } + +int main() + { + V4SF lpic[ARRSZ]; + float pre1[ARRSZ]; + int i; + struct COLOUR col={0.,2.,4.}; + for (i=0; i<20; ++i) + pre1[i]=0.4; + for (i=0;i<10000000;++i) + func(&pre1[0],0.3,&col,&lpic[0]); + return 0; + } + +/* { dg-final { scan-tree-dump-times "Created a replacement" 0 "esra"} } */ +/* { dg-final { cleanup-tree-dump "esra" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr44483.c b/gcc/testsuite/gcc.dg/tree-ssa/pr44483.c new file mode 100644 index 000000000..cdae91a90 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr44483.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-c -O3" { target *-*-* } } */ + +int ffesum (void) { + int ch[4], ii, jj, kk; + char asc[32]; + + for (ii = 0; ii < 4; ii++) + { + for (jj = 0; jj < 4; jj++) + ch[jj] = ii; + for (kk = 0; kk < 13; kk++) + for (jj = 0; jj < 4; jj += 2) + if ((unsigned char) ch[jj] || (unsigned char) ch[jj + 1]) + ch[jj]++; + for (jj = 0; jj < 4; jj++) + asc[4 * jj + ii] = ch[jj]; + } + return asc[0]; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c new file mode 100644 index 000000000..e979b766f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45122.c @@ -0,0 +1,50 @@ +/* PR tree-optimization/27285 */ +/* PR tree-optimization/45122 */ + +/* { dg-do run } */ +/* { dg-options "-O2 -funsafe-loop-optimizations" } */ + +extern void abort (void); + +struct S { unsigned char a, b, c, d[16]; }; + +void __attribute__ ((noinline)) +foo (struct S *x, struct S *y) +{ + int a, b; + unsigned char c, *d, *e; + + b = x->b; + d = x->d; + e = y->d; + a = 0; + while (b) + { + if (b >= 8) + { + c = 0xff; + b -= 8; + } + else + { + c = 0xff << (8 - b); + b = 0; + } + + e[a] = d[a] & c; + a++; + } +} + +int +main (void) +{ + struct S x = { 0, 25, 0, { 0xaa, 0xbb, 0xcc, 0xdd }}; + struct S y = { 0, 0, 0, { 0 }}; + + foo (&x, &y); + if (x.d[0] != y.d[0] || x.d[1] != y.d[1] + || x.d[2] != y.d[2] || (x.d[3] & 0x80) != y.d[3]) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c new file mode 100644 index 000000000..7d8da62a1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45144.c @@ -0,0 +1,46 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void baz (unsigned); + +extern unsigned buf[]; + +struct A +{ + unsigned a1:10; + unsigned a2:3; + unsigned:19; +}; + +union TMP +{ + struct A a; + unsigned int b; +}; + +static unsigned +foo (struct A *p) +{ + union TMP t; + struct A x; + + x = *p; + t.a = x; + return t.b; +} + +void +bar (unsigned orig, unsigned *new) +{ + struct A a; + union TMP s; + + s.b = orig; + a = s.a; + if (a.a1) + baz (a.a2); + *new = foo (&a); +} + +/* { dg-final { scan-tree-dump-not "unnamed-unsigned:19" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c b/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c new file mode 100644 index 000000000..0952b5a04 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr45427.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cunrolli-details" } */ + +extern void abort (void); +int __attribute__((noinline,noclone)) +foo (char *p) +{ + int h = 0; + do + { + if (*p == '\0') + break; + ++h; + if (p == 0) + abort (); + ++p; + } + while (1); + return h; +} +int main() +{ + if (foo("a") != 1) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump-times "bounded by 0" 0 "cunrolli"} } */ +/* { dg-final { cleanup-tree-dump "cunrolli" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c b/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c new file mode 100644 index 000000000..e9dc434ec --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr46076.c @@ -0,0 +1,27 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_error (void) { /* XFAIL */ } + +typedef unsigned char(*Calculable)(void); + +static unsigned char one() { return 1; } +static unsigned char two() { return 2; } + +static int +print(Calculable calculate) +{ + return calculate() + calculate() + 1; +} + +int +main() +{ + /* Make sure we perform indirect inlining of one and two and optimize + the result to a constant. */ + if (print(one) != 3) + link_error (); + if (print(two) != 5) + link_error (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr47286.c b/gcc/testsuite/gcc.dg/tree-ssa/pr47286.c new file mode 100644 index 000000000..b03c59b83 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr47286.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-skip-if "" { ! { i?86-*-* x86_64-*-* } } { "*" } { "" } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct thread_info { int preempt_count; }; +static inline struct thread_info *current_thread_info(void) +{ + register struct thread_info *sp asm("esp"); + return sp; +} +void testcase(void) +{ + current_thread_info()->preempt_count += 1; +} + +/* We have to make sure that alias analysis treats sp as pointing + to globals and thus the store not optimized away. */ + +/* { dg-final { scan-tree-dump "->preempt_count =" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c b/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c new file mode 100644 index 000000000..20161363f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr47392.c @@ -0,0 +1,42 @@ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +struct A +{ + int i; +}; + +struct B +{ + struct A a[2]; +}; + +int i = 1; +struct B b = { 0, 3 }; + +void +test () +{ + if (b.a[0].i != i) + { + int t = b.a[0].i; + b.a[0] = b.a[1]; + b.a[1].i = t; + } + + if (b.a[1].i == i) + __builtin_abort (); + + if (b.a[0].i == 0) + __builtin_abort (); +} + +int +main () +{ + test (); + return 0; +} + +/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c new file mode 100644 index 000000000..3500dbf2a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49039.c @@ -0,0 +1,31 @@ +/* PR tree-optimization/49039 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void bar (void); + +void +foo (unsigned int x, unsigned int y) +{ + unsigned int minv, maxv; + if (x >= 3 && x <= 6) + return; + if (y >= 5 && y <= 8) + return; + minv = x < y ? x : y; + maxv = x > y ? x : y; + if (minv == 5) + bar (); + if (minv == 6) + bar (); + if (maxv == 5) + bar (); + if (maxv == 6) + bar (); +} + +/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 5 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate minv_\[0-9\]* == 6 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 5 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate maxv_\[0-9\]* == 6 to 0" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49094.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49094.c new file mode 100644 index 000000000..5e565f786 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49094.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +struct in_addr { + unsigned int s_addr; +}; + +struct ip { + unsigned char ip_p; + unsigned short ip_sum; + struct in_addr ip_src,ip_dst; +} __attribute__ ((aligned(1), packed)); + +struct ip ip_fw_fwd_addr; + +int test_alignment( char *m ) +{ + struct ip *ip = (struct ip *) m; + struct in_addr pkt_dst; + pkt_dst = ip->ip_dst ; + if( pkt_dst.s_addr == 0 ) + return 1; + else + return 0; +} + +int __attribute__ ((noinline, noclone)) +intermediary (char *p) +{ + return test_alignment (p); +} + +int +main (int argc, char *argv[]) +{ + ip_fw_fwd_addr.ip_dst.s_addr = 1; + return intermediary ((void *) &ip_fw_fwd_addr); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49642.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49642.c new file mode 100644 index 000000000..65a0b128a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49642.c @@ -0,0 +1,49 @@ +/* Verify that ipa-split is disabled following __builtin_constant_p. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef unsigned int u32; +typedef unsigned long long u64; + +static inline __attribute__((always_inline)) __attribute__((const)) +int __ilog2_u32(u32 n) +{ + int bit; + asm ("cntlzw %0,%1" : "=r" (bit) : "r" (n)); + return 31 - bit; +} + + +static inline __attribute__((always_inline)) __attribute__((const)) +int __ilog2_u64(u64 n) +{ + int bit; + asm ("cntlzd %0,%1" : "=r" (bit) : "r" (n)); + return 63 - bit; +} + + + +static u64 ehca_map_vaddr(void *caddr); + +struct ehca_shca { + u32 hca_cap_mr_pgsize; +}; + +static u64 ehca_get_max_hwpage_size(struct ehca_shca *shca) +{ + return 1UL << ( __builtin_constant_p(shca->hca_cap_mr_pgsize) ? ( (shca->hca_cap_mr_pgsize) < 1 ? ____ilog2_NaN() : (shca->hca_cap_mr_pgsize) & (1ULL << 63) ? 63 : (shca->hca_cap_mr_pgsize) & (1ULL << 62) ? 62 : (shca->hca_cap_mr_pgsize) & (1ULL << 61) ? 61 : (shca->hca_cap_mr_pgsize) & (1ULL << 60) ? 60 : (shca->hca_cap_mr_pgsize) & (1ULL << 59) ? 59 : (shca->hca_cap_mr_pgsize) & (1ULL << 58) ? 58 : (shca->hca_cap_mr_pgsize) & (1ULL << 57) ? 57 : (shca->hca_cap_mr_pgsize) & (1ULL << 56) ? 56 : (shca->hca_cap_mr_pgsize) & (1ULL << 55) ? 55 : (shca->hca_cap_mr_pgsize) & (1ULL << 54) ? 54 : (shca->hca_cap_mr_pgsize) & (1ULL << 53) ? 53 : (shca->hca_cap_mr_pgsize) & (1ULL << 52) ? 52 : (shca->hca_cap_mr_pgsize) & (1ULL << 51) ? 51 : (shca->hca_cap_mr_pgsize) & (1ULL << 50) ? 50 : (shca->hca_cap_mr_pgsize) & (1ULL << 49) ? 49 : (shca->hca_cap_mr_pgsize) & (1ULL << 48) ? 48 : (shca->hca_cap_mr_pgsize) & (1ULL << 47) ? 47 : (shca->hca_cap_mr_pgsize) & (1ULL << 46) ? 46 : (shca->hca_cap_mr_pgsize) & (1ULL << 45) ? 45 : (shca->hca_cap_mr_pgsize) & (1ULL << 44) ? 44 : (shca->hca_cap_mr_pgsize) & (1ULL << 43) ? 43 : (shca->hca_cap_mr_pgsize) & (1ULL << 42) ? 42 : (shca->hca_cap_mr_pgsize) & (1ULL << 41) ? 41 : (shca->hca_cap_mr_pgsize) & (1ULL << 40) ? 40 : (shca->hca_cap_mr_pgsize) & (1ULL << 39) ? 39 : (shca->hca_cap_mr_pgsize) & (1ULL << 38) ? 38 : (shca->hca_cap_mr_pgsize) & (1ULL << 37) ? 37 : (shca->hca_cap_mr_pgsize) & (1ULL << 36) ? 36 : (shca->hca_cap_mr_pgsize) & (1ULL << 35) ? 35 : (shca->hca_cap_mr_pgsize) & (1ULL << 34) ? 34 : (shca->hca_cap_mr_pgsize) & (1ULL << 33) ? 33 : (shca->hca_cap_mr_pgsize) & (1ULL << 32) ? 32 : (shca->hca_cap_mr_pgsize) & (1ULL << 31) ? 31 : (shca->hca_cap_mr_pgsize) & (1ULL << 30) ? 30 : (shca->hca_cap_mr_pgsize) & (1ULL << 29) ? 29 : (shca->hca_cap_mr_pgsize) & (1ULL << 28) ? 28 : (shca->hca_cap_mr_pgsize) & (1ULL << 27) ? 27 : (shca->hca_cap_mr_pgsize) & (1ULL << 26) ? 26 : (shca->hca_cap_mr_pgsize) & (1ULL << 25) ? 25 : (shca->hca_cap_mr_pgsize) & (1ULL << 24) ? 24 : (shca->hca_cap_mr_pgsize) & (1ULL << 23) ? 23 : (shca->hca_cap_mr_pgsize) & (1ULL << 22) ? 22 : (shca->hca_cap_mr_pgsize) & (1ULL << 21) ? 21 : (shca->hca_cap_mr_pgsize) & (1ULL << 20) ? 20 : (shca->hca_cap_mr_pgsize) & (1ULL << 19) ? 19 : (shca->hca_cap_mr_pgsize) & (1ULL << 18) ? 18 : (shca->hca_cap_mr_pgsize) & (1ULL << 17) ? 17 : (shca->hca_cap_mr_pgsize) & (1ULL << 16) ? 16 : (shca->hca_cap_mr_pgsize) & (1ULL << 15) ? 15 : (shca->hca_cap_mr_pgsize) & (1ULL << 14) ? 14 : (shca->hca_cap_mr_pgsize) & (1ULL << 13) ? 13 : (shca->hca_cap_mr_pgsize) & (1ULL << 12) ? 12 : (shca->hca_cap_mr_pgsize) & (1ULL << 11) ? 11 : (shca->hca_cap_mr_pgsize) & (1ULL << 10) ? 10 : (shca->hca_cap_mr_pgsize) & (1ULL << 9) ? 9 : (shca->hca_cap_mr_pgsize) & (1ULL << 8) ? 8 : (shca->hca_cap_mr_pgsize) & (1ULL << 7) ? 7 : (shca->hca_cap_mr_pgsize) & (1ULL << 6) ? 6 : (shca->hca_cap_mr_pgsize) & (1ULL << 5) ? 5 : (shca->hca_cap_mr_pgsize) & (1ULL << 4) ? 4 : (shca->hca_cap_mr_pgsize) & (1ULL << 3) ? 3 : (shca->hca_cap_mr_pgsize) & (1ULL << 2) ? 2 : (shca->hca_cap_mr_pgsize) & (1ULL << 1) ? 1 : (shca->hca_cap_mr_pgsize) & (1ULL << 0) ? 0 : ____ilog2_NaN() ) : (sizeof(shca->hca_cap_mr_pgsize) <= 4) ? __ilog2_u32(shca->hca_cap_mr_pgsize) : __ilog2_u64(shca->hca_cap_mr_pgsize) ); +} + +int x(struct ehca_shca *shca) { + return ehca_get_max_hwpage_size(shca); +} + +int y(struct ehca_shca *shca) +{ + return ehca_get_max_hwpage_size(shca); +} + +/* { dg-final { scan-tree-dump-times "____ilog2_NaN" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49671-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49671-1.c new file mode 100644 index 000000000..acc9980db --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49671-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +volatile int t; +static inline int cvmx_atomic_get32(volatile int *ptr) +{ + return *ptr; +} +void f(void) +{ + while (!cvmx_atomic_get32(&t)) + ; +} + +/* { dg-final { scan-tree-dump "\{v\}" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49671-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49671-2.c new file mode 100644 index 000000000..ba5a9d99c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49671-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int t; +static inline int cvmx_atomic_get32(int *ptr) +{ + return *(volatile int*)ptr; +} +void f(void) +{ + while (!cvmx_atomic_get32(&t)) + ; +} + +/* { dg-final { scan-tree-dump "\{v\}" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr49923.c b/gcc/testsuite/gcc.dg/tree-ssa/pr49923.c new file mode 100644 index 000000000..83113f815 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr49923.c @@ -0,0 +1,55 @@ +/* { dg-do run } */ +/* { dg-options "-O3" } */ + +#define PACKED __attribute__(( packed )) + +struct PACKED aostk_point_u8 { + unsigned char x; + unsigned char y; +}; + +struct PACKED aostk_size_u8 { + unsigned char width; + unsigned char height; +}; + +struct PACKED aostk_glyph { + unsigned short i; + struct aostk_size_u8 size; + char top; + struct aostk_point_u8 advance; + unsigned char pitch; + unsigned char* data; + char left; +}; + + +struct PACKED aostk_font { + unsigned short numglyphs; + unsigned char height; + struct aostk_glyph* glyphs; +}; + +struct aostk_font glob_font; + +static struct aostk_glyph* aostk_get_glyph(struct aostk_font* f, unsigned int c) { + return f->glyphs; +} + +int aostk_font_strwidth(struct aostk_font* font, const char* str) { + struct aostk_glyph* g = aostk_get_glyph(font, 0); + return (g != 0); +} + +struct aostk_font* +__attribute__ ((noinline, noclone)) +get_some_font (void) +{ + return &glob_font; +} + +int main (int argc, char *argv[]) +{ + return (int) aostk_font_strwidth (get_some_font (), "sth"); + +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr51583.c b/gcc/testsuite/gcc.dg/tree-ssa/pr51583.c new file mode 100644 index 000000000..2c4ec4723 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr51583.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O1" } */ + +typedef __complex__ double Value; + +union U +{ + Value v; + char c[sizeof(Value)]; +}; + +struct S +{ + union U u; + int i,j; +}; + +Value gv; +int gi, gj; + +Value foo (void) +{ + struct S s,t; + + t.i = gi; + t.j = gj; + t.u.v = gv; + t.u.c[0] = 0; + + s = t; + __imag__ s.u.v += s.i; + + return s.u.v; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c new file mode 100644 index 000000000..16bd5c910 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-1.c @@ -0,0 +1,51 @@ +/* { dg-do compile } */ +/* { dg-do run } */ +/* { dg-options "-O2 -fpredictive-commoning -fdump-tree-pcom-details" } */ + +void abort (void); + +unsigned fib[1000]; + +__attribute__ ((noinline)) +void count_fib(void) +{ + int i; + + fib[0] = 0; + fib[1] = 1; + for (i = 2; i < 1000; i++) + fib[i] = (fib[i-1] + fib[i - 2]) & 0xffff; +} + +unsigned avg[1000]; + +__attribute__ ((noinline)) +void count_averages(int n) +{ + int i; + + for (i = 1; i < n; i++) + avg[i] = (((unsigned long) fib[i - 1] + fib[i] + fib[i + 1]) / 3) & 0xffff; +} + +int main(void) +{ + count_fib (); + count_averages (999); + + if (fib[19] != 4181 || avg[19] != 4510) + abort (); + + if (fib[999] != 162 || avg[998] != 21953) + abort (); + + return 0; +} + +/* Verify that both loops were transformed and unrolled. */ +/* { dg-final { scan-tree-dump-times "Unrolling 2 times." 2 "pcom"} } */ + +/* Also check that we undid the transformation previously made by PRE. */ +/* { dg-final { scan-tree-dump-times "looparound ref" 1 "pcom"} } */ + +/* { dg-final { cleanup-tree-dump "pcom" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c new file mode 100644 index 000000000..7275f2868 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-2.c @@ -0,0 +1,47 @@ +/* { dg-do compile } */ +/* { dg-do run } */ +/* { dg-options "-O2 -fpredictive-commoning -fdump-tree-pcom-details" } */ + +void abort (void); + +long int fib[1000]; + +__attribute__ ((noinline)) +void count_fib(void) +{ + int i; + + fib[0] = 0; + fib[1] = 1; + for (i = 2; i < 1000; i++) + fib[i] = (fib[i-1] + fib[i - 2]) & 0xffff; +} + +int avg[1000]; + +__attribute__ ((noinline)) +void count_averages(void) +{ + int i; + + for (i = 1; i < 999; i++) + avg[i] = ((fib[i - 1] + fib[i] + fib[i + 1]) / 3) & 0xffff; +} + +int main(void) +{ + count_fib (); + count_averages (); + + if (fib[19] != 4181 || avg[19] != 4510) + abort (); + + if (fib[999] != 162 || avg[998] != 21953) + abort (); + + return 0; +} + +/* Verify that both loops were transformed and unrolled. */ +/* { dg-final { scan-tree-dump-times "Unrolling 2 times." 2 "pcom"} } */ +/* { dg-final { cleanup-tree-dump "pcom" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c new file mode 100644 index 000000000..d5002346e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fpredictive-commoning -fdump-tree-pcom-details" } */ + +int a[1000], b[1000]; + +void test(void) +{ + int i; + + for (i = 1; i < 999; i++) + b[i] = (a[i + 1] + a[i] + a[i - 1]) / 3; +} + +/* Verify that we used 3 temporary variables for the loop. */ +/* { dg-final { scan-tree-dump-times "Unrolling 3 times." 1 "pcom"} } */ +/* { dg-final { cleanup-tree-dump "pcom" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-4.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-4.c new file mode 100644 index 000000000..6f06b7f8b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-4.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-do run } */ +/* { dg-options "-O2 -fpredictive-commoning -fdump-tree-pcom-details" } */ + +/* Test for predictive commoning of expressions, without reassociation. */ + +void abort (void); + +int a[1000], b[1000], c[1000]; + +int main(void) +{ + int i; + + for (i = 0; i < 1000; i++) + a[i] = b[i] = i; + + for (i = 1; i < 998; i++) + c[i] = a[i + 2] * b[i + 1] - b[i - 1] * a[i]; + + for (i = 1; i < 998; i++) + if (c[i] != 4 * i + 2) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "Combination" 1 "pcom"} } */ +/* { dg-final { scan-tree-dump-times "Unrolling 3 times." 1 "pcom"} } */ +/* { dg-final { cleanup-tree-dump "pcom" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/predcom-5.c b/gcc/testsuite/gcc.dg/tree-ssa/predcom-5.c new file mode 100644 index 000000000..134fc3765 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/predcom-5.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-do run } */ +/* { dg-options "-O2 -fpredictive-commoning -fdump-tree-pcom-details" } */ + +/* Test for predictive commoning of expressions, with reassociation. */ + +void abort (void); + +unsigned a[1000], b[1000], c[1000], d[1000]; + +int main(void) +{ + unsigned i; + + for (i = 0; i < 1000; i++) + a[i] = b[i] = d[i] = i; + + for (i = 1; i < 998; i++) + c[i] = d[i + 1] * a[i + 2] * b[i + 1] - b[i - 1] * a[i] * d[i - 1]; + + for (i = 1; i < 998; i++) + if (c[i] != (i+1)*(i+2)*(i+1) - (i - 1) * i * (i - 1)) + abort (); + + return 0; +} + +/* { dg-final { scan-tree-dump-times "Combination" 2 "pcom"} } */ +/* { dg-final { scan-tree-dump-times "Unrolling 3 times." 1 "pcom"} } */ +/* { dg-final { cleanup-tree-dump "pcom" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c new file mode 100644 index 000000000..2c1282d9d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-3.c @@ -0,0 +1,23 @@ +/* Prefetching used to prefer nonsensical unroll factor of 5 in this testcase. */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -msse2 -mfpmath=sse -fdump-tree-aprefetch-details" } */ + +#define N 1000000 + +double a[N]; + +double test(void) +{ + unsigned i; + double sum = 0; + + for (i = 0; i < N; i += 2) + sum += (a[i] * a[i+1]); + + return sum; +} + +/* { dg-final { scan-tree-dump-times "unroll factor 4" 1 "aprefetch" } } */ +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-4.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-4.c new file mode 100644 index 000000000..bff4b9fbf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-4.c @@ -0,0 +1,18 @@ +/* The loop rolls too little, hence the prefetching would not be useful. */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -fdump-tree-optimized" } */ + +int xxx[20]; + +void foo (int n) +{ + int i; + + for (i = 0; i < n; i++) + xxx[i] = i; +} + +/* { dg-final { scan-tree-dump-times "prefetch" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-5.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-5.c new file mode 100644 index 000000000..19914cabf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-5.c @@ -0,0 +1,60 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O2 --param min-insn-to-prefetch-ratio=5 -fprefetch-loop-arrays -march=athlon -fdump-tree-aprefetch-details" } */ + +/* These are common idioms for writing variable-length arrays at the end + of structures. We should not deduce anything about the number of iterations + of the loops from them. */ + +struct tail0 +{ + int xxx; + int yyy[0]; +}; + +int loop0 (int n, struct tail0 *x) +{ + int i, s = 0; + + for (i = 0; i < n; i++) + s += x->yyy[i]; + + return s; +} + +struct tail1 +{ + int xxx; + int yyy[1]; +}; +int loop1 (int n, struct tail1 *x) +{ + int i, s = 0; + + for (i = 0; i < n; i++) + s += x->yyy[i]; + + return s; +} + +/* It is unlikely that this should be a tail array. We may deduce that most + likely, the loop iterates about 5 times, and the array is not worth prefetching. */ + +struct tail5 +{ + int xxx; + int yyy[5]; +}; +int loop5 (int n, struct tail5 *x) +{ + int i, s = 0; + + for (i = 0; i < n; i++) + s += x->yyy[i]; + + return s; +} + +/* { dg-final { scan-tree-dump-times "Issued prefetch" 2 "aprefetch" } } */ +/* { dg-final { scan-tree-dump-times "Not prefetching" 1 "aprefetch" } } */ +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c new file mode 100644 index 000000000..7a1de5a45 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-6.c @@ -0,0 +1,55 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-require-effective-target sse2 } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -msse2 -mfpmath=sse --param simultaneous-prefetches=100 --param min-insn-to-prefetch-ratio=6 -fdump-tree-aprefetch-details" } */ + +#define N 1000 +#define K 900 + +double a[N][N]; + +double test(void) +{ + unsigned i, j; + double sum = 0; + + /* Here, we should use non-temporal prefetch instruction. */ + for (i = 0; i < K; i++) + for (j = 0; j < K; j++) + sum += a[i][j]; + + /* Here, we should not use non-temporal prefetch instruction, since the + value of a[i+10][j] is reused in L2 cache. */ + for (i = 0; i < K; i++) + for (j = 0; j < K; j++) + sum += a[i][j] * a[i + 10][j]; + + /* Here, we should use non-temporal prefetch instruction, since the + value of a[i+100][j] is too far to be reused in L2 cache. */ + for (i = 0; i < K; i++) + for (j = 0; j < K; j++) + sum += a[i][j] * a[i + 100][j]; + + /* Here, temporal prefetches should be used, since the volume of the + memory accesses is smaller than L2 cache. */ + for (i = 0; i < 100; i++) + for (j = 0; j < 100; j++) + sum += a[i][j] * a[i + 100][j]; + + /* Temporal prefetches should be used here (even though the accesses to + a[j][i] are independent, the same cache line is almost always hit + every N iterations). */ + for (i = 0; i < N; i++) + for (j = 0; j < N; j++) + sum += a[j][i]; + + return sum; +} + +/* { dg-final { scan-tree-dump-times "Issued prefetch" 5 "aprefetch" } } */ +/* { dg-final { scan-tree-dump-times "Issued nontemporal prefetch" 3 "aprefetch" } } */ + +/* { dg-final { scan-assembler-times "prefetcht" 5 } } */ +/* { dg-final { scan-assembler-times "prefetchnta" 3 } } */ + +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c new file mode 100644 index 000000000..9e453a7c0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-7.c @@ -0,0 +1,49 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-require-effective-target sse2 } */ +/* { dg-skip-if "" { i?86-*-* x86_64-*-* } { "-march=*" } { "-march=athlon" } } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -msse2 -mfpmath=sse --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */ + +#define K 1000000 +int a[K]; + +void test(int *p) +{ + unsigned i; + + /* Nontemporal store should not be used here (only write and read temporal + prefetches). */ + for (i = 0; i < K - 10000; i++) + a[i + 10000] = a[i]; + + /* Nontemporal store should not be used here (only write and read nontemporal + prefetches). */ + for (i = 0; i < K - 100000; i++) + a[i + 100000] = a[i]; + + /* Nontemporal store should be used neither for a nor for p, as we do not know + whether they alias or not. */ + for (i = 0; i < K; i++) + { + a[i] = 0; + *p++ = 1; + } + + /* Nontemporal store should not be used for a, as we do not know whether its + value will be reused or not. */ + for (i = 0; i < 1000; i++) + a[i] = 0; +} + +/* { dg-final { scan-tree-dump-times "Issued prefetch" 5 "aprefetch" } } */ +/* { dg-final { scan-tree-dump-times "Issued nontemporal prefetch" 2 "aprefetch" } } */ +/* { dg-final { scan-tree-dump-times "a nontemporal store" 0 "aprefetch" } } */ + +/* { dg-final { scan-tree-dump-times "builtin_prefetch" 7 "optimized" } } */ + +/* { dg-final { scan-assembler-times "prefetchw" 5 } } */ +/* { dg-final { scan-assembler-times "prefetcht" 1 } } */ +/* { dg-final { scan-assembler-times "prefetchnta" 1 } } */ + +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c new file mode 100644 index 000000000..a05d552ac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-8.c @@ -0,0 +1,28 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-require-effective-target sse2 } */ +/* { dg-skip-if "" { i?86-*-* x86_64-*-* } { "-march=*" } { "-march=athlon" } } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -msse2 -mfpmath=sse --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */ + +#define K 1000000 +int a[K]; + +void test() +{ + unsigned i; + + /* Nontemporal store should be used for a. */ + for (i = 0; i < K; i++) + a[i] = 0; +} + +/* { dg-final { scan-tree-dump-times "a nontemporal store" 1 "aprefetch" } } */ + +/* { dg-final { scan-tree-dump "=\\{nt\\}" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_ia32_mfence" 1 "optimized" } } */ + +/* { dg-final { scan-assembler "movnti" } } */ +/* { dg-final { scan-assembler-times "mfence" 1 } } */ + +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c new file mode 100644 index 000000000..eb22a660e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/prefetch-9.c @@ -0,0 +1,32 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-require-effective-target sse2 } */ +/* { dg-skip-if "" { i?86-*-* x86_64-*-* } { "-march=*" } { "-march=athlon" } } */ +/* { dg-options "-O2 -fprefetch-loop-arrays -march=athlon -msse2 -mfpmath=sse --param simultaneous-prefetches=100 -fdump-tree-aprefetch-details -fdump-tree-optimized" } */ + +#define K 1000000 +int a[K], b[K]; + +void test() +{ + unsigned i; + + /* Nontemporal store should be used for a, nontemporal prefetch for b. */ + for (i = 0; i < K; i++) + a[i] = b[i]; + +} + +/* { dg-final { scan-tree-dump-times "Issued nontemporal prefetch" 1 "aprefetch" } } */ +/* { dg-final { scan-tree-dump-times "a nontemporal store" 1 "aprefetch" } } */ + +/* { dg-final { scan-tree-dump-times "builtin_prefetch" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump "=\\{nt\\}" "optimized" } } */ +/* { dg-final { scan-tree-dump-times "__builtin_ia32_mfence" 1 "optimized" } } */ + +/* { dg-final { scan-assembler-times "prefetchnta" 1 } } */ +/* { dg-final { scan-assembler "movnti" } } */ +/* { dg-final { scan-assembler-times "mfence" 1 } } */ + +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c new file mode 100644 index 000000000..9c8ec3034 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-callused.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 --param max-fields-for-field-sensitive=2 -fdump-tree-alias" } */ + +struct Foo { + int *p, *q; +}; + +int *foo (int ***x) __attribute__((pure)); + +int bar (int b) +{ + int i; + struct Foo f; + int *p, **q; + p = &i; + f.p = &i; + f.q = f.p; + if (b) + q = &f.p; + else + q = &f.q; + return *foo (&q); +} + +/* { dg-final { scan-tree-dump "CALLUSED = { ESCAPED NONLOCAL f.* i q }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c new file mode 100644 index 000000000..7cc19be6c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-1.c @@ -0,0 +1,37 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-alias-details" } */ + +int *i; +void __attribute__((noinline)) +foo (void) +{ + *i = 1; +} +int __attribute__((noinline)) +bar(int local_p) +{ + int x = 0; + int *j; + int **p; + if (local_p) + p = &j; + else + p = &i; + *p = &x; /* This makes x escape. */ + foo (); + return x; +} +extern void abort (void); +int main() +{ + int k = 2; + i = &k; + if (bar (1) != 0 || k != 1) + abort (); + if (bar (0) != 1) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "ESCAPED, points-to non-local, points-to NULL, points-to vars: { x }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c new file mode 100644 index 000000000..878352d26 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-2.c @@ -0,0 +1,38 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-alias-details" } */ + +int *i; +void __attribute__((noinline)) +foo (void) +{ + *i = 1; +} +int __attribute__((noinline)) +bar(int local_p, int **q) +{ + int x = 0; + int *j; + int **p; + if (local_p) + p = &j; + else + p = q; + *p = &x; /* This makes x escape. */ + foo (); + return x; +} +extern void abort (void); +int main() +{ + int k = 2; + int **q = &i; + i = &k; + if (bar (1, q) != 0 || k != 1) + abort (); + if (bar (0, q) != 1) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "ESCAPED, points-to non-local, points-to NULL, points-to vars: { x }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c new file mode 100644 index 000000000..8e779d846 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-escape-3.c @@ -0,0 +1,42 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-alias-details" } */ + +int *i; +void __attribute__((noinline)) +foo (void) +{ + *i = 1; +} +int **__attribute__((noinline,const)) +foobar (void) +{ + return &i; +} +int __attribute__((noinline)) +bar(int local_p) +{ + int x = 0; + int *j; + int **p; + if (local_p) + p = &j; + else + p = foobar(); + *p = &x; /* This makes x escape. */ + foo (); + return x; +} +extern void abort (void); +int main() +{ + int k = 2; + i = &k; + if (bar (1) != 0 || k != 1) + abort (); + if (bar (0) != 1) + abort (); + return 0; +} + +/* { dg-final { scan-tree-dump "ESCAPED, points-to non-local, points-to NULL, points-to vars: { x }" "alias" } } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-fp.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-fp.c new file mode 100644 index 000000000..022783df1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-fp.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-alias" } */ +extern double cos (double); +extern double sin (double); +double f(double a) +{ + double b; + double c,d; + double (*fp) (double); + if (a < 2.0) + { + fp = sin; + c = fp (a); + } + else + { + c = 1.0; + fp = cos; + } + d = fp (a); + return d + c; +} +/* The points-to set of the final function pointer should be "sin cos" */ + +/* { dg-final { scan-tree-dump-times "{ sin cos }" 1 "alias"} } */ +/* { dg-final { cleanup-tree-dump "alias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-1.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-1.c new file mode 100644 index 000000000..2a60e1daa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fdump-tree-ealias" } */ + +extern void abort (void); +struct X { + int *p; + int *q; + int *r; +}; +int __attribute__((noinline)) +foo(int i, int j, int k, int off) +{ + struct X x; + int **p, *q; + x.p = &i; + x.q = &j; + x.r = &k; + p = &x.q; + p += 1; + /* *p points to { k } */ + q = *p; + return *q; +} + +/* { dg-final { scan-tree-dump "q_., points-to vars: { k }" "ealias" } } */ +/* { dg-final { cleanup-tree-dump "ealias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-2.c b/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-2.c new file mode 100644 index 000000000..ddf934bf8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/pta-ptrarith-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-forwprop -fno-tree-ccp -fdump-tree-ealias" } */ + +extern void abort (void); +struct X { + int *p; + int *q; + int *r; +}; +int __attribute__((noinline)) +foo(int i, int j, int k, int off) +{ + struct X x; + int **p, *q; + x.p = &i; + x.q = &j; + x.r = &k; + p = &x.q; + p -= 1; + /* *p points to { i } */ + q = *p; + return *q; +} + +/* { dg-final { scan-tree-dump "q_., points-to vars: { i }" "ealias" } } */ +/* { dg-final { cleanup-tree-dump "ealias" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-1.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-1.c new file mode 100644 index 000000000..43ccd8eaa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int a, b, c, d; +extern int printf (const char *, ...); +int main(void) +{ + int e; + int f; + /* We should be able to transform these into the same expression, and only have two additions. */ + e = a + b; + e = e + c; + f = c + a; + f = f + b; + printf ("%d %d\n", e, f); +} + +/* We cannot reassociate these expressions because of undefined signed + integer overflow. Instead the value-numberer has to be extended + to canonicalize these expressions. */ + +/* { dg-final { scan-tree-dump-times "b.._. \\\+ a.._." 1 "optimized" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times " \\\+ " 2 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-10.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-10.c new file mode 100644 index 000000000..cdc277431 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-10.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int main(int a, int b, int c, int d) +{ + /* Should become just a & b & c & d */ + int e = (a & b) & (c & d); + int f = (c & a) & (b & d); + return e & f; +} +/* { dg-final { scan-tree-dump-times "\\\& " 3 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-11.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-11.c new file mode 100644 index 000000000..f48f04e99 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-11.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ +int main(int a, int b, int c, int d) +{ + /* All the xor's cancel each other out, leaving 0 */ + int e = (a ^ b) ^ (c ^ d); + int f = (c ^ a) ^ (b ^ d); + return e ^ f; +} +/* { dg-final { scan-tree-dump-times "= 0" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-12.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-12.c new file mode 100644 index 000000000..65e2931ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-12.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1-details" } */ +int f(int a, int b) +{ + /* MAX_EXPR <a, a> should cause it to be equivalent to a. */ + int c = a>=b?a:b; + int d = c>=a?c:a; + return d; +} +/* { dg-final { scan-tree-dump-times "Equivalence:" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-13.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-13.c new file mode 100644 index 000000000..f05401cba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-13.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ffast-math -fdump-tree-reassoc1 -fdump-tree-optimized" } */ + +double foo(double a) +{ + double tmp = 5.0; + double tmp2 = a + tmp; + tmp2 = tmp2 - a; + return a + tmp2 - 5.0; +} + +/* { dg-final { scan-tree-dump-not "\\\+ 0.0" "reassoc1" } } */ +/* { dg-final { scan-tree-dump "return a_..D.;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-14.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-14.c new file mode 100644 index 000000000..5b57160bc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-14.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +unsigned int test1 (unsigned int x, unsigned int y, unsigned int z, + unsigned int weight) +{ + unsigned int tmp1 = x * weight; + unsigned int tmp2 = y * weight; + unsigned int tmp3 = (x - y) * weight; + return tmp1 + (tmp2 + tmp3); +} + +unsigned int test2 (unsigned int x, unsigned int y, unsigned int z, + unsigned int weight) +{ + unsigned int tmp1 = x * weight; + unsigned int tmp2 = y * weight * weight; + unsigned int tmp3 = z * weight * weight * weight; + return tmp1 + tmp2 + tmp3; +} + +/* There should be one multiplication left in test1 and three in test2. */ + +/* { dg-final { scan-tree-dump-times "\\\*" 4 "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-15.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-15.c new file mode 100644 index 000000000..df6fd5213 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-15.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +unsigned int test3 (unsigned int x, unsigned int y, unsigned int z, + unsigned int weight, + unsigned int w1, unsigned int w2, unsigned int w3) +{ + unsigned int wtmp1 = w1 * weight; + unsigned int wtmp2 = w2 * weight; + unsigned int wtmp3 = w3 * weight; + unsigned int tmp1 = x * wtmp1; + unsigned int tmp2 = y * wtmp2; + unsigned int tmp3 = z * wtmp3; + return tmp1 + tmp2 + tmp3; +} + +/* The multiplication with weight should be un-distributed. + ??? This pattern is not recognized currently. */ + +/* { dg-final { scan-tree-dump-times "\\\*" 4 "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-16.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-16.c new file mode 100644 index 000000000..4dd54a8cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-16.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ + +double test1 (double x, double y, double z, double weight) +{ + double tmp1 = x / weight; + double tmp2 = y / weight; + double tmp3 = -x / weight; + return tmp1 + tmp2 + tmp3; +} + +/* The division should be un-distributed and all references to x should + be gone. */ + +/* { dg-final { scan-tree-dump-times "/" 1 "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-17.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-17.c new file mode 100644 index 000000000..255c786d7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-17.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -ffast-math -fdump-tree-reassoc1" } */ + +double test2 (double x, double y, double ddj, int b) +{ + double tmp1, tmp2, sum; + sum = 0.0; + if (b) + sum = 1.0; + tmp1 = sum/ddj; + tmp2 = x/ddj; + return tmp1 + y + tmp2; +} + +/* { dg-final { scan-tree-dump-times "/" 1 "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-18.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-18.c new file mode 100644 index 000000000..ab7fe295a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-18.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-reassoc1" } */ + +unsigned int +ETree_nFactorEntriesInFront (unsigned int b, unsigned int m) +{ + unsigned int nent = b*b + 2*b*m; + return nent; +} + +/* { dg-final { scan-tree-dump-times "\\\*" 2 "reassoc1" } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-19.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-19.c new file mode 100644 index 000000000..c13e1d36f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-19.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -fdump-tree-reassoc2" } */ + +/* Slightly changed testcase from PR middle-end/40815. */ +void bar(char*, char*, int); +void foo(char* left, char* rite, int element) +{ + while (left <= rite) + { + /* This should expand into + D.zzzz = D.zzzz - D.xxxx; + and NOT to + D.D.yyyy = -D.xxxx; D.zzzz = D.zzzz + D.yyyy; */ + rite -= element; + bar(left, rite, element); + } +} + +/* There should be no " + " in the dump. */ +/* { dg-final { scan-tree-dump-times " \\\+ " 0 "reassoc2" } } */ +/* { dg-final { cleanup-tree-dump "reassoc2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-2.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-2.c new file mode 100644 index 000000000..c5787ab5a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-2.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int f (int a0,int a1,int a2,int a3,int a4) +{ +int b0, b1, b2, b3, b4,e; + /* this can be optimized to four additions... */ + b4 = a4 + a3 + a2 + a1 + a0; + b3 = a3 + a2 + a1 + a0; + b2 = a2 + a1 + a0; + b1 = a1 + a0; + /* This is actually 0 */ + e = b4 - b3 + b2 - b1 - a4 - a2; + return e; +} + +/* We can't reassociate the expressions due to undefined signed overflow. */ + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c new file mode 100644 index 000000000..1cfb98093 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-20.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +unsigned int a, b, c, d; +extern int printf (const char *, ...); +int main(void) +{ + unsigned int e; + unsigned int f; + /* We should be able to transform these into the same expression, and only have two additions. */ + e = a + b; + e = e + c; + f = c + a; + f = f + b; + printf ("%d %d\n", e, f); +} + +/* { dg-final { scan-tree-dump-times "b.._. \\\+ a.._." 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times " \\\+ " 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-21.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-21.c new file mode 100644 index 000000000..e02de1b47 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-21.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +unsigned int f (unsigned int a0, unsigned int a1, unsigned int a2, + unsigned int a3, unsigned int a4) +{ + unsigned int b0, b1, b2, b3, b4, e; + /* this can be optimized to four additions... */ + b4 = a4 + a3 + a2 + a1 + a0; + b3 = a3 + a2 + a1 + a0; + b2 = a2 + a1 + a0; + b1 = a1 + a0; + /* This is actually 0 */ + e = b4 - b3 + b2 - b1 - a4 - a2; + return e; +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-22.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-22.c new file mode 100644 index 000000000..7eb97f456 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-22.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ +unsigned int foo(unsigned int a, unsigned int b, unsigned int c, unsigned int d) +{ + /* Should be transformed into a + c + 8 */ + unsigned int e = a + 3; + unsigned int f = c + 5; + unsigned int g = e + f; + return g; +} + +/* { dg-final { scan-tree-dump-times "\\\+ 8" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-23.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-23.c new file mode 100644 index 000000000..65aee7237 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-23.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +unsigned int +foo(unsigned int a, unsigned int b, unsigned int c, unsigned int d, + unsigned int e, unsigned int f, unsigned int g, unsigned int h) +{ + /* Should be transformed into e = 20 */ + unsigned int i = (a + 9) + (c + 8); + unsigned int j = (-c + 1) + (-a + 2); + + e = i + j; + return e; +} + +/* { dg-final { scan-tree-dump-times "= 20" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-3.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-3.c new file mode 100644 index 000000000..178e6a448 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-3.c @@ -0,0 +1,7 @@ +/* { dg-options "" } */ +int main(int a, int b, int c, int d) +{ + int e = (a & ~b) & (~c & d); + int f = (~c & a) & (b & ~d); + return (e & f); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-4.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-4.c new file mode 100644 index 000000000..8f9de464e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -ffast-math" } */ +float a, b, c, d; +extern int printf (const char *, ...); +int main(void) +{ + float e; + float f; + /* We should not be able to transform these into the same expression, and only have two additions. */ + e = a + b; + e = e + c; + f = c + a; + f = f + b; + printf ("%f %f\n", e, f); +} + +/* { dg-final { scan-tree-dump-times "\\\+" 2 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-5.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-5.c new file mode 100644 index 000000000..8d168f90f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-5.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +extern int printf (const char *, ...); +int main(int argc, int b) +{ + /* We should be able to get rid of the a - i. */ + int i; + for (i = 0; i < 50; i++) + { + int a = b + i; + int c = a - i; + int d = argc + b; + printf ("%d %d\n", c,d); + } +} +/* { dg-final { scan-tree-dump-times "a - i" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-6.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-6.c new file mode 100644 index 000000000..480f7c016 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-6.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ +int main(int a, int b, int c, int d) +{ + /* Should be transformed into a + c + 8 */ + int e = a + 3; + int f = c + 5; + int g = e + f; + return g; +} + +/* We cannot re-associate the additions due to undefined signed overflow. */ + +/* { dg-final { scan-tree-dump-times "\\\+ 8" 1 "reassoc1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-7.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-7.c new file mode 100644 index 000000000..ee9b80fd9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-7.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +unsigned int +foo(unsigned int a, unsigned int b, unsigned int c, unsigned int d, + unsigned int e, unsigned int f, unsigned int g, unsigned int h) +{ + /* Should be transformed into a + c + d + e + g + 15 */ + unsigned int i = (a + 9) + (c + d); + unsigned int j = (e + 4) + (2 + g); + e = i + j; + return e; +} + +/* { dg-final { scan-tree-dump-times "\\\+ 15" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-8.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-8.c new file mode 100644 index 000000000..b2ca4ae03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-8.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +int main(int a, int b, int c, int d, int e, int f, int g, int h) +{ + /* e & ~e -> 0 */ + int i = (a & 9) & (c & d); + int j = (~e & d) & (~c & e); + e = i & j; + return e; +} +/* { dg-final { scan-tree-dump-times "= 0" 1 "reassoc1"} } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/reassoc-9.c b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-9.c new file mode 100644 index 000000000..d09303ccf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/reassoc-9.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-reassoc1" } */ + +int main(int a, int b, int c, int d, int e, int f, int g, int h) +{ + /* Should be transformed into e = 20 */ + int i = (a + 9) + (c + 8); + int j = (-c + 1) + (-a + 2); + + e = i + j; + return e; +} + +/* We can always re-associate to a final constant but the current + implementation does not allow easy roll-back without IL changes. */ + +/* { dg-final { scan-tree-dump-times "= 20" 1 "reassoc1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "reassoc1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-1.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-1.c new file mode 100644 index 000000000..36f2c23de --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -funsafe-math-optimizations -fdump-tree-recip" } */ + +float e(float *x, float *y, float *z) +{ + float m = __builtin_sqrt (*x * *x + *y * *y + *z * *z); + *x /= m; + *y /= m; + *z /= m; +} + +/* Look for only one division. */ +/* { dg-final { scan-tree-dump-times "= .* /" 1 "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-2.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-2.c new file mode 100644 index 000000000..be754145e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-2.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -funsafe-math-optimizations -fdump-tree-recip" } */ + +float u, v, w, x, y, z; + +void e(float a, float b, float c, float d, float e, float f) +{ + if (a < b) + { + a = a + b; + c = c + d; + } + + /* The PHI nodes for these divisions should be combined. */ + d = d / a; + e = e / a; + f = f / a; + + a = a / c; + b = b / c; + + /* This should not be left as a multiplication. */ + c = 1 / c; + + u = a; + v = b; + w = c; + x = d; + y = e; + z = f; +} + +/* { dg-final { scan-tree-dump-times " / " 2 "recip" } } */ +/* { dg-final { scan-tree-dump-times " \\* " 5 "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c new file mode 100644 index 000000000..04b40f32a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-3.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-trapping-math -funsafe-math-optimizations -fdump-tree-recip" } */ + +double F[2] = { 0.0, 0.0 }, e; + +/* In this case the optimization is interesting. */ +float h () +{ + int i; + double E, W, P, d; + + W = 1.1; + d = 2.*e; + E = 1. - d; + + for( i=0; i < 2; i++ ) + if( d > 0.01 ) + { + P = ( W < E ) ? (W - E)/d : (E - W)/d; + F[i] += P; + } + + F[0] += E / d; +} + +/* { dg-final { scan-tree-dump-times " / " 1 "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-4.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-4.c new file mode 100644 index 000000000..20d7681d2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-4.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-trapping-math -funsafe-math-optimizations -fdump-tree-recip" } */ + +/* based on the test case in pr23109 */ + +double F[2] = { 0., 0. }, e = 0.; + +/* Nope, we cannot prove the optimization is worthwhile in this case. */ +void f () +{ + int i; + double E, W, P, d; + + W = 1.; + d = 2.*e; + E = 1. - d; + + if( d > 0.01 ) + { + P = ( W < E ) ? (W - E)/d : (E - W)/d; + F[i] += P; + } +} + +/* We also cannot prove the optimization is worthwhile in this case. */ +float g () +{ + int i; + double E, W, P, d; + + W = 1.; + d = 2.*e; + E = 1. - d; + + if( d > 0.01 ) + { + P = ( W < E ) ? (W - E)/d : (E - W)/d; + F[i] += P; + } + + return 1.0 / d; +} + +/* { dg-final { scan-tree-dump-not "reciptmp" "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-5.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-5.c new file mode 100644 index 000000000..aafa98f16 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-5.c @@ -0,0 +1,32 @@ +/* { dg-options "-O1 -funsafe-math-optimizations -ftrapping-math -fdump-tree-recip -fdump-tree-optimized" } */ +/* { dg-do compile } */ +/* { dg-warning "-fassociative-math disabled" "" { target *-*-* } 1 } */ + +/* Test the reciprocal optimizations together with trapping math. */ + +extern int f2(); + +double f1(double y, double z, double w, double j, double k) +{ + double b, c, d, e, f, g; + + if (f2 ()) + /* inserts one division here */ + b = 1 / y, c = z / y, d = j / y; + else + /* one division here */ + b = 3 / y, c = w / y, d = k / y; + + /* and one here, that should be removed afterwards but is not right now */ + e = b / y; + f = c / y; + g = d / y; + + return e + f + g; +} + +/* { dg-final { scan-tree-dump-times " / " 3 "recip" } } */ +/* { dg-final { scan-tree-dump-times " / " 2 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-6.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-6.c new file mode 100644 index 000000000..b3334fb86 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-6.c @@ -0,0 +1,30 @@ +/* { dg-options "-O1 -funsafe-math-optimizations -fno-trapping-math -fdump-tree-recip" } */ +/* { dg-do compile } */ + +/* Test inserting in a block that does not contain a division. */ + +extern int f2(); + +double m, n, o; + +void f1(double y, double z, double w) +{ + double b, c, d, e, f; + + if (g ()) + b = 1 / y, c = z / y; + else + b = 3 / y, c = w / y; + + d = b / y; + e = c / y; + f = 1 / y; + + m = d; + n = e; + o = f; +} + +/* { dg-final { scan-tree-dump-times " / " 1 "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/recip-7.c b/gcc/testsuite/gcc.dg/tree-ssa/recip-7.c new file mode 100644 index 000000000..98bbdca6e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/recip-7.c @@ -0,0 +1,31 @@ +/* { dg-options "-O1 -funsafe-math-optimizations -fno-trapping-math -fdump-tree-recip" } */ +/* { dg-do compile } */ + +/* Test inserting in a block that does not contain a division. */ + +extern double h(); + +double m, n, o; + +void f(int x, double z, double w) +{ + double b, c, d, e, f; + double y = h (); + + if (x) + b = 1 / y, c = z / y; + else + b = 3 / y, c = w / y; + + d = b / y; + e = c / y; + f = 1 / y; + + m = d; + n = e; + o = f; +} + +/* { dg-final { scan-tree-dump-times " / " 1 "recip" } } */ +/* { dg-final { cleanup-tree-dump "recip" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c b/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c new file mode 100644 index 000000000..90f62aa4d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/restrict-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-strict-aliasing -fdump-tree-lim-details" } */ + +void f(int * __restrict__ r, + int a[__restrict__ 16][16], + int b[__restrict__ 16][16], + int i, int j) +{ + int x; + *r = 0; + for (x = 1; x < 16; ++x) + *r = *r + a[i][x] * b[x][j]; +} + +/* We should apply store motion to the store to *r. */ + +/* { dg-final { scan-tree-dump "Executing store motion of \\\*r" "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-1.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-1.c new file mode 100644 index 000000000..b959fa17b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-1.c @@ -0,0 +1,19 @@ +/* PR tree-optimization/19899 */ +/* Decrementing a floating-point variable in a loop caused an ICE. */ + +/* { dg-do run } */ +/* { dg-options "-O -ftree-vectorize" } */ + +extern void abort (void); + +int main() +{ + float i=1; + + while (i>=0) + --i; + + if (i != -1) + abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-2.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-2.c new file mode 100644 index 000000000..0cac99475 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-2.c @@ -0,0 +1,20 @@ +/* PR tree-optimization/19899 */ +/* Decrementing a floating-point variable in a loop caused an ICE. */ + +/* { dg-do run } */ +/* { dg-options "-O -ftree-vectorize" } */ + +extern void abort (void); + +int main() +{ + double a = 20; + int i; + + for (i = 0; i < 10; ++i) + a -= 2; + + if (a) + abort(); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/scev-cast.c b/gcc/testsuite/gcc.dg/tree-ssa/scev-cast.c new file mode 100644 index 000000000..2cf245460 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/scev-cast.c @@ -0,0 +1,26 @@ +/* A test for various conversions of chrecs. */ + +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +void blas (char xxx); +void blau (unsigned char xxx); + +void tst(void) +{ + unsigned i; + + for (i = 0; i < 128; i++) /* This cast to char has to be preserved. */ + blas ((char) i); + for (i = 0; i < 127; i++) /* And this one does not. */ + blas ((char) i); + for (i = 0; i < 255; i++) /* This cast is not necessary. */ + blau ((unsigned char) i); + for (i = 0; i < 256; i++) + blau ((unsigned char) i); /* This one is necessary. */ +} + +/* { dg-final { scan-tree-dump-times "= \\(unsigned char\\)" 1 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "= \\(char\\)" 1 "optimized" } } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c new file mode 100644 index 000000000..e5af24751 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-1.c @@ -0,0 +1,73 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* Tests for SRA. */ + +typedef struct teststruct +{ + double d; + char f1; +} teststruct; + +void +copystruct1 (teststruct param) +{ + teststruct local; + param.f1 = 0; + local = param; + if (local.f1 != 0) + link_error (); +} + +void +copystruct11 (teststruct *param) +{ + teststruct local; + param->f1 = 0; + local = *param; + if (local.f1 != 0) + link_error (); +} + +void +copystruct111 (teststruct param) +{ + teststruct *local = ¶m; + param.f1 = 0; + if (local->f1 != 0) + link_error (); +} + +teststruct globf; +void +copystruct1111 (void) +{ + teststruct local; + globf.f1 = 0; + local = globf; + if (local.f1 != 0) + link_error (); +} + +void +copystruct11111 (void) +{ + teststruct *local = &globf; + globf.f1 = 0; + if (local->f1 != 0) + link_error (); +} + +void +copystruct111111 (teststruct param) +{ + static teststruct local; + param.f1 = 0; + local = param; + if (local.f1 != 0) + link_error (); +} + +/* There should be no referenc to link_error. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-10.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-10.c new file mode 100644 index 000000000..49bfa31fa --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-10.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct S +{ + int a[1]; + int z[256]; +}; + +void foo (struct S *s, int i) +{ + struct S disappear; + + disappear.a[i] = 12; + *s = disappear; +} + +/* { dg-final { scan-tree-dump-times "disappear" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-11.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-11.c new file mode 100644 index 000000000..c8a90eac5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-11.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-esra-details" } */ + +struct S +{ + int i; + int j; + char c[32]; /* this disables total scalarization */ +}; + +extern struct S bar(void); + +int foo1 (int b) +{ + struct S s1; + + s1 = bar (); + return s1.i; +} + +extern struct S *g; + +int foo2 (void) +{ + struct S s2; + + s2 = *g; + return s2.i; +} + +/* { dg-final { scan-tree-dump-times "Created a replacement for s1" 0 "esra"} } */ +/* { dg-final { scan-tree-dump-times "Created a replacement for s2" 1 "esra"} } */ +/* { dg-final { cleanup-tree-dump "esra" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-13.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-13.c new file mode 100644 index 000000000..12b77fe2f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-13.c @@ -0,0 +1,114 @@ +/* Test that SRA replacement can deal with assignments that have + sub-replacements on one side and a single scalar replacement on another. */ +/* { dg-do run } */ +/* { dg-options "-O1" } */ + +struct A +{ + int i1, i2; +}; + +struct B +{ + long long int l; +}; + +union U +{ + struct A a; + struct B b; +}; + +int b, gi; +long gl; +union U gu1, gu2; + +int __attribute__ ((noinline, noclone)) +foo (void) +{ + union U x, y; + int r; + + y = gu1; + if (b) + y.b.l = gl; + + x = y; + + if (!b) + r = x.a.i1; + else + r = 0; + + gu2 = x; + return r; +} + +long long int __attribute__ ((noinline, noclone)) +bar (void) +{ + union U x, y; + int r; + + y = gu1; + if (b) + y.a.i1 = gi; + + x = y; + + if (!b) + r = x.b.l; + else + r = 0; + + gu2 = x; + return r; +} + + +int +main (void) +{ + int r; + long long int s; + + b = 0; + gu1.a.i1 = 123; + gu1.a.i2 = 234; + r = foo (); + if (r != 123) + __builtin_abort (); + if (gu2.a.i1 != 123) + __builtin_abort (); + if (gu2.a.i2 != 234) + __builtin_abort (); + + b = 1; + gl = 10000001; + gu1.b.l = 10000000; + r = foo (); + if (r != 0) + __builtin_abort (); + if (gu2.b.l != 10000001) + __builtin_abort (); + + b = 0; + gu1.b.l = 20000000; + s = bar (); + if (s != 20000000) + __builtin_abort (); + if (gu2.b.l != 20000000) + __builtin_abort (); + + b = 1; + gi = 456; + gu1.a.i1 = 123; + gu1.a.i2 = 234; + s = bar (); + if (s != 0) + __builtin_abort (); + if (gu2.a.i1 != 456) + __builtin_abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c new file mode 100644 index 000000000..5682b8afb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-2.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fno-tree-fre -fdump-tree-optimized" } */ + +/* Test for SRA. */ + +typedef struct teststruct +{ + double d; + char f1; +} teststruct; + + +void +copystruct11 (teststruct *param) +{ + static teststruct local; + param->f1 = 0; + local = *param; + if (local.f1 != 0) + link_error (); +} + + +/* There should be no reference to link_error. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c new file mode 100644 index 000000000..d89081523 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-3.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* Test for SRA. */ + +typedef struct teststruct +{ + double d; + char f1; +} teststruct; + +teststruct *globf1; + +extern void link_error (void); + +void +copystruct1 (void) +{ + teststruct local; + globf1->f1 = 0; + local = *globf1; + if (local.f1 != 0) + link_error (); +} + +/* There should be no reference to link_error. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c new file mode 100644 index 000000000..e6ca7561f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-4.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized -w" } */ +/* { dg-options "-O1 -fdump-tree-optimized -w -msse" { target { i?86-*-* x86_64-*-* } } } */ +/* Check that SRA replaces structures containing vectors. */ + +#define vector __attribute__((vector_size(16))) + +struct vt +{ + vector int t; +}; + + +vector int f(vector int t1, vector int t2) +{ + struct vt st1, st2, st3; + st1.t = t1; + st2 = st1; + st2.t += t2; + st3 = st2; + return st3.t; +} + +/* { dg-final { scan-tree-dump-times "st" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-5.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-5.c new file mode 100644 index 000000000..869d2f55f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-5.c @@ -0,0 +1,74 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* Tests for SRA of unions. */ + + +typedef union testunion +{ + double d; + char f1; +} testunion; + +void +copyunion1 (testunion param) +{ + testunion local; + param.f1 = 0; + local = param; + if (local.f1 != 0) + link_error (); +} + +void +copyunion11 (testunion *param) +{ + testunion local; + param->f1 = 0; + local = *param; + if (local.f1 != 0) + link_error (); +} + +void +copyunion111 (testunion param) +{ + testunion *local = ¶m; + param.f1 = 0; + if (local->f1 != 0) + link_error (); +} + +testunion globuf; +void +copyunion1111 (void) +{ + testunion local; + globuf.f1 = 0; + local = globuf; + if (local.f1 != 0) + link_error (); +} + +void +copyunion11111 (void) +{ + testunion *local = &globuf; + globuf.f1 = 0; + if (local->f1 != 0) + link_error (); +} + +void +copyunion111111 (testunion param) +{ + static testunion local; + param.f1 = 0; + local = param; + if (local.f1 != 0) + link_error (); +} + +/* There should be no reference to link_error. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-6.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-6.c new file mode 100644 index 000000000..e59b536c1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-6.c @@ -0,0 +1,40 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized -fdump-tree-esra-details" } */ + +typedef struct teststruct +{ + double d; + int i1; + char c1; + float z; + char c2; + int i2; +} teststruct; + + +void cow (int i) +{ + teststruct a, b, c, d; + + a.d = 3.2; + a.i1 = i; + + b = a; + c = b; + d = c; + + if (d.i1 != i) + link_error (); +} + + +/* Suaccesses of b and c should have been created. */ +/* { dg-final { scan-tree-dump "expr = b.d" "esra"} } */ +/* { dg-final { scan-tree-dump "expr = b.i1" "esra"} } */ +/* { dg-final { scan-tree-dump "expr = c.d" "esra"} } */ +/* { dg-final { scan-tree-dump "expr = c.i1" "esra"} } */ +/* { dg-final { cleanup-tree-dump "esra" } } */ + +/* There should be no reference to link_error. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-7.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-7.c new file mode 100644 index 000000000..325a329f3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-7.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +typedef struct { char f[4]; } __attribute__((aligned (4))) s; + +void a(s *s1, s *s2) +{ + *s1 = *s2; +} + +/* Struct copies should not be split into members. */ +/* { dg-final { scan-tree-dump "\\\*s1_.\\\(D\\\) = \\\*s2" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-8.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-8.c new file mode 100644 index 000000000..d43bbe0d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-8.c @@ -0,0 +1,35 @@ +/* A testcase for PR 40744. We do not want to create replacements for object + that are dead or have only a single use, whenever it can be avoided + simply. */ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-esra-details" } */ + +struct X { int i; int j; }; + +void foo(void) +{ + struct X x; + x.i = 1; + x.j = 2; +} + + +int bar(struct X x) +{ + return x.i; +} + + +extern void do_something (struct X); + +void bar2(int i, int j) +{ + struct X x; + + x.i = i; + x.j = j; + do_something (x); +} + +/* { dg-final { scan-tree-dump-times "Created a replacement" 0 "esra"} } */ +/* { dg-final { cleanup-tree-dump "esra" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/sra-9.c b/gcc/testsuite/gcc.dg/tree-ssa/sra-9.c new file mode 100644 index 000000000..54f42179e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/sra-9.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +struct S +{ + int a, b, c; + int z[20]; +}; + +int foo (int d) +{ + struct S s; + + s.a = d; + return s.a + s.b; +} + +/* There should be no reference to s.b. */ +/* { dg-final { scan-tree-dump-times "= s\.b" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-1.c new file mode 100644 index 000000000..82f37abc8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-1.c @@ -0,0 +1,75 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +extern void link_error (void); + +/* check folding */ + +void test1 (void) +{ + unsigned int l = 3 * 4 - 5 / 2; + if (l != 10) + link_error (); +} + +void test11 (void) +{ + unsigned int l = (((((((3 / 2 + 2) * 4) & 7) ^ 3) % 8) << 2) + 1) >> 2; + if (l != 7) + link_error (); +} + +/* cprop in a basic block */ +void test111 (void) +{ + unsigned int l0 = 3 / 2 + 2; + unsigned int l1 = l0 * 4; + unsigned int l2 = 7; + unsigned int l3 = l1 & l2; + unsigned int l4 = 3; + unsigned int l5 = l3 ^ l4; + unsigned int l6 = 8; + unsigned int l7 = l5 % l6; + unsigned int l8 = 2; + unsigned int l9 = l7 << l8; + unsigned int l10 = l9 + 1; + unsigned int l11 = l10 >> 2; + if (l11 != 7) + link_error (); +} + + +/* cprop after an if statement */ +void test1111 (int p) +{ + int l = 53; + if (p) + { + if ((67 + l - 25) != 95) + link_error (); + } + else + { + if ((93 - l + 25) != 65) + link_error (); + } +} + +/* cprop after a loop */ +void test11111 (int p, int q, int r) +{ + int l = 53; + while (p < r) + { + if ((67 + l - 25) != 95) + link_error (); + p -= q; + } +} + + + +/* There should be not link_error calls, if there is any the + optimization has failed */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "ccp1"} } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-10.c new file mode 100644 index 000000000..7177d991e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-10.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-fab" } */ + +/* Check that we fold strlen of equally long strings, and that we do not + fail to terminate when there is a nontrivial cycle in the corresponding + ssa graph. */ + +extern __SIZE_TYPE__ strlen (const char *); + +void foo(int i) +{ + char *s = "abcde"; + + if (i) + { + s = "defgh"; + goto middle; + } + +start: + + bla (); + +middle: + + if (bla ()) + goto start; + + bar (strlen (s)); +} + +/* There should be no calls to strlen. */ +/* { dg-final { scan-tree-dump-times "strlen" 0 "fab"} } */ +/* { dg-final { cleanup-tree-dump "fab" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c new file mode 100644 index 000000000..4eaad28b1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-11.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* Test for CPROP across a DAG. */ + +int test111 (int param) +{ + int a, b, c; + if (param) { + a = 3; + b = 2; + } + else { + a = 2; + b = 3; + } + c = a + b; + if (c != 5) + return 2; + return 0; +} + +int test1111 (int param) +{ + _Bool a, b, c; + if (param) { + a = 1; + b = 0; + } + else { + a = 0; + b = 1; + } + c = a && b; + if (c) + return 2; + return 0; +} + +/* All ifs should be eliminated. */ +/* { dg-final { scan-tree-dump-times "if " 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-12.c new file mode 100644 index 000000000..8ee9eb8d0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-12.c @@ -0,0 +1,32 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +struct A +{ + int a; + int b; +}; + +struct A a; +const int B = 42; + +void foo (int i) +{ + if (i > 10) + a.a = 42; + else + { + a.b = 21; + a.a = a.b + 21; + } + + /* This should be folded to 'if (0)' as a.a and B are both 42. */ + if (a.a != B) + link_error (); +} + +main () +{ + foo (3); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-13.c new file mode 100644 index 000000000..d35adee51 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-13.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static const char f[3] = "?"; + +int foo() +{ + int i = 0; + return f[i] != '?'; +} + +/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c new file mode 100644 index 000000000..3be025f07 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-14.c @@ -0,0 +1,21 @@ +/* PR tree-optimization/29738. We used not to realize that "i" can never + become nonzero. */ + +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int i; + +void foo (void); +void bar (void) +{ + int j; + i = 0; + for (j = 0; j < 10000; j++) + if (i) + foo (); +} + +/* Everything except for the "i = 0" assignment should get removed. */ +/* { dg-final { scan-tree-dump-times "if" 0 "optimized" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-15.c new file mode 100644 index 000000000..aaf57126a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-15.c @@ -0,0 +1,49 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +/* Check that the initial values are honored when necessary. */ + +void link_error (void); + +/* The call to link_error cannot be eliminated in this case. */ + +void test1 (int param1, int param2, int x) +{ + if (param1) + x = 3; + + if (param2) + if (x != 3) + link_error (); +} + +/* The call to link_error cannot be eliminated in this case. */ + +int global; +void test2 (int param1, int param2) +{ + if (param1) + global = 3; + + if (param2) + if (global != 3) + link_error (); +} + +/* In this case, we can eliminate the call, as unless "local" is set + to 3, its value is undefined. */ + +void test3 (int param1, int param2) +{ + int local; + + if (param1) + local = 3; + + if (param2) + if (local != 3) + link_error (); +} + +/* { dg-final { scan-tree-dump-times "link_error" 2 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-16.c new file mode 100644 index 000000000..33f9744d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-16.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +static const int x; + +int test1 (void) +{ + char *p = "hello"; + int i = x; + i = i + 5; + return p[i]; +} + +int test2 (void) +{ + int i = x; + i = i + 5; + return "hello"[i]; +} + +/* { dg-final { scan-tree-dump-times "return 0;" 2 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-17.c new file mode 100644 index 000000000..aece3c7cd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-17.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +int foo(void) +{ + int i = 0; + char *p = (char *)&i; + return *(int *)p; +} + +struct Foo { + int i; +} f; + +int bar(void) +{ + char *p = (char *)&f; + return ((struct Foo *)p)->i; +} + +extern const struct Foo g; + +int foobar(void) +{ + struct Foo *p = (struct Foo *)&g; + return ((const struct Foo *)p)->i; +} + +/* { dg-final { scan-tree-dump "= i;" "ccp1" } } */ +/* { dg-final { scan-tree-dump "= f.i;" "ccp1" } } */ +/* { dg-final { scan-tree-dump "= g.i;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-18.c new file mode 100644 index 000000000..cbe12598b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-18.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +/* Check that we constant propagate &&c into the goto and remove + the unreachable BBs. */ + +void a(int*); void b(int*); void c(int*); void d(int*); +void func2(int* val) +{ + const void *const labels[] = { &&a, &&b, &&c, &&d }; + goto *labels[2]; + a: a(val); + b: b(val); + c: c(val); + d: d(val); +} + +/* { dg-final { scan-tree-dump-not "a \\\(" "ccp1" } } */ +/* { dg-final { scan-tree-dump-not "b \\\(" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c new file mode 100644 index 000000000..ab4182246 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-19.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +struct f { int i; }; +int g() +{ + struct f a, *a1; + int *i; + a.i = 1; + a1 = &a; + i = &a1->i; + return *i; /* This should be turned into a.i */ +} + +/* { dg-final { scan-tree-dump "= a.i;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-2.c new file mode 100644 index 000000000..19975a392 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-2.c @@ -0,0 +1,172 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +extern void link_error (void); + + +/* check that cprop for variables of different types still works even + if function calls or assignments to different types of data are + interposed. */ + +int test7 (int *intarr) +{ + extern int foo7 (int); + int u = 7, v1; + foo7 (u); + v1 = u; + if (v1 != 7) + link_error (); + return v1; +} + +int test77 (int *arr) +{ + int u = 7, v1; + arr[0] = 4; + v1 = u; + if (v1 != 7) + link_error (); + return v1 + arr[0]; +} + +int test777 (void) +{ + extern int foo(int *); + int u = 7, v1; + static int sarr[10]; + sarr[0] = 4; + v1 = u; + if (v1 != 7) + link_error (); + foo (sarr); + return v1 + sarr[0]; +} + +int garr[10]; +int test7777 (void) +{ + int u = 7, v1; + garr[0] = 4; + v1 = u; + if (v1 != 7) + link_error (); + return v1 + garr[0]; +} + +int test88 (int *arr) +{ + static int l; + int v1; + l = 8; + arr[0] = 4; + v1 = l; + if (v1 != 8) + link_error (); + l = foo88 (l); + return v1 + arr[0]; +} + +int test888 (void) +{ + static int l; + extern int foo(int *); + int v1; + static int sarr[10]; + l = 8; + sarr[0] = 4; + v1 = l; + if (v1 != 8) + link_error (); + foo (sarr); + l = foo88(l); + return v1 + sarr[0]; +} + +int test8888 (void) +{ + static int l; + int v1; + l = 8; + garr[0] = 4; + v1 = l; + if (v1 != 8) + link_error (); + return v1 + garr[0]; +} + + + +/* global var */ +int g9; +int garr9[10]; +int test9 (int *intarr) +{ + extern int foo9 (int) __attribute__ ((const)); + int h, v; + g9 = 9; + h = foo9 (g9); + v = g9; + if (v != 9) + link_error (); + return g9; +} + +int test99 (int *intarr) +{ + extern int foo9 (int) __attribute__ ((pure)); + int h, v; + g9 = 9; + h = foo9 (g9); + v = g9; + if (v != 9) + link_error (); + return g9; +} + +extern int foo99 (int); + +int test999 (int *arr) +{ + static int l; + int v1; + g9 = 9; + l = 4; + v1 = g9; + if (v1 != 9) + link_error (); + l = foo99 (l); + return v1 + l; +} + + +int test9999 (void) +{ + int v1; + static int sarr[10]; + g9 = 9; + sarr[0] = 4; + v1 = g9; + if (v1 != 9) + link_error (); + foo (sarr); + g9 = foo99 (g9); + return v1 + sarr[0]; +} + + +int test99999 (void) +{ + int v1; + g9 = 9; + garr9[0] = 4; + v1 = g9; + if (v1 != 9) + link_error (); + return v1 + garr9[0]; +} + + +/* There should be not link_error calls, if there is any the + optimization has failed */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c new file mode 100644 index 000000000..63febd0e0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-20.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +/* Make sure CCP propagates through indirect calls. */ + +int foo (void) +{ + int i = -5; + int (*fn)(int) = __builtin_abs; + int j = fn(i); + return j + 5; +} + +/* { dg-final { scan-tree-dump "return 10;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c new file mode 100644 index 000000000..3f4adf434 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-21.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +struct A { + struct B { + int i; + } b; +} a; + +int foo (void) +{ + struct B *p = &a.b; + struct A *q = (struct A *) p; + return q->b.i; +} + +int bar (void) +{ + struct A *p = &a; + struct B *q = (struct B *) p; + return q->i; +} + +/* The first access is through struct A, so a.b.i is fine, + the second access needs to preserve the original access type struct B. */ + +/* { dg-final { scan-tree-dump-times "a.b.i" 1 "ccp1" } } */ +/* { dg-final { scan-tree-dump-times "MEM\\\[\\\(struct B \\\*\\\)&a\\\].i" 1 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c new file mode 100644 index 000000000..01d11ecac --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-22.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +/* Make sure we propagate through builtins. */ + +int foo (unsigned b) +{ + unsigned t = -1; + int x = b <= t; + long l = __builtin_expect (x, 0); + return l; +} + +/* { dg-final { scan-tree-dump "return 1;" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c new file mode 100644 index 000000000..fb4af2d48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-23.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +/* Make sure we propagate through POINTER_PLUS_EXPRs. */ + +struct A { + int i[2]; +} a; + +int foo (void) +{ + struct A *p = &a; + int *q = (int *)p; + int *x = q + 1; + return *x; +} + +/* { dg-final { scan-tree-dump "MEM\\\[\\\(int \\\*\\\)&a \\\+ 4B\\\]" "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c new file mode 100644 index 000000000..84f69e9d3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-24.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +static const int x; +int foo() +{ + const int *p = &x; + int y = *p; + return y + 1; +} + +static const int x2[3] = { 1, 0, 2 }; +int bar() +{ + int i = 1; + const int *p = &x2[i]; + int y = *p; + return y + 1; +} + +/* { dg-final { scan-tree-dump-times "return 1;" 2 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c new file mode 100644 index 000000000..7912a57f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-25.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1 -fdump-tree-forwprop1" } */ + +int a[256]; +int foo(int i) +{ + int *p = &a[0]; + return *(p + i); +} + +/* { dg-final { scan-tree-dump "&a\\\[\[iD\]\\\." "ccp1" } } */ +/* { dg-final { scan-tree-dump "= .*&a\\\]\\\[\[iD\]\\\." "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c new file mode 100644 index 000000000..c0a548155 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-26.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-forwprop1" } */ + +int a[256]; +int foo(int i) +{ + return (a + 1)[i]; +} + +/* { dg-final { scan-tree-dump "=.*&a\\\]\\\[D\\\." "forwprop1" } } */ +/* { dg-final { cleanup-tree-dump "forwprop1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-27.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-27.c new file mode 100644 index 000000000..c27963454 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-27.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-ccp1" } */ + +#include <string.h> + +char c[10]; + +void +f1 () +{ + const char *p = "123456"; + memcpy (c, p, 6); +} + +void +f2 () +{ + const char *p = "12345678"; + p += 2; + memcpy (c, p, 6); +} + +/* { dg-final { scan-tree-dump-times "memcpy\[^\n\]*123456" 2 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c new file mode 100644 index 000000000..f5dbe70b3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-28.c @@ -0,0 +1,26 @@ +/* { dg-do run } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +extern void abort (void); + +static int g[1]; + +static int * const p = &g[0]; +static int * const q = &g[0]; + +int main(void) +{ + g[0] = 1; + *p = 0; + *p = *q; + if (g[0] != 0) + abort (); + return 0; +} + +/* We should have replaced all loads from p and q with the constant + initial value. */ + +/* { dg-final { scan-tree-dump-times "= p;" 0 "ccp1" } } */ +/* { dg-final { scan-tree-dump-times "= q;" 0 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-29.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-29.c new file mode 100644 index 000000000..44d2945a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-29.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp2" } */ + +static double num; +int foo (void) +{ + return *(unsigned *)# +} + +/* { dg-final { scan-tree-dump "return 0;" "ccp2" } } */ +/* { dg-final { cleanup-tree-dump "ccp2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-3.c new file mode 100644 index 000000000..86a706b80 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-3.c @@ -0,0 +1,137 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp2" } */ + +extern void link_error (void); + +/* Some addresses clearly cannot be equal, check that some address + expressions can be evaluated as constants. + Most of the tests are folding tests, but at least some require + points-to analysis, so we scan the first CCP dump after PTA. */ + +char g1, g2; +void test6 (char p1, char p2) +{ + char l1 = 1, l2 = 2; + static char s1 = 5, s2 = 7; + if (&l1 == &l2) + link_error (); + + if (&p1 == &p2) + link_error (); + + if (&s1 == &s2) + link_error (); + + if (&g1 == &g2) + link_error (); + + if (&p1 == &l1) + link_error (); + + if (&p1 == &s1) + link_error (); + + if (&p1 == &l2) + link_error (); + + if (&p1 == &g1) + link_error (); + + if (&l1 == &g1) + link_error (); + + if (&s1 == &g1) + link_error (); +} + +extern void *alloc (int) __attribute__ ((malloc)); +char gca1[128]; +char* __restrict__ rgc1; +char* test66 (char * __restrict__ rp1, char * __restrict__ rp2, char *p1) +{ + char * __restrict__ rl1 = p1; + char * l1 = (char*) alloc (20); + + if (l1 == rgc1) + link_error (); + + if (l1 == rp1) + link_error (); + + if (l1 == rl1) + link_error (); + + if (l1 == gca1) + link_error (); + + if (rl1 == rgc1) + link_error (); + + if (rl1 == rp1) + link_error (); + + if (rl1 == gca1) + link_error (); + + if (rp1 == rp2) + link_error (); + + if (rp1 == rgc1) + link_error (); + + if (rp1 == gca1) + link_error (); + + if (gca1 == rgc1) + link_error (); + +} + +int gci1[128]; +int* __restrict__ rgi1; +int* test666 (int * __restrict__ rp1, int * __restrict__ rp2, int *p1) +{ + int * __restrict__ rl1 = p1; + int * l1 = (int*) alloc (20); + + if (l1 == rgi1) + link_error (); + + if (l1 == rp1) + link_error (); + + if (l1 == rl1) + link_error (); + + if (l1 == gci1) + link_error (); + + if (rl1 == rgi1) + link_error (); + + if (rl1 == rp1) + link_error (); + + if (rl1 == gci1) + link_error (); + + if (rp1 == rp2) + link_error (); + + if (rp1 == rgi1) + link_error (); + + if (rp1 == gci1) + link_error (); + + if (gci1 == rgi1) + link_error (); +} + + +/* There should be not link_error calls, if there is any the + optimization has failed */ +/* ??? While we indeed don't handle some of these, a couple of the + restrict tests are incorrect. */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "ccp2" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "ccp2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-30.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-30.c new file mode 100644 index 000000000..47675ed5d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-30.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +int +foo (int a) +{ + int b = a & 0xff; + if (b > 300) + return 2; + else + return 1; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate b_.* > 300 to 0" 1 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-31.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-31.c new file mode 100644 index 000000000..c155e921c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-31.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ccp1" } */ + +int g (int i, int j) +{ + int t = 0; + int i1; + + if (i == j) + t = 3; + for (i1 = 0; i1 < 10000; i1++) h(); + if (t != 5) + return 0; + else + return 1; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "ccp1" } } */ +/* { dg-final { cleanup-tree-dump "ccp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-32.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-32.c new file mode 100644 index 000000000..7487d07d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-32.c @@ -0,0 +1,58 @@ +/* { dg-do run } */ +/* { dg-options "-O" } */ + +extern void link_error (void); +unsigned int __attribute__((noinline,noclone)) +test0 (unsigned int a) +{ + a = a & 1; + a = a << 1 | a >> (sizeof (unsigned int) * 8 - 1); + if (a & 1) + { + a = a | 4; + link_error (); + } + if (a & 4) + link_error (); + return a; +} +int __attribute__((noinline,noclone)) +test1 (int a) +{ + a |= 1; + a = a << (sizeof (int) * 8 - 1); + if (a >= 0) + link_error (); + a = a * 4; + if (a & ~3) + link_error (); + if (a == -1) + link_error (); + return a; +} +int __attribute__((noinline,noclone)) +test2 (int a) +{ + a = a | 0xff; + a = a + 1; + if (a & 0xff) + link_error (); + a = -a; + if (a & 0xff) + link_error (); + a = a - 1; + if ((a & 0xff) != 0xff) + link_error (); + return a; +} +extern void abort (void); +int main() +{ + if (test0 (1) != 2) + abort (); + if (test1 (0) != 0) + abort (); + if (test2 (-1) != -1) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-33.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-33.c new file mode 100644 index 000000000..753676994 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-33.c @@ -0,0 +1,17 @@ +/* { dg-do link } */ +/* { dg-options "-O" } */ + +extern void link_error (); +int a[256]; +void foo(int n) +{ + int *p; + for (p = a; n != 0; --n, ++p) + ; + if ((__SIZE_TYPE__)p & (__alignof__ (int) - 1)) + link_error (); +} +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-7.c new file mode 100644 index 000000000..b34974130 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-7.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +extern void link_error (void); + +/* tests to check if cprop works when using non-return functions */ + +extern int not_returning (int) __attribute__ ((noreturn)); + +int b; +int test7 (int a) +{ + b = 7; + if (a) + { + not_returning (a); + } + if (b != 7) + link_error (); + return b; +} + + +/* There should be not link_error calls, if there is any the + optimization has failed */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-9.c new file mode 100644 index 000000000..af23f8beb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ccp-9.c @@ -0,0 +1,55 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ + +/* Check that cprop works for assignments to array elements and structs. */ + +struct foo { + int a; +}; + +extern void link_error (void); + +void +test9 (struct foo f) +{ + f.a = 0; + if (f.a != 0) + link_error (); +} + +void +test99 (struct foo *f) +{ + f->a = 0; + if (f->a != 0) + link_error (); +} + +void +test999 (int *arr) +{ + *arr = 0; + if (*arr != 0) + link_error (); +} + +void +test9999 (int *arr) +{ + arr[13] = 0; + if (arr[13] != 0) + link_error (); +} + +void +test99999 (int *arr, int j) +{ + arr[j] = 0; + if (arr[j] != 0) + link_error (); +} + +/* There should be no link_error calls, if there is any, the + optimization has failed */ +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-copyprop-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-copyprop-1.c new file mode 100644 index 000000000..41ad6ce6e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-copyprop-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-optimized" } */ + +typedef struct { int i; int j; } A; +int foo(A *a, int i) +{ + a->i = i; + return a->i; +} + +/* { dg-final { scan-tree-dump "return i" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-1.c new file mode 100644 index 000000000..12d982629 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-dce2" } */ + +int t() __attribute__ ((const)); +q() +{ + int i = t(); + if (!i) + i = t(); +} +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dce2"} } */ +/* { dg-final { cleanup-tree-dump "dce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-2.c new file mode 100644 index 000000000..5e5302486 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-2.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dce2" } */ + +/* We should notice constantness of this function. */ +static int __attribute__((noinline)) t(int a) +{ + return a+1; +} +void q(void) +{ + int i = t(1); + if (!i) + i = t(1); +} +/* There should be no IF conditionals. */ +/* { dg-final { scan-tree-dump-times "if " 0 "dce2"} } */ +/* { dg-final { cleanup-tree-dump "dce2" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c new file mode 100644 index 000000000..72020aac7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-3.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-cddce1" } */ + +int main(void) +{ + unsigned i, j; + + for (i = 1, j = 0; i != 0; i+=2) + { + j += 500; + if (j % 7) + { + j++; + } + else + { + j--; + } + } + + return 0; +} + +/* We now can prove the infiniteness of the loop during CCP and fail + to eliminate the code inside the infinite loop because we start + by marking the j % 7 condition as useful. See PR45178. */ + +/* We should eliminate the inner condition, but the loop must be preserved + as it is infinite. Therefore there should be just one phi node (for i): */ +/* { dg-final { scan-tree-dump-times "PHI " 1 "cddce1" { xfail *-*-* } } } */ + +/* And one if (for the exit condition of the loop): */ +/* { dg-final { scan-tree-dump-times "if " 1 "cddce1" } } */ + +/* { dg-final { cleanup-tree-dump "cddce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-4.c new file mode 100644 index 000000000..89118a626 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-cddce1" } */ + +int foo(int b) +{ + int a[128]; + a[b] = 1; + if (b) + { + b = 2; + a[2] = 0; + } + a[2] = 3; + return a[2] + b; +} + +/* { dg-final { scan-tree-dump-times "a\\\[\[^\n\]\\\]" 2 "cddce1" } } */ +/* { dg-final { cleanup-tree-dump "cddce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-5.c new file mode 100644 index 000000000..11c9e666b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-5.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-cddce1" } */ + +struct X { int i; }; +struct X foo(int b) +{ + struct X x; + if (b) + x.i = 0; + x.i = 1; + return x; +} + +/* { dg-final { scan-tree-dump-times "x.i =" 1 "cddce1" } } */ +/* { dg-final { cleanup-tree-dump "cddce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-6.c new file mode 100644 index 000000000..30a06a102 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-6.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-cddce1" } */ + +struct object { int field; }; +void o(struct object *); +int globl; +void t(int x) +{ + struct object a, b; + struct object *p; + o(&a); + if (x) + p = &a; + else + p = &b; + p->field = 1; + globl = 0; + return; +} + +/* The global store should not prevent deleting the store to p->field. */ + +/* { dg-final { scan-tree-dump-not "p_.->field" "cddce1" } } */ +/* { dg-final { cleanup-tree-dump "cddce1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-7.c new file mode 100644 index 000000000..792dfb028 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dce-7.c @@ -0,0 +1,33 @@ +/* { dg-do link } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +extern void link_error (void); +void foo(int n) +{ + int * f = (int*) __builtin_malloc (n * sizeof (int)); + int * ff = (int*) __builtin_malloc (n * sizeof (int)); + int i; + + for (i = 0; i < n; ++i) + { + f[i] = 1; + ff[i] = 2; + if (f[i] != 1) + link_error (); + if (ff[i] != 2) + link_error (); + } + + __builtin_free (f); + __builtin_free (ff); +} +int main() +{ + return 0; +} + +/* We should have removed the calls to link_error () and all stores + to the allocated memory. */ + +/* { dg-final { scan-tree-dump-times "\\\*D" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-ccp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-ccp-1.c new file mode 100644 index 000000000..b2bcd06be --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-ccp-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int t(int a) __attribute__ ((const)); +void abort (void); +int +ccp(int b) +{ + int a=1; + a++; + a++; + a++; + if (b) + abort(); + return a; +} +/* We should propagate constant 4 into return. */ +/* { dg-final { scan-tree-dump-times "return 4" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c new file mode 100644 index 000000000..5bbfd3d17 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-cse-1.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-details" } */ +int t(int a) __attribute__ ((const)); +void q (void); +void +threading(int a,int b) +{ + if (t(a)) + { + if (t(a)) + q(); + } +} +/* We should thread the jump twice and eliminate it. */ +/* { dg-final { scan-tree-dump-times "Replaced.* t " 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-dse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-dse-1.c new file mode 100644 index 000000000..504e4bc03 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-dse-1.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int x; +void +foo (void) +{ + if (x == 0) + x = 0; +} +void +bar (int i) +{ + if (x == i) + x = i; +} + +/* { dg-final { scan-tree-dump-not "x =" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-1.c new file mode 100644 index 000000000..7671e93ad --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-1.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-vrp -fdump-tree-dom1-details" } */ +void t(void); +void q(void); +void q1(void); +void +threading(int a,int b) +{ + if (a>b) + t(); + else + q(); + if (a<=b) + q1(); +} +/* We should thread the jump twice and elliminate it. */ +/* { dg-final { scan-tree-dump-times "Threaded" 2 "dom1"} } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2.c new file mode 100644 index 000000000..6aaea8ecb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dom-thread-2.c @@ -0,0 +1,119 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-stats -fdump-tree-dom1-stats" } */ + +void foo(); +void bla(); +void bar(); + +/* In the following two cases, we should be able to thread edge through + the loop header. */ + +void thread_entry_through_header (void) +{ + int i; + + for (i = 0; i < 170; i++) + bla (); +} + +void thread_latch_through_header (void) +{ + int i = 0; + int first = 1; + + do + { + if (first) + foo (); + + first = 0; + bla (); + } while (i++ < 100); +} + +/* This is a TODO -- it is correct to thread both entry and latch edge through + the header, but we do not handle this case yet. */ + +void dont_thread_1 (void) +{ + int i = 0; + int first = 1; + + do + { + if (first) + foo (); + else + bar (); + + first = 0; + bla (); + } while (i++ < 100); +} + +/* Avoid threading in the following two cases, to prevent creating subloops. */ + +void dont_thread_2 (int first) +{ + int i = 0; + + do + { + if (first) + foo (); + else + bar (); + + first = 0; + bla (); + } while (i++ < 100); +} + +void dont_thread_3 (int nfirst) +{ + int i = 0; + int first = 0; + + do + { + if (first) + foo (); + else + bar (); + + first = nfirst; + bla (); + } while (i++ < 100); +} + +/* Avoid threading in this case, in order to avoid creating loop with + multiple entries. */ + +void dont_thread_4 (int a, int nfirst) +{ + int i = 0; + int first; + + if (a) + first = 0; + else + first = 1; + + do + { + if (first) + foo (); + else + bar (); + + first = nfirst; + bla (); + } while (i++ < 100); +} + +/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 1 "vrp1"} } */ +/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 0 "vrp1"} } */ +/* { dg-final { scan-tree-dump-times "Jumps threaded: 1" 0 "dom1"} } */ +/* { dg-final { scan-tree-dump-times "Jumps threaded: 2" 1 "dom1"} } */ +/* { dg-final { cleanup-tree-dump "dom1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-1.c new file mode 100644 index 000000000..d0263e3a2 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-1.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1" } */ + +int +foo (int a, int b, int c) +{ + int *p; + if (c) + p = &a; + else + p = &b; + + *p = 3; + *p = 4; + return *p; +} + + +/* We should eliminate both assignments to *p. */ +/* { dg-final { scan-tree-dump-times " = 3" 0 "dse1"} } */ +/* { dg-final { scan-tree-dump-times " = 4" 0 "dse1"} } */ + +/* The return *p should be turned into return 4. */ +/* { dg-final { scan-tree-dump-times " return 4" 1 "dse1"} } */ + +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c new file mode 100644 index 000000000..bce2c315a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-10.c @@ -0,0 +1,1523 @@ +/* { dg-do compile } */ +/* { dg-options "-O -w -fdump-tree-dse-vops" } */ + +__extension__ typedef __SIZE_TYPE__ size_t; +typedef struct _IO_FILE FILE; +typedef struct +{ +} __mbstate_t; +typedef struct +{ +} _G_fpos_t; +typedef struct +{ +}; +typedef int (*__gconv_trans_fct) (struct __gconv_step *, + size_t *); +typedef int (*__gconv_trans_context_fct) (void *, __const unsigned char *, + size_t *); +struct __gconv_trans_data +{ +}; +struct __gconv_step_data +{ +}; +typedef struct __gconv_info +{ +} *__gconv_t; +typedef union +{ + struct + { + } __combined; +} _G_iconv_t; +typedef __builtin_va_list __gnuc_va_list; +enum __codecvt_result +{ + __codecvt_noconv +}; +struct _IO_FILE { +}; +vprintf (__const char *__restrict __fmt, __gnuc_va_list __arg) +{ +} +putchar (int __c) +{ +} +fputc_unlocked (int __c, FILE *__stream) +{ +} +putc_unlocked (int __c, FILE *__stream) +{ +} +__attribute__ ((__nothrow__)) ferror_unlocked (FILE *__stream) +{ +} +extern int __sprintf_chk (char *__restrict __s, int __flag, size_t __slen, + __gnuc_va_list __ap); +gets (char *__str) +{ +} +extern char *__fgets_chk (char *__restrict __s, size_t __size, int __n, + FILE *__restrict __stream) __attribute__ ((__warn_unused_result__)); +fgets (char *__restrict __s, int __n, FILE *__restrict __stream) +{ +} +typedef void *LPVOID; +typedef int BOOL, *PBOOL, *LPBOOL; +typedef unsigned char BYTE, *PBYTE, *LPBYTE; +typedef unsigned short WORD, *PWORD, *LPWORD; +typedef unsigned int DWORD, *PDWORD, *LPDWORD; +typedef struct _GUID +{ +} GUID; +enum +{ + _ISupper = ((0) < 8 ? ((1 << (0)) << 8) : ((1 << (0)) >> 8)), +}; +extern char *__strtok_r (char *__restrict __s, + __const char *__restrict __delim, + char **__restrict __save_ptr) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (2, 3))); +__strcspn_c3 (__const char *__s, int __reject1, int __reject2, + int __reject3) +{ +} +extern __inline size_t __strspn_c3 (__const char *__s, int __accept1, + int __accept2, int __accept3); +extern __inline size_t +__strspn_c3 (__const char *__s, int __accept1, int __accept2, int __accept3) +{ +} +extern __inline char *__strpbrk_c2 (__const char *__s, int __accept1, + int __accept2); +extern __inline char * +__strpbrk_c2 (__const char *__s, int __accept1, int __accept2) +{ +} +extern __inline char *__strpbrk_c3 (__const char *__s, int __accept1, + int __accept3) +{ +} +__strtok_r_1c (char *__s, char __sep, char **__nextp) +{ + { + { + } + } +} +__strsep_1c (char **__s, char __reject) +{ +} +__strsep_2c (char **__s, char __reject1, char __reject2) +{ + { + { + } + } +} +extern __inline char *__strsep_3c (char **__s, char __reject1, char __reject2, + char __reject3); +extern __inline char * +__strsep_3c (char **__s, char __reject1, char __reject2, char __reject3) +{ + { + { + { + } + } + } +} +__attribute__ ((__nothrow__)) __memcpy_ichk (void *__restrict __dest, __const void *__restrict __src, size_t __len) +{ +} +__attribute__ ((__nothrow__)) __memmove_ichk (void *__dest, __const void *__src, size_t __len) +{ +} +__attribute__ ((__nothrow__)) __strncpy_ichk (char *__restrict __dest, __const char *__restrict __src, size_t __len) +{ +} +__attribute__ ((__nothrow__)) stpncpy (char *__dest, __const char *__src, size_t __n) +{ + if (__builtin_object_size (__dest, 2 > 1) != (size_t) -1 + && (!__builtin_constant_p (__n) || __n <= __builtin_object_size (__dest, 2 > 1))) + return __stpncpy_chk (__dest, __src, __n, __builtin_object_size (__dest, 2 > 1)); +} +__attribute__ ((__nothrow__)) __strncat_ichk (char *__restrict __dest, __const char *__restrict __src, size_t __len) +{ +} +typedef void *PVOID; +typedef char CHAR, *PCHAR; +typedef int LONG, *PLONG; +typedef unsigned short WCHAR, *PWCHAR; +typedef CHAR *PSTR, *LPSTR, *NPSTR; +typedef const CHAR *PCSTR, *LPCSTR; +typedef WCHAR *PWSTR, *LPWSTR, *NWPSTR; +typedef LONG HRESULT; +typedef struct _MEMORY_BASIC_INFORMATION +{ +} SINGLE_LIST_ENTRY, *PSINGLE_LIST_ENTRY; +typedef enum _HEAP_INFORMATION_CLASS { + HeapCompatibilityInformation, +} HEAP_INFORMATION_CLASS; +typedef struct _FLOATING_SAVE_AREA +{ +} CONTEXT86; +typedef struct _LDT_ENTRY { + union { + struct { + } Bits; + } HighWord; +} LDT_ENTRY, *PLDT_ENTRY; +typedef struct _EXCEPTION_RECORD +{ +} EXCEPTION_RECORD, *PEXCEPTION_RECORD; +typedef struct _EXCEPTION_POINTERS +{ +} EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; +typedef struct _NT_TIB +{ + union { + } ; +} NT_TIB, *PNT_TIB; +extern inline struct _TEB * __attribute__((__stdcall__)) NtCurrentTeb(void) +{ +} IMAGE_SECTION_HEADER, *PIMAGE_SECTION_HEADER; +typedef struct _IMAGE_SYMBOL { + union { + struct { + } FcnAry; + } Section; +} IMAGE_AUX_SYMBOL; +typedef struct _IMAGE_EXPORT_DIRECTORY { + union { + } u1; +} IMAGE_BOUND_FORWARDER_REF, *PIMAGE_BOUND_FORWARDER_REF; +typedef struct _IMAGE_BASE_RELOCATION +{ +} IMAGE_BASE_RELOCATION,*PIMAGE_BASE_RELOCATION; +typedef struct _IMAGE_RELOCATION +{ + union { + } ; +} IMAGE_RELOCATION, *PIMAGE_RELOCATION; +typedef struct _IMAGE_ARCHIVE_MEMBER_HEADER +{ +} IMAGE_RESOURCE_DIRECTORY,*PIMAGE_RESOURCE_DIRECTORY; +typedef struct _IMAGE_RESOURCE_DIRECTORY_ENTRY { + union { + struct { + } ; + struct { + } ; + } ; +} IMAGE_DEBUG_DIRECTORY, *PIMAGE_DEBUG_DIRECTORY; +typedef enum ReplacesCorHdrNumericDefines +{ + MAX_PACKAGE_NAME = 1024, +} ReplacesCorHdrNumericDefines; +typedef struct IMAGE_COR20_HEADER +{ +} MESSAGE_RESOURCE_DATA,*PMESSAGE_RESOURCE_DATA; +typedef PVOID PSECURITY_DESCRIPTOR; +typedef enum _TOKEN_INFORMATION_CLASS { + TokenUser = 1, +} TOKEN_INFORMATION_CLASS; +typedef struct _GENERIC_MAPPING { +} ACL, *PACL; +typedef struct _ACL_SIZE_INFORMATION +{ +} ACL_SIZE_INFORMATION, *PACL_SIZE_INFORMATION; +typedef WORD SECURITY_DESCRIPTOR_CONTROL, *PSECURITY_DESCRIPTOR_CONTROL; +typedef struct { +} SID_AND_ATTRIBUTES; +typedef enum { + WinBuiltinTerminalServerLicenseServersSid = 60 +} WELL_KNOWN_SID_TYPE; +typedef struct _TOKEN_USER { +} TOKEN_GROUPS, *PTOKEN_GROUPS; +typedef union _LARGE_INTEGER { + struct { + }; +} LARGE_INTEGER, *PLARGE_INTEGER; +typedef union _ULARGE_INTEGER { + struct { + }; +} LUID, *PLUID; +typedef struct _LUID_AND_ATTRIBUTES { +} LUID_AND_ATTRIBUTES, *PLUID_AND_ATTRIBUTES; +typedef enum tagTOKEN_TYPE { + TokenPrimary = 1, +} SECURITY_IMPERSONATION_LEVEL, *PSECURITY_IMPERSONATION_LEVEL; +typedef struct _SECURITY_QUALITY_OF_SERVICE { +} QUOTA_LIMITS_EX, *PQUOTA_LIMITS_EX; +typedef enum _LATENCY_TIME { + VerifyProcessorPowerPolicyDc, +} POWER_INFORMATION_LEVEL; +typedef struct _ADMINISTRATOR_POWER_POLICY { +} RTL_CRITICAL_SECTION_DEBUG, *PRTL_CRITICAL_SECTION_DEBUG, RTL_RESOURCE_DEBUG, *PRTL_RESOURCE_DEBUG; +typedef struct _RTL_CRITICAL_SECTION { +} RTL_CRITICAL_SECTION, *PRTL_CRITICAL_SECTION; +typedef struct _IO_COUNTERS { +} OSVERSIONINFOA, *POSVERSIONINFOA, *LPOSVERSIONINFOA; +typedef struct { +} OSVERSIONINFOW, *POSVERSIONINFOW, *LPOSVERSIONINFOW, RTL_OSVERSIONINFOW, *PRTL_OSVERSIONINFOW; +typedef struct { +} OSVERSIONINFOEXA, *POSVERSIONINFOEXA, *LPOSVERSIONINFOEXA; +typedef struct { +} OSVERSIONINFOEXW, *POSVERSIONINFOEXW, *LPOSVERSIONINFOEXW, RTL_OSVERSIONINFOEXW, *PRTL_OSVERSIONINFOEXW; +typedef struct tagSIZE +{ +} POINT, *PPOINT, *LPPOINT; +typedef struct _POINTL +{ +} FILETIME, *PFILETIME, *LPFILETIME; +typedef struct tagRECT +{ + } ldiv_t; +extern double strtod (__const char *__restrict __nptr, + char **__restrict __endptr) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))) __attribute__ ((__warn_unused_result__)); +extern long int strtol (__const char *__restrict __nptr, + char **__restrict __endptr, int __base) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))) __attribute__ ((__warn_unused_result__)); +extern long int __strtol_internal (__const char *__restrict __nptr, + int __base, int __group) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))) __attribute__ ((__warn_unused_result__)); +extern unsigned long int __strtoul_internal (__const char *__restrict __nptr, + int __base, int __group) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1))) __attribute__ ((__warn_unused_result__)); +extern __inline double +__attribute__ ((__nothrow__)) strtod (__const char *__restrict __nptr, char **__restrict __endptr) +{ +} +extern __inline long int +__attribute__ ((__nothrow__)) strtol (__const char *__restrict __nptr, char **__restrict __endptr, int __base) +{ +} +__attribute__ ((__nothrow__)) strtoll (__const char *__restrict __nptr, char **__restrict __endptr, int __base) +{ +} +__attribute__ ((__nothrow__)) atoi (__const char *__nptr) +{ +} +typedef int int32_t __attribute__ ((__mode__ (__SI__))); +typedef struct + { + }; +extern int random_r (struct random_data *__restrict __buf, + int32_t *__restrict __result) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); +struct drand48_data + { + }; +extern int drand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); +extern int mrand48_r (struct drand48_data *__restrict __buffer, + long int *__restrict __result) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); +extern int jrand48_r (unsigned short int __xsubi[3], + long int *__restrict __result) + __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (2))); +extern int seed48_r (unsigned short int __seed16v[3], + struct drand48_data *__buffer) __attribute__ ((__nothrow__)) __attribute__ ((__nonnull__ (1, 2))); +extern char *qfcvt (long double __value, int __ndigit, + size_t __resolvedlen) __attribute__ ((__nothrow__)) __attribute__ ((__warn_unused_result__)); +__attribute__ ((__nothrow__)) realpath (__const char *__restrict __name, char *__restrict __resolved) +{ +} +__attribute__ ((__nothrow__)) ptsname_r (int __fd, char *__buf, size_t __buflen) +{ +} +typedef struct _EXCEPTION_DEBUG_INFO { +} EXCEPTION_DEBUG_INFO; +typedef struct _CREATE_THREAD_DEBUG_INFO { +} CREATE_THREAD_DEBUG_INFO; +typedef struct _CREATE_PROCESS_DEBUG_INFO { +} CREATE_PROCESS_DEBUG_INFO; +typedef struct _EXIT_THREAD_DEBUG_INFO { +} LOAD_DLL_DEBUG_INFO; +typedef struct _UNLOAD_DLL_DEBUG_INFO { +} RIP_INFO; +typedef struct _DEBUG_EVENT { + union { + } u; +} DEBUG_EVENT, *LPDEBUG_EVENT; +typedef struct _OFSTRUCT +{ +} WIN32_FIND_DATAA, *PWIN32_FIND_DATAA, *LPWIN32_FIND_DATAA; +typedef struct _WIN32_FIND_DATAW +{ +} WIN32_FIND_DATAW, *PWIN32_FIND_DATAW, *LPWIN32_FIND_DATAW; +typedef enum _FINDEX_SEARCH_OPS +{ + FindExSearchNameMatch, +} FINDEX_SEARCH_OPS; +typedef struct _PROCESS_HEAP_ENTRY +{ + union { + struct { + } Block; + struct { + } Region; + } ; +} PROCESS_HEAP_ENTRY, *PPROCESS_HEAP_ENTRY, *LPPROCESS_HEAP_ENTRY; +typedef struct tagMEMORYSTATUS +{ +} MEMORYSTATUSEX, *LPMEMORYSTATUSEX; +typedef struct _SYSTEMTIME{ + WORD wYear; +} SYSTEMTIME, *PSYSTEMTIME, *LPSYSTEMTIME; +typedef struct _OVERLAPPED { + union { + struct { + } ; + } ; +} PROCESS_INFORMATION, *PPROCESS_INFORMATION, *LPPROCESS_INFORMATION; +typedef struct _TIME_ZONE_INFORMATION{ +} TIME_ZONE_INFORMATION, *PTIME_ZONE_INFORMATION, *LPTIME_ZONE_INFORMATION; +typedef struct _BY_HANDLE_FILE_INFORMATION +{ +} ACTCTX_SECTION_KEYED_DATA_ASSEMBLY_METADATA, *PACTCTX_SECTION_KEYED_DATA_ASSEMBLY_METADATA; +typedef struct tagACTCTX_SECTION_KEYED_DATA { +} COMMTIMEOUTS,*LPCOMMTIMEOUTS; +typedef enum _COMPUTER_NAME_FORMAT +{ + ComputerNameNetBIOS, +} COMPUTER_NAME_FORMAT; +typedef struct tagHW_PROFILE_INFOA { +} HW_PROFILE_INFOA, *LPHW_PROFILE_INFOA; +typedef struct tagHW_PROFILE_INFOW { +} HW_PROFILE_INFOW, *LPHW_PROFILE_INFOW; +BOOL __attribute__((__stdcall__)) SetSecurityDescriptorControl(PSECURITY_DESCRIPTOR,SECURITY_DESCRIPTOR_CONTROL, + SECURITY_DESCRIPTOR_CONTROL); +typedef struct tagSYSLEVEL +{ +} SYSLEVEL; +static inline PVOID __attribute__((__stdcall__)) InterlockedCompareExchangePointer( PVOID volatile *dest, PVOID xchg, PVOID compare ) +{ +} +static inline PVOID __attribute__((__stdcall__)) InterlockedExchangePointer( PVOID volatile *dest, PVOID val ) +{ +} +typedef unsigned long HCRYPTPROV; +typedef unsigned long HCRYPTKEY; +typedef void *HCERTSTOREPROV; +typedef struct _PROV_ENUMALGS { +} PROV_ENUMALGS; +typedef struct _HMAC_INFO { +} HMAC_INFO, *PHMAC_INFO; +typedef struct _CRYPTOAPI_BLOB { + DWORD cbData; + BYTE* pbData; +} CRYPT_INTEGER_BLOB, *PCRYPT_INTEGER_BLOB, + CRYPT_OBJID_BLOB, *PCRYPT_OBJID_BLOB, + CERT_NAME_BLOB, *PCERT_NAME_BLOB, + CERT_RDN_VALUE_BLOB, *PCERT_RDN_VALUE_BLOB, + CRYPT_DER_BLOB, *PCRYPT_DER_BLOB, + CRYPT_ATTR_BLOB, *PCRYPT_ATTR_BLOB; +typedef struct _CRYPTPROTECT_PROMPTSTRUCT{ +} CRYPTPROTECT_PROMPTSTRUCT, *PCRYPTPROTECT_PROMPTSTRUCT; +typedef struct _CRYPT_ALGORITHM_IDENTIFIER { + LPSTR pszObjId; + CRYPT_OBJID_BLOB Parameters; +} CRYPT_ALGORITHM_IDENTIFIER, *PCRYPT_ALGORITHM_IDENTIFIER; +typedef struct _CRYPT_ATTRIBUTE_TYPE_VALUE { +} CRYPT_ATTRIBUTE_TYPE_VALUE, *PCRYPT_ATTRIBUTE_TYPE_VALUE; +typedef struct _PUBLICKEYSTRUC { +} BLOBHEADER, PUBLICKEYSTRUC; +typedef struct _RSAPUBKEY { + DWORD magic; + DWORD pubexp; +} RSAPUBKEY; +typedef struct _CRYPT_BIT_BLOB { + DWORD cbData; + BYTE *pbData; + DWORD cUnusedBits; +} CRYPT_BIT_BLOB, *PCRYPT_BIT_BLOB; +typedef struct _CRYPT_KEY_PROV_PARAM { +} CRYPT_KEY_PROV_PARAM, *PCRYPT_KEY_PROV_PARAM; +typedef struct _CRYPT_KEY_PROV_INFO { + CRYPT_ALGORITHM_IDENTIFIER Algorithm; + CRYPT_BIT_BLOB PublicKey; +} CERT_PUBLIC_KEY_INFO, *PCERT_PUBLIC_KEY_INFO; +typedef struct _CERT_EXTENSION { + LPSTR pszObjId; + CRYPT_OBJID_BLOB Value; +} CERT_EXTENSION, *PCERT_EXTENSION; +typedef struct _CERT_EXTENSIONS { + DWORD cExtension; + PCERT_EXTENSION rgExtension; +} CERT_EXTENSIONS, *PCERT_EXTENSIONS; +typedef struct _CERT_INFO { + CRYPT_INTEGER_BLOB SerialNumber; + CERT_NAME_BLOB Subject; + CERT_PUBLIC_KEY_INFO SubjectPublicKeyInfo; +} CERT_INFO, *PCERT_INFO; +typedef struct _CERT_RDN_ATTR { + LPSTR pszObjId; + CERT_RDN_VALUE_BLOB Value; +} CERT_RDN_ATTR, *PCERT_RDN_ATTR; +typedef struct _CERT_RDN { +} CERT_RDN, *PCERT_RDN; +typedef struct _CERT_NAME_INFO { + DWORD cRDN; +} CERT_NAME_INFO, *PCERT_NAME_INFO; +typedef struct _CERT_NAME_VALUE { + DWORD dwValueType; + CERT_RDN_VALUE_BLOB Value; +} CERT_NAME_VALUE, *PCERT_NAME_VALUE; +typedef struct _CERT_ENCRYPTED_PRIVATE_KEY_INFO { + CERT_NAME_BLOB CertIssuer; +} CERT_AUTHORITY_KEY_ID_INFO, *PCERT_AUTHORITY_KEY_ID_INFO; +typedef struct _CERT_PRIVATE_KEY_VALIDITY { +} CERT_OTHER_NAME, *PCERT_OTHER_NAME; +typedef struct _CERT_ALT_NAME_ENTRY { + DWORD dwAltNameChoice; + union { + LPWSTR pwszURL; + } ; +} CERT_ALT_NAME_ENTRY, *PCERT_ALT_NAME_ENTRY; +typedef struct _CERT_ALT_NAME_INFO { + DWORD cAltEntry; + PCERT_ALT_NAME_ENTRY rgAltEntry; +} CERT_ALT_NAME_INFO, *PCERT_ALT_NAME_INFO; +typedef struct _CERT_BASIC_CONSTRAINTS_INFO { + CERT_NAME_BLOB *rgSubtreesConstraint; +} CERT_BASIC_CONSTRAINTS_INFO, *PCERT_BASIC_CONSTRAINTS_INFO; +typedef struct _CERT_BASIC_CONSTRAINTS2_INFO { +} CERT_BASIC_CONSTRAINTS2_INFO, *PCERT_BASIC_CONSTRAINTS2_INFO; +typedef struct _CERT_POLICY_QUALIFIER_INFO { +} CERT_POLICY_QUALIFIER_INFO, *PCERT_POLICY_QUALIFIER_INFO; +typedef struct _CERT_POLICY_QUALIFIER_NOTICE_REFERENCE { +} CERT_POLICY_QUALIFIER_NOTICE_REFERENCE, + *PCERT_POLICY_QUALIFIER_NOTICE_REFERENCE; +typedef struct _CERT_POLICY_QUALIFIER_USER_NOTICE { + DWORD cValue; + PCRYPT_DER_BLOB rgValue; +} CRYPT_SEQUENCE_OF_ANY, *PCRYPT_SEQUENCE_OF_ANY; +typedef struct _CERT_AUTHORITY_KEY_ID2_INFO { + PCERT_INFO pCertInfo; +} CERT_CONTEXT, *PCERT_CONTEXT; +typedef const CERT_CONTEXT *PCCERT_CONTEXT; +typedef struct _CRL_ENTRY { +} CRL_ENTRY, *PCRL_ENTRY; +typedef struct _CRL_INFO { + DWORD cCRLEntry; + DWORD cExtension; +} CRL_INFO, *PCRL_INFO; +typedef struct _CRL_DIST_POINT_NAME { + DWORD dwDistPointNameChoice; + union { + } ; +} CRL_DIST_POINT_NAME, *PCRL_DIST_POINT_NAME; +typedef struct _CRL_DIST_POINT { + CRL_DIST_POINT_NAME DistPointName; + CRYPT_BIT_BLOB ReasonFlags; + CERT_ALT_NAME_INFO CRLIssuer; +} CRL_DIST_POINT, *PCRL_DIST_POINT; +typedef struct _CRL_DIST_POINTS_INFO { + DWORD cDistPoint; + PCRL_DIST_POINT rgDistPoint; +} CRL_DIST_POINTS_INFO, *PCRL_DIST_POINTS_INFO; +typedef struct _CRL_ISSUING_DIST_POINT { + BOOL fOnlyContainsUserCerts; +} CRL_ISSUING_DIST_POINT, *PCRL_ISSUING_DIST_POINT; +typedef struct _CERT_GENERAL_SUBTREE { +} CRYPT_ATTRIBUTE, *PCRYPT_ATTRIBUTE; +typedef struct _CRYPT_ATTRIBUTES { +} CRYPT_ATTRIBUTES, *PCRYPT_ATTRIBUTES; +typedef struct _CERT_REQUEST_INFO { + DWORD dwVersion; + CRYPT_ALGORITHM_IDENTIFIER SignatureAlgorithm; + CRYPT_BIT_BLOB Signature; +} CERT_SIGNED_CONTENT_INFO, *PCERT_SIGNED_CONTENT_INFO; +typedef struct _CRL_CONTEXT { +} CRL_CONTEXT, *PCRL_CONTEXT; +typedef struct _VTableProvStruc { +} CTL_CONTEXT, *PCTL_CONTEXT; +typedef struct _CRYPT_TIME_STAMP_REQUEST_INFO { +} CERT_REVOCATION_STATUS, *PCERT_REVOCATION_STATUS; +typedef struct _CERT_TRUST_STATUS { +} CERT_SYSTEM_STORE_RELOCATE_PARA, *PCERT_SYSTEM_STORE_RELOCATE_PARA; +typedef BOOL (__attribute__((__stdcall__)) *PFN_CERT_ENUM_SYSTEM_STORE_LOCATION)( + void *pvArg); +typedef struct _CRYPT_ENCODE_PARA { +} CERT_STORE_PROV_INFO, *PCERT_STORE_PROV_INFO; +typedef BOOL (__attribute__((__stdcall__)) *PFN_CERT_DLL_OPEN_STORE_PROV_FUNC)( + DWORD dwFlags, DWORD dwCtrlType, void const *pvCtrlPara); +typedef struct _CERT_STORE_PROV_FIND_INFO { +} CERT_STORE_PROV_FIND_INFO, *PCERT_STORE_PROV_FIND_INFO; +typedef BOOL (__attribute__((__stdcall__)) *PFN_CERT_STORE_PROV_FIND_CERT)(HCERTSTOREPROV hStoreProv, + DWORD dwFlags, void **ppvStoreProvFindInfo, PCCERT_CONTEXT *ppProvCertContext); +typedef BOOL (__attribute__((__stdcall__)) *PFN_CERT_STORE_PROV_FREE_FIND_CERT)( + DWORD dwFlags, void *pvData, DWORD *pcbData); +typedef BOOL (__attribute__((__stdcall__)) *PFN_CERT_STORE_PROV_GET_CTL_PROPERTY)( + DWORD dwFlags, void *pvData); +typedef struct _CERT_CREATE_CONTEXT_PARA { +} CRYPT_OID_FUNC_ENTRY, *PCRYPT_OID_FUNC_ENTRY; +typedef BOOL (__attribute__((__stdcall__)) *PFN_CRYPT_ENUM_OID_FUNC)(DWORD dwEncodingType, + const DWORD rgcbValueData[], void *pvArg); +typedef struct _CRYPT_OID_INFO { + union { + } ; +} CRYPT_OID_INFO, *PCRYPT_OID_INFO; +typedef const CRYPT_OID_INFO CCRYPT_OID_INFO, *PCCRYPT_OID_INFO; +typedef BOOL (__attribute__((__stdcall__)) *PFN_CRYPT_ENUM_OID_INFO)(PCCRYPT_OID_INFO pInfo, + void *pvArg); +typedef struct _CRYPT_SIGN_MESSAGE_PARA { +} CRYPT_HASH_MESSAGE_PARA, *PCRYPT_HASH_MESSAGE_PARA; +typedef struct _CRYPT_KEY_SIGN_MESSAGE_PARA { +} CRYPT_URL_INFO, *PCRYPT_URL_INFO; +typedef void (__attribute__((__stdcall__)) *PFN_CRYPT_ASYNC_PARAM_FREE_FUNC)(LPSTR pszParamOid, + LPVOID pvParam); +typedef struct _CRYPT_CREDENTIALS { +} CRYPT_CREDENTIALS, *PCRYPT_CREDENTIALS; +typedef struct _CRYPT_PASSWORD_CREDENTIALSA { +} CRYPT_PASSWORD_CREDENTIALSW, *PCRYPT_PASSWORD_CREDENTIALSW; +typedef struct _CRYPT_RETRIEVE_AUX_INFO { +} CRYPT_RETRIEVE_AUX_INFO, *PCRYPT_RETRIEVE_AUX_INFO; +typedef struct _CERT_CHAIN_ENGINE_CONFIG +{ +} CERT_CHAIN_ENGINE_CONFIG, *PCERT_CHAIN_ENGINE_CONFIG; +BOOL __attribute__((__stdcall__)) CryptExportPublicKeyInfoEx(HCRYPTPROV hCryptProv, DWORD dwKeySpec, + DWORD dwCertEncodingType, LPSTR pszPublicKeyObjId, DWORD dwFlags, + void *pvAuxInfo, PCERT_PUBLIC_KEY_INFO pInfo, DWORD *pcbInfo); +BOOL __attribute__((__stdcall__)) CryptImportPublicKeyInfo(HCRYPTPROV hCryptProv, + PCRYPT_RETRIEVE_AUX_INFO pAuxInfo); +struct encodedInt +{ + int val; + const BYTE *encoded; +}; +static const struct encodedInt ints[] = { +}; +struct encodedBigInt +{ + const BYTE *val; + const BYTE *encoded; +}; +static const struct encodedBigInt bigInts[] = { +}; +static const struct encodedBigInt bigUInts[] = { +}; +static void test_encodeInt(DWORD dwEncoding) +{ + DWORD bufSize = 0; + int i; + BOOL ret; + CRYPT_INTEGER_BLOB blob; + BYTE *buf = ((void *)0); + ret = CryptEncodeObjectEx(0, ((LPCSTR)27), &ints[0].val, 0, ((void *)0), ((void *)0), + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + { + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)27), &ints[i].val, + 0x08000, ((void *)0), &buf, &bufSize); + { + (winetest_set_location("encode.c", 119), 0) ? 0 : winetest_ok(buf[0] == 2, "Got unexpected type %d for integer (expected 2)\n", + buf[1], ints[i].encoded[1]); + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)28), &blob, + 0, ((void *)0), ((void *)0), &bufSize); + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)38), &blob, + 0x08000, ((void *)0), &buf, &bufSize); + { + (winetest_set_location("encode.c", 187), 0) ? 0 : winetest_ok(buf[1] == bigUInts[i].encoded[1], "Got length %d, expected %d\n", + buf[1], bigUInts[i].encoded[1]); + (winetest_set_location("encode.c", 189), 0) ? 0 : winetest_ok(!memcmp(buf + 1, bigUInts[i].encoded + 1, + bigUInts[i].encoded[1] + 1), + "Encoded value didn't match expected\n"); + } + } +} +static void test_decodeInt(DWORD dwEncoding) +{ + static const BYTE longForm[] = { 2, 0x81, 0x01, 0x01 }; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + int i; + BOOL ret; + ret = CryptDecodeObjectEx(3, ((LPCSTR)27), (BYTE *)&ints[0].encoded, + ints[0].encoded[1] + 2, 0, ((void *)0), ((void *)0), &bufSize); + (winetest_set_location("encode.c", 225), 0) ? 0 : winetest_ok(!ret && GetLastError() == ((HRESULT)0x80093104L), + "Expected CRYPT_E_ASN1_BADTAG, got %d\n", GetLastError()); + { + { + (winetest_set_location("encode.c", 249), 0) ? 0 : winetest_ok(!memcmp(buf, &ints[i].val, bufSize), "Expected %d, got %d\n", + ints[i].val, *(int *)buf); + } + } + { + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)28), + &bufSize); + { + CRYPT_INTEGER_BLOB *blob = (CRYPT_INTEGER_BLOB *)buf; + (winetest_set_location("encode.c", 296), 0) ? 0 : winetest_ok(blob->cbData == strlen((const char*)bigUInts[i].val), + "Unexpected value\n"); + } + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)28), longForm, + sizeof(longForm), 0x08000, ((void *)0), (BYTE *)&buf, &bufSize); + { + } +} +static const struct encodedInt enums[] = { +}; +static const LPCSTR enumeratedTypes[] = { ((LPCSTR)29), + "2.5.29.21" }; +static void test_encodeEnumerated(DWORD dwEncoding) +{ + DWORD i, j; + { + { + BOOL ret; + DWORD bufSize = 0; + ret = CryptEncodeObjectEx(dwEncoding, enumeratedTypes[i], + &bufSize); + { + } + } + } +} +static void test_decodeEnumerated(DWORD dwEncoding) +{ + DWORD i, j; + { + { + BOOL ret; + DWORD bufSize = sizeof(int); + int val; + ret = CryptDecodeObjectEx(dwEncoding, enumeratedTypes[i], + (BYTE *)&val, &bufSize); + (winetest_set_location("encode.c", 403), 0) ? 0 : winetest_ok(val == enums[j].val, "Unexpected value %d, expected %d\n", + val, enums[j].val); + } + } +} +struct encodedFiletime +{ + SYSTEMTIME sysTime; + const BYTE *encodedTime; +}; +static void testTimeEncoding(DWORD dwEncoding, LPCSTR structType, + const struct encodedFiletime *time) +{ +} +static void testTimeDecoding(DWORD dwEncoding, LPCSTR structType, + const struct encodedFiletime *time) +{ + BOOL ret; + if (structType == ((LPCSTR)30) || + (time->sysTime.wYear >= 1950 && time->sysTime.wYear <= 2050)) + { + } + (winetest_set_location("encode.c", 476), 0) ? 0 : winetest_ok(!ret && GetLastError() == ((HRESULT)0x8009310BL), + "Expected CRYPT_E_ASN1_BADTAG, got 0x%08x\n", GetLastError()); +} +static const BYTE bin22[] = { + 0x18,0x0f,'2','1','4','5','0','6','0','6','1','6','1','0','0','0','Z'}; +static const struct encodedFiletime times[] = { +}; +static void test_encodeFiletime(DWORD dwEncoding) +{ + { + } +} +static const BYTE bin23[] = { + 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','0','0','0','Z'}; +static const BYTE bin24[] = { + 0x18,0x13,'1','9','4','5','0','6','0','6','1','6','1','0','0','0','.','9','9','9','Z'}; +static const BYTE bin26[] = { + 0x17,0x0b,'4','5','0','6','0','6','1','6','1','0','Z'}; +static const BYTE bin33[] = { + 0x17,0x0f,'4','5','0','6','0','6','1','6','1','0','-','0','1','0','0'}; +static const BYTE bin35[] = { + 0x17,0x08, '4','5','0','6','0','6','1','6'}; +static const BYTE bin38[] = { + 0x18,0x08, '2','1','4','5','0','6','0','6'}; +static void test_decodeFiletime(DWORD dwEncoding) +{ + static const struct encodedFiletime otherTimes[] = { + }; + static const unsigned char *bogusTimes[] = { + }; + { + } +} +static const char commonName[] = "Juan Lang"; +static const char surName[] = "Lang"; +static const BYTE emptySequence[] = { 0x30, 0 }; +static const BYTE emptyRDNs[] = { 0x30, 0x02, 0x31, 0 }; +static const BYTE twoRDNs[] = { + 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0}; +static const BYTE encodedTwoRDNs[] = { +}; +static const BYTE us[] = { 0x55, 0x53 }; +static const BYTE minnesota[] = { 0x4d, 0x69, 0x6e, 0x6e, 0x65, 0x73, 0x6f, + 0x6f, 0x6c, 0x69, 0x73 }; +static const BYTE codeweavers[] = { 0x43, 0x6f, 0x64, 0x65, 0x57, 0x65, 0x61, + 0x76, 0x65, 0x72, 0x73 }; +static const BYTE wine[] = { 0x57, 0x69, 0x6e, 0x65, 0x20, 0x44, 0x65, 0x76, + 0x65, 0x6c, 0x6f, 0x70, 0x6d, 0x65, 0x6e, 0x74 }; +static const BYTE aric[] = { 0x61, 0x72, 0x69, 0x63, 0x40, 0x63, 0x6f, 0x64, + 0x65, 0x77, 0x65, 0x61, 0x76, 0x65, 0x72, 0x73, 0x2e, 0x63, 0x6f, 0x6d }; +static CHAR oid_us[] = "2.5.4.6", + oid_aric[] = "1.2.840.113549.1.9.1"; +static CERT_RDN_ATTR rdnAttrs[] = { { oid_us, 4, { sizeof(us), (LPBYTE)us } }, + { oid_aric, 7, { sizeof(aric), (LPBYTE)aric } } }; +static const BYTE encodedRDNAttrs[] = { +}; +static void test_encodeName(DWORD dwEncoding) +{ + CERT_NAME_INFO info; + static CHAR oid_common_name[] = "2.5.4.3", + oid_sur_name[] = "2.5.4.4"; + BOOL ret; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)7), ((void *)0), + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)7), &info, + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + { + } + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)7), &info, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + { + } +} +static WCHAR commonNameW[] = { 'J','u','a','n',' ','L','a','n','g',0 }; +static const BYTE twoRDNsNoNull[] = { + 0x20,0x4c,0x61,0x6e,0x67 }; +static const BYTE anyType[] = { + 0x61,0x4c,0x67,0x6e }; +static void test_encodeUnicodeName(DWORD dwEncoding) +{ + BOOL ret; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)20), ((void *)0), + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + { + } +} +static void compareNameValues(const CERT_NAME_VALUE *expected, + const CERT_NAME_VALUE *got) +{ + (winetest_set_location("encode.c", 913), 0) ? 0 : winetest_ok(got->dwValueType == expected->dwValueType, + expected->dwValueType, got->Value.cbData, expected->Value.cbData); + (winetest_set_location("encode.c", 920), 0) ? 0 : winetest_ok(!memcmp(got->Value.pbData, expected->Value.pbData, + (((got->Value.cbData) < (expected->Value.cbData)) ? (got->Value.cbData) : (expected->Value.cbData))), + "String type %d: unexpected value\n", expected->dwValueType); +} +static void compareRDNAttrs(const CERT_RDN_ATTR *expected, + const CERT_RDN_ATTR *got) +{ + { + { + (winetest_set_location("encode.c", 934), 0) ? 0 : winetest_ok(!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (got->pszObjId) && __builtin_constant_p (expected->pszObjId) && (__s1_len = strlen (got->pszObjId), __s2_len = strlen (expected->pszObjId), (!((size_t)(const void *)((got->pszObjId) + 1) - (size_t)(const void *)(got->pszObjId) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((expected->pszObjId) + 1) - (size_t)(const void *)(expected->pszObjId) == 1) || __s2_len >= 4)) ? __builtin_strcmp (got->pszObjId, expected->pszObjId) : (__builtin_constant_p (got->pszObjId) && ((size_t)(const void *)((got->pszObjId) + 1) - (size_t)(const void *)(got->pszObjId) == 1) && (__s1_len = strlen (got->pszObjId), __s1_len < 4) ? (__builtin_constant_p (expected->pszObjId) && ((size_t)(const void *)((expected->pszObjId) + 1) - (size_t)(const void *)(expected->pszObjId) == 1) ? __builtin_strcmp (got->pszObjId, expected->pszObjId) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (expected->pszObjId); register int __result = (((__const unsigned char *) (__const char *) (got->pszObjId))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (got->pszObjId))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (got->pszObjId))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (got->pszObjId))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (expected->pszObjId) && ((size_t)(const void *)((expected->pszObjId) + 1) - (size_t)(const void *)(expected->pszObjId) == 1) && (__s2_len = strlen (expected->pszObjId), __s2_len < 4) ? (__builtin_constant_p (got->pszObjId) && ((size_t)(const void *)((got->pszObjId) + 1) - (size_t)(const void *)(got->pszObjId) == 1) ? __builtin_strcmp (got->pszObjId, expected->pszObjId) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (got->pszObjId); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (expected->pszObjId))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (expected->pszObjId))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (expected->pszObjId))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (expected->pszObjId))[3]); } } __result; }))) : __builtin_strcmp (got->pszObjId, expected->pszObjId)))); }), + expected->pszObjId); + } + } +} +static void compareRDNs(const CERT_RDN *expected, const CERT_RDN *got) +{ + { + } +} +static void compareNames(const CERT_NAME_INFO *expected, + const CERT_NAME_INFO *got) +{ + (winetest_set_location("encode.c", 959), 0) ? 0 : winetest_ok(got->cRDN == expected->cRDN, "Expected %d RDNs, got %d\n", + expected->cRDN, got->cRDN); + { + } +} +static void test_decodeName(DWORD dwEncoding) +{ + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + BOOL ret; + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)7), emptySequence, + (BYTE *)&buf, &bufSize); + { + static CHAR oid_sur_name[] = "2.5.4.4", + oid_common_name[] = "2.5.4.3"; + CERT_RDN_ATTR attrs[] = { + { oid_sur_name, 4, { sizeof(surName), + (BYTE *)commonName } }, + }; + } + { + } +} +static void test_decodeUnicodeName(DWORD dwEncoding) +{ + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + BOOL ret; + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)20), emptySequence, + (BYTE *)&buf, &bufSize); + { + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)20), emptyRDNs, + (BYTE *)&buf, &bufSize); + { + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)20), twoRDNsNoNull, + (BYTE *)&buf, &bufSize); + { + static CHAR oid_sur_name[] = "2.5.4.4", + oid_common_name[] = "2.5.4.3"; + CERT_RDN_ATTR attrs[] = { + { oid_sur_name, 4, + { lstrlenW(commonNameW) * sizeof(WCHAR), (BYTE *)commonNameW } }, + }; + } +} +struct EncodedNameValue +{ + CERT_NAME_VALUE value; +}; +static const char bogusPrintable[] = "~"; +static const BYTE bin42[] = { 0x16,0x02,0x80,0x00 }; +static const BYTE bin43[] = { 0x13,0x02,0x7e,0x00 }; +static BYTE octetCommonNameValue[] = { + 0x12,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; +static BYTE printableCommonNameValue[] = { + 0x13,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; +static BYTE t61CommonNameValue[] = { + 0x14,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; +static BYTE graphicCommonNameValue[] = { + 0x61,0x00,0x6e,0x00,0x67,0x00,0x00 }; +static BYTE utf8CommonNameValue[] = { + 0x0c,0x0a,0x4a,0x75,0x61,0x6e,0x20,0x4c,0x61,0x6e,0x67,0x00 }; +static struct EncodedNameValue nameValues[] = { + { { 5, { sizeof(commonName), (BYTE *)commonName } }, + sizeof(bin42) }, + { { 4, { sizeof(bogusPrintable), + (BYTE *)bogusPrintable } }, bin43, sizeof(bin43) }, +}; +static void test_encodeNameValue(DWORD dwEncoding) +{ + DWORD size = 0, i; + BOOL ret; + CERT_NAME_VALUE value = { 0, { 0, ((void *)0) } }; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)6), &value, + "Expected CRYPT_E_ASN1_CHOICE, got %08x\n", GetLastError()); + { + (winetest_set_location("encode.c", 1209), 0) ? 0 : winetest_ok(size == sizeof(printableCommonNameValue), "Unexpected size %d\n", + "Unexpected encoding\n"); + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)6), + nameValues[i].value.dwValueType, GetLastError()); + { + } + } +} +static void test_decodeNameValue(DWORD dwEncoding) +{ + int i; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + BOOL ret; + { + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)6), + (BYTE *)&buf, &bufSize); + { + compareNameValues(&nameValues[i].value, + (const CERT_NAME_VALUE *)buf); + } + } +} +static const BYTE emptyURL[] = { 0x30, 0x02, 0x86, 0x00 }; +static const WCHAR url[] = { 'h','t','t','p',':','/','/','w','i','n','e', + 0x6f, 0x72, 0x67 }; +static const BYTE encodedIPAddr[] = { 0x30, 0x06, 0x87, 0x04, 0x7f, 0x00, 0x00, + 0x01 }; +static void test_encodeAltName(DWORD dwEncoding) +{ + CERT_ALT_NAME_INFO info = { 0 }; + BYTE *buf = ((void *)0); + DWORD size = 0; + BOOL ret; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)12), &info, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + } + { + } +} +static void test_decodeAltName(DWORD dwEncoding) +{ + BOOL ret; + DWORD bufSize = 0; + CERT_ALT_NAME_INFO *info; + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)12), + &bufSize); + { + (winetest_set_location("encode.c", 1392), 0) ? 0 : winetest_ok(info->cAltEntry == 0, "Expected 0 entries, got %d\n", + info->cAltEntry); + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)12), emptyURL, + &bufSize); + { + } +} +struct encodedBits +{ + const BYTE *encoded; + DWORD cbDecoded; +}; +static const struct encodedBits bits[] = { +}; +static void test_encodeBits(DWORD dwEncoding) +{ + DWORD i; + { + DWORD bufSize = 0; + { + (winetest_set_location("encode.c", 1802), 0) ? 0 : winetest_ok(bufSize == bits[i].encoded[1] + 2, + bits[i].encoded[1] + 2); + } + } +} +static void test_decodeBits(DWORD dwEncoding) +{ + DWORD i; + { + { + CRYPT_BIT_BLOB *blob; + (winetest_set_location("encode.c", 1835), 0) ? 0 : winetest_ok(blob->cbData == bits[i].cbDecoded, + "Unexpected value\n"); + } + } + { + } +} +struct Constraints2 +{ + CERT_BASIC_CONSTRAINTS2_INFO info; +}; +static const struct Constraints2 constraints2[] = { +}; +static const BYTE encodedDomainName[] = { 0x30, 0x2b, 0x31, 0x29, 0x30, 0x11, + 0x16, 0x06, 0x77, 0x69, 0x6e, 0x65, 0x68, 0x71 }; +static void test_encodeBasicConstraints(DWORD dwEncoding) +{ + CERT_NAME_BLOB nameBlob = { sizeof(encodedDomainName), + (LPBYTE)encodedDomainName }; + { + { + } + } + { + } +} +static const unsigned char encodedCommonName[] = { + 0x30,0x15,0x31,0x13,0x30,0x11,0x06,0x03,0x55,0x04,0x03,0x13,0x0a,'J','u','a','n',' ','L','a','n','g',0}; +static void test_decodeBasicConstraints(DWORD dwEncoding) +{ + static const BYTE inverted[] = { 0x30, 0x06, 0x02, 0x01, 0x01, 0x01, 0x01, + 0xff }; + DWORD i; + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + { + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)15), + 0x08000, ((void *)0), (BYTE *)&buf, &bufSize); + { + CERT_BASIC_CONSTRAINTS2_INFO *info = + (winetest_set_location("encode.c", 1984), 0) ? 0 : winetest_ok(!memcmp(info, &constraints2[i].info, sizeof(*info)), + "Unexpected value for item %d\n", i); + } + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)15), + (BYTE *)&buf, &bufSize); + { + CERT_BASIC_CONSTRAINTS_INFO *info = (CERT_BASIC_CONSTRAINTS_INFO *)buf; + { + (winetest_set_location("encode.c", 2043), 0) ? 0 : winetest_ok(info->rgSubtreesConstraint[0].cbData == + info->rgSubtreesConstraint[0].cbData); + (winetest_set_location("encode.c", 2046), 0) ? 0 : winetest_ok(!memcmp(info->rgSubtreesConstraint[0].pbData, encodedDomainName, + sizeof(encodedDomainName)), "Unexpected value\n"); + } + } +} +static const BYTE modulus1[] = { 0,0,0,1,1,1,1,1 }; +struct EncodedRSAPubKey +{ + const BYTE *modulus; + size_t decodedModulusLen; +}; +struct EncodedRSAPubKey rsaPubKeys[] = { +}; +static void test_encodeRsaPublicKey(DWORD dwEncoding) +{ + BYTE toEncode[sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + sizeof(modulus1)]; + RSAPUBKEY *rsaPubKey = (RSAPUBKEY *)(toEncode + sizeof(BLOBHEADER)); + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0, i; + ret = CryptDecodeObjectEx(dwEncoding, "1.2.840.113549.1.1.1", + "Expected ERROR_FILE_NOT_FOUND, got %08x\n", GetLastError()); + { + { + (winetest_set_location("encode.c", 2210), 0) ? 0 : winetest_ok(bufSize >= sizeof(BLOBHEADER) + sizeof(RSAPUBKEY) + + "Wrong size %d\n", bufSize); + (winetest_set_location("encode.c", 2223), 0) ? 0 : winetest_ok(rsaPubKey->magic == 0x31415352, + rsaPubKey->pubexp); + (winetest_set_location("encode.c", 2229), 0) ? 0 : winetest_ok(!memcmp(buf + sizeof(BLOBHEADER) + sizeof(RSAPUBKEY), + rsaPubKeys[i].modulus, rsaPubKeys[i].decodedModulusLen), + "Unexpected modulus\n"); + } + } +} +static const BYTE intSequence[] = { 0x30, 0x1b, 0x02, 0x01, 0x01, 0x02, 0x01, + 0x02, 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d }; +static const BYTE mixedSequence[] = { 0x30, 0x27, 0x17, 0x0d, 0x30, 0x35, 0x30, + 0xff, 0x7f, 0x02, 0x04, 0xba, 0xdd, 0xf0, 0x0d }; +static void test_encodeSequenceOfAny(DWORD dwEncoding) +{ + BYTE *buf = ((void *)0); + { + } + { + (winetest_set_location("encode.c", 2284), 0) ? 0 : winetest_ok(!memcmp(buf, mixedSequence, mixedSequence[1] + 2), + "Unexpected value\n"); + } +} +static void test_decodeSequenceOfAny(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + { + { + } + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)34), mixedSequence, + &bufSize); + { + CRYPT_SEQUENCE_OF_ANY *seq = (CRYPT_SEQUENCE_OF_ANY *)buf; + (winetest_set_location("encode.c", 2324), 0) ? 0 : winetest_ok(seq->cValue == sizeof(ints) / sizeof(ints[0]), + seq->rgValue[0].cbData); + (winetest_set_location("encode.c", 2330), 0) ? 0 : winetest_ok(!memcmp(seq->rgValue[0].pbData, times[0].encodedTime, + times[0].encodedTime[1] + 2), "Unexpected value\n"); + } +} +struct encodedExtensions +{ + CERT_EXTENSIONS exts; +}; +static BYTE noncrit_ext_data[] = { 0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; +static CHAR oid_basic_constraints2[] = "2.5.29.19"; +static CERT_EXTENSION nonCriticalExt = + { oid_basic_constraints2, 0, { 8, noncrit_ext_data } }; +static const struct encodedExtensions exts[] = { +}; +static void test_encodeExtensions(DWORD dwEncoding) +{ + DWORD i; + { + { + } + } + { + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)5), + ((void *)0), (BYTE *)&buf, &bufSize); + { + CERT_EXTENSIONS *ext = (CERT_EXTENSIONS *)buf; + DWORD j; + (winetest_set_location("encode.c", 2405), 0) ? 0 : winetest_ok(ext->cExtension == exts[i].exts.cExtension, + ext->cExtension); + { + (winetest_set_location("encode.c", 2410), 0) ? 0 : winetest_ok(!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (ext->rgExtension[j].pszObjId) && __builtin_constant_p (exts[i].exts.rgExtension[j].pszObjId) && (__s1_len = strlen (ext->rgExtension[j].pszObjId), __s2_len = strlen (exts[i].exts.rgExtension[j].pszObjId), (!((size_t)(const void *)((ext->rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(ext->rgExtension[j].pszObjId) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((exts[i].exts.rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(exts[i].exts.rgExtension[j].pszObjId) == 1) || __s2_len >= 4)) ? __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId) : (__builtin_constant_p (ext->rgExtension[j].pszObjId) && ((size_t)(const void *)((ext->rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(ext->rgExtension[j].pszObjId) == 1) && (__s1_len = strlen (ext->rgExtension[j].pszObjId), __s1_len < 4) ? (__builtin_constant_p (exts[i].exts.rgExtension[j].pszObjId) && ((size_t)(const void *)((exts[i].exts.rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(exts[i].exts.rgExtension[j].pszObjId) == 1) ? __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId); register int __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (exts[i].exts.rgExtension[j].pszObjId) && ((size_t)(const void *)((exts[i].exts.rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(exts[i].exts.rgExtension[j].pszObjId) == 1) && (__s2_len = strlen (exts[i].exts.rgExtension[j].pszObjId), __s2_len < 4) ? (__builtin_constant_p (ext->rgExtension[j].pszObjId) && ((size_t)(const void *)((ext->rgExtension[j].pszObjId) + 1) - (size_t)(const void *)(ext->rgExtension[j].pszObjId) == 1) ? __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (ext->rgExtension[j].pszObjId); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (exts[i].exts.rgExtension[j].pszObjId))[3]); } } __result; }))) : __builtin_strcmp (ext->rgExtension[j].pszObjId, exts[i].exts.rgExtension[j].pszObjId)))); }), + ext->rgExtension[j].pszObjId); + (winetest_set_location("encode.c", 2415), 0) ? 0 : winetest_ok(!memcmp(ext->rgExtension[j].Value.pbData, + exts[i].exts.rgExtension[j].Value.cbData), + "Unexpected value\n"); + } + } + } +} +struct encodedPublicKey +{ + const BYTE *encoded; + const BYTE *encodedNoNull; +}; +static const BYTE aKey[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, + 0xe, 0xf }; +static const BYTE params[] = { 0x02, 0x01, 0x01 }; +static const unsigned char bin66[] = { + 0x30,0x0f,0x30,0x0a,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x05,0x00,0x03,0x01,0x00}; +static const unsigned char bin67[] = { + 0x30,0x0d,0x30,0x08,0x06,0x06,0x2a,0x86,0x48,0x86,0xf7,0x0d,0x03,0x01,0x00}; +static const unsigned char bin69[] = { + 0x0f}; +static unsigned char bin72[] = { 0x05,0x00}; +static CHAR oid_bogus[] = "1.2.3", + oid_rsa[] = "1.2.840.113549"; +static const struct encodedPublicKey pubKeys[] = { + { { { oid_rsa, { 0, ((void *)0) } }, { 0, ((void *)0), 0} }, + { { oid_rsa, { 2, bin72 } }, { sizeof(aKey), (BYTE *)aKey, 0} } }, + { { { oid_rsa, { sizeof(params), (BYTE *)params } }, { sizeof(aKey), + (BYTE *)aKey, 0 } } }, +}; +static void test_encodePublicKeyInfo(DWORD dwEncoding) +{ + DWORD i; + { + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)8), + &bufSize); + { + (winetest_set_location("encode.c", 2505), 0) ? 0 : winetest_ok(bufSize == pubKeys[i].encoded[1] + 2 || + pubKeys[i].encodedNoNull[1] + 2, bufSize); + (winetest_set_location("encode.c", 2510), 0) ? 0 : winetest_ok(!memcmp(buf, pubKeys[i].encoded, pubKeys[i].encoded[1] + 2), + "Unexpected value\n"); + (winetest_set_location("encode.c", 2513), 0) ? 0 : winetest_ok(!memcmp(buf, pubKeys[i].encodedNoNull, + pubKeys[i].encodedNoNull[1] + 2), "Unexpected value\n"); + } + } +} +static void comparePublicKeyInfo(const CERT_PUBLIC_KEY_INFO *expected, + const CERT_PUBLIC_KEY_INFO *got) +{ + (winetest_set_location("encode.c", 2523), 0) ? 0 : winetest_ok(!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p (expected->Algorithm.pszObjId) && __builtin_constant_p (got->Algorithm.pszObjId) && (__s1_len = strlen (expected->Algorithm.pszObjId), __s2_len = strlen (got->Algorithm.pszObjId), (!((size_t)(const void *)((expected->Algorithm.pszObjId) + 1) - (size_t)(const void *)(expected->Algorithm.pszObjId) == 1) || __s1_len >= 4) && (!((size_t)(const void *)((got->Algorithm.pszObjId) + 1) - (size_t)(const void *)(got->Algorithm.pszObjId) == 1) || __s2_len >= 4)) ? __builtin_strcmp (expected->Algorithm.pszObjId, got->Algorithm.pszObjId) : (__builtin_constant_p (expected->Algorithm.pszObjId) && ((size_t)(const void *)((expected->Algorithm.pszObjId) + 1) - (size_t)(const void *)(expected->Algorithm.pszObjId) == 1) && (__s1_len = strlen (expected->Algorithm.pszObjId), __s1_len < 4) ? (__builtin_constant_p (got->Algorithm.pszObjId) && ((size_t)(const void *)((got->Algorithm.pszObjId) + 1) - (size_t)(const void *)(got->Algorithm.pszObjId) == 1) ? __builtin_strcmp (expected->Algorithm.pszObjId, got->Algorithm.pszObjId) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (got->Algorithm.pszObjId); register int __result = (((__const unsigned char *) (__const char *) (expected->Algorithm.pszObjId))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (expected->Algorithm.pszObjId))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) (expected->Algorithm.pszObjId))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) (expected->Algorithm.pszObjId))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (got->Algorithm.pszObjId) && ((size_t)(const void *)((got->Algorithm.pszObjId) + 1) - (size_t)(const void *)(got->Algorithm.pszObjId) == 1) && (__s2_len = strlen (got->Algorithm.pszObjId), __s2_len < 4) ? (__builtin_constant_p (expected->Algorithm.pszObjId) && ((size_t)(const void *)((expected->Algorithm.pszObjId) + 1) - (size_t)(const void *)(expected->Algorithm.pszObjId) == 1) ? __builtin_strcmp (expected->Algorithm.pszObjId, got->Algorithm.pszObjId) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) (expected->Algorithm.pszObjId); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (got->Algorithm.pszObjId))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (got->Algorithm.pszObjId))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (got->Algorithm.pszObjId))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (got->Algorithm.pszObjId))[3]); } } __result; }))) : __builtin_strcmp (expected->Algorithm.pszObjId, got->Algorithm.pszObjId)))); }), + expected->PublicKey.cbData, got->PublicKey.cbData); + (winetest_set_location("encode.c", 2538), 0) ? 0 : winetest_ok(!memcmp(expected->PublicKey.pbData, got->PublicKey.pbData, + got->PublicKey.cbData), "Unexpected public key value\n"); +} +static void test_decodePublicKeyInfo(DWORD dwEncoding) +{ + static const BYTE bogusPubKeyInfo[] = { 0x30, 0x22, 0x30, 0x0d, 0x06, 0x06, + 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f }; + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + { + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)8), + 0x08000, ((void *)0), (BYTE *)&buf, &bufSize); + { + } + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)8), + "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError()); +} +static const BYTE v1Cert[] = { 0x30, 0x33, 0x02, 0x00, 0x30, 0x02, 0x06, 0x00, + 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 }; +static const BYTE v2Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x01, 0x02, + 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 }; +static const BYTE v3Cert[] = { 0x30, 0x38, 0xa0, 0x03, 0x02, 0x01, 0x02, 0x02, + 0x30, 0x5a, 0x30, 0x07, 0x30, 0x02, 0x06, 0x00, 0x03, 0x01, 0x00 }; +static const BYTE v1CertWithConstraints[] = { 0x30, 0x4b, 0x02, 0x00, 0x30, + 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; +static const BYTE v1CertWithSerial[] = { 0x30, 0x4c, 0x02, 0x01, 0x01, 0x30, + 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; +static const BYTE bigCert[] = { 0x30, 0x7a, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, + 0x01, 0xff, 0x04, 0x08, 0x30, 0x06, 0x01, 0x01, 0xff, 0x02, 0x01, 0x01 }; +static void test_encodeCertToBeSigned(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + CERT_INFO info = { 0 }; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)2), ((void *)0), + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + } + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)2), &info, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + } + { + } +} +static void test_decodeCertToBeSigned(DWORD dwEncoding) +{ + static const BYTE *corruptCerts[] = { v1Cert, v2Cert, v3Cert, + v1CertWithConstraints, v1CertWithSerial }; + BOOL ret; + (winetest_set_location("encode.c", 2727), 0) ? 0 : winetest_ok(!ret && GetLastError() == ((HRESULT)0x80093102L), + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + { + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)2), + "Expected CRYPT_E_ASN1_CORRUPT, got %08x\n", GetLastError()); + } + { + } +} +static const BYTE hash[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 0xa, 0xb, 0xc, 0xd, + 0xe, 0xf }; +static const BYTE signedBigCert[] = { + 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, 0x00 }; +static void test_encodeCert(DWORD dwEncoding) +{ + CERT_SIGNED_CONTENT_INFO info = { { sizeof(bigCert), (BYTE *)bigCert }, + { ((void *)0), { 0, ((void *)0) } }, { sizeof(hash), (BYTE *)hash, 0 } }; + BOOL ret; + BYTE *buf = ((void *)0); + DWORD bufSize = 0; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)1), &info, + 0x08000, ((void *)0), (BYTE *)&buf, &bufSize); + { + } +} +static void test_decodeCert(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + { + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)2), signedBigCert, + sizeof(signedBigCert), 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + CERT_INFO *info = (CERT_INFO *)buf; + (winetest_set_location("encode.c", 2843), 0) ? 0 : winetest_ok(info->SerialNumber.cbData == 1, + *info->SerialNumber.pbData); + (winetest_set_location("encode.c", 2852), 0) ? 0 : winetest_ok(info->Subject.cbData == sizeof(encodedCommonName), + "Wrong size %d\n", info->Subject.cbData); + (winetest_set_location("encode.c", 2854), 0) ? 0 : winetest_ok(!memcmp(info->Subject.pbData, encodedCommonName, + info->Subject.cbData), "Unexpected subject\n"); + } +} +static const BYTE distPointWithUrl[] = { 0x30, 0x19, 0x30, 0x17, 0xa0, 0x15, + 0x6e, 0x65, 0x68, 0x71, 0x2e, 0x6f, 0x72, 0x67 }; +static const BYTE distPointWithIssuer[] = { 0x30, 0x17, 0x30, 0x15, 0xa2, 0x13, + 0x2e, 0x6f, 0x72, 0x67 }; +static const BYTE crlReason = 1 | + 3; +static void test_encodeCRLDistPoints(DWORD dwEncoding) +{ + CRL_DIST_POINTS_INFO xxxinfo = { 0 }; + CRL_DIST_POINT point = { { 0 } }; + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)35), &xxxinfo, + "Expected E_INVALIDARG, got %08x\n", GetLastError()); + xxxinfo.cDistPoint = 1; + xxxinfo.rgDistPoint = &point; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)35), &xxxinfo, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + point.ReasonFlags.cbData = sizeof(crlReason); + { + } +} +static void test_decodeCRLDistPoints(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + PCERT_ALT_NAME_ENTRY entry; + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)35), + (BYTE *)&buf, &size); + { + (winetest_set_location("encode.c", 3065), 0) ? 0 : winetest_ok(entry->dwAltNameChoice == 7, + "Expected CERT_ALT_NAME_URL, got %d\n", entry->dwAltNameChoice); + } +} +static const BYTE urlIDP[] = { 0x30,0x17,0xa0,0x15,0xa0,0x13,0x86,0x11,0x68, + 0x67 }; +static void test_encodeCRLIssuingDistPoint(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + CRL_ISSUING_DIST_POINT point = { { 0 } }; + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)54), ((void *)0), + "Expected STATUS_ACCESS_VIOLATION, got %08x\n", GetLastError()); + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)54), &point, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + } + { + } +} +static void compareAltNameEntry(const CERT_ALT_NAME_ENTRY *expected, + const CERT_ALT_NAME_ENTRY *got) +{ + (winetest_set_location("encode.c", 3149), 0) ? 0 : winetest_ok(expected->dwAltNameChoice == got->dwAltNameChoice, + got->dwAltNameChoice); + { + { + (winetest_set_location("encode.c", 3161), 0) ? 0 : winetest_ok((!(*expected).pwszURL && !(*got).pwszURL) || + !lstrcmpW((*expected).pwszURL, (*got).pwszURL), "Unexpected name\n"); + } + } +} +static void compareAltNameInfo(const CERT_ALT_NAME_INFO *expected, + const CERT_ALT_NAME_INFO *got) +{ +} +static const BYTE v1CRL[] = { 0x30, 0x15, 0x30, 0x02, 0x06, 0x00, 0x18, 0x0f, + 0x30, 0x5a }; +static const BYTE v2CRL[] = { 0x30, 0x18, 0x02, 0x01, 0x01, 0x30, 0x02, 0x06, + 0x30, 0x30, 0x30, 0x30, 0x5a }; +static const BYTE v1CRLWithIssuer[] = { 0x30, 0x2c, 0x30, 0x02, 0x06, 0x00, + 0x5a }; +static const BYTE v1CRLWithIssuerAndEmptyEntry[] = { 0x30, 0x43, 0x30, 0x02, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a }; +static const BYTE v1CRLWithIssuerAndEntry[] = { 0x30, 0x44, 0x30, 0x02, 0x06, + 0x30, 0x31, 0x30, 0x31, 0x30, 0x31, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x5a }; +static const BYTE v1CRLWithEntryExt[] = { 0x30,0x5a,0x30,0x02,0x06,0x00,0x30, + 0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; +static const BYTE v1CRLWithExt[] = { 0x30,0x5c,0x30,0x02,0x06,0x00,0x30,0x15, + 0xff,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; +static const BYTE v2CRLWithExt[] = { 0x30,0x5c,0x02,0x01,0x01,0x30,0x02,0x06, + 0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; +static const BYTE v2CRLWithIssuingDistPoint[] = { 0x30,0x5c,0x02,0x01,0x01, + 0x03,0x55,0x1d,0x13,0x04,0x08,0x30,0x06,0x01,0x01,0xff,0x02,0x01,0x01 }; +static void test_encodeCRLToBeSigned(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + CRL_INFO info = { 0 }; + { + (winetest_set_location("encode.c", 3386), 0) ? 0 : winetest_ok(size == sizeof(v1CRLWithIssuerAndEntry), + "Wrong size %d\n", size); + } + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)3), &info, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + } + { + } +} +static const BYTE verisignCRL[] = { 0x30, 0x82, 0x01, 0xb1, 0x30, 0x82, 0x01, +0x61,0xc0,0x99,0x16,0x71,0x05,0xb6,0x25,0x14,0x64,0x4f,0x30 }; +static void test_decodeCRLToBeSigned(DWORD dwEncoding) +{ + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0, i; + { + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)3), + (BYTE *)&buf, &size); + { + CRL_INFO *info = (CRL_INFO *)buf; + (winetest_set_location("encode.c", 4016), 0) ? 0 : winetest_ok(info->cCRLEntry == 0, "Expected 0 CRL entries, got %d\n", + "Unexpected issuer\n"); + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)3), + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + CRL_INFO *info = (CRL_INFO *)buf; + (winetest_set_location("encode.c", 4041), 0) ? 0 : winetest_ok(info->cCRLEntry == 1, "Expected 1 CRL entries, got %d\n", + "Unexpected issuer\n"); + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)3), + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + CRL_INFO *info = (CRL_INFO *)buf; + (winetest_set_location("encode.c", 4085), 0) ? 0 : winetest_ok(info->cCRLEntry == 209, "Expected 209 CRL entries, got %d\n", + info->cExtension); + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)3), + ((void *)0), (BYTE *)&buf, &size); + { + } +} +static const BYTE authorityKeyIdWithIssuer[] = { 0x30,0x19,0xa1,0x17,0x30,0x15, + 0x20,0x4c,0x61,0x6e,0x67,0x00 }; +static const BYTE authorityKeyIdWithSerial[] = { 0x30,0x03,0x82,0x01,0x01 }; +static void test_encodeAuthorityKeyId(DWORD dwEncoding) +{ + CERT_AUTHORITY_KEY_ID_INFO info = { { 0 } }; + BOOL ret; + BYTE *buf = ((void *)0); + DWORD size = 0; + { + } + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)9), &info, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + } + ret = CryptEncodeObjectEx(dwEncoding, ((LPCSTR)9), &info, + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + (winetest_set_location("encode.c", 4284), 0) ? 0 : winetest_ok(size == sizeof(authorityKeyIdWithSerial), "Unexpected size %d\n", + size); + } +} +static void test_decodeAuthorityKeyId(DWORD dwEncoding) +{ + BOOL ret; + LPBYTE buf = ((void *)0); + DWORD size = 0; + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)9), + (BYTE *)&buf, &size); + { + } + ret = CryptDecodeObjectEx(dwEncoding, ((LPCSTR)9), + 0x08000, ((void *)0), (BYTE *)&buf, &size); + { + (winetest_set_location("encode.c", 4355), 0) ? 0 : winetest_ok(size >= sizeof(CERT_AUTHORITY_KEY_ID_INFO), "Unexpected size %d\n", + "Unexpected serial number\n"); + } +} +static void testExportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO *pInfo) +{ + BOOL ret; + DWORD size = 0; + { + ret = CryptExportPublicKeyInfoEx(csp, 2, 0x00000001, + ((void *)0), 0, ((void *)0), ((void *)0), &size); + { + { + (winetest_set_location("encode.c", 4416), 0) ? 0 : winetest_ok(!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p ((*pInfo)->Algorithm.pszObjId) && __builtin_constant_p ("1.2.840.113549.1.1.1") && (__s1_len = strlen ((*pInfo)->Algorithm.pszObjId), __s2_len = strlen ("1.2.840.113549.1.1.1"), (!((size_t)(const void *)(((*pInfo)->Algorithm.pszObjId) + 1) - (size_t)(const void *)((*pInfo)->Algorithm.pszObjId) == 1) || __s1_len >= 4) && (!((size_t)(const void *)(("1.2.840.113549.1.1.1") + 1) - (size_t)(const void *)("1.2.840.113549.1.1.1") == 1) || __s2_len >= 4)) ? __builtin_strcmp ((*pInfo)->Algorithm.pszObjId, "1.2.840.113549.1.1.1") : (__builtin_constant_p ((*pInfo)->Algorithm.pszObjId) && ((size_t)(const void *)(((*pInfo)->Algorithm.pszObjId) + 1) - (size_t)(const void *)((*pInfo)->Algorithm.pszObjId) == 1) && (__s1_len = strlen ((*pInfo)->Algorithm.pszObjId), __s1_len < 4) ? (__builtin_constant_p ("1.2.840.113549.1.1.1") && ((size_t)(const void *)(("1.2.840.113549.1.1.1") + 1) - (size_t)(const void *)("1.2.840.113549.1.1.1") == 1) ? __builtin_strcmp ((*pInfo)->Algorithm.pszObjId, "1.2.840.113549.1.1.1") : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"); register int __result = (((__const unsigned char *) (__const char *) ((*pInfo)->Algorithm.pszObjId))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) ((*pInfo)->Algorithm.pszObjId))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) ((*pInfo)->Algorithm.pszObjId))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) ((*pInfo)->Algorithm.pszObjId))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p ("1.2.840.113549.1.1.1") && ((size_t)(const void *)(("1.2.840.113549.1.1.1") + 1) - (size_t)(const void *)("1.2.840.113549.1.1.1") == 1) && (__s2_len = strlen ("1.2.840.113549.1.1.1"), __s2_len < 4) ? (__builtin_constant_p ((*pInfo)->Algorithm.pszObjId) && ((size_t)(const void *)(((*pInfo)->Algorithm.pszObjId) + 1) - (size_t)(const void *)((*pInfo)->Algorithm.pszObjId) == 1) ? __builtin_strcmp ((*pInfo)->Algorithm.pszObjId, "1.2.840.113549.1.1.1") : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) ((*pInfo)->Algorithm.pszObjId); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[3]); } } __result; }))) : __builtin_strcmp ((*pInfo)->Algorithm.pszObjId, "1.2.840.113549.1.1.1")))); }), + (*pInfo)->Algorithm.pszObjId); + } + } + } +} +static const BYTE expiredCert[] = { 0x30, 0x82, 0x01, 0x33, 0x30, 0x81, 0xe2, + 0x49, 0xe5, 0xf9, 0x65, 0xf3 }; +static void testImportPublicKey(HCRYPTPROV csp, PCERT_PUBLIC_KEY_INFO info) +{ + BOOL ret; + HCRYPTKEY key; + PCCERT_CONTEXT context; + (winetest_set_location("encode.c", 4464), 0) ? 0 : winetest_ok(!ret && GetLastError() == 2, + GetLastError()); + { + (winetest_set_location("encode.c", 4485), 0) ? 0 : winetest_ok(!__extension__ ({ size_t __s1_len, __s2_len; (__builtin_constant_p ("1.2.840.113549.1.1.1") && __builtin_constant_p (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) && (__s1_len = strlen ("1.2.840.113549.1.1.1"), __s2_len = strlen (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId), (!((size_t)(const void *)(("1.2.840.113549.1.1.1") + 1) - (size_t)(const void *)("1.2.840.113549.1.1.1") == 1) || __s1_len >= 4) && (!((size_t)(const void *)((context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) + 1) - (size_t)(const void *)(context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) == 1) || __s2_len >= 4)) ? __builtin_strcmp ("1.2.840.113549.1.1.1", context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) : (__builtin_constant_p ("1.2.840.113549.1.1.1") && ((size_t)(const void *)(("1.2.840.113549.1.1.1") + 1) - (size_t)(const void *)("1.2.840.113549.1.1.1") == 1) && (__s1_len = strlen ("1.2.840.113549.1.1.1"), __s1_len < 4) ? (__builtin_constant_p (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) && ((size_t)(const void *)((context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) + 1) - (size_t)(const void *)(context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) == 1) ? __builtin_strcmp ("1.2.840.113549.1.1.1", context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) : (__extension__ ({ __const unsigned char *__s2 = (__const unsigned char *) (__const char *) (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId); register int __result = (((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[0] - __s2[0]); if (__s1_len > 0 && __result == 0) { __result = (((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[1] - __s2[1]); if (__s1_len > 1 && __result == 0) { __result = (((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[2] - __s2[2]); if (__s1_len > 2 && __result == 0) __result = (((__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"))[3] - __s2[3]); } } __result; }))) : (__builtin_constant_p (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) && ((size_t)(const void *)((context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) + 1) - (size_t)(const void *)(context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) == 1) && (__s2_len = strlen (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId), __s2_len < 4) ? (__builtin_constant_p ("1.2.840.113549.1.1.1") && ((size_t)(const void *)(("1.2.840.113549.1.1.1") + 1) - (size_t)(const void *)("1.2.840.113549.1.1.1") == 1) ? __builtin_strcmp ("1.2.840.113549.1.1.1", context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId) : (__extension__ ({ __const unsigned char *__s1 = (__const unsigned char *) (__const char *) ("1.2.840.113549.1.1.1"); register int __result = __s1[0] - ((__const unsigned char *) (__const char *) (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId))[0]; if (__s2_len > 0 && __result == 0) { __result = (__s1[1] - ((__const unsigned char *) (__const char *) (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId))[1]); if (__s2_len > 1 && __result == 0) { __result = (__s1[2] - ((__const unsigned char *) (__const char *) (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId))[2]); if (__s2_len > 2 && __result == 0) __result = (__s1[3] - ((__const unsigned char *) (__const char *) (context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId))[3]); } } __result; }))) : __builtin_strcmp ("1.2.840.113549.1.1.1", context->pCertInfo->SubjectPublicKeyInfo.Algorithm.pszObjId)))); }), + &context->pCertInfo->SubjectPublicKeyInfo, 0, 0, ((void *)0), &key); + } +} +static const char cspName[] = "WineCryptTemp"; +static void testPortPublicKeyInfo(void) +{ + HCRYPTPROV csp; + BOOL ret; + CryptAcquireContextA(&csp, cspName, "Microsoft Base Cryptographic Provider v1.0", 1, + 0x00000008); + ret = CryptAcquireContextA(&csp, cspName, "Microsoft Base Cryptographic Provider v1.0", 1, + 0x00000010); +} +void func_encode(void) +{ + test_encodeCRLDistPoints(0x00000001); +} + +/* { dg-final { scan-tree-dump-times " xxxinfo = {}" 1 "dse1"} } */ +/* { dg-final { cleanup-tree-dump "dse\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-11.c new file mode 100644 index 000000000..6e13e1875 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-11.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-dse1-details" } */ + +extern void abort(void); +void foo(int *p) +{ + while (1) + { + *p = 1; + *p = 0; + } +} +void bar(int *p) +{ + *p = 1; + *p = 0; + abort (); +} + +/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1" } } */ +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-12.c new file mode 100644 index 000000000..dd8f69c8a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-12.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-dse1" } */ + +void foo (int *p, int b) +{ + if (b) + *p = 1; + *p = 0; +} + +/* { dg-final { scan-tree-dump-times "\\\*p" 1 "dse1" } } */ +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-13.c new file mode 100644 index 000000000..92e0f2b53 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-13.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-dse1-details" } */ + +struct A { char c[4]; } a, b; + +void +f1 (void) +{ + __builtin_memcpy (&a.c[0], "a", 1); + a = b; +} + +void +f2 (void) +{ + __builtin_memcpy (&a.c[0], "a", 1); + __builtin_memcpy (&a.c[0], "cdef", 4); +} + +/* { dg-final { scan-tree-dump-times "Deleted dead store" 2 "dse1" } } */ +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-2.c new file mode 100644 index 000000000..104ef26df --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1" } */ + +int a, b, c; +int +foo () +{ + int *p; + if (c) + p = &a; + else + p = &b; + + *p = 3; + *p = 4; + return *p; +} + + +/* We should eliminate the first assignment to *p, but not the second. */ +/* { dg-final { scan-tree-dump-times " = 3" 0 "dse1"} } */ +/* { dg-final { scan-tree-dump-times " = 4" 1 "dse1"} } */ + +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-3.c new file mode 100644 index 000000000..4292f2384 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1" } */ + +char Bool_Glob; +void f(void) +{ + Bool_Glob = 0; + Bool_Glob = 1; +} + +/* We should eliminate the first assignment to *p, but not the second. */ +/* { dg-final { scan-tree-dump-times "Bool_Glob = 0" 0 "dse1"} } */ +/* { dg-final { scan-tree-dump-times "Bool_Glob = 1" 1 "dse1"} } */ + +/* { dg-final { cleanup-tree-dump "dse1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-4.c new file mode 100644 index 000000000..39fc85e69 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-4.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1" } */ + +foo( int *a) +{ + *a = 5; + *a = 3; +} + + + + +/* We should eliminate the first assignment to *p, but not the second. */ +/* { dg-final { scan-tree-dump-times "= 5" 0 "dse1"} } */ +/* { dg-final { scan-tree-dump-times "= 3" 1 "dse1"} } */ + +/* { dg-final { cleanup-tree-dump "dse1" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-5.c new file mode 100644 index 000000000..537a5e57b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-5.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int x; + +int +f1 (int i, int j, int k) +{ + int *p = k ? &i : &j; + i = 3; + *p = 5; + x = j; +} + +/* The assignment "i = 3" is partialy dead. Our DSE pass doesn't handle + detection of partially dead assignments. + + There's two outputs which would indicate that the optimization was + performed. + + If we used block copying to detect and eliminate the partially dead + store, then we should see an assignment "i = 5" somewhere in the + dump file. + + Another approach would be to redirect the path from the true arm + of the first conditional so that it reaches the statement *p = 5 + rather than i = 3. */ + +/* { dg-final { scan-tree-dump-times "i = 5" 1 "optimized" { xfail *-*-* }} } */ +/* { dg-final { scan-tree-dump-times "<L.*>:;\[\n\t \]*\\*p = 5" 1 "optimized" { xfail *-*-*}} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c new file mode 100644 index 000000000..3d020067c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-6.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1" } */ + +int foo11 (int c) +{ + static int local1, local2; + local1 = 0; + local2 += c; + local1 = 2; + local2++; + return local1 + local2; +} + +/* There should only be one assignment to local1 and local2. */ +/* { dg-final { scan-tree-dump-times "local1 = " 1 "dse1"} } */ +/* { dg-final { scan-tree-dump-times "local2 = " 1 "dse1"} } */ + +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-7.c new file mode 100644 index 000000000..77e4a6246 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-7.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1" } */ + +int glob1, glob2; + +int foo1 (void) +{ + glob1 = 0; + glob2 = 1; + glob1 = 2; + glob2 = 3; + return glob1 + glob2; +} + + + +/* There should only be one assignment to glob1 and glob2, the final + return statement should just return a constant. */ +/* { dg-final { scan-tree-dump-times "glob1 = " 1 "dse1"} } */ +/* { dg-final { scan-tree-dump-times "glob2 = " 1 "dse1"} } */ +/* { dg-final { scan-tree-dump-times "return 5" 1 "dse1"} } */ + +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-8.c new file mode 100644 index 000000000..de1d5bb62 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-8.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dce -fno-tree-ccp -fno-tree-copy-prop -fno-tree-dominator-opts" } */ + +/* This caused the compiler to enter an infinite loop if copies are not + fully propagated. The options are to disable copy propagation and + thus expose the bug. */ + +int foo (void); + +struct A { + struct B { + struct B *n; + } *p; +}; + +static inline void baz (struct A *a) +{ + a->p = a->p->n; +} + +void bar (struct A a) +{ + while (foo ()) + baz (&a); + while (foo ()); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-9.c new file mode 100644 index 000000000..4cb67f0ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-dse-9.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-dse1-vops" } */ + +struct { int a, b; } soup1, soup2; +foo () +{ + soup1 = soup2; + soup1.a = 66; + soup1.b = 77; +} + +/* We should eliminate the first assignment. */ +/* { dg-final { scan-tree-dump-times "VDEF" 2 "dse1" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "dse1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-1.c new file mode 100644 index 000000000..b9ec6bc72 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +/* From PR27090. */ + +int f(int *a) +{ + int t = *a; + unsigned *b = (unsigned *)a; + int *c = (int*)b; + return *c + t; +} + +/* { dg-final { scan-tree-dump "Replaced \\\*a_\[^\n\].*with t_" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c new file mode 100644 index 000000000..34217a029 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-10.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +union loc { unsigned reg; signed offset; }; +void __frame_state_for (volatile char *state_in, int x) +{ + /* We should move all the loads out of this loop. Right now, we only + move one. It takes two insertions because we insert a cast. */ + union loc fs; + int reg; + for (;;) { + switch (x) { + case 0: + *state_in = fs.reg; + case 1: + *state_in = fs.offset; + } + } +} + +/* This is a weird testcase. It should need PPRE to hoist the loop + invariants and the volatileness of state_in prevents DSE of the + first store. Thus, this is XFAILed. */ + +/* { dg-final { scan-tree-dump "Insertions: 2" "pre" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-11.c new file mode 100644 index 000000000..50bb5d960 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-11.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +struct +{ + int x; + int y; +} S[100]; + +int z[100]; + +int +foo (int y) +{ + int x; + + S[5].x = 4; + S[5].y = 0; + + x = S[5].x; + + return (x); +} + +/* { dg-final { scan-tree-dump "Replaced S\\\[5\\\].x with 4" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-12.c new file mode 100644 index 000000000..50bb5d960 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-12.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +struct +{ + int x; + int y; +} S[100]; + +int z[100]; + +int +foo (int y) +{ + int x; + + S[5].x = 4; + S[5].y = 0; + + x = S[5].x; + + return (x); +} + +/* { dg-final { scan-tree-dump "Replaced S\\\[5\\\].x with 4" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-13.c new file mode 100644 index 000000000..972e6c69e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-13.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fstrict-aliasing -fno-tree-sra -fdump-tree-fre-details" } */ + +/* Should be optimized, propagating &a into (*p)[i]. */ + +/* For this testcase we need TBAA to work. */ + +struct Foo +{ + void *data; + int size; +}; +void foo(double (*q)[4], struct Foo *tmp1) +{ + double a[4]; + int i; + tmp1->data = &a; + tmp1->size = 4; + for (i=0; i<4; ++i) + { + double (*p)[4] = tmp1->data; + (*p)[i] = (*q)[i]; + } +} + +/* { dg-final { scan-tree-dump "Replaced tmp1_.\\\(D\\\)->data with &a" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c new file mode 100644 index 000000000..9d1b3f2ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-14.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */ + +/* Should be optimized, propagating &a into (*p)[i]. */ + +struct Foo +{ + void *data; + double size; +}; +void bar(double *); +void foo(double (*q)[4]) +{ + struct Foo tmp1; + double a[4]; + int i; + tmp1.data = &a; + tmp1.size = 4; + for (i=0; i<4; ++i) + { + double (*p)[4] = tmp1.data; + (*p)[i] = (*q)[i]; + /* We want a PHI for the VOP for accessing tmp1.data, so place + this store to tmp1 here. */ + tmp1.size -= 1.0; + } + bar(a); +} + +/* { dg-final { scan-tree-dump "Replaced tmp1.data with &a" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c new file mode 100644 index 000000000..d24cd1e4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-15.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */ + +/* Should be optimized, propagating &a into (*p)[i]. */ + +struct Foo +{ + void *data; + double size; +}; +void bar(double *); +void foo(double (*q)[4]) +{ + struct Foo tmp1; + double a[4]; + int i; + tmp1.data = &a; + for (i=0; i<4; ++i) + { + double (*p)[4] = tmp1.data; + (*p)[i] = (*q)[i]; + /* We want a PHI for the VOP for accessing tmp1.data, so place + this store to tmp1 here. */ + tmp1.size -= 1.0; + } + bar(a); +} + +/* { dg-final { scan-tree-dump "Replaced" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-16.c new file mode 100644 index 000000000..56d85e58e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-16.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre" } */ + +/* FRE should be able to combine i and j and perform simplification + on the condition. */ + +extern void link_error (void); +int i; +int foo(int b, int c) +{ + i = b + 1; + int j = i - 1; + if (b != j) + link_error (); +} + +/* { dg-final { scan-tree-dump-not "link_error" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-17.c new file mode 100644 index 000000000..aced64977 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-17.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details -fno-tree-sra" } */ + +struct Bar { + int dom; +}; +struct Foo { + struct Bar doms[3]; +}; + +int foo(int i, int j, int k) +{ + struct Foo f; + + f.doms[0].dom = i; + f.doms[1].dom = j; + f.doms[2].dom = k; + return f.doms[0LL].dom; +} + +/* { dg-final { scan-tree-dump "Replaced f.doms\\\[0\\\].dom with i_" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c new file mode 100644 index 000000000..392b1f6cf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-18.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre" } */ + +struct a +{ + union + { + int a; + int b; + }; + union + { + int c; + int d; + }; +}; + +int f(struct a *c) +{ + int d = c->a; + c->c = 1; + return c->a + d; +} + +/* We should have CSEd the load from c->a. */ + +/* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c new file mode 100644 index 000000000..688fe8640 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-19.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre" } */ + +struct a +{ + union + { + int a; + int b; + }; + union + { + int c; + int d; + }; + int e; +}; + +int f(struct a *c) +{ + int d; + c->e = 2; + d = c->a; + c->c = 1; + return c->a + d; +} + +/* We should have CSEd the load from c->a. */ + +/* { dg-final { scan-tree-dump-times "c_.*\\\.a" 1 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-2.c new file mode 100644 index 000000000..d1eabf69b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-2.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +/* From PR14287. */ + +short g, h; + +void +foo (long a) +{ + short b = a & 3; + long c = b; + g = c; + h = c; +} + +/* { dg-final { scan-tree-dump "Replaced \\\(short int\\\) c_.*with b_" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-20.c new file mode 100644 index 000000000..f73ad36c5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-20.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int i, j; +int foo(int b) +{ + j = 0; + if (b) + goto L2; +L1: + i = i + 1; +L2: + i = i + 1; + if (i == 1) + goto L1; + return j; +} + +/* { dg-final { scan-tree-dump "return 0;" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-21.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-21.c new file mode 100644 index 000000000..aadf32e21 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-21.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre" } */ + +struct f { + float a; + float b; + float c; + float d; +}; + +struct f a; + +void h(float, float, float, float); + +void g(void) +{ + float a1 = a.a, b = a.b, c = a.c, d = a.d; + a.a = a1; + a.b = b; + a.c = c; + a.d = d; + h(a1, b, c, d); +} + +/* { dg-final { scan-tree-dump-not "a\\\.? = " "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-22.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-22.c new file mode 100644 index 000000000..ce311b68b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-22.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre" } */ + +int i; +int foo (void) +{ + int j; + i = j; + return i; +} + +/* We should eliminate the redundant load of i. */ + +/* { dg-final { scan-tree-dump-not "= i;" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-23.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-23.c new file mode 100644 index 000000000..491836d28 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-23.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre" } */ + +int f(int t, int a, int b) +{ + int c, d; + if (t) + { + c = a; + d = a; + } + else + { + c = b; + d = b; + } + return c+d; +} + +/* { dg-final { scan-tree-dump-times "PHI" 1 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c new file mode 100644 index 000000000..705993a4f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-24.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre" } */ + +int foo(void) +{ + int a[16] = {}; + return a[3]; +} + +int bar(void) +{ + int a[16]; + __builtin_memset (a, 0, sizeof(a)); + return a[3]; +} + +struct X { int i; }; +int baz(void) +{ + struct X a,b; + a.i = 0; + b = a; + return b.i; +} + +int bazzoo (void) +{ + struct X b, a = {}; + b = a; + return b.i; +} + +/* { dg-final { scan-tree-dump-times "= 0;" 5 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c new file mode 100644 index 000000000..f7f99bf74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-25.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre" } */ + +struct X { int i; int j; }; +void bar (struct X *); +int foo (struct X *p) +{ + struct X x; + p->i = 1; + x = *p; + x.j = 2; + return p->i - x.i; +} + +/* We should optimize this to return 0. */ + +/* { dg-final { scan-tree-dump "= 0;" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c new file mode 100644 index 000000000..2b8e8e063 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-26.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */ + +union U { + float f; + int i; +}; + +int foo (union U *p) +{ + union U u; + p->f = 0.0; + u = *p; + return u.i; +} + +/* avr has 16 bit int and 32 bit float */ +/* { dg-final { scan-tree-dump "Replaced u.i with 0 in" "fre" {xfail avr-*-* } } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-27.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-27.c new file mode 100644 index 000000000..39368707c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-27.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +int *q; +void __attribute__((noinline)) +bar (void) +{ + *q = 1; +} +int foo(int which_p) +{ + int x = 0; + int *i,*j; + int **p; + if (which_p) + p = &i; + else + p = &j; + *p = &x; + bar (); + return x; +} + +/* { dg-final { scan-tree-dump "Replaced x with 0" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c new file mode 100644 index 000000000..85e444886 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-3.c @@ -0,0 +1,22 @@ +/* This test requires: + + TRULY_NOOP_TRUNCATION (sizeof (int) * CHAR_BIT, + sizeof (long long) * CHAR_BIT) + + When the condition is true, we distribute "(int) (a + b)" as + "(int) a + (int) b", otherwise we keep the original. */ +/* { dg-do compile { target { { ! mips64 } && { ! spu-*-* } } } } */ +/* { dg-options "-O -fwrapv -fdump-tree-fre-details" } */ + +/* From PR14844. */ + +int +foo (int a, int b) +{ + long long aa = a; + long long bb = b; + return aa + bb; +} + +/* { dg-final { scan-tree-dump "Replaced \\\(int\\\) aa_.*with a_" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-30.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-30.c new file mode 100644 index 000000000..bfbef804d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-30.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O -ffinite-math-only -fdump-tree-optimized" } */ + +float foo(float x, float y, float z) +{ + float a = __builtin_fmaf (x, y, z); + float b = __builtin_fmaf (x, y, z); + return a - b; +} + +/* { dg-final { scan-tree-dump "return 0" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-4.c new file mode 100644 index 000000000..ca8d4c96b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-4.c @@ -0,0 +1,15 @@ +/* If the target returns false for TARGET_PROMOTE_PROTOTYPES, then there + will be no casts for FRE to eliminate and the test will fail. */ +/* { dg-do compile { target i?86-*-* x86_64-*-* hppa*-*-* mips*-*-* m68k*-*-* } } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +/* From PR21608. */ + +static inline char wrap(char f) { return f; } +char bar(char f) +{ + return wrap(f); +} + +/* { dg-final { scan-tree-dump "Replaced \\\(char\\\) .*with " "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-5.c new file mode 100644 index 000000000..7ef20c221 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-5.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +/* From PR19792. */ + +int +bar (unsigned int t) +{ + int a = t; + return a == t; +} + +/* { dg-final { scan-tree-dump "Replaced \\\(unsigned int\\\) a_.*with t_" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-6.c new file mode 100644 index 000000000..6963c1ce4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-6.c @@ -0,0 +1,6 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + + int i; int foo(void) { i = 2; int j = i * 2; int k = i + 2; return j == k; } +/* { dg-final { scan-tree-dump-times "Replaced " 5 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c new file mode 100644 index 000000000..895c05fdf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-7.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details -fdump-tree-optimized" } */ +#if (__SIZEOF_INT__ == __SIZEOF_FLOAT__) +typedef int intflt; +#elif (__SIZEOF_LONG__ == __SIZEOF_FLOAT__) +typedef long intflt; +#else +#error Add target support here for type that will union float size +#endif + +struct X { + int i; + union { + intflt j; + intflt k; + float f; + } u; +}; + +intflt foo(intflt j) +{ + struct X a; + + a.u.j = j; + a.u.f = a.u.f; + a.u.f = a.u.f; + a.u.j = a.u.j; + a.u.f = a.u.f; + return a.u.k; +} + +/* { dg-final { scan-tree-dump-times "Inserted pretmp" 1 "fre" } } */ +/* { dg-final { scan-tree-dump-times "Replaced a.u.f with pretmp" 3 "fre" } } */ +/* { dg-final { scan-tree-dump-times "Replaced a.u.k with j" 1 "fre" } } */ +/* { dg-final { scan-tree-dump "= VIEW_CONVERT_EXPR<float>\\\(j_" "fre" } } */ +/* { dg-final { scan-tree-dump "return j" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c new file mode 100644 index 000000000..bc9f8e399 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-8.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-details" } */ +#if (__SIZEOF_INT__ == __SIZEOF_FLOAT__) +typedef int intflt; +#elif (__SIZEOF_LONG__ == __SIZEOF_FLOAT__) +typedef long intflt; +#else +#error Add target support here for type that will union float size +#endif +union U { + intflt i; + float f; +}; +intflt foo(int i, int b) +{ + union U u; + if (b) + { + i = i << 2; + u.i = i; + return u.f; + } + else + { + i = i << 2; + u.i = i; + return u.f; + } +} + +/* { dg-final { scan-tree-dump-times "Replaced u.f with pretmp" 2 "fre" } } */ +/* { dg-final { scan-tree-dump-times "Inserted pretmp" 2 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c new file mode 100644 index 000000000..c8a434a2b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-fre-9.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fno-tree-sra -fdump-tree-fre-stats" } */ + +union loc { + unsigned reg; + signed offset; +}; +void __frame_state_for2 (volatile char *state_in) +{ + union loc fs; + { + *state_in = fs.reg; + *state_in = fs.offset; + } +} +void __frame_state_for1 (volatile char *state_in) +{ + union loc fs; + for (;;) + { + *state_in = fs.offset; + *state_in = fs.reg; + } +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 2 "fre" } } */ +/* { dg-final { scan-tree-dump-times "Insertions: 1" 2 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-1.c new file mode 100644 index 000000000..20854813d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase for PR31657. */ + +int foo (int x, int a, int b) +{ + int c = 1 << a; + if (x & c) + if (x & (1 << b)) + /* returning 1 causes phiopt to trigger in */ + return 2; + return 0; +} + +/* { dg-final { scan-tree-dump "\\|" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-2.c new file mode 100644 index 000000000..dab30addd --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase for PR31657. */ + +int foo (int x, int a, int b) +{ + /* if ((x & a) || (x & b)) */ + if (x & a) + goto doit; + if (x & b) + goto doit; + + /* else */ + return 0; + + /* then - returing 1 causes phiopt to trigger */ +doit: + return 2; +} + +/* { dg-final { scan-tree-dump "\\|" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-3.c new file mode 100644 index 000000000..79fec8ba9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-3.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase extracted from PR15353. */ + +int foo (int x, int a) +{ + /* if ((x > a) || (x == a)) */ + if (x > a) + goto doit; + if (x == a) + goto doit; + + /* else */ + return 0; + + /* then - returing 1 causes phiopt to trigger */ +doit: + return 2; +} + +/* { dg-final { scan-tree-dump ">=" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-4.c new file mode 100644 index 000000000..da477867e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-4.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase extracted from PR15353. */ + +extern void bar(void); + +void foo (int x, int a) +{ + /* if ((x < a) || (x != a)) return; else bar (); */ + if (x < a) + return; + if (x != a) + return; + + /* else */ + bar (); +} + +/* { dg-final { scan-tree-dump "!=" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-5.c new file mode 100644 index 000000000..88bd81e25 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-5.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +/* Testcase from PR15353. */ + +int g(void); +int h(void); +int f(int *i, int *j) +{ + while (1) + { + if (*i > *j || *i == *j) + break; + return g(); + } + return h(); +} + +/* { dg-final { scan-tree-dump ">=" "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-6.c new file mode 100644 index 000000000..90abc8deb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-6.c @@ -0,0 +1,37 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-ifcombine" } */ + +void bar (void); + +void +foo1 (unsigned int a) +{ + if (a & 1) + goto heaven; + if (a & 4) + goto heaven; + return; + + heaven: + bar (); +} + +void +foo2 (unsigned int a) +{ + if (a & 1) + if (a & 4) + goto heaven; + return; + + heaven: + bar (); +} + + +/* The special treatment of a & 1 != 0 in fold caused the pattern not + to be recognized due to extra conversions inserted. */ + +/* { dg-final { scan-tree-dump "optimizing bits or bits test" "ifcombine" } } */ +/* { dg-final { scan-tree-dump "optimizing double bit test" "ifcombine" } } */ +/* { dg-final { cleanup-tree-dump "ifcombine" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c new file mode 100644 index 000000000..fd2025092 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-ifcombine-7.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-optimized" } */ + +int test1 (int i, int j) +{ + if (i >= j) + if (i != j) + return 0; + return -1; +} + +/* The above should be optimized to a i > j test by ifcombine. */ + +/* { dg-final { scan-tree-dump " > " "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-1.c new file mode 100644 index 000000000..aa40d443b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-lim" } */ + +/* This is a variant that does cause fold to place a cast to + int before testing bit 1. */ + +void +quantum_toffoli (int control1, int control2, int target, + unsigned long *state, int size) +{ + int i; + + for(i=0; i<size; i++) + { + if (state[i] & ((unsigned long) 1 << control1)) + if (state[i] & ((unsigned long) 1 << control2)) + state[i] ^= ((unsigned long) 1 << target); + } +} + +/* { dg-final { scan-tree-dump-times "1 <<" 3 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-2.c new file mode 100644 index 000000000..9274261cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-2.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-lim" } */ + +/* This is a variant that doesn't cause fold to place a cast to + int before testing bit 1. */ + +void +quantum_toffoli(int control1, int control2, int target, int *state, +int size) +{ + int i; + + for(i=0; i<size; i++) + { + if (state[i] & ( 1 << control1)) + if (state[i] & ( 1 << control2)) + state[i] ^= ( 1 << target); + } +} + +/* { dg-final { scan-tree-dump-times "1 <<" 3 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c new file mode 100644 index 000000000..85800588d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-3.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-lim-details" } */ + +struct { int x; int y; } global; +void foo(int n) +{ + int i; + for ( i=0; i<n; i++) + global.y += global.x*global.x; +} + +/* { dg-final { scan-tree-dump "Executing store motion of global.y" "lim1" } } */ +/* { dg-final { scan-tree-dump "Moving statement.*global.x.*out of loop 1" "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-5.c new file mode 100644 index 000000000..4a428515d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-5.c @@ -0,0 +1,29 @@ +/* { dg-do link } */ +/* { dg-options "-O" } */ + +/* We should apply store motion here. */ + +struct BUF1 +{ + int b1; + int b12; +}; + +void link_error(); + +int foo(struct BUF1 * p) +{ + int i = 0; +#if(__SIZEOF_INT__ >= 4) + for (i = 0; i < 1024*1024; i++) +#else + for (i = 0; i < 128*128; i++) +#endif + p->b1 = 1; + + if (p->b1 != 1) + link_error (); + return 0; +} + +int main() { return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-6.c new file mode 100644 index 000000000..e29f50c71 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-6.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim-details" } */ + +double a[16][64], y[64], x[16]; +void foo(void) +{ + int i, j; + for (j = 0; j < 64; ++j) + for (i = 0; i < 16; ++i) + y[j] = y[j] + a[i][j] * x[i]; +} + +/* { dg-final { scan-tree-dump "Executing store motion of y" "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-7.c new file mode 100644 index 000000000..f8e15f344 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-7.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-lim1-details" } */ + +extern const int srcshift; + +void foo (int *srcdata, int *dstdata) +{ + int i; + + for (i = 0; i < 256; i++) + dstdata[i] = srcdata[i] << srcshift; +} + +/* { dg-final { scan-tree-dump "Moving statement" "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-9.c new file mode 100644 index 000000000..c5a67653b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-lim-9.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-lim1-details" } */ + +void bar (int); +void foo (int n, int m) +{ + unsigned i; + for (i = 0; i < n; ++i) + { + int x; + if (m < 0) + x = 1+n; + else + x = m-n; + bar (x); + } +} + +/* { dg-final { scan-tree-dump-times "Moving PHI node" 1 "lim1" } } */ +/* { dg-final { cleanup-tree-dump "lim1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c new file mode 100644 index 000000000..3dd3b5263 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +extern int printf (const char *, ...); +int foo(int argc, char **argv) +{ + int a; + int b; + int c; + b = argc + 1; + c = argc + 2; + a = b + c; + if (argc * 2) + { + c = argc + 3; + } + printf ("%d, %d\n", a, b + c); +} +/* We should eliminate one evaluation of b + c along the main path, + causing one reload. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c new file mode 100644 index 000000000..41af34498 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-10.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats" } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats -fno-finite-math-only" { target sh*-*-* } } */ +double cos (double); +void link_error(); +void f(double a) +{ + double b = cos (a); + double c = cos (a); + if (b != c) + link_error(); +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c new file mode 100644 index 000000000..26c47b183 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-11.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +double cos (double); +double f(double a) +{ + double b; + double c,d; + if (a < 2.0) + { + c = cos (a); + } + else + { + c = 1.0; + } + d = cos (a); + return d + c; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c new file mode 100644 index 000000000..fd80e3d8d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-12.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +double cos (double) __attribute__ ((const)); +double sin (double) __attribute__ ((const)); +double f(double a) +{ + double b; + double c,d; + double (*fp) (double) __attribute__ ((const)); + /* Fully redundant call, but we need a phi node to merge the results. */ + if (a < 2.0) + { + fp = sin; + c = fp (a); + } + else + { + c = 1.0; + fp = cos; + c = fp (a); + } + d = fp (a); + return d + c; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c new file mode 100644 index 000000000..dfce46b99 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-13.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +double cos (double) __attribute__ ((const)); +double sin (double) __attribute__ ((const)); +double f(double a) +{ + double b; + double c,d; + double (*fp) (double) __attribute__ ((const)); + /* Partially redundant call */ + if (a < 2.0) + { + fp = sin; + c = fp (a); + } + else + { + c = 1.0; + fp = cos; + } + d = fp (a); + return d + c; +} + +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-14.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-14.c new file mode 100644 index 000000000..2371cfa1a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-14.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +extern __SIZE_TYPE__ strlen (const char *) __attribute__ ((__pure__)); + +void +foo (const char *str) +{ + __SIZE_TYPE__ a = strlen (str); + __SIZE_TYPE__ b = strlen (str); + if (a != b) + link_error (); +} +/* { dg-final { scan-tree-dump-times "link_error" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-15.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-15.c new file mode 100644 index 000000000..ed3b2f784 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-15.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-rtl-expand-details" } */ + +/* Verify we PRE the strlen call, as strlen("") folds to zero. */ + +extern __SIZE_TYPE__ strlen (const char *); + +__SIZE_TYPE__ mystrlen (const char *s) +{ + if (!s) + s = ""; + return strlen(s); +} + +/* { dg-final { scan-rtl-dump "PART.. = 0" "expand" } } */ +/* { dg-final { cleanup-rtl-dump "expand" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-16.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-16.c new file mode 100644 index 000000000..b087dc1b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-16.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats -std=c99" } */ +int foo(int k, int *x) +{ + int j=0; + int res = 0; + /* We should pull res = *x all the way out of the do-while */ + do { + for (int n=0;n<3;++n); + res = *x; + } while (++j<k); + return res; +} +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c new file mode 100644 index 000000000..d4274dbe0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-17.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +typedef union { + int i; + float f; +} U; + +int foo(U *u, int b, int i) +{ + u->i = 0; + if (b) + u->i = i; + return u->i; +} + +/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c new file mode 100644 index 000000000..5e92934f0 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-18.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-details" } */ + +struct Bar { int a; int b; }; +struct Foo { int x; struct Bar y; }; + +int __attribute__((const)) foo (struct Bar); + +int bar (int b) +{ + struct Foo f; + int c; + while (b--) + { + c = foo(f.y); + } + return c; +} + +/* { dg-final { scan-tree-dump "Replaced foo \\(f.y\\)" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-19.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-19.c new file mode 100644 index 000000000..0fd0dc542 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-19.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +struct Loc { + int x[3]; +}; + +void bar (struct Loc *); + +int foo (int i, int j, int k, int b) +{ + struct Loc IND; + int res; + + if (b) + { + IND.x[0] = i; + IND.x[1] = j; + IND.x[2] = k-1; + } + else + { + IND.x[0] = i; + IND.x[1] = j; + IND.x[2] = k; + } + + /* This should be optimized to i + j + {k, k + 1}. */ + res = IND.x[0] + IND.x[1] + IND.x[2]; + + /* This is just to prevent SRA. */ + bar (&IND); + + return res; +} + +/* All three loads should be eliminated. */ +/* { dg-final { scan-tree-dump "Eliminated: 3" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c new file mode 100644 index 000000000..311f12781 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int motion_test1(int data, int data_0, int data_3, int v) +{ + int i; + int t, u; + + if (data) + i = data_0 + data_3; + else { + v = 2; + i = 5; + } + t = data_0 + data_3; + u = i; + return v * t * u; +} +/* We should eliminate one computation of data_0 + data_3 along the + main path. We cannot re-associate v * t * u due to undefined + signed overflow so we do not eliminate one computation of v * i along + the main path. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre" { xfail *-*-* } } } */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-20.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-20.c new file mode 100644 index 000000000..6361b679c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-20.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +double pcheck; + +void foo(int n, int m, int b) +{ + int i, j; + + goto bb18; + +start: + i = 1; + do { + j = 1; + do { + double x = pcheck; + x = x + 1; + pcheck = x; + j = j + 1; + } while (j != m); + i = i + 1; + } while (i != n); + +bb18: + pcheck = 0.0; + goto start; +} + +/* We should have inserted two PHI nodes and the one in the i-loop + should have 0.0 in the argument coming from the bb18 block. */ + +/* { dg-final { scan-tree-dump "New PHIs: 2" "pre" } } */ +/* { dg-final { scan-tree-dump "PHI <.*0\\\.0" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-21.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-21.c new file mode 100644 index 000000000..10efb12b4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-21.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre" } */ + +long +NumSift (long *array, unsigned long k) +{ + if (array[k] < array[k + 1L]) + ++k; + return array[k]; +} + +/* There should be only two loads left. */ + +/* { dg-final { scan-tree-dump-times "= \\\*D\[^\n;\]*;" 2 "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-22.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-22.c new file mode 100644 index 000000000..3a1697e6c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-22.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +int foo (int i, int b) +{ + int j = 1; + if (b) + j = i; + return j - i; +} + +/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c new file mode 100644 index 000000000..6aeb06af9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-23.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +struct { int x; int y; } global; +void foo(int n) +{ + int i; + for ( i=0; i<n; i++) + global.y += global.x*global.x; +} + +/* { dg-final { scan-tree-dump "Eliminated: 3" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c new file mode 100644 index 000000000..f91f4af74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-24.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre" } */ + +void foo(int *p, double *x, int n) +{ + int i; + for (i = 0; i < n; ++i) + *(x + *p * i) = 0.0; +} + +/* We should remove the unnecessary insertion of a phi-node and + _not_ end up using the phi result for replacement *p. */ + +/* { dg-final { scan-tree-dump-not "= prephitmp" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-25.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-25.c new file mode 100644 index 000000000..32b068275 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-25.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ + +struct X { int i; }; + +int foo (int x) +{ + struct X a; + struct X b; + struct X *p; + a.i = 1; + b.i = 2; + if (x) + p = &a; + else + p = &b; + return p->i; +} + +/* We should eliminate the load from p for a PHI node with values 1 and 2. */ + +/* { dg-final { scan-tree-dump "Eliminated: 1" "pre" } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-26.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-26.c new file mode 100644 index 000000000..b986bdd92 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-26.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O -fdump-tree-fre-details" } */ + +typedef union +{ + int* data; +} SA; + +typedef struct +{ + int reserved; + char* array; +}SB; + +typedef struct +{ + int status; +}SC; + +void foo(SA* pResult, SB* method, SC* self) +{ + if (method->array[0] == 'L' && !self->status && pResult->data != 0) + pResult->data = pResult->data; +} + +/* { dg-final { scan-tree-dump "Deleted redundant store" "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-27.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-27.c new file mode 100644 index 000000000..1d60a3013 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-27.c @@ -0,0 +1,29 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre" } */ + +int foo (int i, int j, int b) +{ + int res = 0; + if (b) + res = i/j; + /* We should insert the possibly trapping i/j. */ + res += i/j; + return res; +} + +extern void bar (void); +int foo2 (int i, int j, int b) +{ + int res = 0; + if (b) + res = i/j; + /* But we fail so here because of the possibly not returning + call in the same basic-block. */ + res += i/j; + bar (); + return res; +} + +/* { dg-final { scan-tree-dump-times "# prephitmp" 1 "pre" } } */ +/* { dg-final { scan-tree-dump-times "# prephitmp" 2 "pre" { xfail *-*-* } } } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c new file mode 100644 index 000000000..3925f7529 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +unsigned foo1 (unsigned a, unsigned b) +{ + unsigned i, j, k; + for (i = 0; i != a; i++) + { + j += 4*b; + k += 4*a; + } + return j + k; +} +/* We should eliminate both 4*b and 4*a from the main body of the loop */ +/* { dg-final { scan-tree-dump-times "Eliminated: 2" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c new file mode 100644 index 000000000..274737ac4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-4.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int foo(void) +{ + int x, c, y; + x = 3; + if (c) + x = 2; + y = x + 1; + return y; +} +/* We should eliminate the x+1 computation from this routine, replacing + it with a phi of 3, 4 */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c new file mode 100644 index 000000000..8756944b9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-5.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int +foo (int i) +{ + int a, b; + if (i) + a = 3, b = 2; + else + a = 2, b = 3; + return a + b; +} +/* We should detect that a+b is the same along both edges, and replace it with + 5 */ +/* { dg-final { scan-tree-dump-times "Constified: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c new file mode 100644 index 000000000..2811f4379 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-6.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-pre-stats" } */ +int foo(int x) +{ + int c, y; + if (c) + x = 2; + y = x + 1; + return y; +} +/* We should eliminate one evaluation of x + 1 along the x = 2 path, + causing one elimination. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "pre"} } */ +/* { dg-final { cleanup-tree-dump "pre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c new file mode 100644 index 000000000..f87476a3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-7.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats" } */ +int +foo (int *array) +{ + if (array[1] != 0) + return array[1]; + return 0; +} +/* We should eliminate one load. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c new file mode 100644 index 000000000..ae933bbcc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-8.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats" } */ +struct s { + int *n; +}; + +int +foo (__SIZE_TYPE__ i, struct s *array) +{ + int *p = array[i].n; + if (p) + { + int *q = array[i].n; + if (p != q) + return 1; + } + return 0; +} +/* We should eliminate two address calculations, and one load. */ +/* We used to eliminate a cast but that was before POINTER_PLUS_EXPR + was added. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c new file mode 100644 index 000000000..30d968b7c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-pre-9.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-dominator-opts -fdump-tree-fre-stats" } */ +int +foo (unsigned long a) +{ + int b = __builtin_clzl (a); + int c = __builtin_clzl (a); + if (b == c) + return 1; + return 0; +} +/* { dg-final { scan-tree-dump-times "return 0;" 0 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-1.c new file mode 100644 index 000000000..65cd83d7c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-1.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-stats" } */ + +void vnum_test8(int *data) +{ + int i; + int stop = data[3]; + int m = data[4]; + int n = m; + for (i=0; i<stop; i++) { + int k = data[2]; + data[k] = 2; + data[0] = m - n; + k = data[1]; + m = m + k; + n = n + k; + } +} +/* We should eliminate m - n, and set n = n + k into n = m. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 3" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-2.c new file mode 100644 index 000000000..cc3661cc6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-2.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-stats" } */ + +int vnum_test8(int *data) +{ + int i; + int stop = data[3]; + int m = data[4]; + int n = m; + int p; + for (i=0; i<stop; i++) { + int k = data[2]; + data[k] = 2; + data[0] = m - n; + k = data[1]; + m = m + k; + n = n + k; + p = data[0]; + } + return p; +} +/* We should eliminate m - n, and set n = n + k into n = m, and + set p to 0 */ +/* { dg-final { scan-tree-dump-times "Eliminated: 4" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-3.c new file mode 100644 index 000000000..b80a8dc3b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-3.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-stats" } */ +int main(int argc, char **argv) +{ + int *p; + int result; + *p = 2; + if (argc) + *p = 2; + result = *p; + return result; +} +/* We should eliminate result = *p by saying it has the value 2. */ +/* { dg-final { scan-tree-dump-times "Eliminated: 1" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-4.c new file mode 100644 index 000000000..7caf4eec6 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sccvn-4.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-stats" } */ + +int vnum_test8(int *data) +{ + int i; + int stop = data[3]; + int m = data[4]; + int n = m; + int p = 0; + + for (i=0; i<stop; i++) { + int k = data[2]; + data[5] = 0; + if (i < 30) + data[5] = m - n; + p = data[5]; + k = data[1]; + m = m + k; + n = n + k; + } + return p; +} +/* We should eliminate m - n, n + k, set data[5] = 0, eliminate the + address arithmetic for data[5], and set p = 0. +/* { dg-final { scan-tree-dump-times "Eliminated: 5" 1 "fre"} } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c new file mode 100644 index 000000000..c3326d27e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-1.c @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sink-stats" } */ +int +foo (int a, int b, int c) +{ + int x = a * b; + return c ? x : a; +} +/* We should sink the x = a * b calculation into the branch that returns x. */ +/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */ +/* { dg-final { cleanup-tree-dump "sink" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c new file mode 100644 index 000000000..1d54d019e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sink-stats" } */ +int +bar (int a, int b, int c) +{ + int y = a * b; + if (c) + y = 12; + return y; +} +/* We should sink the x = a * b calculation into the else branch */ +/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */ +/* { dg-final { cleanup-tree-dump "sink" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c new file mode 100644 index 000000000..fceb509e8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sink-stats" } */ +extern void foo(int a); +int +main (int argc) +{ + int a; + a = argc + 1; + if (argc + 3) + { + foo (a); + } +} +/* We should sink the a = argc + 1 calculation into the if branch */ +/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */ +/* { dg-final { cleanup-tree-dump "sink" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c new file mode 100644 index 000000000..6e1cc50dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-4.c @@ -0,0 +1,21 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-sink-stats" } */ +extern int foo (int *, int *); +extern int foo2 (int); +int +main (int argc) +{ + int a, b, c; + b = argc + 1; + c = argc + 2; + a = b + c; + if (argc) + { + foo (&b, &c); + a = b + c; + } + foo2 (a); +} +/* We should sink the first a = b + c calculation into the else branch */ +/* { dg-final { scan-tree-dump-times "Sunk statements: 1" 1 "sink" } } */ +/* { dg-final { cleanup-tree-dump "sink" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c new file mode 100644 index 000000000..f51d485d4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-sink-5.c @@ -0,0 +1,48 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -fdump-tree-sink-stats" } */ + +typedef short int16_t; +typedef unsigned char uint8_t; + +void foo(int16_t runs[], uint8_t alpha[], int x, int count) +{ + int16_t* next_runs = runs + x; + uint8_t* next_alpha = alpha + x; + + while (x > 0) + { + int n = runs[0]; + + if (x < n) + { + alpha[x] = alpha[0]; + runs[0] = (int16_t)(x); + runs[x] = (int16_t)(n - x); + break; + } + runs += n; + alpha += n; + x -= n; + } + + runs = next_runs; + alpha = next_alpha; + x = count; + + for (;;) + { + int n = runs[0]; + + if (x < n) + { + alpha[x] = alpha[0]; + break; + } + x -= n; + runs += n; + } +} + +/* We should not sink the next_runs = runs + x calculation after the loop. */ +/* { dg-final { scan-tree-dump-times "Sunk statements:" 0 "sink" } } */ +/* { dg-final { cleanup-tree-dump "sink" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-1.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-1.c new file mode 100644 index 000000000..aaa3d13ca --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-1.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +static const int conststaticvariable; + +int f(void) +{ + return conststaticvariable; +} + +/* There should be no reference to conststaticvariable as we should have + inlined the 0. */ +/* { dg-final { scan-tree-dump-times "conststaticvariable" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-2.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-2.c new file mode 100644 index 000000000..be37a21d4 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-2.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +const int conststaticvariable; + +int f(void) +{ + return conststaticvariable; +} + +/* There should be a reference to conststaticvariable since it may + may be overriden at link time. */ +/* { dg-final { scan-tree-dump-times "conststaticvariable" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c new file mode 100644 index 000000000..fd6b7c812 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-3.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* Skipped on MIPS GNU/Linux and IRIX target because __PIC__ can be + defined for executables as well as shared libraries. */ +/* { dg-skip-if "" { *-*-darwin* hppa*64*-*-* mips*-*-linux* mips*-*-irix* } { "*" } { "" } } */ +/* { dg-options "-O2 -fno-common -fdump-tree-optimized" } */ + +const int conststaticvariable; + +int f(void) +{ + return conststaticvariable; +} + +/* There should be no reference for nonpic targets to + conststaticvariable as we should have inlined the 0. */ +/* { dg-final { scan-tree-dump-times "conststaticvariable" 0 "optimized" { target nonpic } } } */ +/* { dg-final { scan-tree-dump-times "conststaticvariable" 1 "optimized" { target { ! nonpic } } } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-4.c b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-4.c new file mode 100644 index 000000000..571fc02a3 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/ssa-store-ccp-4.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-require-effective-target fpic } */ +/* { dg-skip-if "" { *-*-darwin* } { "*" } { "" } } */ +/* { dg-options "-O2 -fno-common -fpic -fdump-tree-optimized" } */ + +const int conststaticvariable; + +int f(void) +{ + return conststaticvariable; +} + +/* There should be a reference to conststaticvariable since it may + may be overriden at run time. */ +/* { dg-final { scan-tree-dump-times "conststaticvariable" 1 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-1.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-1.c new file mode 100644 index 000000000..3cba2928f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-1.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-stdarg" } */ + +#include <stdarg.h> + +/* This can be handled on all arches. If there is no va_start, registers don't need + to be saved. */ +void +f1 (int i, ...) +{ +} +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" } } */ +/* { dg-final { cleanup-tree-dump "stdarg" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c new file mode 100644 index 000000000..6b4783c53 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-2.c @@ -0,0 +1,298 @@ +/* First dg-final line after each function is for architectures that use + a struct {...} va_list[1] with separate GPR and FPR counters in the + structure. Second dg-final line is for architectures that use void * + or char * va_list. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-stdarg" } */ + +#include <stdarg.h> + +extern void foo (int, va_list); +extern void bar (int); +long x; +double d; +va_list gap; +va_list *pap; + +void +f1 (int i, ...) +{ + va_list ap; + va_start (ap, i); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f2 (int i, ...) +{ + va_list ap; + va_start (ap, i); + bar (d); + x = va_arg (ap, long); + bar (x); + va_end (ap); +} +/* Assume the counters can be number of registers or bytes on 32-bit + architecture or bytes on 64-bit architecture. */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 8 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 1 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f3 (int i, ...) +{ + va_list ap; + va_start (ap, i); + d = va_arg (ap, double); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and 1 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[1-9\]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f4 (int i, ...) +{ + va_list ap; + va_start (ap, i); + x = va_arg (ap, double); + foo (i, ap); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f5 (int i, ...) +{ + va_list ap; + va_start (ap, i); + va_copy (gap, ap); + bar (i); + va_end (ap); + va_end (gap); +} +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f6 (int i, ...) +{ + va_list ap; + va_start (ap, i); + bar (d); + va_arg (ap, long); + va_arg (ap, long); + x = va_arg (ap, long); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 24 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 3 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f7 (int i, ...) +{ + va_list ap; + va_start (ap, i); + pap = ≈ + bar (6); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f8 (int i, ...) +{ + va_list ap; + va_start (ap, i); + pap = ≈ + bar (d); + x = va_arg (ap, long); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f9 (int i, ...) +{ + va_list ap; + va_start (ap, i); + __asm __volatile ("" : "=r" (pap) : "0" (&ap)); + bar (6); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f9: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f10 (int i, ...) +{ + va_list ap; + va_start (ap, i); + __asm __volatile ("" : "=r" (pap) : "0" (&ap)); + bar (d); + x = va_arg (ap, long); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f11 (int i, ...) +{ + va_list ap; + va_start (ap, i); + bar (d); + x = va_arg (ap, long); + x += va_arg (ap, long); + x += va_arg (ap, long); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save 24 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save 3 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 0, needs to save (3|12|24) GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f12 (int i, ...) +{ + va_list ap; + va_start (ap, i); + bar (d); + va_arg (ap, double); + va_arg (ap, double); + x = va_arg (ap, double); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 24 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save 0 GPR units and 3 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f13 (int i, ...) +{ + va_list ap; + va_start (ap, i); + bar (d); + x = va_arg (ap, double); + x += va_arg (ap, double); + x += va_arg (ap, double); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 24 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save 0 GPR units and 3 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f13: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f14 (int i, ...) +{ + va_list ap; + va_start (ap, i); + bar (d); + x = va_arg (ap, double); + x += va_arg (ap, long); + x += va_arg (ap, double); + bar (x); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save 24 GPR units and 3" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save 1 GPR units and 2 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f14: va_list escapes 0, needs to save \[1-9]\[0-9\]* GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +inline void __attribute__((always_inline)) +f15_1 (va_list ap) +{ + x = va_arg (ap, double); + x += va_arg (ap, long); + x += va_arg (ap, double); +} + +void +f15 (int i, ...) +{ + va_list ap; + va_start (ap, i); + f15_1 (ap); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save \[148\] GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f15: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f15: va_list escapes 0, needs to save 1 GPR units and 2 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump-not "f15: va_list escapes 0, needs to save 0 GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ +/* { dg-final { cleanup-tree-dump "stdarg" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-3.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-3.c new file mode 100644 index 000000000..9ffbe3fae --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-3.c @@ -0,0 +1,193 @@ +/* First dg-final line after each function is for architectures that use + a struct {...} va_list[1] with separate GPR and FPR counters in the + structure. Second dg-final line is for architectures that use void * + or char * va_list. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-stdarg" } */ + +#include <stdarg.h> + +extern void foo (int, va_list); +extern void bar (int); +long x; +va_list gap; + +/* If va_list is not local variable, it escapes the function. */ +void +f1 (int i, ...) +{ + va_start (gap, i); + x = va_arg (gap, long); + va_end (gap); +} +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f2 (int i, ...) +{ + va_start (gap, i); + bar (i); + va_end (gap); +} +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +/* tree-stdarg.c only handles va_list variables, not arrays of them or + va_list fields embedded in structures. */ +void +f3 (int i, ...) +{ + va_list aps[10]; + va_start (aps[4], i); + x = va_arg (aps[4], long); + va_end (aps[4]); +} +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f4 (int i, ...) +{ + va_list aps[10]; + va_start (aps[4], i); + bar (i); + va_end (aps[4]); +} +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f5 (int i, ...) +{ + va_list aps[10]; + va_start (aps[4], i); + foo (i, aps[4]); + va_end (aps[4]); +} +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +struct A { int i; va_list g; va_list h[2]; }; + +void +f6 (int i, ...) +{ + struct A a; + va_start (a.g, i); + x = va_arg (a.g, long); + va_end (a.g); +} +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f7 (int i, ...) +{ + struct A a; + va_start (a.g, i); + bar (i); + va_end (a.g); +} +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f8 (int i, ...) +{ + struct A a; + va_start (a.g, i); + foo (i, a.g); + va_end (a.g); +} +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f8: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f10 (int i, ...) +{ + struct A a; + va_start (a.h[1], i); + x = va_arg (a.h[1], long); + va_end (a.h[1]); +} +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f10: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f11 (int i, ...) +{ + struct A a; + va_start (a.h[1], i); + bar (i); + va_end (a.h[1]); +} +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f11: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f12 (int i, ...) +{ + struct A a; + va_start (a.h[1], i); + foo (i, a.h[1]); + va_end (a.h[1]); +} +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f12: va_list escapes 1, needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ +/* { dg-final { cleanup-tree-dump "stdarg" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c new file mode 100644 index 000000000..d0e47e18b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-4.c @@ -0,0 +1,94 @@ +/* First dg-final line after each function is for architectures that use + a struct {...} va_list[1] with separate GPR and FPR counters in the + structure. Second dg-final line is for architectures that use void * + or char * va_list. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-stdarg" } */ + +#include <stdarg.h> + +extern void foo (int, va_list); +extern void bar (int); +long x; +double d; + +/* Here va_arg can be executed more than once for one va_start. All GPR + registers needs to be saved. */ +void +f1 (int i, ...) +{ + va_list ap; + va_start (ap, i); + while (i-- > 0) + x = va_arg (ap, long); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f2 (int i, ...) +{ + va_list ap; + va_start (ap, i); + while (i-- > 0) + d = va_arg (ap, double); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save 0 GPR units and all FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes \[01\], needs to save all GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +/* Here va_arg can be executed at most as many times as va_start. + Only one GPR needs to be saved. */ +void +f3 (int i, ...) +{ + va_list ap; + int j = i; + while (j-- > 0) + { + va_start (ap, i); + x = va_arg (ap, long); + va_end (ap); + bar (x); + } +} +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units and 0 FPR units" "stdarg" { target { powerpc*-*-linux* && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 8 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 1 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ + +void +f4 (int i, ...) +{ + va_list ap; + int j = i; + while (j-- > 0) + { + va_start (ap, i); + d = va_arg (ap, double); + va_end (ap); + bar (d + 2.5); + } +} +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and \[1-9\]\[0-9\]* FPR units" "stdarg" { target { powerpc*-*-linux* && { powerpc_fprs && ilp32 } } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 8 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 0 GPR units and 1 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && ilp32 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target ia64-*-* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save \[148\] GPR units" "stdarg" { target { powerpc*-*-* && lp64 } } } } */ +/* { dg-final { cleanup-tree-dump "stdarg" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c new file mode 100644 index 000000000..08f278725 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/stdarg-5.c @@ -0,0 +1,119 @@ +/* This test has architecture specific function passing details. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-stdarg" } */ + +#include <stdarg.h> + +extern void foo (int, va_list); +extern void bar (int); +struct S1 { int i; double d; int j; double e; } s1; +struct S2 { double d; long i; } s2; +int y; +_Complex int ci; +_Complex double cd; + +/* Here va_arg can be executed more than once for one va_start. */ +void +f1 (int i, ...) +{ + va_list ap; + va_start (ap, i); + while (i-- > 0) + s1 = va_arg (ap, struct S1); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f1: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ + +void +f2 (int i, ...) +{ + va_list ap; + va_start (ap, i); + while (i-- > 0) + s2 = va_arg (ap, struct S2); + va_end (ap); +} +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and all FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f2: va_list escapes 0, needs to save all GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ + +/* Here va_arg can be executed at most as many times as va_start. */ +void +f3 (int i, ...) +{ + va_list ap; + int j = i; + while (j-- > 0) + { + va_start (ap, i); + s1 = va_arg (ap, struct S1); + va_end (ap); + bar (s1.i); + } +} +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 0 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 32 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f3: va_list escapes 0, needs to save 1 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ + +void +f4 (int i, ...) +{ + va_list ap; + int j = i; + while (j-- > 0) + { + va_start (ap, i); + s2 = va_arg (ap, struct S2); + y = va_arg (ap, int); + va_end (ap); + bar (s2.i); + } +} +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 16 GPR units and 16 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 24 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f4: va_list escapes 0, needs to save 2 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ + +void +f5 (int i, ...) +{ + va_list ap; + va_start (ap, i); + ci = va_arg (ap, _Complex int); + ci += va_arg (ap, _Complex int); + va_end (ap); + bar (__real__ ci + __imag__ ci); +} +/* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 16 GPR units and 0 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save 32 GPR units and 1" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f5: va_list escapes 0, needs to save (4|2) GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ + +void +f6 (int i, ...) +{ + va_list ap; + va_start (ap, i); + ci = va_arg (ap, _Complex int); + cd = va_arg (ap, _Complex double); + va_end (ap); + bar (__real__ ci + __imag__ cd); +} +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 8 GPR units and 32 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save 32 GPR units and 3" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f6: va_list escapes 0, needs to save (3|2) GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ + +void +f7 (int i, ...) +{ + va_list ap; + va_start (ap, i); + cd = va_arg (ap, _Complex double); + cd += va_arg (ap, _Complex double); + va_end (ap); + bar (__real__ cd + __imag__ cd); +} +/* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 0 GPR units and 64 FPR units" "stdarg" { target { { i?86-*-* x86_64-*-* } && lp64 } } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 32 GPR units and 2" "stdarg" { target alpha*-*-linux* } } } */ +/* { dg-final { scan-tree-dump "f7: va_list escapes 0, needs to save 2 GPR units and 0 FPR units" "stdarg" { target s390*-*-linux* } } } */ +/* { dg-final { cleanup-tree-dump "stdarg" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-1.c b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-1.c new file mode 100644 index 000000000..87b44b530 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre-details" } */ + +struct S { float f; }; +int __attribute__((noinline)) +foo (float *r, struct S *p) +{ + int *q = (int *)&p->f; + int i = *q; + *r = 0.0; + return i + *q; +} + +/* { dg-final { scan-tree-dump "Replaced\[^\n\]*with i_." "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c new file mode 100644 index 000000000..5acf083c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/struct-aliasing-2.c @@ -0,0 +1,19 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-fre" } */ + +struct S { unsigned f; }; + +int +foo ( struct S *p) +{ + int *q = (int *)&p->f; + int i = *q; + return i + p->f; +} + + +/* There should only be one load of p->f because fwprop can change + *(int *)&p->f into just (int)p->f. */ +/* { dg-final { scan-tree-dump-times "= \[^\n\]*p_.\\\(D\\\)" 1 "fre" } } */ +/* { dg-final { cleanup-tree-dump "fre" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/structopt-1.c b/gcc/testsuite/gcc.dg/tree-ssa/structopt-1.c new file mode 100644 index 000000000..75183052e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/structopt-1.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-lim-details" } */ +int x; int y; +struct { int x; int y; } global; +int foo() { + int i; + for ( i=0; i<10; i++) + y += x*x; + for ( i=0; i<10; i++) + global.y += global.x*global.x; +} + +/* { dg-final { scan-tree-dump-times "Executing store motion of global.y" 1 "lim1" } } */ +/* XXX: We should also check for the load motion of global.x, but there is no easy way to do this. */ +/* { dg-final { cleanup-tree-dump "lim\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/structopt-2.c b/gcc/testsuite/gcc.dg/tree-ssa/structopt-2.c new file mode 100644 index 000000000..b4d28257e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/structopt-2.c @@ -0,0 +1,46 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized -fno-tree-sra" } */ + +/* Even without SRA being enabled, we should be able to eliminate every structure store and load here. */ +extern void foo (const int); +int main(void) +{ + struct a + { + int e; + int f; + int g; + } a; + struct a b; + int x, c; + a.e = 50; + a.f = 9; + a.g = a.e * a.f; + foo (a.f); + foo (a.g); + x = a.f; + c = a.e; + foo (x); + foo (c); + a.e = 5; + a.f = 40; + a.g = 90; + foo (a.e); + foo (a.f); + foo (a.g); + c = a.f; + foo (c); + b.e = 9; + a.e = b.e + 1 * c; + a.f = 30; + foo (a.e); + foo (a.f); + x = a.e * a.f; + foo (x); + +} +/* { dg-final { scan-tree-dump-times "a.e" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "a.f" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "a.g" 0 "optimized" } } */ +/* { dg-final { scan-tree-dump-times "b.e" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/structopt-3.c b/gcc/testsuite/gcc.dg/tree-ssa/structopt-3.c new file mode 100644 index 000000000..a7fcb5bf8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/structopt-3.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +struct foo +{ + int a; + int b; +} temp; +/* We should be able to optimize this to return 11. */ +int main(void) +{ + temp.a = 5; + temp.b = 6; + return temp.a + temp.b; +} +/* { dg-final { scan-tree-dump-times "return 11" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-1.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-1.c new file mode 100644 index 000000000..422ee2d7b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-1.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-tailc-details" } */ +extern void *alloca (__SIZE_TYPE__); +int q(int a); +int *v; +int +t(int a) +{ + int r,r1; + if (a) + r1=r = q(a-1); + else + return 0; + /* Dead alloca should not disturb us. */ + if (r!=r1) + v=alloca(r); + return r; +} +/* { dg-final { scan-tree-dump-times "Found tail call" 1 "tailc"} } */ +/* { dg-final { cleanup-tree-dump "tailc" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-2.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-2.c new file mode 100644 index 000000000..bd9a85354 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-2.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-tailc-details" } */ +/* Test provided by Richard Earnshaw in PR 14312. */ + +void bar (int i); +void baz (int *); + +void +foo (int *x) +{ + if (*x < 0) + { + baz (x); + return; + } + bar (*x); +} + +/* The test has no local call-clobbered variables. Only the memory + tag for 'x' is call-clobbered. And since tags are not real + variables, they ought to be ignored. There should be two tail + calls here. */ +/* { dg-final { scan-tree-dump-times "Found tail call" 2 "tailc"} } */ +/* { dg-final { cleanup-tree-dump "tailc" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-3.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-3.c new file mode 100644 index 000000000..4055bc3f5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-3.c @@ -0,0 +1,28 @@ +/* The return argument needs a type conversion which on some targets + (e.g. s390) needs additional code. So it is invalid to do tail + call optimization here. */ + +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + +long long __attribute__((noinline)) +foo () +{ + return 3; +} + +int __attribute__((noinline)) +boo () +{ + return foo (); +} + +int +main () +{ + if (boo () != 3) + abort (); +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-4.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-4.c new file mode 100644 index 000000000..e7983da31 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-4.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-tailc-details" } */ +/* PR tree-opt/37024 */ + +double doubleValue(); + +long +longValue () +{ + return (long) doubleValue (); +} + +/* We should not tail call doubleValue in longValue as the mode changes. */ +/* { dg-final { scan-tree-dump-times "Found tail call" 0 "tailc"} } */ +/* { dg-final { cleanup-tree-dump "tailc" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-5.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-5.c new file mode 100644 index 000000000..7aa433ecf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-5.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-tailc" } */ + +void +set_integer (void *dest, int value, int length) +{ + int tmp = value; + __builtin_memcpy (dest, (void *) &tmp, length); +} + +/* { dg-final { scan-tree-dump-not "tail call" "tailc" } } */ +/* { dg-final { cleanup-tree-dump "tailc" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailcall-6.c b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-6.c new file mode 100644 index 000000000..4997f9b83 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailcall-6.c @@ -0,0 +1,33 @@ +/* PR tree-optimization/43904. */ +/* { dg-do run } */ +/* { dg-options "-O1 -foptimize-sibling-calls" } */ + +typedef __SIZE_TYPE__ size_t; +extern void abort(void); + +void *memcpy(void *dest, const void *src, size_t n); + +void +buggy_init(void *ptr, size_t size) +{ + const char *str = "Hello world!"; + memcpy(ptr, &str, size); +} + +void +expose_bug(void *ptr, size_t size) +{ + const char *str; + memcpy(&str, ptr, size); + if (*str != 'H') + abort (); +} + +int +main() +{ + const char *ptr; + buggy_init(&ptr, sizeof(ptr)); + expose_bug(&ptr, sizeof(ptr)); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-1.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-1.c new file mode 100644 index 000000000..ba9a0d65e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-1.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr-details" } */ +int +t(int a) +{ + if (a) + return t(a-1); + else + return 0; +} +/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 1 "tailr1"} } */ +/* { dg-final { cleanup-tree-dump "tailr\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-2.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-2.c new file mode 100644 index 000000000..b5fee4d59 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-2.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr-details" } */ +int +t(char *a) +{ + static char p[100]; + if (a) + return t(p); + else + return 0; +} +/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 1 "tailr1"} } */ +/* { dg-final { cleanup-tree-dump "tailr\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-3.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-3.c new file mode 100644 index 000000000..f14140355 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-3.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr-details" } */ +int +t(int a) +{ + int r; + if (a) + r = t(a-1); + else + return 0; + if (r) + r=r; + return r; +} +/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 1 "tailr1"} } */ +/* { dg-final { cleanup-tree-dump "tailr\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-4.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-4.c new file mode 100644 index 000000000..d89739f3a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-4.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr-details" } */ +int +t(int a) +{ + int r; + if (a&1) + r = t(a-1); + else if (a) + r = t(a-2); + else + return 0; + if (r) + r=r; + return r; +} +/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 2 "tailr1"} } */ +/* { dg-final { cleanup-tree-dump "tailr\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-5.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-5.c new file mode 100644 index 000000000..53a2cdb15 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-5.c @@ -0,0 +1,77 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-optimized" } */ + +extern void abort (void); +extern void exit (int); + +int sum (int n) +{ + if (n == 0) + return 0; + + return n + sum (n - 1); +} + +int fac (int n) +{ + if (n == 0) + return 1; + + return n * fac (n - 1); +} + +int sq_sum (int n) +{ + if (n == 0) + return 0; + + return n * n + sq_sum (n - 1); +} + +int pow2m1 (int n) +{ + if (n == 0) + return 0; + + return 2 * pow2m1 (n - 1) + 1; +} + +int fib (int n) +{ + if (n <= 1) + return 1; + + return fib (n - 2) + fib (n - 1); +} + +int main(void) +{ + if (sum (5) != 15) + abort (); + + if (fac (5) != 120) + abort (); + + if (sq_sum (5) != 55) + abort (); + + if (pow2m1 (5) != 31) + abort (); + + if (fib (5) != 8) + abort (); + + exit (0); +} + +/* There is one call of sum in main and then 2 instances of the word in + ;; Function sum (sum) and one in the function header. */ +/* { dg-final { scan-tree-dump-times "\\msum\\M" 4 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "\\mfac\\M" 4 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "\\msq_sum\\M" 4 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "\\mpow2m1\\M" 4 "optimized"} } */ + +/* There is one recursive call to fib. */ +/* { dg-final { scan-tree-dump-times "\\mfib\\M" 5 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c new file mode 100644 index 000000000..37942752a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-6.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-tailr-details" } */ +int +foo (int a) +{ + if (a) + return a * (2 * (foo (a - 1))) + a + 1; + else + return 0; +} +/* { dg-final { scan-tree-dump-times "Eliminated tail recursion" 1 "tailr1"} } */ +/* { dg-final { cleanup-tree-dump "tailr\[1-2\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-7.c b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-7.c new file mode 100644 index 000000000..875a6aa78 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tailrecursion-7.c @@ -0,0 +1,40 @@ +/* { dg-do run } */ +/* { dg-options "-O1 -foptimize-sibling-calls -fdump-tree-optimized" } */ + +extern void abort (void); +extern void exit (int); + +int foo (int n) +{ + return n == 0 ? 1 : n * (n - foo (n - 1)); +} + +int bar (int n) +{ + return n == 0 ? 1 : n * (- bar (n - 1)); +} + +int baz (int n, int m) +{ + return n == 0 ? 100 : (baz (n - 1, m) - m); +} + +int main (void) +{ + if (foo (6) != 726) + abort (); + + if (bar (7) != -5040) + abort (); + + if (baz (10, 5) != 50) + abort (); + + exit (0); +} + +/* { dg-final { scan-tree-dump-times "\\mfoo\\M" 4 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "\\mbar\\M" 4 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "\\mbaz\\M" 4 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/tree-ssa.exp b/gcc/testsuite/gcc.dg/tree-ssa/tree-ssa.exp new file mode 100644 index 000000000..14225223a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/tree-ssa.exp @@ -0,0 +1,36 @@ +# Copyright (C) 1997,2002,2003, 2007 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with GCC; see the file COPYING3. If not see +# <http://www.gnu.org/licenses/>. + +# GCC testsuite that uses the `dg.exp' driver. + +# Load support procs. +load_lib gcc-dg.exp + +# If a testcase doesn't have special options, use these. +global DEFAULT_CFLAGS +if ![info exists DEFAULT_CFLAGS] then { + set DEFAULT_CFLAGS " -ansi -pedantic-errors" +} + +# Initialize `dg'. +dg-init + +# Main loop. +dg-runtest [lsort [glob -nocomplain $srcdir/$subdir/*.\[cS\]]] \ + "" $DEFAULT_CFLAGS + +# All done. +dg-finish diff --git a/gcc/testsuite/gcc.dg/tree-ssa/unreachable.c b/gcc/testsuite/gcc.dg/tree-ssa/unreachable.c new file mode 100644 index 000000000..279a27770 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/unreachable.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-optimized" } */ +static void bad_boy() +{ +} +int +main() +{ + void *t=(void *)bad_boy; + if (!t) + return 1; + return 0; +} +/* { dg-final { scan-tree-dump-not "bad_boy" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/upcast-1.c b/gcc/testsuite/gcc.dg/tree-ssa/upcast-1.c new file mode 100644 index 000000000..12c2b91ba --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/upcast-1.c @@ -0,0 +1,12 @@ +/* { do-go compile } */ +/* { dg-options "-fdump-tree-gimple" } */ + +typedef struct { int i; } Foo; +Foo foo; +Foo *bar(void) +{ + return (Foo *)&foo.i; +} + +/* { dg-final { scan-tree-dump "&foo;" "gimple" } } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c b/gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c new file mode 100644 index 000000000..dafd44bb9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/update-cunroll.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ +int a[8]; +int t() +{ + int i; + for (i = 0; i < 3; i++) + if (a[i]) + break; + return i; +} +/* { dg-final { scan-tree-dump-times "Invalid sum" 0 "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c b/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c new file mode 100644 index 000000000..58b26e615 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/update-threading.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +typedef struct { unsigned short a; } A; + +extern void abort (void); +extern void exit (int); + +void foo (unsigned int x) +{ + if (x != 0x800 && x != 0x810) + abort (); +} + +int +main (int argc, char **argv) +{ + int i; + for (i = 0; i < 2; ++i) + foo (((A) { ((!(i >> 4) ? 8 : 64 + (i >> 4)) << 8) + (i << 4) } ).a); + exit (0); +} +/* { dg-final { scan-tree-dump-times "Invalid sum" 0 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/update-unroll-1.c b/gcc/testsuite/gcc.dg/tree-ssa/update-unroll-1.c new file mode 100644 index 000000000..d911dd8e5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/update-unroll-1.c @@ -0,0 +1,22 @@ +/* { dg-do compile { target i?86-*-* x86_64-*-* } } */ +/* { dg-require-effective-target ilp32 } */ +/* { dg-options "-O1 -fprefetch-loop-arrays -march=athlon -fdump-tree-aprefetch-blocks" } */ + +int a[10000]; + +int foo(unsigned n) +{ + unsigned i, s = 0; + + for (i = 0; i < n; i++) + s += a[i]; + + return s; +} + +/* We used to make the probability that the body of the loop (unrolled + to enable prefetching) is entered 0, which is not correct. */ + +/* { dg-final { scan-tree-dump-not "Invalid sum" "aprefetch"} } */ +/* { dg-final { scan-tree-dump-not "SUCC: 7 .100.0%" "aprefetch"} } */ +/* { dg-final { cleanup-tree-dump "aprefetch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/update-unswitch-1.c b/gcc/testsuite/gcc.dg/tree-ssa/update-unswitch-1.c new file mode 100644 index 000000000..499b78b01 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/update-unswitch-1.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -funswitch-loops -fdump-tree-unswitch-blocks" } */ + +int bla(int p) +{ + unsigned i, s = 1; + + for (i = 4; i < 100; i++) + { + if (p) + s += i/2; + else + s *= i/2; + } + + return s; +} + +/* We used to make the probability that the first of the loops created + by unswitching is entered 100%, which is not correct. */ + +/* { dg-final { scan-tree-dump-not "Invalid sum" "unswitch"} } */ +/* { dg-final { scan-tree-dump-not "SUCC: 3 .100.0%" "unswitch"} } */ +/* { dg-final { cleanup-tree-dump "unswitch" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/useless-1.c b/gcc/testsuite/gcc.dg/tree-ssa/useless-1.c new file mode 100644 index 000000000..68eab7004 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/useless-1.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -fdump-tree-gimple" } */ + +void +foo (void) +{ + int i, a; + for (i = 0; i < 10; i++) + { a = i; } +} + +/* There should be three gotos in the dump. If one was removed + in the loop exit condition, it would be re-introduced during + GIMPLE lowering, at the cost of an extra statement, label, + and basic block. */ +/* { dg-final { scan-tree-dump-times "goto" 3 "gimple"} } */ +/* { dg-final { cleanup-tree-dump "gimple" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-1.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-1.c new file mode 100644 index 000000000..6fe0e872b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-1.c @@ -0,0 +1,33 @@ +/* { dg-do compile } */ +/* { dg-options "-w -O1 -fdump-tree-gimple" } */ +/* { dg-options "-w -O1 -fdump-tree-gimple -msse" { target { i?86-*-* x86_64-*-* } } } */ + + +/* We should be able to produce a BIT_FIELD_REF for each of these vector access. */ +#define vector __attribute__((vector_size(16))) +float f0(vector float t) +{ + return ((float*)&t)[0]; +} + +float f1(vector float t) +{ + return ((float*)&t)[1]; +} + +float f2(vector float t) +{ + return ((float*)&t)[2]; +} + +float f3(vector float t) +{ + return ((float*)&t)[3]; +} + + +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 4 "gimple"} } */ + +/* { dg-final { cleanup-tree-dump "gimple" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-2.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-2.c new file mode 100644 index 000000000..e34532d3f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-2.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-w -O1 -fdump-tree-optimized" } */ +/* { dg-options "-w -O1 -fdump-tree-optimized -msse" { target { i?86-*-* x86_64-*-* } } } */ + +#define vector __attribute__(( vector_size(16) )) + +float f(vector float a, int b, vector float c) +{ + vector float dd = c*a; + a = (vector float){0,0,0,0}; + c = (vector float){0,0,0,0}; + { + float d = ((float*)&a)[0]; + float d1 = ((float*)&c)[0]; + return d*d1; + } +} + +/* We should be able to optimize this to just "return 0.0;" */ +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "0.0" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c b/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c new file mode 100644 index 000000000..15a700c65 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vector-3.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-w -O1 -fdump-tree-optimized" } */ + +#define vector __attribute((vector_size(16) )) +vector float a; + +float f(float b) +{ + vector float c = {0, 0, 0, 0}; + vector float d = {0, 0, 0, 0}; + d += c; + return ((float*)&c)[2]; +} + +/* We should be able to optimize this to just "return 0.0;" */ +/* { dg-final { scan-tree-dump-times "BIT_FIELD_REF" 0 "optimized"} } */ +/* { dg-final { scan-tree-dump-times "0.0" 1 "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c new file mode 100644 index 000000000..3f8e82061 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp01.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +foo (int *p, int i) +{ + int x; + + if (i > 10) + { + if (p) + { + x = *p; + p = 0; + } + } + else + p = 0; + + /* This should be folded to if (1), but only if we insert an + assertion on the ELSE edge from the inner 'if (p)'. */ + if (p == 0) + return x + 1; + + return i; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c new file mode 100644 index 000000000..56fca9711 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp02.c @@ -0,0 +1,25 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +struct A +{ + int a; + int b; +}; + +foo (struct A *p, struct A *q) +{ + int x = p->a; + if (p == q) + return q->a; + + /* We should fold this to 'if (1)' but the assertion for 'p == q' + was overwriting the assertion 'p != 0' from the first dereference + of 'p'. */ + if (p) + return x + p->b; +} +/* Target with fno-delete-null-pointer-checks should not fold check */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c new file mode 100644 index 000000000..9b7c08256 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp03.c @@ -0,0 +1,35 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +struct A +{ + int a; + int b; +}; + +foo (struct A *p, struct A *q) +{ + int *r = 0; + + if (p) + { + if (p == q) + { + /* This should be folded to 'if (1)' because q is [p, p] + and p is ~[0, 0]. */ + if (q) + r = &q->a; + + /* This should be folded to 'if (1)' because q should be + ~[0, 0] and thus &q->a should be ~[0, 0]. */ + if (r) + return 5; + } + } + + return q->a; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate q_.*to 1" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate r_.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c new file mode 100644 index 000000000..bf5d683cb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp04.c @@ -0,0 +1,13 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +foo (int a, int b) +{ + if (a == b) + /* This should be folded to if (1) */ + if (a == b) + return a + b; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate a_.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c new file mode 100644 index 000000000..7b8b61b44 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp05.c @@ -0,0 +1,30 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining" } */ + + +inline int ten() +{ + return 10; +} +inline int zero() +{ + return 0; +} + +foo (int k, int j) +{ + if (k >= ten()) + { + if (j > k) + { + /* We should fold this to if (1). */ + if (j > zero()) + return j; + } + } + + return j+1; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c new file mode 100644 index 000000000..1ef6c922e --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp06.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +foo (int i, int j, int a) +{ + if (i >= 10) + if (i <= 30) + if (i == j) + { + a--; + + /* This should fold to 'if (0)'. */ + if (i < 0) + i = baz (); + + /* This should fold to 'if (1)'. */ + if (j > 0) + a--; + + /* This should fold to 'if (0)'. */ + if (i != j) + return 0; + } + + return i + a + j; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate j_.*to 1" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate i_.*to 0" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c new file mode 100644 index 000000000..6584919b5 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp07.c @@ -0,0 +1,39 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + +foo (int i, int *p) +{ + int j; + + if (i > 10) + { + if (p) + { + j = *p; + /* This should be folded to if (1) because of the parent 'if + (p)'. But the dereference of p above does not need an + assertion. */ + if (p) + return j + 1; + } + } + else + { + j = *p - 3; + /* This should be folded to if (0), because p has just been + dereferenced. But we were not inserting enough ASSERT_EXPRs + to figure it out. */ + if (!p) + return j - 4; + } + + return i; +} +/* Target with fno-delete-null-pointer-checks should not fold checks */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 0" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 0" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ + +/* { dg-final { scan-tree-dump-times "PREDICATE: p_\[0-9\]" 2 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "PREDICATE: p_\[0-9\]" 1 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c new file mode 100644 index 000000000..193199fbf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp08.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fno-tree-fre -fdump-tree-vrp1-details" } */ + +/* Compile with -fno-tree-fre -O2 to prevent CSEing *p. */ +foo (int a, int *p) +{ + int x = *p + 2; + int y = *p - 1; + int z = *p + 9; + + /* This should be folded to if (1), but only one ASSERT_EXPR should + be inserted. */ + if (p) + a = x + y + z; + else + a = x - y; + + return a; +} +/* Target with fno-delete-null-pointer-checks should not fold checks */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "PREDICATE: p_.* ne_expr 0" 1 "vrp1" { target { ! keeps_null_pointer_checks } } } } */ +/* { dg-final { scan-tree-dump-times "Folding predicate p_.*to 1" 0 "vrp1" { target { keeps_null_pointer_checks } } } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c new file mode 100644 index 000000000..9ff0f14f7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp09.c @@ -0,0 +1,31 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +foo (int *p) +{ + int x = baz (); + + if (p == 0) + goto L78; + else + { + x = *p; + /* This should be folded to if (1). */ + if (p) + x = x + 1; +L78: + /* This should not be folded to if (1). */ + if (p) + { + x = baz (*p); + /* This should be folded to if (1). */ + if (p) + return x + 3; + } + + return x - 3; + } +} + +/* { dg-final { scan-tree-dump-times "Folding predicate p_.. != 0B to 1" 2 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c new file mode 100644 index 000000000..5a7458459 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp10.c @@ -0,0 +1,25 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +extern void abort (void); + +foo (int k, int j) +{ + if (k >= 10) + { + if (j > k) + { + /* We should fold this to if (0). */ + if (j < 10) + abort (); + } + } + + return j; +} + +main() +{ + foo (10, 3); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c new file mode 100644 index 000000000..591507c22 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp11.c @@ -0,0 +1,26 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fno-early-inlining" } */ + +inline int +bounce (int arg) +{ + return arg; +} + +foo (int k, int j, int z) +{ + if (k > z) + { + if (j > k) + { + /* We should fold this to if (1). */ + if (j > bounce (z)) + return j; + } + } + + return j+1; +} + +/* { dg-final { scan-tree-dump-times "Folding predicate.*to 1" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c new file mode 100644 index 000000000..1714a561c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp12.c @@ -0,0 +1,23 @@ +/* { dg-do link } */ +/* { dg-options -O2 } */ + +foo (int i) +{ + int x; + + x = i; + if (i < -10) + { + x = __builtin_abs (i); + /* VRP was incorrectly folding this to if (1). */ + if (x < 0) + link_error (); + } + + return x; +} + +main() +{ + foo (-30); +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c new file mode 100644 index 000000000..4b3afdbc8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp13.c @@ -0,0 +1,258 @@ +/* { dg-do run } */ +/* { dg-options -O2 } */ + +extern void abort (void); + +foo_div (int i, int j) +{ + int k; + + /* [-INF, -1] / [1, +INF] should not give [-1, -1]. */ + if (i <= -1) + if (j >= 1) + { + k = i / j; + if (k == -1) + abort (); + + return k; + } + + /* [-20, -10] / [2, 10] should give [-10, -1]. */ + if (i >= -20) + if (i <= -10) + if (j >= 2) + if (j <= 10) + { + k = i / j; + if (k < -10) + link_error (); + if (k > -1) + link_error (); + + return k; + } + + /* [-20, -10] / [-10, -2] should give [1, 10]. */ + if (i >= -20) + if (i <= -10) + if (j >= -10) + if (j <= -2) + { + k = i / j; + if (k < 1) + link_error (); + if (k > 10) + link_error (); + + return k; + } + + /* [-20, 10] / [2, 10] should give [-10, 5]. */ + if (i >= -20) + if (i <= 10) + if (j >= 2) + if (j <= 10) + { + k = i / j; + if (k < -10) + link_error (); + if (k > 5) + link_error (); + + return k; + } + + /* [-20, 10] / [-10, -2] should give [-5, 10]. */ + if (i >= -20) + if (i <= 10) + if (j >= -10) + if (j <= -2) + { + k = i / j; + if (k < -5) + link_error (); + if (k > 10) + link_error (); + + return k; + } + + /* [10, 20] / [2, 10] should give [1, 10]. */ + if (i >= 10) + if (i <= 20) + if (j >= 2) + if (j <= 10) + { + k = i / j; + if (k < 1) + link_error (); + if (k > 10) + link_error (); + + return k; + } + + /* [10, 20] / [-10, -2] should give [-10, -1]. */ + if (i >= 10) + if (i <= 20) + if (j >= -10) + if (j <= -2) + { + k = i / j; + if (k > -1) + link_error (); + if (k < -10) + link_error (); + + return k; + } + + abort (); +} + + +foo_mult (int i, int j) +{ + int k; + + /* [-20, -10] * [2, 10] should give [-200, -20]. */ + if (i >= -20) + if (i <= -10) + if (j >= 2) + if (j <= 10) + { + k = i * j; + if (k < -200) + link_error (); + if (k > -20) + link_error (); + + return k; + } + + /* [-20, -10] * [-10, -2] should give [20, 200]. */ + if (i >= -20) + if (i <= -10) + if (j >= -10) + if (j <= -2) + { + k = i * j; + if (k < 20) + link_error (); + if (k > 200) + link_error (); + + return k; + } + + /* [-20, 10] * [2, 10] should give [-200, 100]. */ + if (i >= -20) + if (i <= 10) + if (j >= 2) + if (j <= 10) + { + k = i * j; + if (k < -200) + link_error (); + if (k > 100) + link_error (); + + return k; + } + + /* [-20, 10] * [-10, -2] should give [-100, 200]. */ + if (i >= -20) + if (i <= 10) + if (j >= -10) + if (j <= -2) + { + k = i * j; + if (k < -100) + link_error (); + if (k > 200) + link_error (); + + return k; + } + + /* [10, 20] * [2, 10] should give [20, 200]. */ + if (i >= 10) + if (i <= 20) + if (j >= 2) + if (j <= 10) + { + k = i * j; + if (k < 20) + link_error (); + if (k > 200) + link_error (); + + return k; + } + + /* [10, 20] * [-10, -2] should give [-200, -20]. */ + if (i >= 10) + if (i <= 20) + if (j >= -10) + if (j <= -2) + { + k = i * j; + if (k < -200) + link_error (); + if (k > -20) + link_error (); + + return k; + } + + abort (); +} + + +main() +{ + if (foo_div (-10, 5) != -2) + abort (); + + if (foo_div (-16, 4) != -4) + abort (); + + if (foo_div (-15, -5) != 3) + abort (); + + if (foo_div (8, 2) != 4) + abort (); + + if (foo_div (10, -2) != -5) + abort (); + + if (foo_div (20, 5) != 4) + abort (); + + if (foo_div (15, -3) != -5) + abort (); + + if (foo_mult (-10, 5) != -50) + abort (); + + if (foo_mult (-16, 4) != -64) + abort (); + + if (foo_mult (-15, -5) != 75) + abort (); + + if (foo_mult (8, 2) != 16) + abort (); + + if (foo_mult (10, -2) != -20) + abort (); + + if (foo_mult (20, 5) != 100) + abort (); + + if (foo_mult (15, -3) != -45) + abort (); + + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp14.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp14.c new file mode 100644 index 000000000..a65d8a16d --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp14.c @@ -0,0 +1,47 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +/* { dg-require-effective-target int32plus } */ + +struct tree_decl +{ + union tree_decl_u1 { + int f; + long i; + struct tree_decl_u1_a { + unsigned int align : 24; + unsigned int off_align : 8; + } a; + } u1; +}; + +extern void abort (void); + +unsigned int +assemble_variable (struct tree_decl decl) +{ + unsigned int align; + + align = decl.u1.a.align; + + if (align > (1 << ((8 * 4) < 64 ? (8 * 4) - 2 : 62))) + align = (1 << ((8 * 4) < 64 ? (8 * 4) - 2 : 62)); + + /* VRP should not be propagating 0 to the RHS of this assignment. + But it was erroneously applying a cast operation between types of + different precision. align is an unsigned int with range [0, + 0x4000000] but the .align field holds only 24 bits. So the cast + was returning a [0, 0] range. */ + decl.u1.a.align = align; + + return decl.u1.a.align; +} + +main () +{ + struct tree_decl decl; + decl.u1.a.align = 13; + unsigned int x = assemble_variable (decl); + if (x == 0) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp15.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp15.c new file mode 100644 index 000000000..7e7226487 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp15.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + + +extern void abort (void) __attribute__ ((__noreturn__)); +union tree_node; +typedef union tree_node *tree; +enum tree_code +{ + ERROR_MARK, + COND_EXPR = 42, +}; +extern const unsigned char tree_code_length[]; +struct tree_common +{ + enum tree_code code:8; +}; +union tree_node +{ + struct tree_common common; +}; +void +blah (tree t) +{ + if (t->common.code != COND_EXPR) + abort (); + if (1 >= tree_code_length[t->common.code]) + abort (); + +} + +/* { dg-final { scan-tree-dump-times "tree_code_length.42." 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c new file mode 100644 index 000000000..166529ab9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp16.c @@ -0,0 +1,23 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + + +extern void abort (void) __attribute__ ((__noreturn__)); +struct rtx_def; +typedef struct rtx_def *rtx; +struct rtx_def +{ + int code; +}; +int +nonlocal_mentioned_p (rtx x) +{ + if (x->code == 6 || x->code == 7) + if (x->code == 7) + if (x->code != 7) + abort (); +} + +/* { dg-final { scan-tree-dump-times "Folding predicate .*to 0" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c new file mode 100644 index 000000000..c04b9ba78 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp17.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void abort (void) __attribute__ ((__noreturn__)); +union tree_node; +typedef union tree_node *tree; +extern const unsigned char tree_code_length[]; +struct tree_common +{ + int code; +}; +struct tree_exp +{ + tree operands[1]; +}; +union tree_node +{ + struct tree_common common; + struct tree_exp exp; +}; +int +gimplify_for_stmt (tree stmt) +{ + if (2 >= tree_code_length[stmt->common.code]) + abort (); + if (3 >= tree_code_length[stmt->common.code]) + abort (); +} + +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c new file mode 100644 index 000000000..a3cc536ae --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp18.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +static int blocksize = 4096; + +int bar (int); + +void foo (void) +{ + int toread; + int bytes; + static char eof_reached = 0; + + toread = blocksize; + bytes = 1; + + while (toread != 0) + { + bytes = bar (toread); + if (bytes <= 0) + { + if (bytes < 0) + continue; + break; + } + toread -= bytes; + } + + if (bytes == 0) + eof_reached = 1; +} + +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp19.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp19.c new file mode 100644 index 000000000..e4c884a85 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp19.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp1" } */ + +#include <limits.h> +extern void abort (); +extern void exit (int); + +int f (int a) { + if (a != INT_MIN) { + a = a > 0 ? a : -a; + if (a < 0) + return 1; + } + return 0; +} + +int g (int b) { + if (b != INT_MIN) { + b = b > 0 ? b : -b; + if (b >= 0) + return 0; + } + return 1; +} +/* { dg-final { scan-tree-dump "Folding predicate a_. < 0 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate b_. >= 0 to 1" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c new file mode 100644 index 000000000..14da7df48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp20.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-fwrapv -O1 -ftree-vrp -fdump-tree-vrp1" } */ + +extern void abort (); +extern void exit (int); + +int f (int a) { + if (a != 0) { + a = a > 0 ? a : -a; + if (a == 0) + return 1; + return 0; + } + return 0; +} + +int g (int b) { + if (b != 0) { + b = b > 0 ? b : -b; + if (b != 0) + return 0; + } + return 1; +} + +/* { dg-final { scan-tree-dump "Folding predicate a_. == 0 to 0" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate b_. != 0 to 1" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c new file mode 100644 index 000000000..9a4e4e783 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp21.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp1" } */ +/* { dg-require-effective-target int32plus } */ + +extern void link_error (); + +void test01(unsigned int a, unsigned int b) +{ + unsigned int x = 0x80000000; + if (a < x) + if (b < x) + if (a > 5) + if (a + b == 0U) + link_error (); +} + +void test02(unsigned int a, unsigned int b) +{ + unsigned int x = 0x80000000; + if (a > x) + if (b < x) + if (a - b == 1U) + link_error (); +} + +/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp22.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp22.c new file mode 100644 index 000000000..cbd4dc529 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp22.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O1 -ftree-vrp -fdump-tree-vrp1" } */ +/* { dg-require-effective-target int32plus } */ + +extern void link_error (); + +void test02(unsigned int a, unsigned int b) +{ + unsigned int x = 0x80000000; + if (a > x) + if (b < x) + if (a == b) + link_error (); +} + +/* { dg-final { scan-tree-dump-times "link_error" 0 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c new file mode 100644 index 000000000..77899a65f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp23.c @@ -0,0 +1,45 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + +blah (int code1, int code2) +{ + int i; + int n_sets; + + n_sets = (int) (code1 == 32); + if (code2 == 64) goto L2; else goto L3; + +L2: + aa (); + +L3: + if (n_sets > 1) goto L4; else goto L10; + +L4: + aos (); + i = 0; + goto L24; + +L10: + if (n_sets > 0) goto L25; else goto L8; + +L25: + i = 0; + +L24: + aob (); + i = i + 1; + if (i < n_sets) goto L24; else goto L8; + +L8: + return; +} + + + +/* The n_sets > 0 test can be simplified into n_sets == 1 since the + only way to reach the test is when n_sets <= 1, and the only value + which satisfies both conditions is n_sets == 1. */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c new file mode 100644 index 000000000..85e5b62d1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp24.c @@ -0,0 +1,91 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + + +struct rtx_def; +typedef struct rtx_def *rtx; +union rtunion_def +{ + rtx rt_rtx; +}; +typedef union rtunion_def rtunion; +struct rtx_def +{ + int code; + union u + { + rtunion fld[1]; + } u; +}; + +sss (rtx insn, int code1, int code2, int code3) +{ + _Bool D1562; + struct rtx_def * body; + int i; + int n_sets; + int D1544; + + body = insn->u.fld[5].rt_rtx; + D1544 = body->code; + n_sets = 1; + if (D1544 == 55) goto L7; else goto L1; + +L1: + n_sets = 0; + if (code3 == 99) goto L2; else goto L11; + +L2: + D1562 = code1 == 10; + n_sets = (int) D1562; + if (n_sets > 0) goto L7; else goto L11; + +L37: + if (code2 == 42) goto L8; else goto L9; + +L8: + arf (); + +L9: + i = i + 1; + if (i < n_sets) goto L37; else goto L32; + +L32: + +L11: + if (n_sets > 1) goto L12; else goto L15; + +L12: + nit (); + +L14: + i = 0; + goto L38; + +L15: + if (n_sets > 0) goto L14; else goto L16; + +L38: + frob (); + i = i + 1; + if (n_sets > i) goto L38; else goto L16; + +L16: + return; + +L7: + i = 0; + goto L37; + +} + +/* The first n_sets > 0 test can be simplfiied into n_sets == 1 since + n_sets can only have the values [0, 1] as it's the result of a + boolean operation. + + The second n_sets > 0 test can also be simplified into n_sets == 1 + as the only way to reach the tests is when n_sets <= 1 and the only + value which satisfies both conditions is n_sets == 1. */ +/* { dg-final { scan-tree-dump-times "Simplified relational" 2 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c new file mode 100644 index 000000000..fa8bbfd4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp25.c @@ -0,0 +1,52 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1-details" } */ + +extern void abort (); +int tree_code_length[100]; + +blah (int code1) +{ + unsigned char D18670; + + if (code1 != 53) goto L0; else goto L1; + +L0: + abort (); + +L1: + D18670 = tree_code_length[53]; + if (D18670 <= 1) goto L2; else goto L3; + +L2: + abort (); + +L3: + if (D18670 == 2) goto L4; else goto L5; + +L4: + abort (); + +L5: + arf (); + if (code1 != 53) goto L6; else goto L7; + +L6: + abort (); + +L7: + if (D18670 <= 2) goto L8; else goto L9; + +L8: + abort (); + +L9: + return; + +} + +/* The second test of (code1 != 53) and the test (D18670 <= 2) are + both totally subsumed by earlier tests and thus should be folded + away using VRP. */ +/* { dg-final { scan-tree-dump-times "Folding predicate" 2 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp26.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp26.c new file mode 100644 index 000000000..621541630 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp26.c @@ -0,0 +1,17 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int +foo(int a) +{ + int z = a | 1; + return z != 0; +} + +/* VRP should optimize this to a trivial "return 1". */ +/* { dg-final { scan-tree-dump-times "return 1" 1 "vrp1" } } * / +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + + + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp27.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp27.c new file mode 100644 index 000000000..09b96f919 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp27.c @@ -0,0 +1,33 @@ +/* PR middle-end/26361. */ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +void abort(void); + +__attribute__((noinline)) +void gen_rtx_CONST_INT(long long x) { + if (-x > 10) + abort(); +} +__attribute__((noinline)) +int alpha_expand_prologue(long frame_size) +{ + unsigned long long a; + int probed; + if (frame_size <= 1) return; + unsigned long long b = -2; + a = -2; + do { + int a1 = a; + probed = -a1; + gen_rtx_CONST_INT (a1); + a -= 2; + a1 = -a; + probed = a1; + } while (probed < frame_size); +} + +int main(void) { + alpha_expand_prologue(10); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp28.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp28.c new file mode 100644 index 000000000..6b2a1fd6b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp28.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int f(_Bool a) +{ + int t = a; + if (t != 2) + return 0; + return 1; +} + +int f1(unsigned char a) +{ + int t = a; + if (t != 256) + return 0; + return 1; +} + +int f3 (unsigned char c) +{ + int i = c; + if (i < 0 || i > 255) + return -1; + else + return 0; +} + +/* { dg-final { scan-tree-dump-times "if " 0 "vrp1" } } * / +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c new file mode 100644 index 000000000..0a370f7d8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp29.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ +#include <limits.h> + +extern void abort(void); + +void decCompareOp (int result) +{ + if (result != (int) (INT_MAX + 1U)) + { + result = -result; + if (result != (int) (INT_MAX + 2U)) + abort (); + } +} + +int main() +{ + decCompareOp (INT_MAX); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp30.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp30.c new file mode 100644 index 000000000..245dcfb74 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp30.c @@ -0,0 +1,30 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern int link_error (int); + +int tst2 (int x, int y) +{ + /* VRP should be able to extract range information for + x and y out of this TRUTH_AND_EXPR. */ + if ((x > 5555) && (y < 6666)) + { + if (x > 5555) + if (y < 6666) + return 1111; + else + return link_error (2222); + else + if (y < 6666) + return link_error (3333); + else + return link_error (4444); + } + else + return 0; +} + +int main() +{ + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp31.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp31.c new file mode 100644 index 000000000..5b4aa5db9 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp31.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int f(int i) +{ + int t = i == 1; + int g = t == 2; + int h = g == 3; + return h; +} + +/* { dg-final { scan-tree-dump "return 0;" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp32.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp32.c new file mode 100644 index 000000000..a42b3ca27 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp32.c @@ -0,0 +1,14 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int f(int i) +{ + _Bool t = !i; + int g = !t && i; + int h = g == 3; + return h; +} + +/* { dg-final { scan-tree-dump "return 0;" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c new file mode 100644 index 000000000..13f60a6e7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp33.c @@ -0,0 +1,9 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +/* This is from PR14052. */ + +int f2(int x) { return x == 1 || x == 3 || x == 1; } + +/* { dg-final { scan-tree-dump "Folding predicate.*== 1 to 0" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp34.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp34.c new file mode 100644 index 000000000..fd92eca65 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp34.c @@ -0,0 +1,20 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +void bar (void); + +void +foo (int a) +{ + switch (a) + { + case 4: + if (a >= 3) + if (a <= 5) + bar (); + } +} + +/* { dg-final { scan-tree-dump "Folding predicate a_. > 2 to 1" "vrp1" } } */ +/* { dg-final { scan-tree-dump "Folding predicate a_. <= 5 to 1" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c new file mode 100644 index 000000000..6402f4d22 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp35.c @@ -0,0 +1,15 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int test1(int i, int k) +{ + if (i > 0 && i <= 5 && k >= 10 && k < 42) + { + int j = i + 1 + k; + return j == 10; + } + return 1; +} + +/* { dg-final { scan-tree-dump-not "j_.* == 10" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c new file mode 100644 index 000000000..de300d727 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp36.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int foo(int i) +{ + if (i < 0 || i >= 5) + return i == 1; + return 1; +} + +/* { dg-final { scan-tree-dump-not "i_.* == 1" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp37.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp37.c new file mode 100644 index 000000000..fba35a48b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp37.c @@ -0,0 +1,12 @@ +/* { dg-do compile } */ +/* { dg-options "-O2" } */ + +unsigned char x; +int foo(void) +{ + unsigned long long i = x; + i = i + 0x80000000; + if (i > 0xffffffff) + return x; + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp38.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp38.c new file mode 100644 index 000000000..b740c6024 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp38.c @@ -0,0 +1,21 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int __attribute__((noinline)) +foo(char c) +{ + unsigned short a = (unsigned short)c; + if (a >= -32000 && a <= 32000) + return c == 0; + return -1; +} + +extern void abort (void); + +int main() +{ + if (foo(1) == 1) + abort (); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp39.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp39.c new file mode 100644 index 000000000..69329affb --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp39.c @@ -0,0 +1,18 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_error (void); + +void test1(int i) +{ + if (i >= -5 && i <= 8) + { + unsigned int j = i; + if (j == -6) + link_error (); + if (j == 9) + link_error (); + } +} + +int main() { return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp40.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp40.c new file mode 100644 index 000000000..23f080acf --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp40.c @@ -0,0 +1,18 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int f(int a) { + switch (a & 1) { + case 0: + case 1: return 3; + case 2: return 5; + case 3: return 7; + case 4: return 11; + case 5: return 13; + case 6: return 17; + case 7: return 19; + } +} + +/* { dg-final { scan-tree-dump "return 3;" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp41.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp41.c new file mode 100644 index 000000000..d573fbb0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp41.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +void bar0 (void); +void bar1 (void); +void bar2 (void); +void bar3 (void); + +void +foo (int a) +{ + if (a < 100) + return; + if (200 < a) + return; + + switch (a) + { + case 99: bar0 (); return; + case 100: bar1 (); return; + case 101: bar2 (); return; + case 102: bar3 (); return; + } +} + +/* { dg-final { scan-tree-dump-not "case 99:" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp42.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp42.c new file mode 100644 index 000000000..79eb22cb1 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp42.c @@ -0,0 +1,22 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -Wuninitialized" } */ + +int foo(int val) +{ + int tmp; + if ((val > 5) && (val < 8)) + { + switch (val) + { + case 6: + tmp = 1; + break; + case 7: + tmp = 2; + break; + } + return tmp; /* { dg-bogus "used uninitialized" } */ + } + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp43.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp43.c new file mode 100644 index 000000000..f475354dc --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp43.c @@ -0,0 +1,22 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +int __attribute__((noinline)) +foo(int i) +{ + if (i != 0) + { + char c = (char)i; + return c != 0; + } + return 0; +} + +extern void abort (void); + +int main() +{ + if (foo(0xff00)) + abort (); + return 0; +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp44.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp44.c new file mode 100644 index 000000000..a2df852c7 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp44.c @@ -0,0 +1,30 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_error (void); + +void test1(int i) +{ + if (i >= -5 && i <= 8) + { + unsigned int j = i + 1; + if (j == -5) + link_error (); + if (j == 10) + link_error (); + } +} + +void test2(unsigned int i) +{ + if (i >= -5 || i <= 8) + { + int j = i; + if (j == -6) + link_error (); + if (j == 9) + link_error (); + } +} + +int main() { return 0; } diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp45.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp45.c new file mode 100644 index 000000000..7916d2da8 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp45.c @@ -0,0 +1,19 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_error (void); + +void foo (int i) +{ + if (i > -128 && i < 127) + { + unsigned char k = i; + if (k == 0x80) + link_error (); + if (k == 0x7f) + link_error (); + } +} + +int main() { return 0; } + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp46.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp46.c new file mode 100644 index 000000000..a67e839de --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp46.c @@ -0,0 +1,28 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +void +func_18 ( int t ) +{ + unsigned l_889; + int l_895 = 1; + for (0; 1; ++l_889) + { + int t1 = 0; + if (func_81 (1)) + { + int rhs = l_895; + if (rhs == 0) + rhs = 1; + if (1 & (t % rhs)) + t1 = 1; + } + func_98 (t1); + l_895 = 0; + } +} + +/* There should be a single if left. */ + +/* { dg-final { scan-tree-dump-times "if" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c new file mode 100644 index 000000000..3def90c4c --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp47.c @@ -0,0 +1,48 @@ +/* Skip on MIPS, where LOGICAL_OP_NON_SHORT_CIRCUIT inhibits the setcc + optimizations that expose the VRP opportunity. */ +/* Skip on S/390 and avr. Lower values in BRANCH_COST lead to two conditional + jumps when evaluating an && condition. VRP is not able to optimize + this. */ +/* { dg-do compile { target { ! "mips*-*-* s390*-*-* avr-*-* mn10300-*-*" } } } */ +/* { dg-options "-O2 -fdump-tree-vrp -fdump-tree-dom" } */ +/* { dg-options "-O2 -fdump-tree-vrp -fdump-tree-dom -march=i586" { target { i?86-*-* && ilp32 } } } */ + +int h(int x, int y) +{ + if ((x >= 0 && x <= 1) && (y >= 0 && y <= 1)) + return x && y; + else + return -1; +} + +int g(int x, int y) +{ + if ((x >= 0 && x <= 1) && (y >= 0 && y <= 1)) + return x || y; + else + return -1; +} + +int f(int x) +{ + if (x != 0 && x != 1) + return -2; + + else + return !x; +} + +/* Test that x and y are never compared to 0 -- they're always known to be + 0 or 1. */ +/* { dg-final { scan-tree-dump-times "\[xy\]\[^ \]* !=" 0 "vrp1" } } */ + +/* This one needs more copy propagation that only happens in dom1. */ +/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "dom1" } } */ +/* { dg-final { scan-tree-dump-times "x\[^ \]* & y" 1 "vrp1" { xfail *-*-* } } } */ + +/* These two are fully simplified by VRP. */ +/* { dg-final { scan-tree-dump-times "x\[^ \]* \[|\] y" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "x\[^ \]* \\^ 1" 1 "vrp1" } } */ + +/* { dg-final { cleanup-tree-dump "vrp\[0-9\]" } } */ +/* { dg-final { cleanup-tree-dump "dom\[0-9\]" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp48.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp48.c new file mode 100644 index 000000000..a42346599 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp48.c @@ -0,0 +1,23 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_failure (void); + +static int __attribute__ ((noinline)) foo (int x) +{ + if (x >= 1) + if (x <= 10) + { + if (x < 1 || x > 10) + link_failure (); + x = x + 1; + } + return x; +} + +int main (void) +{ + int i = foo (0); + return 0; +} + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp49.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp49.c new file mode 100644 index 000000000..664ad93ef --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp49.c @@ -0,0 +1,28 @@ +/* { dg-do link } */ +/* { dg-options "-O2" } */ + +extern void link_error (void) __attribute__((noreturn)); +int n; +float *x; +int main() +{ + if (n > 0) + { + int i = 0; + do + { + long long index; + i = i + 1; + index = i; + if (index <= 0) + link_error (); + x[index] = 0; + i = i + 1; + index = i; + if (index <= 0) + link_error (); + x[index] = 0; + } + while (i < n); + } +} diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp50.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp50.c new file mode 100644 index 000000000..a5b3ee28f --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp50.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int +foo (unsigned int i, unsigned int j) +{ + i &= 15; + j &= 15; + i += 1024; + j += 2048; + i &= j; + return i < 16; +} + +int +bar (int i) +{ + int c = 2; + c &= i > 6; + return c == 0; +} + +int baz (int x, int y) +{ + x &= 15; + y &= 15; + x += 4; + y += 16; + x &= y; + return x < 20; +} + +/* { dg-final { scan-tree-dump-times "return 1;" 3 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c new file mode 100644 index 000000000..5f1cafb0a --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp51.c @@ -0,0 +1,58 @@ +/* PR tree-optimization/28632 */ +/* { dg-do compile } */ +/* { dg-options "-O2 -ftree-vrp" } */ + +void +v4 (unsigned a, unsigned b) +{ + if (a < 0x1000) return; + if (a > 0x1000) return; + if (b < 0x0110) return; + /* constant true. */ + if (!__builtin_constant_p ((a|b) >= 0x01000)) + __asm__("vrp.bug.always.true"); + /* VRP must not think that this is constant. */ + if (__builtin_constant_p ((a|b) >= 0x10000)) + __asm__("vrp.bug.not.always.true"); +} + +void +u4 (unsigned n) +{ + if (n > 0x10111) return; + if (n < 0x10101) return; + /* always true. */ + if (!__builtin_constant_p (n & 0x00100)) + __asm__("vrp.bug.always.true"); + /* VRP must not think that this is constant true. */ + if (__builtin_constant_p (n & 0x00001)) + __asm__("vrp.bug.not.always.true"); + /* Out of range, always evaluates to constant false. */ + if (!__builtin_constant_p (n & 0x01000)) + __asm__("vrp.bug.always.false"); +} + +void +u5 (unsigned n) +{ + struct s {unsigned exp:8;} x; + x.exp = n; + if (__builtin_constant_p(((n + 1) & 255) > 1)) + __asm__("vrp.bug.not.always.true"); +} + +void +v5 (int a, int b) +{ + if (a < 0x1000) return; + if (a > 0x1000) return; + if (b < 0x0110) return; + /* constant true. */ + if (!__builtin_constant_p ((a|b) >= 0x01000)) + __asm__("vrp.bug.always.true"); + /* VRP must not think that this is always true. */ + if (__builtin_constant_p ((a|b) >= 0x10000)) + __asm__("vrp.bug.not.always.true"); +} + +/* { dg-final { scan-assembler-not "vrp\\\.bug\\\." } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp52.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp52.c new file mode 100644 index 000000000..231d08156 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp52.c @@ -0,0 +1,16 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int +foo (unsigned int i, unsigned int j) +{ + i &= 15; + j &= 15; + i += 1024; + j += 2048; + i |= j; + return i >= 1024 + 2048; +} + +/* { dg-final { scan-tree-dump-times "return 1;" 1 "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp53.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp53.c new file mode 100644 index 000000000..66bbfb67b --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp53.c @@ -0,0 +1,24 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +int +f1 (int x) +{ + x &= 0xff; + x += 0x400; + x &= 0x7ff; + return x; +} + +int +f2 (int x) +{ + x &= 0xff; + x += 0x5400; + x |= 0x4400; + return x; +} + +/* { dg-final { scan-tree-dump-not "\& (2047|0x7ff)" "vrp1" } } */ +/* { dg-final { scan-tree-dump-not "\\| (17408|0x4400)" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/vrp54.c b/gcc/testsuite/gcc.dg/tree-ssa/vrp54.c new file mode 100644 index 000000000..6e8da7758 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/vrp54.c @@ -0,0 +1,34 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ + +extern void link_error (void); +void foo (void) +{ + int j = 256; + do + { + if (j < 0 || j > 256) + link_error (); + j--; + } + while (j >= 0); + if (j != -1) + link_error (); +} +extern void link_error (void); +void bar (void) +{ + int j = 0; + do + { + if (j < 0 || j > 256) + link_error (); + j++; + } + while (j <= 256); + if (j != 257) + link_error (); +} + +/* { dg-final { scan-tree-dump-not "link_error" "vrp1" } } */ +/* { dg-final { cleanup-tree-dump "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c new file mode 100644 index 000000000..9d0af1f23 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-1.c @@ -0,0 +1,23 @@ +/* { dg-options "-O2 -fdump-tree-optimized -fwhole-program" } */ +int b[100]; +void abort (void); + +void +large_function () +{ + int i; + for (i = 0; i < 99; i++) + if (b[i] / (b[i+1] + 1)) + abort (); +} + +main () +{ + large_function (); +} + +/* Function should be inlined as called once. */ +/* { dg-final { scan-tree-dump-not "large_function" "optimized"} } */ + +/* { dg-final { cleanup-tree-dump "optimized" } } */ + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c new file mode 100644 index 000000000..bbdd0dd48 --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/wholeprogram-2.c @@ -0,0 +1,8 @@ +/* { dg-options "-O2 -fdump-tree-optimized -fwhole-program" } */ +__attribute__ ((externally_visible)) +void +externally_visible_function () +{ +} +/* { dg-final { scan-tree-dump "externally_visible_function" "optimized"} } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ |