2016-03-01 Jeff Law <law@redhat.com>
+ PR tree-optimization/69196
+ * tree-ssa-threadbackward.c (fsm_find_control_statement_thread_paths):
+ Appropriately clamp the number of statements to copy when the
+ thread path does not traverse a loop backedge.
+
PR tree-optimization/69196
* tree-ssa-threadbackward.c (fsm_find_control_statement_thread_paths):
Do count some PHIs in the thread path against the insn count. Decrease
2016-03-01 Jeff Law <law@redhat.com>
+ PR tree-optimization/69196
+ * gcc.dg/tree-ssa/pr69196.c: New test.
+
PR tree-optimization/69196
* gcc.dg/tree-ssa/vrp46.c: Twiddle threading params to keep it from
duplicating code and spoiling the expected output.
--- /dev/null
+/* { dg-do compile } */
+/* { dg-options "-O2 -fdump-tree-vrp1-details" } */
+
+/* { dg-final { scan-tree-dump "FSM did not thread around loop and would copy too many statements" "vrp1" } } */
+
+
+typedef __builtin_va_list __gnuc_va_list;
+typedef __gnuc_va_list va_list;
+extern void rtems_putc(char c);
+
+void vprintk(
+ const char *fmt,
+ va_list ap
+)
+{
+ for (; *fmt != '\0'; fmt++) {
+ unsigned base = 0;
+ unsigned width = 0;
+ enum {
+ LFLAG_INT,
+ LFLAG_LONG,
+ LFLAG_LONG_LONG
+ } lflag = LFLAG_INT;
+ _Bool minus = 0;
+ _Bool sign = 0;
+ char lead = ' ';
+ char c = *fmt;
+ long long num;
+
+ if (c != '%') {
+ rtems_putc(c);
+ continue;
+ }
+
+ ++fmt; c = *fmt;
+
+ if (c == '0') {
+ lead = '0';
+ ++fmt; c = *fmt;
+ }
+
+ if (c == '-') {
+ minus = 1;
+ ++fmt; c = *fmt;
+ }
+
+ while (c >= '0' && c <= '9' ) {
+ width *= 10;
+ width += ((unsigned) c - '0');
+ ++fmt; c = *fmt;
+ }
+
+ if (c == 'l') {
+ lflag = LFLAG_LONG;
+ ++fmt; c = *fmt;
+
+ if (c == 'l') {
+ lflag = LFLAG_LONG_LONG;
+ ++fmt; c = *fmt;
+ }
+ }
+
+ if ( c == 'c' ) {
+
+ char chr = (char) __builtin_va_arg(ap,int);
+ rtems_putc(chr);
+ continue;
+ }
+
+ if ( c == 's' ) {
+ unsigned i, len;
+ char *s, *str;
+
+ str = __builtin_va_arg(ap,char *);
+
+ if ( str == ((void *)0) ) {
+ str = "";
+ }
+
+
+ for ( len=0, s=str ; *s ; len++, s++ )
+ ;
+
+
+ if ( !minus )
+ for ( i=len ; i<width ; i++ )
+ rtems_putc(' ');
+
+
+ if (width == 0) {
+ width = len;
+ }
+
+
+ for ( i=0 ; i<width && *str ; str++ )
+ rtems_putc(*str);
+
+
+ if ( minus )
+ for ( i=len ; i<width ; i++ )
+ rtems_putc(' ');
+
+ continue;
+ }
+
+
+ if ( c == 'o' || c == 'O' ) {
+ base = 8; sign = 0;
+ } else if ( c == 'i' || c == 'I' ||
+ c == 'd' || c == 'D' ) {
+ base = 10; sign = 1;
+ } else if ( c == 'u' || c == 'U' ) {
+ base = 10; sign = 0;
+ } else if ( c == 'x' || c == 'X' ) {
+ base = 16; sign = 0;
+ } else if ( c == 'p' ) {
+ base = 16; sign = 0; lflag = LFLAG_LONG;
+ } else {
+ rtems_putc(c);
+ continue;
+ }
+
+ switch (lflag) {
+ case LFLAG_LONG:
+ num = sign ? (long long) __builtin_va_arg(ap,long)
+ : (long long) __builtin_va_arg(ap,unsigned long);
+ break;
+ case LFLAG_LONG_LONG:
+ num = __builtin_va_arg(ap,long long);
+ break;
+ case LFLAG_INT:
+ default:
+ num = sign ? (long long) __builtin_va_arg(ap,int)
+ : (long long) __builtin_va_arg(ap,unsigned int);
+ break;
+ }
+ }
+}
continue;
}
+
+ /* If this path does not thread through the loop latch, then we are
+ using the FSM threader to find old style jump threads. This
+ is good, except the FSM threader does not re-use an existing
+ threading path to reduce code duplication.
+
+ So for that case, drastically reduce the number of statements
+ we are allowed to copy. */
+ if (!threaded_through_latch
+ && (n_insns * PARAM_VALUE (PARAM_FSM_SCALE_PATH_STMTS)
+ >= PARAM_VALUE (PARAM_MAX_JUMP_THREAD_DUPLICATION_STMTS)))
+ {
+ if (dump_file && (dump_flags & TDF_DETAILS))
+ fprintf (dump_file,
+ "FSM did not thread around loop and would copy too "
+ "many statements.\n");
+ path->pop ();
+ continue;
+ }
+
/* When there is a multi-way branch on the path, then threading can
explode the CFG due to duplicating the edges for that multi-way
branch. So like above, only allow a multi-way branch on the path