summaryrefslogtreecommitdiff
path: root/gcc/hw-doloop.h
diff options
context:
space:
mode:
authorBernd Schmidt <bernds@codesourcery.com>2011-07-07 15:42:41 +0000
committerBernd Schmidt <bernds@gcc.gnu.org>2011-07-07 15:42:41 +0000
commit9d9c740d1efcd1bd597ef4734227996a8f69151d (patch)
treef9552f79c86d74255de5a691ef17a3767e4337fb /gcc/hw-doloop.h
parentf0ea75811ae63b50e6c06ad694a993a8182ba012 (diff)
hw-doloop.c: New file.
* hw-doloop.c: New file. * hw-doloop.h: New file. * Makefile.in (OBJS): Add hw-doloop.o. (hw-doloop.o): New rule. ($(obj_out_file)): Add hw-doloop.h dependency. * config/bfin/bfin.c: Include "hw-doloop.h". (loop_info, DEF_VEC_P for loop_info, loop_info_d): Remove. (bfin_dump_loops, bfin_bb_in_loop, bfin_scan_loop): Remove. (hwloop_optimize): Renamed from bfin_optimize_loop. Argument type changed to hwloop_info. Return bool, true if the loop was successfully optimized. Remove code that was moved to hw-doloop.c, and adjust other parts. (hwloop_fail): New static function, containing parts that used to be in bfin_optimize_loop. (bfin_discover_loop, bfin_discover_loops, free_loops, bfin_reorder_loops): Remove. (hwloop_pattern_reg): New static function. (bfin_doloop_hooks): New variable. (bfin_reorg_loops): Remove most code, call reorg_loops. * config/bfin/bfin.md (doloop_end splitter): Also enable if loop counter is a memory_operand. From-SVN: r175985
Diffstat (limited to 'gcc/hw-doloop.h')
-rw-r--r--gcc/hw-doloop.h157
1 files changed, 157 insertions, 0 deletions
diff --git a/gcc/hw-doloop.h b/gcc/hw-doloop.h
new file mode 100644
index 00000000000..006b67953b2
--- /dev/null
+++ b/gcc/hw-doloop.h
@@ -0,0 +1,157 @@
+/* Code to analyze doloop loops in order for targets to perform late
+ optimizations converting doloops to other forms of hardware loops.
+ Copyright (C) 2011 Free Software Foundation, Inc.
+
+This file is part of GCC.
+
+GCC 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, or (at your option) any later
+version.
+
+GCC 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/>. */
+
+/* We need to keep a vector of loops */
+typedef struct hwloop_info_d *hwloop_info;
+DEF_VEC_P (hwloop_info);
+DEF_VEC_ALLOC_P (hwloop_info,heap);
+
+/* Information about a loop we have found (or are in the process of
+ finding). */
+struct GTY (()) hwloop_info_d
+{
+ /* loop number, for dumps */
+ int loop_no;
+
+ /* Next loop in the graph. */
+ hwloop_info next;
+
+ /* Vector of blocks only within the loop, including those within
+ inner loops. */
+ VEC (basic_block, heap) *blocks;
+
+ /* Same information in a bitmap. */
+ bitmap block_bitmap;
+
+ /* Vector of inner loops within this loop. Includes loops of every
+ nesting level. */
+ VEC (hwloop_info, heap) *loops;
+
+ /* All edges that jump into the loop. */
+ VEC(edge, gc) *incoming;
+
+ /* The ports currently using this infrastructure can typically
+ handle two cases: all incoming edges have the same destination
+ block, or all incoming edges have the same source block. These
+ two members are set to the common source or destination we found,
+ or NULL if different blocks were found. If both are NULL the
+ loop can't be optimized. */
+ basic_block incoming_src;
+ basic_block incoming_dest;
+
+ /* First block in the loop. This is the one branched to by the loop_end
+ insn. */
+ basic_block head;
+
+ /* Last block in the loop (the one with the loop_end insn). */
+ basic_block tail;
+
+ /* The successor block of the loop. This is the one the loop_end insn
+ falls into. */
+ basic_block successor;
+
+ /* The last instruction in the tail. */
+ rtx last_insn;
+
+ /* The loop_end insn. */
+ rtx loop_end;
+
+ /* The iteration register. */
+ rtx iter_reg;
+
+ /* The new label placed at the beginning of the loop. */
+ rtx start_label;
+
+ /* The new label placed at the end of the loop. */
+ rtx end_label;
+
+ /* The length of the loop. */
+ int length;
+
+ /* The nesting depth of the loop. Innermost loops are given a depth
+ of 1. Only successfully optimized doloops are counted; if an inner
+ loop was marked as bad, it does not increase the depth of its parent
+ loop.
+ This value is valid when the target's optimize function is called. */
+ int depth;
+
+ /* True if we can't optimize this loop. */
+ bool bad;
+
+ /* True if we have visited this loop during the optimization phase. */
+ bool visited;
+
+ /* The following values are collected before calling the target's optimize
+ function and are not valid earlier. */
+
+ /* Record information about control flow: whether the loop has calls
+ or asm statements, whether it has edges that jump out of the loop,
+ or edges that jump within the loop. */
+ bool has_call;
+ bool has_asm;
+ bool jumps_within;
+ bool jumps_outof;
+
+ /* True if there is an instruction other than the doloop_end which uses the
+ iteration register. */
+ bool iter_reg_used;
+ /* True if the iteration register lives past the doloop instruction. */
+ bool iter_reg_used_outside;
+
+ /* Hard registers set at any point in the loop, except for the loop counter
+ register's set in the doloop_end instruction. */
+ HARD_REG_SET regs_set_in_loop;
+};
+
+/* A set of hooks to be defined by a target that wants to use the reorg_loops
+ functionality.
+
+ reorg_loops is intended to handle cases where special hardware loop
+ setup instructions are required before the loop, for example to set
+ up loop counter registers that are not exposed to the register
+ allocator, or to inform the hardware about loop bounds.
+
+ reorg_loops performs analysis to discover loop_end patterns created
+ by the earlier loop-doloop pass, and sets up a hwloop_info
+ structure for each such insn it finds. It then tries to discover
+ the basic blocks containing the loop by tracking the lifetime of
+ the iteration register.
+
+ If a valid loop can't be found, the FAIL function is called;
+ otherwise the OPT function is called for each loop, visiting
+ innermost loops first and ascending. */
+struct hw_doloop_hooks
+{
+ /* Examine INSN. If it is a suitable doloop_end pattern, return the
+ iteration register, which should be a single hard register.
+ Otherwise, return NULL_RTX. */
+ rtx (*end_pattern_reg) (rtx insn);
+ /* Optimize LOOP. The target should perform any additional analysis
+ (e.g. checking that the loop isn't too long), and then perform
+ its transformations. Return true if successful, false if the
+ loop should be marked bad. If it returns false, the FAIL
+ function is called. */
+ bool (*opt) (hwloop_info loop);
+ /* Handle a loop that was marked bad for any reason. This could be
+ used to split the doloop_end pattern. */
+ void (*fail) (hwloop_info loop);
+};
+
+extern void reorg_loops (bool, struct hw_doloop_hooks *);