diff options
author | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-07-07 15:42:41 +0000 |
---|---|---|
committer | bernds <bernds@138bc75d-0d04-0410-961f-82ee72b054a4> | 2011-07-07 15:42:41 +0000 |
commit | 1b727a0a1626f41ef9461a472c266d6a347ee52b (patch) | |
tree | f9552f79c86d74255de5a691ef17a3767e4337fb /gcc/hw-doloop.h | |
parent | 596b2ba34652c9c0fb301522d9a0014a046ec277 (diff) | |
download | gcc-1b727a0a1626f41ef9461a472c266d6a347ee52b.tar.gz |
* 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.
git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@175985 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/hw-doloop.h')
-rw-r--r-- | gcc/hw-doloop.h | 157 |
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 *); |