152284Sobrien/* Global common subexpression elimination/Partial redundancy elimination 250397Sobrien and global constant/copy propagation for GNU compiler. 3169689Skan Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005 490075Sobrien Free Software Foundation, Inc. 550397Sobrien 690075SobrienThis file is part of GCC. 750397Sobrien 890075SobrienGCC is free software; you can redistribute it and/or modify it under 990075Sobrienthe terms of the GNU General Public License as published by the Free 1090075SobrienSoftware Foundation; either version 2, or (at your option) any later 1190075Sobrienversion. 1250397Sobrien 1390075SobrienGCC is distributed in the hope that it will be useful, but WITHOUT ANY 1490075SobrienWARRANTY; without even the implied warranty of MERCHANTABILITY or 1590075SobrienFITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1690075Sobrienfor more details. 1750397Sobrien 1850397SobrienYou should have received a copy of the GNU General Public License 1990075Sobrienalong with GCC; see the file COPYING. If not, write to the Free 20169689SkanSoftware Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 21169689Skan02110-1301, USA. */ 2250397Sobrien 2350397Sobrien/* TODO 2450397Sobrien - reordering of memory allocation and freeing to be more space efficient 2550397Sobrien - do rough calc of how many regs are needed in each block, and a rough 2650397Sobrien calc of how many regs are available in each class and use that to 2750397Sobrien throttle back the code in cases where RTX_COST is minimal. 2852284Sobrien - a store to the same address as a load does not kill the load if the 2952284Sobrien source of the store is also the destination of the load. Handling this 3052284Sobrien allows more load motion, particularly out of loops. 3150397Sobrien - ability to realloc sbitmap vectors would allow one initial computation 3250397Sobrien of reg_set_in_block with only subsequent additions, rather than 3350397Sobrien recomputing it for each pass 3450397Sobrien 3550397Sobrien*/ 3650397Sobrien 3750397Sobrien/* References searched while implementing this. 3850397Sobrien 3950397Sobrien Compilers Principles, Techniques and Tools 4050397Sobrien Aho, Sethi, Ullman 4150397Sobrien Addison-Wesley, 1988 4250397Sobrien 4350397Sobrien Global Optimization by Suppression of Partial Redundancies 4450397Sobrien E. Morel, C. Renvoise 4550397Sobrien communications of the acm, Vol. 22, Num. 2, Feb. 1979 4650397Sobrien 4750397Sobrien A Portable Machine-Independent Global Optimizer - Design and Measurements 4850397Sobrien Frederick Chow 4950397Sobrien Stanford Ph.D. thesis, Dec. 1983 5050397Sobrien 5150397Sobrien A Fast Algorithm for Code Movement Optimization 5250397Sobrien D.M. Dhamdhere 5350397Sobrien SIGPLAN Notices, Vol. 23, Num. 10, Oct. 1988 5450397Sobrien 5550397Sobrien A Solution to a Problem with Morel and Renvoise's 5650397Sobrien Global Optimization by Suppression of Partial Redundancies 5750397Sobrien K-H Drechsler, M.P. Stadel 5850397Sobrien ACM TOPLAS, Vol. 10, Num. 4, Oct. 1988 5950397Sobrien 6050397Sobrien Practical Adaptation of the Global Optimization 6150397Sobrien Algorithm of Morel and Renvoise 6250397Sobrien D.M. Dhamdhere 6350397Sobrien ACM TOPLAS, Vol. 13, Num. 2. Apr. 1991 6450397Sobrien 6550397Sobrien Efficiently Computing Static Single Assignment Form and the Control 6650397Sobrien Dependence Graph 6750397Sobrien R. Cytron, J. Ferrante, B.K. Rosen, M.N. Wegman, and F.K. Zadeck 6850397Sobrien ACM TOPLAS, Vol. 13, Num. 4, Oct. 1991 6950397Sobrien 7050397Sobrien Lazy Code Motion 7150397Sobrien J. Knoop, O. Ruthing, B. Steffen 7250397Sobrien ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI 7350397Sobrien 7450397Sobrien What's In a Region? Or Computing Control Dependence Regions in Near-Linear 7550397Sobrien Time for Reducible Flow Control 7650397Sobrien Thomas Ball 7750397Sobrien ACM Letters on Programming Languages and Systems, 7850397Sobrien Vol. 2, Num. 1-4, Mar-Dec 1993 7950397Sobrien 8050397Sobrien An Efficient Representation for Sparse Sets 8150397Sobrien Preston Briggs, Linda Torczon 8250397Sobrien ACM Letters on Programming Languages and Systems, 8350397Sobrien Vol. 2, Num. 1-4, Mar-Dec 1993 8450397Sobrien 8550397Sobrien A Variation of Knoop, Ruthing, and Steffen's Lazy Code Motion 8650397Sobrien K-H Drechsler, M.P. Stadel 8750397Sobrien ACM SIGPLAN Notices, Vol. 28, Num. 5, May 1993 8850397Sobrien 8950397Sobrien Partial Dead Code Elimination 9050397Sobrien J. Knoop, O. Ruthing, B. Steffen 9150397Sobrien ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994 9250397Sobrien 9350397Sobrien Effective Partial Redundancy Elimination 9450397Sobrien P. Briggs, K.D. Cooper 9550397Sobrien ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994 9650397Sobrien 9750397Sobrien The Program Structure Tree: Computing Control Regions in Linear Time 9850397Sobrien R. Johnson, D. Pearson, K. Pingali 9950397Sobrien ACM SIGPLAN Notices, Vol. 29, Num. 6, Jun. 1994 10050397Sobrien 10150397Sobrien Optimal Code Motion: Theory and Practice 10250397Sobrien J. Knoop, O. Ruthing, B. Steffen 10350397Sobrien ACM TOPLAS, Vol. 16, Num. 4, Jul. 1994 10450397Sobrien 10550397Sobrien The power of assignment motion 10650397Sobrien J. Knoop, O. Ruthing, B. Steffen 10750397Sobrien ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI 10850397Sobrien 10950397Sobrien Global code motion / global value numbering 11050397Sobrien C. Click 11150397Sobrien ACM SIGPLAN Notices Vol. 30, Num. 6, Jun. 1995, '95 Conference on PLDI 11250397Sobrien 11350397Sobrien Value Driven Redundancy Elimination 11450397Sobrien L.T. Simpson 11550397Sobrien Rice University Ph.D. thesis, Apr. 1996 11650397Sobrien 11750397Sobrien Value Numbering 11850397Sobrien L.T. Simpson 11950397Sobrien Massively Scalar Compiler Project, Rice University, Sep. 1996 12050397Sobrien 12150397Sobrien High Performance Compilers for Parallel Computing 12250397Sobrien Michael Wolfe 12350397Sobrien Addison-Wesley, 1996 12450397Sobrien 12552284Sobrien Advanced Compiler Design and Implementation 12652284Sobrien Steven Muchnick 12752284Sobrien Morgan Kaufmann, 1997 12852284Sobrien 12990075Sobrien Building an Optimizing Compiler 13090075Sobrien Robert Morgan 13190075Sobrien Digital Press, 1998 13290075Sobrien 13352284Sobrien People wishing to speed up the code here should read: 13452284Sobrien Elimination Algorithms for Data Flow Analysis 13552284Sobrien B.G. Ryder, M.C. Paull 13652284Sobrien ACM Computing Surveys, Vol. 18, Num. 3, Sep. 1986 13752284Sobrien 13852284Sobrien How to Analyze Large Programs Efficiently and Informatively 13952284Sobrien D.M. Dhamdhere, B.K. Rosen, F.K. Zadeck 14052284Sobrien ACM SIGPLAN Notices Vol. 27, Num. 7, Jul. 1992, '92 Conference on PLDI 14152284Sobrien 14250397Sobrien People wishing to do something different can find various possibilities 14350397Sobrien in the above papers and elsewhere. 14450397Sobrien*/ 14550397Sobrien 14650397Sobrien#include "config.h" 14750397Sobrien#include "system.h" 148132718Skan#include "coretypes.h" 149132718Skan#include "tm.h" 15052284Sobrien#include "toplev.h" 15150397Sobrien 15250397Sobrien#include "rtl.h" 153132718Skan#include "tree.h" 15490075Sobrien#include "tm_p.h" 15550397Sobrien#include "regs.h" 15650397Sobrien#include "hard-reg-set.h" 15750397Sobrien#include "flags.h" 15850397Sobrien#include "real.h" 15950397Sobrien#include "insn-config.h" 16050397Sobrien#include "recog.h" 16150397Sobrien#include "basic-block.h" 16250397Sobrien#include "output.h" 16390075Sobrien#include "function.h" 164117395Skan#include "expr.h" 16596263Sobrien#include "except.h" 16690075Sobrien#include "ggc.h" 16790075Sobrien#include "params.h" 168117395Skan#include "cselib.h" 169132718Skan#include "intl.h" 17050397Sobrien#include "obstack.h" 171169689Skan#include "timevar.h" 172169689Skan#include "tree-pass.h" 173169689Skan#include "hashtab.h" 17450397Sobrien 17550397Sobrien/* Propagate flow information through back edges and thus enable PRE's 17650397Sobrien moving loop invariant calculations out of loops. 17750397Sobrien 17850397Sobrien Originally this tended to create worse overall code, but several 17950397Sobrien improvements during the development of PRE seem to have made following 18050397Sobrien back edges generally a win. 18150397Sobrien 18250397Sobrien Note much of the loop invariant code motion done here would normally 18350397Sobrien be done by loop.c, which has more heuristics for when to move invariants 18450397Sobrien out of loops. At some point we might need to move some of those 18550397Sobrien heuristics into gcse.c. */ 18650397Sobrien 18752284Sobrien/* We support GCSE via Partial Redundancy Elimination. PRE optimizations 18852284Sobrien are a superset of those done by GCSE. 18950397Sobrien 19052284Sobrien We perform the following steps: 19150397Sobrien 19250397Sobrien 1) Compute basic block information. 19350397Sobrien 19450397Sobrien 2) Compute table of places where registers are set. 19550397Sobrien 19650397Sobrien 3) Perform copy/constant propagation. 19750397Sobrien 198169689Skan 4) Perform global cse using lazy code motion if not optimizing 199169689Skan for size, or code hoisting if we are. 20050397Sobrien 20152284Sobrien 5) Perform another pass of copy/constant propagation. 20250397Sobrien 20350397Sobrien Two passes of copy/constant propagation are done because the first one 20450397Sobrien enables more GCSE and the second one helps to clean up the copies that 20550397Sobrien GCSE creates. This is needed more for PRE than for Classic because Classic 20650397Sobrien GCSE will try to use an existing register containing the common 20750397Sobrien subexpression rather than create a new one. This is harder to do for PRE 20850397Sobrien because of the code motion (which Classic GCSE doesn't do). 20950397Sobrien 21050397Sobrien Expressions we are interested in GCSE-ing are of the form 21150397Sobrien (set (pseudo-reg) (expression)). 21250397Sobrien Function want_to_gcse_p says what these are. 21350397Sobrien 21450397Sobrien PRE handles moving invariant expressions out of loops (by treating them as 21552284Sobrien partially redundant). 21650397Sobrien 21750397Sobrien Eventually it would be nice to replace cse.c/gcse.c with SSA (static single 21850397Sobrien assignment) based GVN (global value numbering). L. T. Simpson's paper 21950397Sobrien (Rice University) on value numbering is a useful reference for this. 22050397Sobrien 22150397Sobrien ********************** 22250397Sobrien 22350397Sobrien We used to support multiple passes but there are diminishing returns in 22450397Sobrien doing so. The first pass usually makes 90% of the changes that are doable. 22550397Sobrien A second pass can make a few more changes made possible by the first pass. 22650397Sobrien Experiments show any further passes don't make enough changes to justify 22750397Sobrien the expense. 22850397Sobrien 22950397Sobrien A study of spec92 using an unlimited number of passes: 23050397Sobrien [1 pass] = 1208 substitutions, [2] = 577, [3] = 202, [4] = 192, [5] = 83, 23150397Sobrien [6] = 34, [7] = 17, [8] = 9, [9] = 4, [10] = 4, [11] = 2, 23250397Sobrien [12] = 2, [13] = 1, [15] = 1, [16] = 2, [41] = 1 23350397Sobrien 23450397Sobrien It was found doing copy propagation between each pass enables further 23550397Sobrien substitutions. 23650397Sobrien 23750397Sobrien PRE is quite expensive in complicated functions because the DFA can take 238169689Skan a while to converge. Hence we only perform one pass. The parameter 239169689Skan max-gcse-passes can be modified if one wants to experiment. 24050397Sobrien 24150397Sobrien ********************** 24250397Sobrien 24350397Sobrien The steps for PRE are: 24450397Sobrien 24550397Sobrien 1) Build the hash table of expressions we wish to GCSE (expr_hash_table). 24650397Sobrien 24750397Sobrien 2) Perform the data flow analysis for PRE. 24850397Sobrien 24950397Sobrien 3) Delete the redundant instructions 25050397Sobrien 25150397Sobrien 4) Insert the required copies [if any] that make the partially 25250397Sobrien redundant instructions fully redundant. 25350397Sobrien 25450397Sobrien 5) For other reaching expressions, insert an instruction to copy the value 25550397Sobrien to a newly created pseudo that will reach the redundant instruction. 25650397Sobrien 25750397Sobrien The deletion is done first so that when we do insertions we 25850397Sobrien know which pseudo reg to use. 25950397Sobrien 26050397Sobrien Various papers have argued that PRE DFA is expensive (O(n^2)) and others 26150397Sobrien argue it is not. The number of iterations for the algorithm to converge 26250397Sobrien is typically 2-4 so I don't view it as that expensive (relatively speaking). 26350397Sobrien 26452284Sobrien PRE GCSE depends heavily on the second CSE pass to clean up the copies 26550397Sobrien we create. To make an expression reach the place where it's redundant, 26650397Sobrien the result of the expression is copied to a new register, and the redundant 26750397Sobrien expression is deleted by replacing it with this new register. Classic GCSE 26850397Sobrien doesn't have this problem as much as it computes the reaching defs of 269169689Skan each register in each block and thus can try to use an existing 270169689Skan register. */ 27150397Sobrien 27250397Sobrien/* GCSE global vars. */ 27350397Sobrien 27452284Sobrien/* Note whether or not we should run jump optimization after gcse. We 27552284Sobrien want to do this for two cases. 27652284Sobrien 27752284Sobrien * If we changed any jumps via cprop. 27852284Sobrien 27952284Sobrien * If we added any labels via edge splitting. */ 28052284Sobrienstatic int run_jump_opt_after_gcse; 28152284Sobrien 28250397Sobrien/* An obstack for our working variables. */ 28350397Sobrienstatic struct obstack gcse_obstack; 28450397Sobrien 28590075Sobrienstruct reg_use {rtx reg_rtx; }; 28690075Sobrien 28750397Sobrien/* Hash table of expressions. */ 28850397Sobrien 28950397Sobrienstruct expr 29050397Sobrien{ 29150397Sobrien /* The expression (SET_SRC for expressions, PATTERN for assignments). */ 29250397Sobrien rtx expr; 29350397Sobrien /* Index in the available expression bitmaps. */ 29450397Sobrien int bitmap_index; 29550397Sobrien /* Next entry with the same hash. */ 29650397Sobrien struct expr *next_same_hash; 29750397Sobrien /* List of anticipatable occurrences in basic blocks in the function. 29850397Sobrien An "anticipatable occurrence" is one that is the first occurrence in the 29952284Sobrien basic block, the operands are not modified in the basic block prior 30052284Sobrien to the occurrence and the output is not used between the start of 30152284Sobrien the block and the occurrence. */ 30250397Sobrien struct occr *antic_occr; 30350397Sobrien /* List of available occurrence in basic blocks in the function. 30450397Sobrien An "available occurrence" is one that is the last occurrence in the 30550397Sobrien basic block and the operands are not modified by following statements in 30650397Sobrien the basic block [including this insn]. */ 30750397Sobrien struct occr *avail_occr; 30850397Sobrien /* Non-null if the computation is PRE redundant. 30950397Sobrien The value is the newly created pseudo-reg to record a copy of the 31050397Sobrien expression in all the places that reach the redundant copy. */ 31150397Sobrien rtx reaching_reg; 31250397Sobrien}; 31350397Sobrien 31450397Sobrien/* Occurrence of an expression. 31550397Sobrien There is one per basic block. If a pattern appears more than once the 31650397Sobrien last appearance is used [or first for anticipatable expressions]. */ 31750397Sobrien 31850397Sobrienstruct occr 31950397Sobrien{ 32050397Sobrien /* Next occurrence of this expression. */ 32150397Sobrien struct occr *next; 32250397Sobrien /* The insn that computes the expression. */ 32350397Sobrien rtx insn; 324117395Skan /* Nonzero if this [anticipatable] occurrence has been deleted. */ 32550397Sobrien char deleted_p; 326117395Skan /* Nonzero if this [available] occurrence has been copied to 32750397Sobrien reaching_reg. */ 32850397Sobrien /* ??? This is mutually exclusive with deleted_p, so they could share 32950397Sobrien the same byte. */ 33050397Sobrien char copied_p; 33150397Sobrien}; 33250397Sobrien 33350397Sobrien/* Expression and copy propagation hash tables. 33450397Sobrien Each hash table is an array of buckets. 33550397Sobrien ??? It is known that if it were an array of entries, structure elements 33650397Sobrien `next_same_hash' and `bitmap_index' wouldn't be necessary. However, it is 33750397Sobrien not clear whether in the final analysis a sufficient amount of memory would 33850397Sobrien be saved as the size of the available expression bitmaps would be larger 33950397Sobrien [one could build a mapping table without holes afterwards though]. 34090075Sobrien Someday I'll perform the computation and figure it out. */ 34150397Sobrien 342117395Skanstruct hash_table 343117395Skan{ 344117395Skan /* The table itself. 345117395Skan This is an array of `expr_hash_table_size' elements. */ 346117395Skan struct expr **table; 34790075Sobrien 348117395Skan /* Size of the hash table, in elements. */ 349117395Skan unsigned int size; 35050397Sobrien 351117395Skan /* Number of hash table elements. */ 352117395Skan unsigned int n_elems; 35390075Sobrien 354117395Skan /* Whether the table is expression of copy propagation one. */ 355117395Skan int set_p; 356117395Skan}; 35750397Sobrien 358117395Skan/* Expression hash table. */ 359117395Skanstatic struct hash_table expr_hash_table; 360117395Skan 361117395Skan/* Copy propagation hash table. */ 362117395Skanstatic struct hash_table set_hash_table; 363117395Skan 36450397Sobrien/* Mapping of uids to cuids. 36550397Sobrien Only real insns get cuids. */ 36650397Sobrienstatic int *uid_cuid; 36750397Sobrien 36850397Sobrien/* Highest UID in UID_CUID. */ 36950397Sobrienstatic int max_uid; 37050397Sobrien 37150397Sobrien/* Get the cuid of an insn. */ 37290075Sobrien#ifdef ENABLE_CHECKING 373169689Skan#define INSN_CUID(INSN) \ 374169689Skan (gcc_assert (INSN_UID (INSN) <= max_uid), uid_cuid[INSN_UID (INSN)]) 37590075Sobrien#else 37650397Sobrien#define INSN_CUID(INSN) (uid_cuid[INSN_UID (INSN)]) 37790075Sobrien#endif 37850397Sobrien 37950397Sobrien/* Number of cuids. */ 38050397Sobrienstatic int max_cuid; 38150397Sobrien 38250397Sobrien/* Mapping of cuids to insns. */ 38350397Sobrienstatic rtx *cuid_insn; 38450397Sobrien 38550397Sobrien/* Get insn from cuid. */ 38650397Sobrien#define CUID_INSN(CUID) (cuid_insn[CUID]) 38750397Sobrien 38850397Sobrien/* Maximum register number in function prior to doing gcse + 1. 38950397Sobrien Registers created during this pass have regno >= max_gcse_regno. 39050397Sobrien This is named with "gcse" to not collide with global of same name. */ 39190075Sobrienstatic unsigned int max_gcse_regno; 39250397Sobrien 39350397Sobrien/* Table of registers that are modified. 39490075Sobrien 39550397Sobrien For each register, each element is a list of places where the pseudo-reg 39650397Sobrien is set. 39750397Sobrien 39850397Sobrien For simplicity, GCSE is done on sets of pseudo-regs only. PRE GCSE only 39950397Sobrien requires knowledge of which blocks kill which regs [and thus could use 40052284Sobrien a bitmap instead of the lists `reg_set_table' uses]. 40150397Sobrien 40290075Sobrien `reg_set_table' and could be turned into an array of bitmaps (num-bbs x 40390075Sobrien num-regs) [however perhaps it may be useful to keep the data as is]. One 40490075Sobrien advantage of recording things this way is that `reg_set_table' is fairly 40590075Sobrien sparse with respect to pseudo regs but for hard regs could be fairly dense 40690075Sobrien [relatively speaking]. And recording sets of pseudo-regs in lists speeds 40750397Sobrien up functions like compute_transp since in the case of pseudo-regs we only 40850397Sobrien need to iterate over the number of times a pseudo-reg is set, not over the 40950397Sobrien number of basic blocks [clearly there is a bit of a slow down in the cases 41050397Sobrien where a pseudo is set more than once in a block, however it is believed 41150397Sobrien that the net effect is to speed things up]. This isn't done for hard-regs 41250397Sobrien because recording call-clobbered hard-regs in `reg_set_table' at each 41390075Sobrien function call can consume a fair bit of memory, and iterating over 41490075Sobrien hard-regs stored this way in compute_transp will be more expensive. */ 41550397Sobrien 41690075Sobrientypedef struct reg_set 41790075Sobrien{ 41850397Sobrien /* The next setting of this register. */ 41950397Sobrien struct reg_set *next; 420169689Skan /* The index of the block where it was set. */ 421169689Skan int bb_index; 42250397Sobrien} reg_set; 42390075Sobrien 42450397Sobrienstatic reg_set **reg_set_table; 42590075Sobrien 42650397Sobrien/* Size of `reg_set_table'. 42750397Sobrien The table starts out at max_gcse_regno + slop, and is enlarged as 42850397Sobrien necessary. */ 42950397Sobrienstatic int reg_set_table_size; 43090075Sobrien 43150397Sobrien/* Amount to grow `reg_set_table' by when it's full. */ 43250397Sobrien#define REG_SET_TABLE_SLOP 100 43350397Sobrien 43490075Sobrien/* This is a list of expressions which are MEMs and will be used by load 435117395Skan or store motion. 43690075Sobrien Load motion tracks MEMs which aren't killed by 437169689Skan anything except itself. (i.e., loads and stores to a single location). 438117395Skan We can then allow movement of these MEM refs with a little special 43990075Sobrien allowance. (all stores copy the same value to the reaching reg used 44090075Sobrien for the loads). This means all values used to store into memory must have 441117395Skan no side effects so we can re-issue the setter value. 44290075Sobrien Store Motion uses this structure as an expression table to track stores 44390075Sobrien which look interesting, and might be moveable towards the exit block. */ 44490075Sobrien 44590075Sobrienstruct ls_expr 44690075Sobrien{ 44790075Sobrien struct expr * expr; /* Gcse expression reference for LM. */ 44890075Sobrien rtx pattern; /* Pattern of this mem. */ 449132718Skan rtx pattern_regs; /* List of registers mentioned by the mem. */ 45090075Sobrien rtx loads; /* INSN list of loads seen. */ 45190075Sobrien rtx stores; /* INSN list of stores seen. */ 45290075Sobrien struct ls_expr * next; /* Next in the list. */ 45390075Sobrien int invalid; /* Invalid for some reason. */ 45490075Sobrien int index; /* If it maps to a bitmap index. */ 455132718Skan unsigned int hash_index; /* Index when in a hash table. */ 45690075Sobrien rtx reaching_reg; /* Register to use when re-writing. */ 45790075Sobrien}; 45890075Sobrien 459132718Skan/* Array of implicit set patterns indexed by basic block index. */ 460132718Skanstatic rtx *implicit_sets; 461132718Skan 46290075Sobrien/* Head of the list of load/store memory refs. */ 46390075Sobrienstatic struct ls_expr * pre_ldst_mems = NULL; 46490075Sobrien 465169689Skan/* Hashtable for the load/store memory refs. */ 466169689Skanstatic htab_t pre_ldst_table = NULL; 467169689Skan 46850397Sobrien/* Bitmap containing one bit for each register in the program. 46950397Sobrien Used when performing GCSE to track which registers have been set since 47050397Sobrien the start of the basic block. */ 47190075Sobrienstatic regset reg_set_bitmap; 47250397Sobrien 47350397Sobrien/* For each block, a bitmap of registers set in the block. 474169689Skan This is used by compute_transp. 47550397Sobrien It is computed during hash table computation and not by compute_sets 47650397Sobrien as it includes registers added since the last pass (or between cprop and 47750397Sobrien gcse) and it's currently not easy to realloc sbitmap vectors. */ 47850397Sobrienstatic sbitmap *reg_set_in_block; 47950397Sobrien 48090075Sobrien/* Array, indexed by basic block number for a list of insns which modify 48190075Sobrien memory within that block. */ 48290075Sobrienstatic rtx * modify_mem_list; 483169689Skanstatic bitmap modify_mem_list_set; 48450397Sobrien 48590075Sobrien/* This array parallels modify_mem_list, but is kept canonicalized. */ 48690075Sobrienstatic rtx * canon_modify_mem_list; 487169689Skan 488169689Skan/* Bitmap indexed by block numbers to record which blocks contain 489169689Skan function calls. */ 490169689Skanstatic bitmap blocks_with_calls; 491169689Skan 49250397Sobrien/* Various variables for statistics gathering. */ 49350397Sobrien 49450397Sobrien/* Memory used in a pass. 49550397Sobrien This isn't intended to be absolutely precise. Its intent is only 49650397Sobrien to keep an eye on memory usage. */ 49750397Sobrienstatic int bytes_used; 49890075Sobrien 49950397Sobrien/* GCSE substitutions made. */ 50050397Sobrienstatic int gcse_subst_count; 50150397Sobrien/* Number of copy instructions created. */ 50250397Sobrienstatic int gcse_create_count; 503169689Skan/* Number of local constants propagated. */ 504169689Skanstatic int local_const_prop_count; 505169689Skan/* Number of local copies propagated. */ 506169689Skanstatic int local_copy_prop_count; 507169689Skan/* Number of global constants propagated. */ 508169689Skanstatic int global_const_prop_count; 509169689Skan/* Number of global copies propagated. */ 510169689Skanstatic int global_copy_prop_count; 51150397Sobrien 512169689Skan/* For available exprs */ 513169689Skanstatic sbitmap *ae_kill, *ae_gen; 51450397Sobrien 515132718Skanstatic void compute_can_copy (void); 516132718Skanstatic void *gmalloc (size_t) ATTRIBUTE_MALLOC; 517132718Skanstatic void *gcalloc (size_t, size_t) ATTRIBUTE_MALLOC; 518132718Skanstatic void *grealloc (void *, size_t); 519132718Skanstatic void *gcse_alloc (unsigned long); 520169689Skanstatic void alloc_gcse_mem (void); 521132718Skanstatic void free_gcse_mem (void); 522132718Skanstatic void alloc_reg_set_mem (int); 523132718Skanstatic void free_reg_set_mem (void); 524132718Skanstatic void record_one_set (int, rtx); 525132718Skanstatic void record_set_info (rtx, rtx, void *); 526169689Skanstatic void compute_sets (void); 527132718Skanstatic void hash_scan_insn (rtx, struct hash_table *, int); 528132718Skanstatic void hash_scan_set (rtx, rtx, struct hash_table *); 529132718Skanstatic void hash_scan_clobber (rtx, rtx, struct hash_table *); 530132718Skanstatic void hash_scan_call (rtx, rtx, struct hash_table *); 531132718Skanstatic int want_to_gcse_p (rtx); 532169689Skanstatic bool can_assign_to_reg_p (rtx); 533132718Skanstatic bool gcse_constant_p (rtx); 534132718Skanstatic int oprs_unchanged_p (rtx, rtx, int); 535132718Skanstatic int oprs_anticipatable_p (rtx, rtx); 536132718Skanstatic int oprs_available_p (rtx, rtx); 537132718Skanstatic void insert_expr_in_table (rtx, enum machine_mode, rtx, int, int, 538132718Skan struct hash_table *); 539132718Skanstatic void insert_set_in_table (rtx, rtx, struct hash_table *); 540132718Skanstatic unsigned int hash_expr (rtx, enum machine_mode, int *, int); 541132718Skanstatic unsigned int hash_set (int, int); 542132718Skanstatic int expr_equiv_p (rtx, rtx); 543132718Skanstatic void record_last_reg_set_info (rtx, int); 544132718Skanstatic void record_last_mem_set_info (rtx); 545132718Skanstatic void record_last_set_info (rtx, rtx, void *); 546132718Skanstatic void compute_hash_table (struct hash_table *); 547132718Skanstatic void alloc_hash_table (int, struct hash_table *, int); 548132718Skanstatic void free_hash_table (struct hash_table *); 549132718Skanstatic void compute_hash_table_work (struct hash_table *); 550132718Skanstatic void dump_hash_table (FILE *, const char *, struct hash_table *); 551132718Skanstatic struct expr *lookup_set (unsigned int, struct hash_table *); 552132718Skanstatic struct expr *next_set (unsigned int, struct expr *); 553132718Skanstatic void reset_opr_set_tables (void); 554132718Skanstatic int oprs_not_set_p (rtx, rtx); 555132718Skanstatic void mark_call (rtx); 556132718Skanstatic void mark_set (rtx, rtx); 557132718Skanstatic void mark_clobber (rtx, rtx); 558132718Skanstatic void mark_oprs_set (rtx); 559132718Skanstatic void alloc_cprop_mem (int, int); 560132718Skanstatic void free_cprop_mem (void); 561132718Skanstatic void compute_transp (rtx, int, sbitmap *, int); 562132718Skanstatic void compute_transpout (void); 563132718Skanstatic void compute_local_properties (sbitmap *, sbitmap *, sbitmap *, 564132718Skan struct hash_table *); 565132718Skanstatic void compute_cprop_data (void); 566132718Skanstatic void find_used_regs (rtx *, void *); 567132718Skanstatic int try_replace_reg (rtx, rtx, rtx); 568132718Skanstatic struct expr *find_avail_set (int, rtx); 569132718Skanstatic int cprop_jump (basic_block, rtx, rtx, rtx, rtx); 570132718Skanstatic void mems_conflict_for_gcse_p (rtx, rtx, void *); 571132718Skanstatic int load_killed_in_block_p (basic_block, int, rtx, int); 572132718Skanstatic void canon_list_insert (rtx, rtx, void *); 573132718Skanstatic int cprop_insn (rtx, int); 574132718Skanstatic int cprop (int); 575132718Skanstatic void find_implicit_sets (void); 576169689Skanstatic int one_cprop_pass (int, bool, bool); 577169689Skanstatic bool constprop_register (rtx, rtx, rtx, bool); 578132718Skanstatic struct expr *find_bypass_set (int, int); 579132718Skanstatic bool reg_killed_on_edge (rtx, edge); 580132718Skanstatic int bypass_block (basic_block, rtx, rtx); 581132718Skanstatic int bypass_conditional_jumps (void); 582132718Skanstatic void alloc_pre_mem (int, int); 583132718Skanstatic void free_pre_mem (void); 584132718Skanstatic void compute_pre_data (void); 585132718Skanstatic int pre_expr_reaches_here_p (basic_block, struct expr *, 586132718Skan basic_block); 587132718Skanstatic void insert_insn_end_bb (struct expr *, basic_block, int); 588132718Skanstatic void pre_insert_copy_insn (struct expr *, rtx); 589132718Skanstatic void pre_insert_copies (void); 590132718Skanstatic int pre_delete (void); 591132718Skanstatic int pre_gcse (void); 592132718Skanstatic int one_pre_gcse_pass (int); 593132718Skanstatic void add_label_notes (rtx, rtx); 594132718Skanstatic void alloc_code_hoist_mem (int, int); 595132718Skanstatic void free_code_hoist_mem (void); 596132718Skanstatic void compute_code_hoist_vbeinout (void); 597132718Skanstatic void compute_code_hoist_data (void); 598132718Skanstatic int hoist_expr_reaches_here_p (basic_block, int, basic_block, char *); 599132718Skanstatic void hoist_code (void); 600132718Skanstatic int one_code_hoisting_pass (void); 601132718Skanstatic rtx process_insert_insn (struct expr *); 602132718Skanstatic int pre_edge_insert (struct edge_list *, struct expr **); 603132718Skanstatic int pre_expr_reaches_here_p_work (basic_block, struct expr *, 604132718Skan basic_block, char *); 605132718Skanstatic struct ls_expr * ldst_entry (rtx); 606132718Skanstatic void free_ldst_entry (struct ls_expr *); 607132718Skanstatic void free_ldst_mems (void); 608132718Skanstatic void print_ldst_list (FILE *); 609132718Skanstatic struct ls_expr * find_rtx_in_ldst (rtx); 610132718Skanstatic int enumerate_ldsts (void); 611132718Skanstatic inline struct ls_expr * first_ls_expr (void); 612132718Skanstatic inline struct ls_expr * next_ls_expr (struct ls_expr *); 613132718Skanstatic int simple_mem (rtx); 614132718Skanstatic void invalidate_any_buried_refs (rtx); 615132718Skanstatic void compute_ld_motion_mems (void); 616132718Skanstatic void trim_ld_motion_mems (void); 617132718Skanstatic void update_ld_motion_stores (struct expr *); 618132718Skanstatic void reg_set_info (rtx, rtx, void *); 619132718Skanstatic void reg_clear_last_set (rtx, rtx, void *); 620132718Skanstatic bool store_ops_ok (rtx, int *); 621132718Skanstatic rtx extract_mentioned_regs (rtx); 622132718Skanstatic rtx extract_mentioned_regs_helper (rtx, rtx); 623132718Skanstatic void find_moveable_store (rtx, int *, int *); 624132718Skanstatic int compute_store_table (void); 625132718Skanstatic bool load_kills_store (rtx, rtx, int); 626132718Skanstatic bool find_loads (rtx, rtx, int); 627132718Skanstatic bool store_killed_in_insn (rtx, rtx, rtx, int); 628132718Skanstatic bool store_killed_after (rtx, rtx, rtx, basic_block, int *, rtx *); 629132718Skanstatic bool store_killed_before (rtx, rtx, rtx, basic_block, int *); 630132718Skanstatic void build_store_vectors (void); 631132718Skanstatic void insert_insn_start_bb (rtx, basic_block); 632132718Skanstatic int insert_store (struct ls_expr *, edge); 633132718Skanstatic void remove_reachable_equiv_notes (basic_block, struct ls_expr *); 634132718Skanstatic void replace_store_insn (rtx, rtx, basic_block, struct ls_expr *); 635132718Skanstatic void delete_store (struct ls_expr *, basic_block); 636132718Skanstatic void free_store_memory (void); 637132718Skanstatic void store_motion (void); 638132718Skanstatic void free_insn_expr_list_list (rtx *); 639132718Skanstatic void clear_modify_mem_tables (void); 640132718Skanstatic void free_modify_mem_tables (void); 641132718Skanstatic rtx gcse_emit_move_after (rtx, rtx, rtx); 642132718Skanstatic void local_cprop_find_used_regs (rtx *, void *); 643169689Skanstatic bool do_local_cprop (rtx, rtx, bool, rtx*); 644132718Skanstatic bool adjust_libcall_notes (rtx, rtx, rtx, rtx*); 645169689Skanstatic void local_cprop_pass (bool); 646132718Skanstatic bool is_too_expensive (const char *); 64750397Sobrien 648132718Skan 64950397Sobrien/* Entry point for global common subexpression elimination. 650169689Skan F is the first instruction in the function. Return nonzero if a 651169689Skan change is mode. */ 65250397Sobrien 653169689Skanstatic int 654169689Skangcse_main (rtx f ATTRIBUTE_UNUSED) 65550397Sobrien{ 65650397Sobrien int changed, pass; 65750397Sobrien /* Bytes used at start of pass. */ 65850397Sobrien int initial_bytes_used; 65950397Sobrien /* Maximum number of bytes used by a pass. */ 66050397Sobrien int max_pass_bytes; 66150397Sobrien /* Point to release obstack data from for each pass. */ 66250397Sobrien char *gcse_obstack_bottom; 66350397Sobrien 66452284Sobrien /* We do not construct an accurate cfg in functions which call 66552284Sobrien setjmp, so just punt to be safe. */ 66650397Sobrien if (current_function_calls_setjmp) 66752284Sobrien return 0; 668117395Skan 66952284Sobrien /* Assume that we do not need to run jump optimizations after gcse. */ 67052284Sobrien run_jump_opt_after_gcse = 0; 67152284Sobrien 67252284Sobrien /* Identify the basic block information for this function, including 67352284Sobrien successors and predecessors. */ 67450397Sobrien max_gcse_regno = max_reg_num (); 67550397Sobrien 676169689Skan if (dump_file) 677169689Skan dump_flow_info (dump_file, dump_flags); 67890075Sobrien 679132718Skan /* Return if there's nothing to do, or it is too expensive. */ 680169689Skan if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1 681169689Skan || is_too_expensive (_("GCSE disabled"))) 68290075Sobrien return 0; 683169689Skan 68450397Sobrien gcc_obstack_init (&gcse_obstack); 68590075Sobrien bytes_used = 0; 68650397Sobrien 68790075Sobrien /* We need alias. */ 68890075Sobrien init_alias_analysis (); 68990075Sobrien /* Record where pseudo-registers are set. This data is kept accurate 69090075Sobrien during each pass. ??? We could also record hard-reg information here 69190075Sobrien [since it's unchanging], however it is currently done during hash table 69290075Sobrien computation. 69350397Sobrien 69490075Sobrien It may be tempting to compute MEM set information here too, but MEM sets 69590075Sobrien will be subject to code motion one day and thus we need to compute 69652284Sobrien information about memory sets when we build the hash tables. */ 69752284Sobrien 69850397Sobrien alloc_reg_set_mem (max_gcse_regno); 699169689Skan compute_sets (); 70050397Sobrien 70150397Sobrien pass = 0; 70250397Sobrien initial_bytes_used = bytes_used; 70350397Sobrien max_pass_bytes = 0; 70450397Sobrien gcse_obstack_bottom = gcse_alloc (1); 70550397Sobrien changed = 1; 70690075Sobrien while (changed && pass < MAX_GCSE_PASSES) 70750397Sobrien { 70850397Sobrien changed = 0; 709169689Skan if (dump_file) 710169689Skan fprintf (dump_file, "GCSE pass %d\n\n", pass + 1); 71150397Sobrien 71250397Sobrien /* Initialize bytes_used to the space for the pred/succ lists, 71350397Sobrien and the reg_set_table data. */ 71450397Sobrien bytes_used = initial_bytes_used; 71550397Sobrien 71650397Sobrien /* Each pass may create new registers, so recalculate each time. */ 71750397Sobrien max_gcse_regno = max_reg_num (); 71850397Sobrien 719169689Skan alloc_gcse_mem (); 72050397Sobrien 72152284Sobrien /* Don't allow constant propagation to modify jumps 72252284Sobrien during this pass. */ 723169689Skan timevar_push (TV_CPROP1); 724169689Skan changed = one_cprop_pass (pass + 1, false, false); 725169689Skan timevar_pop (TV_CPROP1); 72650397Sobrien 72750397Sobrien if (optimize_size) 728169689Skan /* Do nothing. */ ; 72950397Sobrien else 730117395Skan { 731169689Skan timevar_push (TV_PRE); 73290075Sobrien changed |= one_pre_gcse_pass (pass + 1); 73390075Sobrien /* We may have just created new basic blocks. Release and 73490075Sobrien recompute various things which are sized on the number of 73590075Sobrien basic blocks. */ 73690075Sobrien if (changed) 73790075Sobrien { 73890075Sobrien free_modify_mem_tables (); 739132718Skan modify_mem_list = gcalloc (last_basic_block, sizeof (rtx)); 740132718Skan canon_modify_mem_list = gcalloc (last_basic_block, sizeof (rtx)); 74190075Sobrien } 74290075Sobrien free_reg_set_mem (); 74390075Sobrien alloc_reg_set_mem (max_reg_num ()); 744169689Skan compute_sets (); 74590075Sobrien run_jump_opt_after_gcse = 1; 746169689Skan timevar_pop (TV_PRE); 74790075Sobrien } 74850397Sobrien 74950397Sobrien if (max_pass_bytes < bytes_used) 75050397Sobrien max_pass_bytes = bytes_used; 75150397Sobrien 75290075Sobrien /* Free up memory, then reallocate for code hoisting. We can 75390075Sobrien not re-use the existing allocated memory because the tables 75490075Sobrien will not have info for the insns or registers created by 75590075Sobrien partial redundancy elimination. */ 75650397Sobrien free_gcse_mem (); 75750397Sobrien 758132718Skan /* It does not make sense to run code hoisting unless we are optimizing 75990075Sobrien for code size -- it rarely makes programs faster, and can make 76090075Sobrien them bigger if we did partial redundancy elimination (when optimizing 761169689Skan for space, we don't run the partial redundancy algorithms). */ 76290075Sobrien if (optimize_size) 763117395Skan { 764169689Skan timevar_push (TV_HOIST); 76590075Sobrien max_gcse_regno = max_reg_num (); 766169689Skan alloc_gcse_mem (); 76790075Sobrien changed |= one_code_hoisting_pass (); 76890075Sobrien free_gcse_mem (); 76990075Sobrien 77090075Sobrien if (max_pass_bytes < bytes_used) 77190075Sobrien max_pass_bytes = bytes_used; 772169689Skan timevar_pop (TV_HOIST); 773117395Skan } 77490075Sobrien 775169689Skan if (dump_file) 77650397Sobrien { 777169689Skan fprintf (dump_file, "\n"); 778169689Skan fflush (dump_file); 77950397Sobrien } 78090075Sobrien 78150397Sobrien obstack_free (&gcse_obstack, gcse_obstack_bottom); 78250397Sobrien pass++; 78350397Sobrien } 78450397Sobrien 78552284Sobrien /* Do one last pass of copy propagation, including cprop into 78652284Sobrien conditional jumps. */ 78750397Sobrien 78852284Sobrien max_gcse_regno = max_reg_num (); 789169689Skan alloc_gcse_mem (); 79052284Sobrien /* This time, go ahead and allow cprop to alter jumps. */ 791169689Skan timevar_push (TV_CPROP2); 792169689Skan one_cprop_pass (pass + 1, true, false); 793169689Skan timevar_pop (TV_CPROP2); 79452284Sobrien free_gcse_mem (); 79552284Sobrien 796169689Skan if (dump_file) 79750397Sobrien { 798169689Skan fprintf (dump_file, "GCSE of %s: %d basic blocks, ", 799132718Skan current_function_name (), n_basic_blocks); 800169689Skan fprintf (dump_file, "%d pass%s, %d bytes\n\n", 80150397Sobrien pass, pass > 1 ? "es" : "", max_pass_bytes); 80250397Sobrien } 80350397Sobrien 80490075Sobrien obstack_free (&gcse_obstack, NULL); 80550397Sobrien free_reg_set_mem (); 806169689Skan 80790075Sobrien /* We are finished with alias. */ 80890075Sobrien end_alias_analysis (); 80990075Sobrien allocate_reg_info (max_reg_num (), FALSE, FALSE); 81090075Sobrien 811132718Skan if (!optimize_size && flag_gcse_sm) 812169689Skan { 813169689Skan timevar_push (TV_LSM); 814169689Skan store_motion (); 815169689Skan timevar_pop (TV_LSM); 816169689Skan } 817132718Skan 81890075Sobrien /* Record where pseudo-registers are set. */ 81952284Sobrien return run_jump_opt_after_gcse; 82050397Sobrien} 82150397Sobrien 82250397Sobrien/* Misc. utilities. */ 82350397Sobrien 824132718Skan/* Nonzero for each mode that supports (set (reg) (reg)). 825132718Skan This is trivially true for integer and floating point values. 826132718Skan It may or may not be true for condition codes. */ 827132718Skanstatic char can_copy[(int) NUM_MACHINE_MODES]; 828132718Skan 82950397Sobrien/* Compute which modes support reg/reg copy operations. */ 83050397Sobrien 83150397Sobrienstatic void 832132718Skancompute_can_copy (void) 83350397Sobrien{ 83450397Sobrien int i; 83550397Sobrien#ifndef AVOID_CCMODE_COPIES 83690075Sobrien rtx reg, insn; 83750397Sobrien#endif 838132718Skan memset (can_copy, 0, NUM_MACHINE_MODES); 83950397Sobrien 84050397Sobrien start_sequence (); 84150397Sobrien for (i = 0; i < NUM_MACHINE_MODES; i++) 84290075Sobrien if (GET_MODE_CLASS (i) == MODE_CC) 84390075Sobrien { 84450397Sobrien#ifdef AVOID_CCMODE_COPIES 845132718Skan can_copy[i] = 0; 84650397Sobrien#else 84790075Sobrien reg = gen_rtx_REG ((enum machine_mode) i, LAST_VIRTUAL_REGISTER + 1); 84890075Sobrien insn = emit_insn (gen_rtx_SET (VOIDmode, reg, reg)); 84990075Sobrien if (recog (PATTERN (insn), insn, NULL) >= 0) 850132718Skan can_copy[i] = 1; 85150397Sobrien#endif 85290075Sobrien } 85390075Sobrien else 854132718Skan can_copy[i] = 1; 85590075Sobrien 85650397Sobrien end_sequence (); 85750397Sobrien} 858132718Skan 859132718Skan/* Returns whether the mode supports reg/reg copy operations. */ 860132718Skan 861132718Skanbool 862132718Skancan_copy_p (enum machine_mode mode) 863132718Skan{ 864132718Skan static bool can_copy_init_p = false; 865132718Skan 866132718Skan if (! can_copy_init_p) 867132718Skan { 868132718Skan compute_can_copy (); 869132718Skan can_copy_init_p = true; 870132718Skan } 871132718Skan 872132718Skan return can_copy[mode] != 0; 873132718Skan} 87450397Sobrien 87550397Sobrien/* Cover function to xmalloc to record bytes allocated. */ 87650397Sobrien 877132718Skanstatic void * 878132718Skangmalloc (size_t size) 87950397Sobrien{ 88050397Sobrien bytes_used += size; 88150397Sobrien return xmalloc (size); 88250397Sobrien} 88350397Sobrien 884132718Skan/* Cover function to xcalloc to record bytes allocated. */ 885132718Skan 886132718Skanstatic void * 887132718Skangcalloc (size_t nelem, size_t elsize) 888132718Skan{ 889132718Skan bytes_used += nelem * elsize; 890132718Skan return xcalloc (nelem, elsize); 891132718Skan} 892132718Skan 89350397Sobrien/* Cover function to xrealloc. 89450397Sobrien We don't record the additional size since we don't know it. 89550397Sobrien It won't affect memory usage stats much anyway. */ 89650397Sobrien 897132718Skanstatic void * 898132718Skangrealloc (void *ptr, size_t size) 89950397Sobrien{ 90050397Sobrien return xrealloc (ptr, size); 90150397Sobrien} 90250397Sobrien 903117395Skan/* Cover function to obstack_alloc. */ 90450397Sobrien 905132718Skanstatic void * 906132718Skangcse_alloc (unsigned long size) 90750397Sobrien{ 908117395Skan bytes_used += size; 909132718Skan return obstack_alloc (&gcse_obstack, size); 91050397Sobrien} 91150397Sobrien 91250397Sobrien/* Allocate memory for the cuid mapping array, 91350397Sobrien and reg/memory set tracking tables. 91450397Sobrien 91550397Sobrien This is called at the start of each pass. */ 91650397Sobrien 91750397Sobrienstatic void 918169689Skanalloc_gcse_mem (void) 91950397Sobrien{ 920132718Skan int i; 921169689Skan basic_block bb; 92250397Sobrien rtx insn; 92350397Sobrien 92450397Sobrien /* Find the largest UID and create a mapping from UIDs to CUIDs. 92550397Sobrien CUIDs are like UIDs except they increase monotonically, have no gaps, 926169689Skan and only apply to real insns. 927169689Skan (Actually, there are gaps, for insn that are not inside a basic block. 928169689Skan but we should never see those anyway, so this is OK.) */ 92950397Sobrien 93050397Sobrien max_uid = get_max_uid (); 931132718Skan uid_cuid = gcalloc (max_uid + 1, sizeof (int)); 932169689Skan i = 0; 933169689Skan FOR_EACH_BB (bb) 934169689Skan FOR_BB_INSNS (bb, insn) 935169689Skan { 936169689Skan if (INSN_P (insn)) 937169689Skan uid_cuid[INSN_UID (insn)] = i++; 938169689Skan else 939169689Skan uid_cuid[INSN_UID (insn)] = i; 940169689Skan } 94150397Sobrien 94250397Sobrien /* Create a table mapping cuids to insns. */ 94350397Sobrien 94450397Sobrien max_cuid = i; 945132718Skan cuid_insn = gcalloc (max_cuid + 1, sizeof (rtx)); 946169689Skan i = 0; 947169689Skan FOR_EACH_BB (bb) 948169689Skan FOR_BB_INSNS (bb, insn) 949169689Skan if (INSN_P (insn)) 950169689Skan CUID_INSN (i++) = insn; 95150397Sobrien 95250397Sobrien /* Allocate vars to track sets of regs. */ 953169689Skan reg_set_bitmap = BITMAP_ALLOC (NULL); 95450397Sobrien 95550397Sobrien /* Allocate vars to track sets of regs, memory per block. */ 956132718Skan reg_set_in_block = sbitmap_vector_alloc (last_basic_block, max_gcse_regno); 95790075Sobrien /* Allocate array to keep a list of insns which modify memory in each 95890075Sobrien basic block. */ 959132718Skan modify_mem_list = gcalloc (last_basic_block, sizeof (rtx)); 960132718Skan canon_modify_mem_list = gcalloc (last_basic_block, sizeof (rtx)); 961169689Skan modify_mem_list_set = BITMAP_ALLOC (NULL); 962169689Skan blocks_with_calls = BITMAP_ALLOC (NULL); 96350397Sobrien} 96450397Sobrien 96550397Sobrien/* Free memory allocated by alloc_gcse_mem. */ 96650397Sobrien 96750397Sobrienstatic void 968132718Skanfree_gcse_mem (void) 96950397Sobrien{ 97050397Sobrien free (uid_cuid); 97150397Sobrien free (cuid_insn); 97250397Sobrien 973169689Skan BITMAP_FREE (reg_set_bitmap); 97450397Sobrien 97590075Sobrien sbitmap_vector_free (reg_set_in_block); 97690075Sobrien free_modify_mem_tables (); 977169689Skan BITMAP_FREE (modify_mem_list_set); 978169689Skan BITMAP_FREE (blocks_with_calls); 97950397Sobrien} 98052284Sobrien 98152284Sobrien/* Compute the local properties of each recorded expression. 98252284Sobrien 98390075Sobrien Local properties are those that are defined by the block, irrespective of 98490075Sobrien other blocks. 98590075Sobrien 98652284Sobrien An expression is transparent in a block if its operands are not modified 98752284Sobrien in the block. 98852284Sobrien 98952284Sobrien An expression is computed (locally available) in a block if it is computed 99052284Sobrien at least once and expression would contain the same value if the 99152284Sobrien computation was moved to the end of the block. 99252284Sobrien 99352284Sobrien An expression is locally anticipatable in a block if it is computed at 99452284Sobrien least once and expression would contain the same value if the computation 99552284Sobrien was moved to the beginning of the block. 99652284Sobrien 99790075Sobrien We call this routine for cprop, pre and code hoisting. They all compute 99890075Sobrien basically the same information and thus can easily share this code. 99952284Sobrien 100090075Sobrien TRANSP, COMP, and ANTLOC are destination sbitmaps for recording local 100190075Sobrien properties. If NULL, then it is not necessary to compute or record that 100290075Sobrien particular property. 100352284Sobrien 1004117395Skan TABLE controls which hash table to look at. If it is set hash table, 1005117395Skan additionally, TRANSP is computed as ~TRANSP, since this is really cprop's 100690075Sobrien ABSALTERED. */ 1007117395Skan 100852284Sobrienstatic void 1009169689Skancompute_local_properties (sbitmap *transp, sbitmap *comp, sbitmap *antloc, 1010169689Skan struct hash_table *table) 101150397Sobrien{ 1012117395Skan unsigned int i; 1013117395Skan 101452284Sobrien /* Initialize any bitmaps that were passed in. */ 101552284Sobrien if (transp) 101652284Sobrien { 1017117395Skan if (table->set_p) 1018117395Skan sbitmap_vector_zero (transp, last_basic_block); 101952284Sobrien else 1020117395Skan sbitmap_vector_ones (transp, last_basic_block); 102152284Sobrien } 102290075Sobrien 102352284Sobrien if (comp) 1024117395Skan sbitmap_vector_zero (comp, last_basic_block); 102552284Sobrien if (antloc) 1026117395Skan sbitmap_vector_zero (antloc, last_basic_block); 102750397Sobrien 1028117395Skan for (i = 0; i < table->size; i++) 102950397Sobrien { 103052284Sobrien struct expr *expr; 103152284Sobrien 1032117395Skan for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash) 103352284Sobrien { 103490075Sobrien int indx = expr->bitmap_index; 103552284Sobrien struct occr *occr; 103652284Sobrien 103752284Sobrien /* The expression is transparent in this block if it is not killed. 103852284Sobrien We start by assuming all are transparent [none are killed], and 103952284Sobrien then reset the bits for those that are. */ 104052284Sobrien if (transp) 1041117395Skan compute_transp (expr->expr, indx, transp, table->set_p); 104252284Sobrien 104352284Sobrien /* The occurrences recorded in antic_occr are exactly those that 1044117395Skan we want to set to nonzero in ANTLOC. */ 104552284Sobrien if (antloc) 104690075Sobrien for (occr = expr->antic_occr; occr != NULL; occr = occr->next) 104790075Sobrien { 104890075Sobrien SET_BIT (antloc[BLOCK_NUM (occr->insn)], indx); 104952284Sobrien 105090075Sobrien /* While we're scanning the table, this is a good place to 105190075Sobrien initialize this. */ 105290075Sobrien occr->deleted_p = 0; 105390075Sobrien } 105452284Sobrien 105552284Sobrien /* The occurrences recorded in avail_occr are exactly those that 1056117395Skan we want to set to nonzero in COMP. */ 105752284Sobrien if (comp) 105890075Sobrien for (occr = expr->avail_occr; occr != NULL; occr = occr->next) 105990075Sobrien { 106090075Sobrien SET_BIT (comp[BLOCK_NUM (occr->insn)], indx); 106152284Sobrien 106290075Sobrien /* While we're scanning the table, this is a good place to 106390075Sobrien initialize this. */ 106490075Sobrien occr->copied_p = 0; 106590075Sobrien } 106652284Sobrien 106752284Sobrien /* While we're scanning the table, this is a good place to 106852284Sobrien initialize this. */ 106952284Sobrien expr->reaching_reg = 0; 107052284Sobrien } 107150397Sobrien } 107250397Sobrien} 107350397Sobrien 107450397Sobrien/* Register set information. 107550397Sobrien 107650397Sobrien `reg_set_table' records where each register is set or otherwise 107750397Sobrien modified. */ 107850397Sobrien 107950397Sobrienstatic struct obstack reg_set_obstack; 108050397Sobrien 108150397Sobrienstatic void 1082132718Skanalloc_reg_set_mem (int n_regs) 108350397Sobrien{ 108450397Sobrien reg_set_table_size = n_regs + REG_SET_TABLE_SLOP; 1085132718Skan reg_set_table = gcalloc (reg_set_table_size, sizeof (struct reg_set *)); 108650397Sobrien 108750397Sobrien gcc_obstack_init (®_set_obstack); 108850397Sobrien} 108950397Sobrien 109050397Sobrienstatic void 1091132718Skanfree_reg_set_mem (void) 109250397Sobrien{ 109350397Sobrien free (reg_set_table); 109490075Sobrien obstack_free (®_set_obstack, NULL); 109550397Sobrien} 109650397Sobrien 109750397Sobrien/* Record REGNO in the reg_set table. */ 109850397Sobrien 109950397Sobrienstatic void 1100132718Skanrecord_one_set (int regno, rtx insn) 110150397Sobrien{ 110290075Sobrien /* Allocate a new reg_set element and link it onto the list. */ 110390075Sobrien struct reg_set *new_reg_info; 110450397Sobrien 110550397Sobrien /* If the table isn't big enough, enlarge it. */ 110650397Sobrien if (regno >= reg_set_table_size) 110750397Sobrien { 110850397Sobrien int new_size = regno + REG_SET_TABLE_SLOP; 110990075Sobrien 1110132718Skan reg_set_table = grealloc (reg_set_table, 1111132718Skan new_size * sizeof (struct reg_set *)); 1112132718Skan memset (reg_set_table + reg_set_table_size, 0, 111390075Sobrien (new_size - reg_set_table_size) * sizeof (struct reg_set *)); 111450397Sobrien reg_set_table_size = new_size; 111550397Sobrien } 111650397Sobrien 1117132718Skan new_reg_info = obstack_alloc (®_set_obstack, sizeof (struct reg_set)); 111850397Sobrien bytes_used += sizeof (struct reg_set); 1119169689Skan new_reg_info->bb_index = BLOCK_NUM (insn); 112090075Sobrien new_reg_info->next = reg_set_table[regno]; 112190075Sobrien reg_set_table[regno] = new_reg_info; 112250397Sobrien} 112350397Sobrien 112490075Sobrien/* Called from compute_sets via note_stores to handle one SET or CLOBBER in 112590075Sobrien an insn. The DATA is really the instruction in which the SET is 112690075Sobrien occurring. */ 112750397Sobrien 112850397Sobrienstatic void 1129132718Skanrecord_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data) 113050397Sobrien{ 113190075Sobrien rtx record_set_insn = (rtx) data; 113250397Sobrien 1133169689Skan if (REG_P (dest) && REGNO (dest) >= FIRST_PSEUDO_REGISTER) 113490075Sobrien record_one_set (REGNO (dest), record_set_insn); 113550397Sobrien} 113650397Sobrien 113750397Sobrien/* Scan the function and record each set of each pseudo-register. 113850397Sobrien 113990075Sobrien This is called once, at the start of the gcse pass. See the comments for 1140132718Skan `reg_set_table' for further documentation. */ 114150397Sobrien 114250397Sobrienstatic void 1143169689Skancompute_sets (void) 114450397Sobrien{ 1145169689Skan basic_block bb; 114690075Sobrien rtx insn; 114750397Sobrien 1148169689Skan FOR_EACH_BB (bb) 1149169689Skan FOR_BB_INSNS (bb, insn) 1150169689Skan if (INSN_P (insn)) 1151169689Skan note_stores (PATTERN (insn), record_set_info, insn); 115250397Sobrien} 115350397Sobrien 115450397Sobrien/* Hash table support. */ 115550397Sobrien 115690075Sobrienstruct reg_avail_info 115790075Sobrien{ 1158117395Skan basic_block last_bb; 115990075Sobrien int first_set; 116090075Sobrien int last_set; 116190075Sobrien}; 116250397Sobrien 116390075Sobrienstatic struct reg_avail_info *reg_avail_info; 1164117395Skanstatic basic_block current_bb; 116550397Sobrien 116650397Sobrien 116790075Sobrien/* See whether X, the source of a set, is something we want to consider for 116890075Sobrien GCSE. */ 116990075Sobrien 117050397Sobrienstatic int 1171132718Skanwant_to_gcse_p (rtx x) 117250397Sobrien{ 1173169689Skan#ifdef STACK_REGS 1174169689Skan /* On register stack architectures, don't GCSE constants from the 1175169689Skan constant pool, as the benefits are often swamped by the overhead 1176169689Skan of shuffling the register stack between basic blocks. */ 1177169689Skan if (IS_STACK_MODE (GET_MODE (x))) 1178169689Skan x = avoid_constant_pool_reference (x); 1179169689Skan#endif 118050397Sobrien 118190075Sobrien switch (GET_CODE (x)) 118250397Sobrien { 118350397Sobrien case REG: 118450397Sobrien case SUBREG: 118550397Sobrien case CONST_INT: 118650397Sobrien case CONST_DOUBLE: 118796263Sobrien case CONST_VECTOR: 118850397Sobrien case CALL: 118950397Sobrien return 0; 119050397Sobrien 119150397Sobrien default: 1192169689Skan return can_assign_to_reg_p (x); 119350397Sobrien } 1194169689Skan} 119550397Sobrien 1196169689Skan/* Used internally by can_assign_to_reg_p. */ 1197169689Skan 1198169689Skanstatic GTY(()) rtx test_insn; 1199169689Skan 1200169689Skan/* Return true if we can assign X to a pseudo register. */ 1201169689Skan 1202169689Skanstatic bool 1203169689Skancan_assign_to_reg_p (rtx x) 1204169689Skan{ 1205169689Skan int num_clobbers = 0; 1206169689Skan int icode; 1207169689Skan 120890075Sobrien /* If this is a valid operand, we are OK. If it's VOIDmode, we aren't. */ 120990075Sobrien if (general_operand (x, GET_MODE (x))) 121090075Sobrien return 1; 121190075Sobrien else if (GET_MODE (x) == VOIDmode) 121290075Sobrien return 0; 121390075Sobrien 121490075Sobrien /* Otherwise, check if we can make a valid insn from it. First initialize 121590075Sobrien our test insn if we haven't already. */ 121690075Sobrien if (test_insn == 0) 121790075Sobrien { 121890075Sobrien test_insn 121990075Sobrien = make_insn_raw (gen_rtx_SET (VOIDmode, 122090075Sobrien gen_rtx_REG (word_mode, 122190075Sobrien FIRST_PSEUDO_REGISTER * 2), 122290075Sobrien const0_rtx)); 122390075Sobrien NEXT_INSN (test_insn) = PREV_INSN (test_insn) = 0; 122490075Sobrien } 122590075Sobrien 122690075Sobrien /* Now make an insn like the one we would make when GCSE'ing and see if 122790075Sobrien valid. */ 122890075Sobrien PUT_MODE (SET_DEST (PATTERN (test_insn)), GET_MODE (x)); 122990075Sobrien SET_SRC (PATTERN (test_insn)) = x; 123090075Sobrien return ((icode = recog (PATTERN (test_insn), test_insn, &num_clobbers)) >= 0 123190075Sobrien && (num_clobbers == 0 || ! added_clobbers_hard_reg_p (icode))); 123250397Sobrien} 123350397Sobrien 1234117395Skan/* Return nonzero if the operands of expression X are unchanged from the 123550397Sobrien start of INSN's basic block up to but not including INSN (if AVAIL_P == 0), 123650397Sobrien or from INSN to the end of INSN's basic block (if AVAIL_P != 0). */ 123750397Sobrien 123850397Sobrienstatic int 1239132718Skanoprs_unchanged_p (rtx x, rtx insn, int avail_p) 124050397Sobrien{ 124190075Sobrien int i, j; 124250397Sobrien enum rtx_code code; 124390075Sobrien const char *fmt; 124450397Sobrien 124550397Sobrien if (x == 0) 124650397Sobrien return 1; 124750397Sobrien 124850397Sobrien code = GET_CODE (x); 124950397Sobrien switch (code) 125050397Sobrien { 125150397Sobrien case REG: 125290075Sobrien { 125390075Sobrien struct reg_avail_info *info = ®_avail_info[REGNO (x)]; 125450397Sobrien 125590075Sobrien if (info->last_bb != current_bb) 125690075Sobrien return 1; 1257117395Skan if (avail_p) 125890075Sobrien return info->last_set < INSN_CUID (insn); 125990075Sobrien else 126090075Sobrien return info->first_set >= INSN_CUID (insn); 126190075Sobrien } 126290075Sobrien 126350397Sobrien case MEM: 1264117395Skan if (load_killed_in_block_p (current_bb, INSN_CUID (insn), 126590075Sobrien x, avail_p)) 126690075Sobrien return 0; 126750397Sobrien else 126890075Sobrien return oprs_unchanged_p (XEXP (x, 0), insn, avail_p); 126950397Sobrien 127050397Sobrien case PRE_DEC: 127150397Sobrien case PRE_INC: 127250397Sobrien case POST_DEC: 127350397Sobrien case POST_INC: 127490075Sobrien case PRE_MODIFY: 127590075Sobrien case POST_MODIFY: 127650397Sobrien return 0; 127750397Sobrien 127850397Sobrien case PC: 127950397Sobrien case CC0: /*FIXME*/ 128050397Sobrien case CONST: 128150397Sobrien case CONST_INT: 128250397Sobrien case CONST_DOUBLE: 128396263Sobrien case CONST_VECTOR: 128450397Sobrien case SYMBOL_REF: 128550397Sobrien case LABEL_REF: 128650397Sobrien case ADDR_VEC: 128750397Sobrien case ADDR_DIFF_VEC: 128850397Sobrien return 1; 128950397Sobrien 129050397Sobrien default: 129150397Sobrien break; 129250397Sobrien } 129350397Sobrien 129490075Sobrien for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--) 129550397Sobrien { 129650397Sobrien if (fmt[i] == 'e') 129750397Sobrien { 129890075Sobrien /* If we are about to do the last recursive call needed at this 129990075Sobrien level, change it into iteration. This function is called enough 130090075Sobrien to be worth it. */ 130190075Sobrien if (i == 0) 130290075Sobrien return oprs_unchanged_p (XEXP (x, i), insn, avail_p); 130350397Sobrien 130490075Sobrien else if (! oprs_unchanged_p (XEXP (x, i), insn, avail_p)) 130550397Sobrien return 0; 130650397Sobrien } 130750397Sobrien else if (fmt[i] == 'E') 130890075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 130990075Sobrien if (! oprs_unchanged_p (XVECEXP (x, i, j), insn, avail_p)) 131090075Sobrien return 0; 131150397Sobrien } 131250397Sobrien 131350397Sobrien return 1; 131450397Sobrien} 131550397Sobrien 131690075Sobrien/* Used for communication between mems_conflict_for_gcse_p and 131790075Sobrien load_killed_in_block_p. Nonzero if mems_conflict_for_gcse_p finds a 131890075Sobrien conflict between two memory references. */ 131990075Sobrienstatic int gcse_mems_conflict_p; 132090075Sobrien 132190075Sobrien/* Used for communication between mems_conflict_for_gcse_p and 132290075Sobrien load_killed_in_block_p. A memory reference for a load instruction, 132390075Sobrien mems_conflict_for_gcse_p will see if a memory store conflicts with 132490075Sobrien this memory load. */ 132590075Sobrienstatic rtx gcse_mem_operand; 132690075Sobrien 132790075Sobrien/* DEST is the output of an instruction. If it is a memory reference, and 132890075Sobrien possibly conflicts with the load found in gcse_mem_operand, then set 132990075Sobrien gcse_mems_conflict_p to a nonzero value. */ 133090075Sobrien 133190075Sobrienstatic void 1332132718Skanmems_conflict_for_gcse_p (rtx dest, rtx setter ATTRIBUTE_UNUSED, 1333132718Skan void *data ATTRIBUTE_UNUSED) 133490075Sobrien{ 133590075Sobrien while (GET_CODE (dest) == SUBREG 133690075Sobrien || GET_CODE (dest) == ZERO_EXTRACT 133790075Sobrien || GET_CODE (dest) == STRICT_LOW_PART) 133890075Sobrien dest = XEXP (dest, 0); 133990075Sobrien 134090075Sobrien /* If DEST is not a MEM, then it will not conflict with the load. Note 134190075Sobrien that function calls are assumed to clobber memory, but are handled 134290075Sobrien elsewhere. */ 1343169689Skan if (! MEM_P (dest)) 134490075Sobrien return; 134590075Sobrien 134690075Sobrien /* If we are setting a MEM in our list of specially recognized MEMs, 1347117395Skan don't mark as killed this time. */ 1348117395Skan 1349132718Skan if (expr_equiv_p (dest, gcse_mem_operand) && pre_ldst_mems != NULL) 135090075Sobrien { 135190075Sobrien if (!find_rtx_in_ldst (dest)) 135290075Sobrien gcse_mems_conflict_p = 1; 135390075Sobrien return; 135490075Sobrien } 135590075Sobrien 135690075Sobrien if (true_dependence (dest, GET_MODE (dest), gcse_mem_operand, 135790075Sobrien rtx_addr_varies_p)) 135890075Sobrien gcse_mems_conflict_p = 1; 135990075Sobrien} 136090075Sobrien 136190075Sobrien/* Return nonzero if the expression in X (a memory reference) is killed 136290075Sobrien in block BB before or after the insn with the CUID in UID_LIMIT. 136390075Sobrien AVAIL_P is nonzero for kills after UID_LIMIT, and zero for kills 136490075Sobrien before UID_LIMIT. 136590075Sobrien 136690075Sobrien To check the entire block, set UID_LIMIT to max_uid + 1 and 136790075Sobrien AVAIL_P to 0. */ 136890075Sobrien 136990075Sobrienstatic int 1370132718Skanload_killed_in_block_p (basic_block bb, int uid_limit, rtx x, int avail_p) 137190075Sobrien{ 137290075Sobrien rtx list_entry = modify_mem_list[bb->index]; 1373169689Skan 1374169689Skan /* If this is a readonly then we aren't going to be changing it. */ 1375169689Skan if (MEM_READONLY_P (x)) 1376169689Skan return 0; 1377169689Skan 137890075Sobrien while (list_entry) 137990075Sobrien { 138090075Sobrien rtx setter; 138190075Sobrien /* Ignore entries in the list that do not apply. */ 138290075Sobrien if ((avail_p 138390075Sobrien && INSN_CUID (XEXP (list_entry, 0)) < uid_limit) 138490075Sobrien || (! avail_p 138590075Sobrien && INSN_CUID (XEXP (list_entry, 0)) > uid_limit)) 138690075Sobrien { 138790075Sobrien list_entry = XEXP (list_entry, 1); 138890075Sobrien continue; 138990075Sobrien } 139090075Sobrien 139190075Sobrien setter = XEXP (list_entry, 0); 139290075Sobrien 139390075Sobrien /* If SETTER is a call everything is clobbered. Note that calls 139490075Sobrien to pure functions are never put on the list, so we need not 139590075Sobrien worry about them. */ 1396169689Skan if (CALL_P (setter)) 139790075Sobrien return 1; 139890075Sobrien 139990075Sobrien /* SETTER must be an INSN of some kind that sets memory. Call 1400117395Skan note_stores to examine each hunk of memory that is modified. 140190075Sobrien 140290075Sobrien The note_stores interface is pretty limited, so we have to 140390075Sobrien communicate via global variables. Yuk. */ 140490075Sobrien gcse_mem_operand = x; 140590075Sobrien gcse_mems_conflict_p = 0; 140690075Sobrien note_stores (PATTERN (setter), mems_conflict_for_gcse_p, NULL); 140790075Sobrien if (gcse_mems_conflict_p) 140890075Sobrien return 1; 140990075Sobrien list_entry = XEXP (list_entry, 1); 141090075Sobrien } 141190075Sobrien return 0; 141290075Sobrien} 141390075Sobrien 1414117395Skan/* Return nonzero if the operands of expression X are unchanged from 141550397Sobrien the start of INSN's basic block up to but not including INSN. */ 141650397Sobrien 141750397Sobrienstatic int 1418132718Skanoprs_anticipatable_p (rtx x, rtx insn) 141950397Sobrien{ 142050397Sobrien return oprs_unchanged_p (x, insn, 0); 142150397Sobrien} 142250397Sobrien 1423117395Skan/* Return nonzero if the operands of expression X are unchanged from 142450397Sobrien INSN to the end of INSN's basic block. */ 142550397Sobrien 142650397Sobrienstatic int 1427132718Skanoprs_available_p (rtx x, rtx insn) 142850397Sobrien{ 142950397Sobrien return oprs_unchanged_p (x, insn, 1); 143050397Sobrien} 143150397Sobrien 143250397Sobrien/* Hash expression X. 143350397Sobrien 143490075Sobrien MODE is only used if X is a CONST_INT. DO_NOT_RECORD_P is a boolean 143590075Sobrien indicating if a volatile operand is found or if the expression contains 1436132718Skan something we don't want to insert in the table. HASH_TABLE_SIZE is 1437169689Skan the current size of the hash table to be probed. */ 143890075Sobrien 143950397Sobrienstatic unsigned int 1440132718Skanhash_expr (rtx x, enum machine_mode mode, int *do_not_record_p, 1441132718Skan int hash_table_size) 144250397Sobrien{ 144350397Sobrien unsigned int hash; 144450397Sobrien 144550397Sobrien *do_not_record_p = 0; 144650397Sobrien 1447169689Skan hash = hash_rtx (x, mode, do_not_record_p, 1448169689Skan NULL, /*have_reg_qty=*/false); 144950397Sobrien return hash % hash_table_size; 145050397Sobrien} 145150397Sobrien 145250397Sobrien/* Hash a set of register REGNO. 145350397Sobrien 145490075Sobrien Sets are hashed on the register that is set. This simplifies the PRE copy 145590075Sobrien propagation code. 145650397Sobrien 145750397Sobrien ??? May need to make things more elaborate. Later, as necessary. */ 145850397Sobrien 145950397Sobrienstatic unsigned int 1460132718Skanhash_set (int regno, int hash_table_size) 146150397Sobrien{ 146250397Sobrien unsigned int hash; 146350397Sobrien 146450397Sobrien hash = regno; 146550397Sobrien return hash % hash_table_size; 146650397Sobrien} 146750397Sobrien 1468169689Skan/* Return nonzero if exp1 is equivalent to exp2. */ 146950397Sobrien 147050397Sobrienstatic int 1471132718Skanexpr_equiv_p (rtx x, rtx y) 147250397Sobrien{ 1473169689Skan return exp_equiv_p (x, y, 0, true); 147450397Sobrien} 147550397Sobrien 1476117395Skan/* Insert expression X in INSN in the hash TABLE. 147750397Sobrien If it is already present, record it as the last occurrence in INSN's 147850397Sobrien basic block. 147950397Sobrien 148050397Sobrien MODE is the mode of the value X is being stored into. 148150397Sobrien It is only used if X is a CONST_INT. 148250397Sobrien 1483117395Skan ANTIC_P is nonzero if X is an anticipatable expression. 1484117395Skan AVAIL_P is nonzero if X is an available expression. */ 148550397Sobrien 148650397Sobrienstatic void 1487132718Skaninsert_expr_in_table (rtx x, enum machine_mode mode, rtx insn, int antic_p, 1488132718Skan int avail_p, struct hash_table *table) 148950397Sobrien{ 149050397Sobrien int found, do_not_record_p; 149150397Sobrien unsigned int hash; 149250397Sobrien struct expr *cur_expr, *last_expr = NULL; 149350397Sobrien struct occr *antic_occr, *avail_occr; 149450397Sobrien 1495117395Skan hash = hash_expr (x, mode, &do_not_record_p, table->size); 149650397Sobrien 149750397Sobrien /* Do not insert expression in table if it contains volatile operands, 149850397Sobrien or if hash_expr determines the expression is something we don't want 149950397Sobrien to or can't handle. */ 150050397Sobrien if (do_not_record_p) 150150397Sobrien return; 150250397Sobrien 1503117395Skan cur_expr = table->table[hash]; 150450397Sobrien found = 0; 150550397Sobrien 150690075Sobrien while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x))) 150750397Sobrien { 150850397Sobrien /* If the expression isn't found, save a pointer to the end of 150950397Sobrien the list. */ 151050397Sobrien last_expr = cur_expr; 151150397Sobrien cur_expr = cur_expr->next_same_hash; 151250397Sobrien } 151350397Sobrien 151450397Sobrien if (! found) 151550397Sobrien { 1516132718Skan cur_expr = gcse_alloc (sizeof (struct expr)); 151750397Sobrien bytes_used += sizeof (struct expr); 1518117395Skan if (table->table[hash] == NULL) 151990075Sobrien /* This is the first pattern that hashed to this index. */ 1520117395Skan table->table[hash] = cur_expr; 152150397Sobrien else 152290075Sobrien /* Add EXPR to end of this hash chain. */ 152390075Sobrien last_expr->next_same_hash = cur_expr; 152490075Sobrien 1525117395Skan /* Set the fields of the expr element. */ 152650397Sobrien cur_expr->expr = x; 1527117395Skan cur_expr->bitmap_index = table->n_elems++; 152850397Sobrien cur_expr->next_same_hash = NULL; 152950397Sobrien cur_expr->antic_occr = NULL; 153050397Sobrien cur_expr->avail_occr = NULL; 153150397Sobrien } 153250397Sobrien 153350397Sobrien /* Now record the occurrence(s). */ 153450397Sobrien if (antic_p) 153550397Sobrien { 153650397Sobrien antic_occr = cur_expr->antic_occr; 153750397Sobrien 1538169689Skan if (antic_occr && BLOCK_NUM (antic_occr->insn) != BLOCK_NUM (insn)) 1539169689Skan antic_occr = NULL; 154050397Sobrien 154150397Sobrien if (antic_occr) 154290075Sobrien /* Found another instance of the expression in the same basic block. 154390075Sobrien Prefer the currently recorded one. We want the first one in the 154490075Sobrien block and the block is scanned from start to end. */ 154590075Sobrien ; /* nothing to do */ 154650397Sobrien else 154750397Sobrien { 154850397Sobrien /* First occurrence of this expression in this basic block. */ 1549132718Skan antic_occr = gcse_alloc (sizeof (struct occr)); 155050397Sobrien bytes_used += sizeof (struct occr); 155150397Sobrien antic_occr->insn = insn; 1552169689Skan antic_occr->next = cur_expr->antic_occr; 1553169689Skan antic_occr->deleted_p = 0; 1554169689Skan cur_expr->antic_occr = antic_occr; 155550397Sobrien } 155650397Sobrien } 155750397Sobrien 155850397Sobrien if (avail_p) 155950397Sobrien { 156050397Sobrien avail_occr = cur_expr->avail_occr; 156150397Sobrien 1562169689Skan if (avail_occr && BLOCK_NUM (avail_occr->insn) == BLOCK_NUM (insn)) 156350397Sobrien { 1564169689Skan /* Found another instance of the expression in the same basic block. 1565169689Skan Prefer this occurrence to the currently recorded one. We want 1566169689Skan the last one in the block and the block is scanned from start 1567169689Skan to end. */ 1568169689Skan avail_occr->insn = insn; 156950397Sobrien } 157050397Sobrien else 157150397Sobrien { 157250397Sobrien /* First occurrence of this expression in this basic block. */ 1573132718Skan avail_occr = gcse_alloc (sizeof (struct occr)); 157450397Sobrien bytes_used += sizeof (struct occr); 157550397Sobrien avail_occr->insn = insn; 1576169689Skan avail_occr->next = cur_expr->avail_occr; 1577169689Skan avail_occr->deleted_p = 0; 1578169689Skan cur_expr->avail_occr = avail_occr; 157950397Sobrien } 158050397Sobrien } 158150397Sobrien} 158250397Sobrien 158350397Sobrien/* Insert pattern X in INSN in the hash table. 158450397Sobrien X is a SET of a reg to either another reg or a constant. 158550397Sobrien If it is already present, record it as the last occurrence in INSN's 158650397Sobrien basic block. */ 158750397Sobrien 158850397Sobrienstatic void 1589132718Skaninsert_set_in_table (rtx x, rtx insn, struct hash_table *table) 159050397Sobrien{ 159150397Sobrien int found; 159250397Sobrien unsigned int hash; 159350397Sobrien struct expr *cur_expr, *last_expr = NULL; 1594169689Skan struct occr *cur_occr; 159550397Sobrien 1596169689Skan gcc_assert (GET_CODE (x) == SET && REG_P (SET_DEST (x))); 159750397Sobrien 1598117395Skan hash = hash_set (REGNO (SET_DEST (x)), table->size); 159950397Sobrien 1600117395Skan cur_expr = table->table[hash]; 160150397Sobrien found = 0; 160250397Sobrien 160390075Sobrien while (cur_expr && 0 == (found = expr_equiv_p (cur_expr->expr, x))) 160450397Sobrien { 160550397Sobrien /* If the expression isn't found, save a pointer to the end of 160650397Sobrien the list. */ 160750397Sobrien last_expr = cur_expr; 160850397Sobrien cur_expr = cur_expr->next_same_hash; 160950397Sobrien } 161050397Sobrien 161150397Sobrien if (! found) 161250397Sobrien { 1613132718Skan cur_expr = gcse_alloc (sizeof (struct expr)); 161450397Sobrien bytes_used += sizeof (struct expr); 1615117395Skan if (table->table[hash] == NULL) 161690075Sobrien /* This is the first pattern that hashed to this index. */ 1617117395Skan table->table[hash] = cur_expr; 161850397Sobrien else 161990075Sobrien /* Add EXPR to end of this hash chain. */ 162090075Sobrien last_expr->next_same_hash = cur_expr; 162190075Sobrien 162250397Sobrien /* Set the fields of the expr element. 162350397Sobrien We must copy X because it can be modified when copy propagation is 162450397Sobrien performed on its operands. */ 162550397Sobrien cur_expr->expr = copy_rtx (x); 1626117395Skan cur_expr->bitmap_index = table->n_elems++; 162750397Sobrien cur_expr->next_same_hash = NULL; 162850397Sobrien cur_expr->antic_occr = NULL; 162950397Sobrien cur_expr->avail_occr = NULL; 163050397Sobrien } 163150397Sobrien 163250397Sobrien /* Now record the occurrence. */ 163350397Sobrien cur_occr = cur_expr->avail_occr; 163450397Sobrien 1635169689Skan if (cur_occr && BLOCK_NUM (cur_occr->insn) == BLOCK_NUM (insn)) 163650397Sobrien { 1637169689Skan /* Found another instance of the expression in the same basic block. 1638169689Skan Prefer this occurrence to the currently recorded one. We want 1639169689Skan the last one in the block and the block is scanned from start 1640169689Skan to end. */ 1641169689Skan cur_occr->insn = insn; 164250397Sobrien } 164350397Sobrien else 164450397Sobrien { 164550397Sobrien /* First occurrence of this expression in this basic block. */ 1646132718Skan cur_occr = gcse_alloc (sizeof (struct occr)); 164750397Sobrien bytes_used += sizeof (struct occr); 164890075Sobrien 1649169689Skan cur_occr->insn = insn; 1650169689Skan cur_occr->next = cur_expr->avail_occr; 1651169689Skan cur_occr->deleted_p = 0; 1652169689Skan cur_expr->avail_occr = cur_occr; 165350397Sobrien } 165450397Sobrien} 165550397Sobrien 1656132718Skan/* Determine whether the rtx X should be treated as a constant for 1657132718Skan the purposes of GCSE's constant propagation. */ 1658132718Skan 1659132718Skanstatic bool 1660132718Skangcse_constant_p (rtx x) 1661132718Skan{ 1662132718Skan /* Consider a COMPARE of two integers constant. */ 1663132718Skan if (GET_CODE (x) == COMPARE 1664132718Skan && GET_CODE (XEXP (x, 0)) == CONST_INT 1665132718Skan && GET_CODE (XEXP (x, 1)) == CONST_INT) 1666132718Skan return true; 1667132718Skan 1668132718Skan /* Consider a COMPARE of the same registers is a constant 1669169689Skan if they are not floating point registers. */ 1670132718Skan if (GET_CODE(x) == COMPARE 1671169689Skan && REG_P (XEXP (x, 0)) && REG_P (XEXP (x, 1)) 1672132718Skan && REGNO (XEXP (x, 0)) == REGNO (XEXP (x, 1)) 1673132718Skan && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 0))) 1674132718Skan && ! FLOAT_MODE_P (GET_MODE (XEXP (x, 1)))) 1675132718Skan return true; 1676132718Skan 1677132718Skan return CONSTANT_P (x); 1678132718Skan} 1679132718Skan 1680117395Skan/* Scan pattern PAT of INSN and add an entry to the hash TABLE (set or 1681117395Skan expression one). */ 168250397Sobrien 168350397Sobrienstatic void 1684132718Skanhash_scan_set (rtx pat, rtx insn, struct hash_table *table) 168550397Sobrien{ 168650397Sobrien rtx src = SET_SRC (pat); 168750397Sobrien rtx dest = SET_DEST (pat); 168890075Sobrien rtx note; 168950397Sobrien 169050397Sobrien if (GET_CODE (src) == CALL) 1691117395Skan hash_scan_call (src, insn, table); 169250397Sobrien 1693169689Skan else if (REG_P (dest)) 169450397Sobrien { 169590075Sobrien unsigned int regno = REGNO (dest); 169650397Sobrien rtx tmp; 169750397Sobrien 1698169689Skan /* See if a REG_NOTE shows this equivalent to a simpler expression. 1699169689Skan This allows us to do a single GCSE pass and still eliminate 1700169689Skan redundant constants, addresses or other expressions that are 1701169689Skan constructed with multiple instructions. */ 1702169689Skan note = find_reg_equal_equiv_note (insn); 1703169689Skan if (note != 0 1704169689Skan && (table->set_p 1705169689Skan ? gcse_constant_p (XEXP (note, 0)) 1706169689Skan : want_to_gcse_p (XEXP (note, 0)))) 170790075Sobrien src = XEXP (note, 0), pat = gen_rtx_SET (VOIDmode, dest, src); 170890075Sobrien 170950397Sobrien /* Only record sets of pseudo-regs in the hash table. */ 1710117395Skan if (! table->set_p 171150397Sobrien && regno >= FIRST_PSEUDO_REGISTER 171250397Sobrien /* Don't GCSE something if we can't do a reg/reg copy. */ 1713132718Skan && can_copy_p (GET_MODE (dest)) 171496263Sobrien /* GCSE commonly inserts instruction after the insn. We can't 171596263Sobrien do that easily for EH_REGION notes so disable GCSE on these 171696263Sobrien for now. */ 1717117395Skan && !find_reg_note (insn, REG_EH_REGION, NULL_RTX) 171850397Sobrien /* Is SET_SRC something we want to gcse? */ 171990075Sobrien && want_to_gcse_p (src) 172090075Sobrien /* Don't CSE a nop. */ 172190075Sobrien && ! set_noop_p (pat) 172290075Sobrien /* Don't GCSE if it has attached REG_EQUIV note. 172390075Sobrien At this point this only function parameters should have 172490075Sobrien REG_EQUIV notes and if the argument slot is used somewhere 172590075Sobrien explicitly, it means address of parameter has been taken, 172690075Sobrien so we should not extend the lifetime of the pseudo. */ 1727169689Skan && (note == NULL_RTX || ! MEM_P (XEXP (note, 0)))) 172850397Sobrien { 172950397Sobrien /* An expression is not anticipatable if its operands are 173090075Sobrien modified before this insn or if this is not the only SET in 173190075Sobrien this insn. */ 173290075Sobrien int antic_p = oprs_anticipatable_p (src, insn) && single_set (insn); 173350397Sobrien /* An expression is not available if its operands are 173490075Sobrien subsequently modified, including this insn. It's also not 173590075Sobrien available if this is a branch, because we can't insert 173690075Sobrien a set after the branch. */ 173790075Sobrien int avail_p = (oprs_available_p (src, insn) 173890075Sobrien && ! JUMP_P (insn)); 173990075Sobrien 1740117395Skan insert_expr_in_table (src, GET_MODE (dest), insn, antic_p, avail_p, table); 174150397Sobrien } 174290075Sobrien 174350397Sobrien /* Record sets for constant/copy propagation. */ 1744117395Skan else if (table->set_p 174550397Sobrien && regno >= FIRST_PSEUDO_REGISTER 1746169689Skan && ((REG_P (src) 174750397Sobrien && REGNO (src) >= FIRST_PSEUDO_REGISTER 1748132718Skan && can_copy_p (GET_MODE (dest)) 174990075Sobrien && REGNO (src) != regno) 1750132718Skan || gcse_constant_p (src)) 175150397Sobrien /* A copy is not available if its src or dest is subsequently 175250397Sobrien modified. Here we want to search from INSN+1 on, but 175350397Sobrien oprs_available_p searches from INSN on. */ 1754132718Skan && (insn == BB_END (BLOCK_FOR_INSN (insn)) 175550397Sobrien || ((tmp = next_nonnote_insn (insn)) != NULL_RTX 175650397Sobrien && oprs_available_p (pat, tmp)))) 1757117395Skan insert_set_in_table (pat, insn, table); 175850397Sobrien } 1759132718Skan /* In case of store we want to consider the memory value as available in 1760132718Skan the REG stored in that memory. This makes it possible to remove 1761132718Skan redundant loads from due to stores to the same location. */ 1762169689Skan else if (flag_gcse_las && REG_P (src) && MEM_P (dest)) 1763132718Skan { 1764132718Skan unsigned int regno = REGNO (src); 1765132718Skan 1766132718Skan /* Do not do this for constant/copy propagation. */ 1767132718Skan if (! table->set_p 1768132718Skan /* Only record sets of pseudo-regs in the hash table. */ 1769132718Skan && regno >= FIRST_PSEUDO_REGISTER 1770132718Skan /* Don't GCSE something if we can't do a reg/reg copy. */ 1771132718Skan && can_copy_p (GET_MODE (src)) 1772132718Skan /* GCSE commonly inserts instruction after the insn. We can't 1773132718Skan do that easily for EH_REGION notes so disable GCSE on these 1774132718Skan for now. */ 1775132718Skan && ! find_reg_note (insn, REG_EH_REGION, NULL_RTX) 1776132718Skan /* Is SET_DEST something we want to gcse? */ 1777132718Skan && want_to_gcse_p (dest) 1778132718Skan /* Don't CSE a nop. */ 1779132718Skan && ! set_noop_p (pat) 1780132718Skan /* Don't GCSE if it has attached REG_EQUIV note. 1781132718Skan At this point this only function parameters should have 1782132718Skan REG_EQUIV notes and if the argument slot is used somewhere 1783132718Skan explicitly, it means address of parameter has been taken, 1784132718Skan so we should not extend the lifetime of the pseudo. */ 1785132718Skan && ((note = find_reg_note (insn, REG_EQUIV, NULL_RTX)) == 0 1786169689Skan || ! MEM_P (XEXP (note, 0)))) 1787132718Skan { 1788132718Skan /* Stores are never anticipatable. */ 1789132718Skan int antic_p = 0; 1790132718Skan /* An expression is not available if its operands are 1791132718Skan subsequently modified, including this insn. It's also not 1792132718Skan available if this is a branch, because we can't insert 1793132718Skan a set after the branch. */ 1794132718Skan int avail_p = oprs_available_p (dest, insn) 1795132718Skan && ! JUMP_P (insn); 1796132718Skan 1797132718Skan /* Record the memory expression (DEST) in the hash table. */ 1798132718Skan insert_expr_in_table (dest, GET_MODE (dest), insn, 1799132718Skan antic_p, avail_p, table); 1800132718Skan } 1801132718Skan } 180250397Sobrien} 180350397Sobrien 180450397Sobrienstatic void 1805132718Skanhash_scan_clobber (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED, 1806132718Skan struct hash_table *table ATTRIBUTE_UNUSED) 180750397Sobrien{ 180850397Sobrien /* Currently nothing to do. */ 180950397Sobrien} 181050397Sobrien 181150397Sobrienstatic void 1812132718Skanhash_scan_call (rtx x ATTRIBUTE_UNUSED, rtx insn ATTRIBUTE_UNUSED, 1813132718Skan struct hash_table *table ATTRIBUTE_UNUSED) 181450397Sobrien{ 181550397Sobrien /* Currently nothing to do. */ 181650397Sobrien} 181750397Sobrien 181850397Sobrien/* Process INSN and add hash table entries as appropriate. 181950397Sobrien 182050397Sobrien Only available expressions that set a single pseudo-reg are recorded. 182150397Sobrien 182250397Sobrien Single sets in a PARALLEL could be handled, but it's an extra complication 182350397Sobrien that isn't dealt with right now. The trick is handling the CLOBBERs that 182450397Sobrien are also in the PARALLEL. Later. 182550397Sobrien 1826117395Skan If SET_P is nonzero, this is for the assignment hash table, 182750397Sobrien otherwise it is for the expression hash table. 182850397Sobrien If IN_LIBCALL_BLOCK nonzero, we are in a libcall block, and should 182950397Sobrien not record any expressions. */ 183050397Sobrien 183150397Sobrienstatic void 1832132718Skanhash_scan_insn (rtx insn, struct hash_table *table, int in_libcall_block) 183350397Sobrien{ 183450397Sobrien rtx pat = PATTERN (insn); 183590075Sobrien int i; 183650397Sobrien 183790075Sobrien if (in_libcall_block) 183890075Sobrien return; 183990075Sobrien 184050397Sobrien /* Pick out the sets of INSN and for other forms of instructions record 184150397Sobrien what's been modified. */ 184250397Sobrien 184390075Sobrien if (GET_CODE (pat) == SET) 1844117395Skan hash_scan_set (pat, insn, table); 184550397Sobrien else if (GET_CODE (pat) == PARALLEL) 184690075Sobrien for (i = 0; i < XVECLEN (pat, 0); i++) 184790075Sobrien { 184890075Sobrien rtx x = XVECEXP (pat, 0, i); 184950397Sobrien 185090075Sobrien if (GET_CODE (x) == SET) 1851117395Skan hash_scan_set (x, insn, table); 185290075Sobrien else if (GET_CODE (x) == CLOBBER) 1853117395Skan hash_scan_clobber (x, insn, table); 185490075Sobrien else if (GET_CODE (x) == CALL) 1855117395Skan hash_scan_call (x, insn, table); 185690075Sobrien } 185750397Sobrien 185850397Sobrien else if (GET_CODE (pat) == CLOBBER) 1859117395Skan hash_scan_clobber (pat, insn, table); 186050397Sobrien else if (GET_CODE (pat) == CALL) 1861117395Skan hash_scan_call (pat, insn, table); 186250397Sobrien} 186350397Sobrien 186450397Sobrienstatic void 1865132718Skandump_hash_table (FILE *file, const char *name, struct hash_table *table) 186650397Sobrien{ 186750397Sobrien int i; 186850397Sobrien /* Flattened out table, so it's printed in proper order. */ 186990075Sobrien struct expr **flat_table; 187090075Sobrien unsigned int *hash_val; 187190075Sobrien struct expr *expr; 187250397Sobrien 1873132718Skan flat_table = xcalloc (table->n_elems, sizeof (struct expr *)); 1874132718Skan hash_val = xmalloc (table->n_elems * sizeof (unsigned int)); 187590075Sobrien 1876117395Skan for (i = 0; i < (int) table->size; i++) 1877117395Skan for (expr = table->table[i]; expr != NULL; expr = expr->next_same_hash) 187890075Sobrien { 187990075Sobrien flat_table[expr->bitmap_index] = expr; 188090075Sobrien hash_val[expr->bitmap_index] = i; 188190075Sobrien } 188250397Sobrien 188350397Sobrien fprintf (file, "%s hash table (%d buckets, %d entries)\n", 1884117395Skan name, table->size, table->n_elems); 188550397Sobrien 1886117395Skan for (i = 0; i < (int) table->n_elems; i++) 188790075Sobrien if (flat_table[i] != 0) 188890075Sobrien { 188990075Sobrien expr = flat_table[i]; 189090075Sobrien fprintf (file, "Index %d (hash value %d)\n ", 189190075Sobrien expr->bitmap_index, hash_val[i]); 189290075Sobrien print_rtl (file, expr->expr); 189390075Sobrien fprintf (file, "\n"); 189490075Sobrien } 189550397Sobrien 189690075Sobrien fprintf (file, "\n"); 189750397Sobrien 189890075Sobrien free (flat_table); 189990075Sobrien free (hash_val); 190050397Sobrien} 190150397Sobrien 190250397Sobrien/* Record register first/last/block set information for REGNO in INSN. 190390075Sobrien 190490075Sobrien first_set records the first place in the block where the register 190550397Sobrien is set and is used to compute "anticipatability". 190690075Sobrien 190790075Sobrien last_set records the last place in the block where the register 190850397Sobrien is set and is used to compute "availability". 190990075Sobrien 191090075Sobrien last_bb records the block for which first_set and last_set are 191190075Sobrien valid, as a quick test to invalidate them. 191290075Sobrien 191350397Sobrien reg_set_in_block records whether the register is set in the block 191450397Sobrien and is used to compute "transparency". */ 191550397Sobrien 191650397Sobrienstatic void 1917132718Skanrecord_last_reg_set_info (rtx insn, int regno) 191850397Sobrien{ 191990075Sobrien struct reg_avail_info *info = ®_avail_info[regno]; 192090075Sobrien int cuid = INSN_CUID (insn); 192190075Sobrien 192290075Sobrien info->last_set = cuid; 192390075Sobrien if (info->last_bb != current_bb) 192490075Sobrien { 192590075Sobrien info->last_bb = current_bb; 192690075Sobrien info->first_set = cuid; 1927117395Skan SET_BIT (reg_set_in_block[current_bb->index], regno); 192890075Sobrien } 192950397Sobrien} 193050397Sobrien 193150397Sobrien 193290075Sobrien/* Record all of the canonicalized MEMs of record_last_mem_set_info's insn. 193390075Sobrien Note we store a pair of elements in the list, so they have to be 193490075Sobrien taken off pairwise. */ 193590075Sobrien 1936117395Skanstatic void 1937132718Skancanon_list_insert (rtx dest ATTRIBUTE_UNUSED, rtx unused1 ATTRIBUTE_UNUSED, 1938132718Skan void * v_insn) 193990075Sobrien{ 194090075Sobrien rtx dest_addr, insn; 194196263Sobrien int bb; 194290075Sobrien 194390075Sobrien while (GET_CODE (dest) == SUBREG 194490075Sobrien || GET_CODE (dest) == ZERO_EXTRACT 194590075Sobrien || GET_CODE (dest) == STRICT_LOW_PART) 194690075Sobrien dest = XEXP (dest, 0); 194790075Sobrien 194890075Sobrien /* If DEST is not a MEM, then it will not conflict with a load. Note 194990075Sobrien that function calls are assumed to clobber memory, but are handled 195090075Sobrien elsewhere. */ 195190075Sobrien 1952169689Skan if (! MEM_P (dest)) 195390075Sobrien return; 195490075Sobrien 195590075Sobrien dest_addr = get_addr (XEXP (dest, 0)); 195690075Sobrien dest_addr = canon_rtx (dest_addr); 1957117395Skan insn = (rtx) v_insn; 195896263Sobrien bb = BLOCK_NUM (insn); 195990075Sobrien 1960117395Skan canon_modify_mem_list[bb] = 196196263Sobrien alloc_EXPR_LIST (VOIDmode, dest_addr, canon_modify_mem_list[bb]); 1962117395Skan canon_modify_mem_list[bb] = 196396263Sobrien alloc_EXPR_LIST (VOIDmode, dest, canon_modify_mem_list[bb]); 196490075Sobrien} 196590075Sobrien 196690075Sobrien/* Record memory modification information for INSN. We do not actually care 196790075Sobrien about the memory location(s) that are set, or even how they are set (consider 196890075Sobrien a CALL_INSN). We merely need to record which insns modify memory. */ 196990075Sobrien 197050397Sobrienstatic void 1971132718Skanrecord_last_mem_set_info (rtx insn) 197250397Sobrien{ 197396263Sobrien int bb = BLOCK_NUM (insn); 197496263Sobrien 197590075Sobrien /* load_killed_in_block_p will handle the case of calls clobbering 197690075Sobrien everything. */ 197796263Sobrien modify_mem_list[bb] = alloc_INSN_LIST (insn, modify_mem_list[bb]); 197896263Sobrien bitmap_set_bit (modify_mem_list_set, bb); 197990075Sobrien 1980169689Skan if (CALL_P (insn)) 198190075Sobrien { 198290075Sobrien /* Note that traversals of this loop (other than for free-ing) 198390075Sobrien will break after encountering a CALL_INSN. So, there's no 198490075Sobrien need to insert a pair of items, as canon_list_insert does. */ 1985117395Skan canon_modify_mem_list[bb] = 1986117395Skan alloc_INSN_LIST (insn, canon_modify_mem_list[bb]); 1987169689Skan bitmap_set_bit (blocks_with_calls, bb); 198890075Sobrien } 198990075Sobrien else 199096263Sobrien note_stores (PATTERN (insn), canon_list_insert, (void*) insn); 199150397Sobrien} 199250397Sobrien 199350397Sobrien/* Called from compute_hash_table via note_stores to handle one 199490075Sobrien SET or CLOBBER in an insn. DATA is really the instruction in which 199590075Sobrien the SET is taking place. */ 199650397Sobrien 199750397Sobrienstatic void 1998132718Skanrecord_last_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, void *data) 199950397Sobrien{ 200090075Sobrien rtx last_set_insn = (rtx) data; 200190075Sobrien 200250397Sobrien if (GET_CODE (dest) == SUBREG) 200350397Sobrien dest = SUBREG_REG (dest); 200450397Sobrien 2005169689Skan if (REG_P (dest)) 200650397Sobrien record_last_reg_set_info (last_set_insn, REGNO (dest)); 2007169689Skan else if (MEM_P (dest) 200850397Sobrien /* Ignore pushes, they clobber nothing. */ 200950397Sobrien && ! push_operand (dest, GET_MODE (dest))) 201050397Sobrien record_last_mem_set_info (last_set_insn); 201150397Sobrien} 201250397Sobrien 201350397Sobrien/* Top level function to create an expression or assignment hash table. 201450397Sobrien 201550397Sobrien Expression entries are placed in the hash table if 201650397Sobrien - they are of the form (set (pseudo-reg) src), 201750397Sobrien - src is something we want to perform GCSE on, 201850397Sobrien - none of the operands are subsequently modified in the block 201950397Sobrien 202050397Sobrien Assignment entries are placed in the hash table if 202150397Sobrien - they are of the form (set (pseudo-reg) src), 202250397Sobrien - src is something we want to perform const/copy propagation on, 202350397Sobrien - none of the operands or target are subsequently modified in the block 202490075Sobrien 202550397Sobrien Currently src must be a pseudo-reg or a const_int. 202650397Sobrien 2027117395Skan TABLE is the table computed. */ 202850397Sobrien 202950397Sobrienstatic void 2030132718Skancompute_hash_table_work (struct hash_table *table) 203150397Sobrien{ 203290075Sobrien unsigned int i; 203350397Sobrien 203450397Sobrien /* While we compute the hash table we also compute a bit array of which 203550397Sobrien registers are set in which blocks. 203650397Sobrien ??? This isn't needed during const/copy propagation, but it's cheap to 203750397Sobrien compute. Later. */ 2038117395Skan sbitmap_vector_zero (reg_set_in_block, last_basic_block); 203950397Sobrien 204090075Sobrien /* re-Cache any INSN_LIST nodes we have allocated. */ 204190075Sobrien clear_modify_mem_tables (); 204250397Sobrien /* Some working arrays used to track first and last set in each block. */ 2043132718Skan reg_avail_info = gmalloc (max_gcse_regno * sizeof (struct reg_avail_info)); 204450397Sobrien 204590075Sobrien for (i = 0; i < max_gcse_regno; ++i) 2046117395Skan reg_avail_info[i].last_bb = NULL; 204790075Sobrien 2048117395Skan FOR_EACH_BB (current_bb) 204950397Sobrien { 205050397Sobrien rtx insn; 205190075Sobrien unsigned int regno; 205250397Sobrien int in_libcall_block; 205350397Sobrien 205450397Sobrien /* First pass over the instructions records information used to 205550397Sobrien determine when registers and memory are first and last set. 205690075Sobrien ??? hard-reg reg_set_in_block computation 205750397Sobrien could be moved to compute_sets since they currently don't change. */ 205850397Sobrien 2059169689Skan FOR_BB_INSNS (current_bb, insn) 206050397Sobrien { 206190075Sobrien if (! INSN_P (insn)) 206250397Sobrien continue; 206350397Sobrien 2064169689Skan if (CALL_P (insn)) 206550397Sobrien { 206690075Sobrien for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 2067169689Skan if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) 206850397Sobrien record_last_reg_set_info (insn, regno); 206990075Sobrien 207090075Sobrien mark_call (insn); 207150397Sobrien } 207250397Sobrien 207390075Sobrien note_stores (PATTERN (insn), record_last_set_info, insn); 207450397Sobrien } 207550397Sobrien 2076132718Skan /* Insert implicit sets in the hash table. */ 2077132718Skan if (table->set_p 2078132718Skan && implicit_sets[current_bb->index] != NULL_RTX) 2079132718Skan hash_scan_set (implicit_sets[current_bb->index], 2080132718Skan BB_HEAD (current_bb), table); 2081132718Skan 208250397Sobrien /* The next pass builds the hash table. */ 2083169689Skan in_libcall_block = 0; 2084169689Skan FOR_BB_INSNS (current_bb, insn) 208590075Sobrien if (INSN_P (insn)) 208690075Sobrien { 208790075Sobrien if (find_reg_note (insn, REG_LIBCALL, NULL_RTX)) 2088117395Skan in_libcall_block = 1; 2089117395Skan else if (table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX)) 2090117395Skan in_libcall_block = 0; 2091117395Skan hash_scan_insn (insn, table, in_libcall_block); 2092117395Skan if (!table->set_p && find_reg_note (insn, REG_RETVAL, NULL_RTX)) 2093117395Skan in_libcall_block = 0; 209490075Sobrien } 209550397Sobrien } 209650397Sobrien 209790075Sobrien free (reg_avail_info); 209890075Sobrien reg_avail_info = NULL; 209950397Sobrien} 210050397Sobrien 2101117395Skan/* Allocate space for the set/expr hash TABLE. 210250397Sobrien N_INSNS is the number of instructions in the function. 2103117395Skan It is used to determine the number of buckets to use. 2104117395Skan SET_P determines whether set or expression table will 2105117395Skan be created. */ 210650397Sobrien 210750397Sobrienstatic void 2108132718Skanalloc_hash_table (int n_insns, struct hash_table *table, int set_p) 210950397Sobrien{ 211050397Sobrien int n; 211150397Sobrien 2112117395Skan table->size = n_insns / 4; 2113117395Skan if (table->size < 11) 2114117395Skan table->size = 11; 211590075Sobrien 211650397Sobrien /* Attempt to maintain efficient use of hash table. 211750397Sobrien Making it an odd number is simplest for now. 211850397Sobrien ??? Later take some measurements. */ 2119117395Skan table->size |= 1; 2120117395Skan n = table->size * sizeof (struct expr *); 2121132718Skan table->table = gmalloc (n); 2122117395Skan table->set_p = set_p; 212350397Sobrien} 212450397Sobrien 2125117395Skan/* Free things allocated by alloc_hash_table. */ 212650397Sobrien 212750397Sobrienstatic void 2128132718Skanfree_hash_table (struct hash_table *table) 212950397Sobrien{ 2130117395Skan free (table->table); 213150397Sobrien} 213250397Sobrien 2133117395Skan/* Compute the hash TABLE for doing copy/const propagation or 2134117395Skan expression hash table. */ 213550397Sobrien 213650397Sobrienstatic void 2137132718Skancompute_hash_table (struct hash_table *table) 213850397Sobrien{ 213950397Sobrien /* Initialize count of number of entries in hash table. */ 2140117395Skan table->n_elems = 0; 2141132718Skan memset (table->table, 0, table->size * sizeof (struct expr *)); 214250397Sobrien 2143117395Skan compute_hash_table_work (table); 214450397Sobrien} 214550397Sobrien 214650397Sobrien/* Expression tracking support. */ 214750397Sobrien 2148132718Skan/* Lookup REGNO in the set TABLE. The result is a pointer to the 2149132718Skan table entry, or NULL if not found. */ 215050397Sobrien 215150397Sobrienstatic struct expr * 2152132718Skanlookup_set (unsigned int regno, struct hash_table *table) 215350397Sobrien{ 2154117395Skan unsigned int hash = hash_set (regno, table->size); 215550397Sobrien struct expr *expr; 215650397Sobrien 2157117395Skan expr = table->table[hash]; 215850397Sobrien 2159132718Skan while (expr && REGNO (SET_DEST (expr->expr)) != regno) 2160132718Skan expr = expr->next_same_hash; 216150397Sobrien 216250397Sobrien return expr; 216350397Sobrien} 216450397Sobrien 216550397Sobrien/* Return the next entry for REGNO in list EXPR. */ 216650397Sobrien 216750397Sobrienstatic struct expr * 2168132718Skannext_set (unsigned int regno, struct expr *expr) 216950397Sobrien{ 217050397Sobrien do 217150397Sobrien expr = expr->next_same_hash; 217250397Sobrien while (expr && REGNO (SET_DEST (expr->expr)) != regno); 217390075Sobrien 217450397Sobrien return expr; 217550397Sobrien} 217650397Sobrien 217796263Sobrien/* Like free_INSN_LIST_list or free_EXPR_LIST_list, except that the node 217896263Sobrien types may be mixed. */ 217996263Sobrien 218096263Sobrienstatic void 2181132718Skanfree_insn_expr_list_list (rtx *listp) 218296263Sobrien{ 218396263Sobrien rtx list, next; 218496263Sobrien 218596263Sobrien for (list = *listp; list ; list = next) 218696263Sobrien { 218796263Sobrien next = XEXP (list, 1); 218896263Sobrien if (GET_CODE (list) == EXPR_LIST) 218996263Sobrien free_EXPR_LIST_node (list); 219096263Sobrien else 219196263Sobrien free_INSN_LIST_node (list); 219296263Sobrien } 219396263Sobrien 219496263Sobrien *listp = NULL; 219596263Sobrien} 219696263Sobrien 219790075Sobrien/* Clear canon_modify_mem_list and modify_mem_list tables. */ 219890075Sobrienstatic void 2199132718Skanclear_modify_mem_tables (void) 220090075Sobrien{ 2201169689Skan unsigned i; 2202169689Skan bitmap_iterator bi; 220390075Sobrien 2204169689Skan EXECUTE_IF_SET_IN_BITMAP (modify_mem_list_set, 0, i, bi) 2205169689Skan { 2206169689Skan free_INSN_LIST_list (modify_mem_list + i); 2207169689Skan free_insn_expr_list_list (canon_modify_mem_list + i); 2208169689Skan } 220996263Sobrien bitmap_clear (modify_mem_list_set); 2210169689Skan bitmap_clear (blocks_with_calls); 221190075Sobrien} 221290075Sobrien 2213169689Skan/* Release memory used by modify_mem_list_set. */ 221490075Sobrien 221590075Sobrienstatic void 2216132718Skanfree_modify_mem_tables (void) 221790075Sobrien{ 221890075Sobrien clear_modify_mem_tables (); 221990075Sobrien free (modify_mem_list); 222090075Sobrien free (canon_modify_mem_list); 222190075Sobrien modify_mem_list = 0; 222290075Sobrien canon_modify_mem_list = 0; 222390075Sobrien} 222490075Sobrien 222550397Sobrien/* Reset tables used to keep track of what's still available [since the 222650397Sobrien start of the block]. */ 222750397Sobrien 222850397Sobrienstatic void 2229132718Skanreset_opr_set_tables (void) 223050397Sobrien{ 223150397Sobrien /* Maintain a bitmap of which regs have been set since beginning of 223250397Sobrien the block. */ 223390075Sobrien CLEAR_REG_SET (reg_set_bitmap); 223490075Sobrien 223550397Sobrien /* Also keep a record of the last instruction to modify memory. 223650397Sobrien For now this is very trivial, we only record whether any memory 223750397Sobrien location has been modified. */ 223890075Sobrien clear_modify_mem_tables (); 223950397Sobrien} 224050397Sobrien 2241117395Skan/* Return nonzero if the operands of X are not set before INSN in 224250397Sobrien INSN's basic block. */ 224350397Sobrien 224450397Sobrienstatic int 2245132718Skanoprs_not_set_p (rtx x, rtx insn) 224650397Sobrien{ 224790075Sobrien int i, j; 224850397Sobrien enum rtx_code code; 224990075Sobrien const char *fmt; 225050397Sobrien 225150397Sobrien if (x == 0) 225250397Sobrien return 1; 225350397Sobrien 225450397Sobrien code = GET_CODE (x); 225550397Sobrien switch (code) 225650397Sobrien { 225750397Sobrien case PC: 225850397Sobrien case CC0: 225950397Sobrien case CONST: 226050397Sobrien case CONST_INT: 226150397Sobrien case CONST_DOUBLE: 226296263Sobrien case CONST_VECTOR: 226350397Sobrien case SYMBOL_REF: 226450397Sobrien case LABEL_REF: 226550397Sobrien case ADDR_VEC: 226650397Sobrien case ADDR_DIFF_VEC: 226750397Sobrien return 1; 226850397Sobrien 226950397Sobrien case MEM: 2270117395Skan if (load_killed_in_block_p (BLOCK_FOR_INSN (insn), 227190075Sobrien INSN_CUID (insn), x, 0)) 227250397Sobrien return 0; 227390075Sobrien else 227490075Sobrien return oprs_not_set_p (XEXP (x, 0), insn); 227550397Sobrien 227650397Sobrien case REG: 227790075Sobrien return ! REGNO_REG_SET_P (reg_set_bitmap, REGNO (x)); 227850397Sobrien 227950397Sobrien default: 228050397Sobrien break; 228150397Sobrien } 228250397Sobrien 228390075Sobrien for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--) 228450397Sobrien { 228550397Sobrien if (fmt[i] == 'e') 228650397Sobrien { 228750397Sobrien /* If we are about to do the last recursive call 228850397Sobrien needed at this level, change it into iteration. 228950397Sobrien This function is called enough to be worth it. */ 229050397Sobrien if (i == 0) 229190075Sobrien return oprs_not_set_p (XEXP (x, i), insn); 229290075Sobrien 229390075Sobrien if (! oprs_not_set_p (XEXP (x, i), insn)) 229450397Sobrien return 0; 229550397Sobrien } 229650397Sobrien else if (fmt[i] == 'E') 229790075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 229890075Sobrien if (! oprs_not_set_p (XVECEXP (x, i, j), insn)) 229990075Sobrien return 0; 230050397Sobrien } 230150397Sobrien 230250397Sobrien return 1; 230350397Sobrien} 230450397Sobrien 230550397Sobrien/* Mark things set by a CALL. */ 230650397Sobrien 230750397Sobrienstatic void 2308132718Skanmark_call (rtx insn) 230950397Sobrien{ 231090075Sobrien if (! CONST_OR_PURE_CALL_P (insn)) 231190075Sobrien record_last_mem_set_info (insn); 231250397Sobrien} 231350397Sobrien 231450397Sobrien/* Mark things set by a SET. */ 231550397Sobrien 231650397Sobrienstatic void 2317132718Skanmark_set (rtx pat, rtx insn) 231850397Sobrien{ 231950397Sobrien rtx dest = SET_DEST (pat); 232050397Sobrien 232150397Sobrien while (GET_CODE (dest) == SUBREG 232250397Sobrien || GET_CODE (dest) == ZERO_EXTRACT 232350397Sobrien || GET_CODE (dest) == STRICT_LOW_PART) 232450397Sobrien dest = XEXP (dest, 0); 232550397Sobrien 2326169689Skan if (REG_P (dest)) 232790075Sobrien SET_REGNO_REG_SET (reg_set_bitmap, REGNO (dest)); 2328169689Skan else if (MEM_P (dest)) 232990075Sobrien record_last_mem_set_info (insn); 233050397Sobrien 233150397Sobrien if (GET_CODE (SET_SRC (pat)) == CALL) 233252284Sobrien mark_call (insn); 233350397Sobrien} 233450397Sobrien 233550397Sobrien/* Record things set by a CLOBBER. */ 233650397Sobrien 233750397Sobrienstatic void 2338132718Skanmark_clobber (rtx pat, rtx insn) 233950397Sobrien{ 234050397Sobrien rtx clob = XEXP (pat, 0); 234150397Sobrien 234250397Sobrien while (GET_CODE (clob) == SUBREG || GET_CODE (clob) == STRICT_LOW_PART) 234350397Sobrien clob = XEXP (clob, 0); 234450397Sobrien 2345169689Skan if (REG_P (clob)) 234690075Sobrien SET_REGNO_REG_SET (reg_set_bitmap, REGNO (clob)); 234750397Sobrien else 234890075Sobrien record_last_mem_set_info (insn); 234950397Sobrien} 235050397Sobrien 235150397Sobrien/* Record things set by INSN. 235250397Sobrien This data is used by oprs_not_set_p. */ 235350397Sobrien 235450397Sobrienstatic void 2355132718Skanmark_oprs_set (rtx insn) 235650397Sobrien{ 235750397Sobrien rtx pat = PATTERN (insn); 235890075Sobrien int i; 235950397Sobrien 236050397Sobrien if (GET_CODE (pat) == SET) 236150397Sobrien mark_set (pat, insn); 236250397Sobrien else if (GET_CODE (pat) == PARALLEL) 236390075Sobrien for (i = 0; i < XVECLEN (pat, 0); i++) 236490075Sobrien { 236590075Sobrien rtx x = XVECEXP (pat, 0, i); 236650397Sobrien 236790075Sobrien if (GET_CODE (x) == SET) 236890075Sobrien mark_set (x, insn); 236990075Sobrien else if (GET_CODE (x) == CLOBBER) 237090075Sobrien mark_clobber (x, insn); 237190075Sobrien else if (GET_CODE (x) == CALL) 237290075Sobrien mark_call (insn); 237390075Sobrien } 237450397Sobrien 237550397Sobrien else if (GET_CODE (pat) == CLOBBER) 237650397Sobrien mark_clobber (pat, insn); 237750397Sobrien else if (GET_CODE (pat) == CALL) 237852284Sobrien mark_call (insn); 237950397Sobrien} 238052284Sobrien 238150397Sobrien 238250397Sobrien/* Compute copy/constant propagation working variables. */ 238350397Sobrien 238450397Sobrien/* Local properties of assignments. */ 238550397Sobrienstatic sbitmap *cprop_pavloc; 238650397Sobrienstatic sbitmap *cprop_absaltered; 238750397Sobrien 238850397Sobrien/* Global properties of assignments (computed from the local properties). */ 238950397Sobrienstatic sbitmap *cprop_avin; 239050397Sobrienstatic sbitmap *cprop_avout; 239150397Sobrien 239290075Sobrien/* Allocate vars used for copy/const propagation. N_BLOCKS is the number of 239390075Sobrien basic blocks. N_SETS is the number of sets. */ 239450397Sobrien 239550397Sobrienstatic void 2396132718Skanalloc_cprop_mem (int n_blocks, int n_sets) 239750397Sobrien{ 239850397Sobrien cprop_pavloc = sbitmap_vector_alloc (n_blocks, n_sets); 239950397Sobrien cprop_absaltered = sbitmap_vector_alloc (n_blocks, n_sets); 240050397Sobrien 240150397Sobrien cprop_avin = sbitmap_vector_alloc (n_blocks, n_sets); 240250397Sobrien cprop_avout = sbitmap_vector_alloc (n_blocks, n_sets); 240350397Sobrien} 240450397Sobrien 240550397Sobrien/* Free vars used by copy/const propagation. */ 240650397Sobrien 240750397Sobrienstatic void 2408132718Skanfree_cprop_mem (void) 240950397Sobrien{ 241090075Sobrien sbitmap_vector_free (cprop_pavloc); 241190075Sobrien sbitmap_vector_free (cprop_absaltered); 241290075Sobrien sbitmap_vector_free (cprop_avin); 241390075Sobrien sbitmap_vector_free (cprop_avout); 241450397Sobrien} 241550397Sobrien 241690075Sobrien/* For each block, compute whether X is transparent. X is either an 241790075Sobrien expression or an assignment [though we don't care which, for this context 241890075Sobrien an assignment is treated as an expression]. For each block where an 241990075Sobrien element of X is modified, set (SET_P == 1) or reset (SET_P == 0) the INDX 242090075Sobrien bit in BMAP. */ 242150397Sobrien 242250397Sobrienstatic void 2423132718Skancompute_transp (rtx x, int indx, sbitmap *bmap, int set_p) 242450397Sobrien{ 2425117395Skan int i, j; 2426117395Skan basic_block bb; 242750397Sobrien enum rtx_code code; 242890075Sobrien reg_set *r; 242990075Sobrien const char *fmt; 243050397Sobrien 243190075Sobrien /* repeat is used to turn tail-recursion into iteration since GCC 243290075Sobrien can't do it when there's no return value. */ 243350397Sobrien repeat: 243450397Sobrien 243550397Sobrien if (x == 0) 243650397Sobrien return; 243750397Sobrien 243850397Sobrien code = GET_CODE (x); 243950397Sobrien switch (code) 244050397Sobrien { 244150397Sobrien case REG: 244250397Sobrien if (set_p) 244350397Sobrien { 244490075Sobrien if (REGNO (x) < FIRST_PSEUDO_REGISTER) 244590075Sobrien { 2446117395Skan FOR_EACH_BB (bb) 2447117395Skan if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x))) 2448117395Skan SET_BIT (bmap[bb->index], indx); 244990075Sobrien } 245090075Sobrien else 245190075Sobrien { 245290075Sobrien for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next) 2453169689Skan SET_BIT (bmap[r->bb_index], indx); 245490075Sobrien } 245550397Sobrien } 245650397Sobrien else 245750397Sobrien { 245890075Sobrien if (REGNO (x) < FIRST_PSEUDO_REGISTER) 245990075Sobrien { 2460117395Skan FOR_EACH_BB (bb) 2461117395Skan if (TEST_BIT (reg_set_in_block[bb->index], REGNO (x))) 2462117395Skan RESET_BIT (bmap[bb->index], indx); 246390075Sobrien } 246490075Sobrien else 246590075Sobrien { 246690075Sobrien for (r = reg_set_table[REGNO (x)]; r != NULL; r = r->next) 2467169689Skan RESET_BIT (bmap[r->bb_index], indx); 246890075Sobrien } 246950397Sobrien } 247090075Sobrien 247190075Sobrien return; 247290075Sobrien 247390075Sobrien case MEM: 2474169689Skan if (! MEM_READONLY_P (x)) 247590075Sobrien { 2476169689Skan bitmap_iterator bi; 2477169689Skan unsigned bb_index; 247890075Sobrien 2479169689Skan /* First handle all the blocks with calls. We don't need to 2480169689Skan do any list walking for them. */ 2481169689Skan EXECUTE_IF_SET_IN_BITMAP (blocks_with_calls, 0, bb_index, bi) 248290075Sobrien { 2483169689Skan if (set_p) 2484169689Skan SET_BIT (bmap[bb_index], indx); 2485169689Skan else 2486169689Skan RESET_BIT (bmap[bb_index], indx); 2487169689Skan } 248890075Sobrien 2489169689Skan /* Now iterate over the blocks which have memory modifications 2490169689Skan but which do not have any calls. */ 2491169689Skan EXECUTE_IF_AND_COMPL_IN_BITMAP (modify_mem_list_set, 2492169689Skan blocks_with_calls, 2493169689Skan 0, bb_index, bi) 2494169689Skan { 2495169689Skan rtx list_entry = canon_modify_mem_list[bb_index]; 249690075Sobrien 2497169689Skan while (list_entry) 2498169689Skan { 2499169689Skan rtx dest, dest_addr; 2500117395Skan 2501169689Skan /* LIST_ENTRY must be an INSN of some kind that sets memory. 2502169689Skan Examine each hunk of memory that is modified. */ 2503169689Skan 2504169689Skan dest = XEXP (list_entry, 0); 2505169689Skan list_entry = XEXP (list_entry, 1); 2506169689Skan dest_addr = XEXP (list_entry, 0); 2507169689Skan 2508169689Skan if (canon_true_dependence (dest, GET_MODE (dest), dest_addr, 2509169689Skan x, rtx_addr_varies_p)) 2510169689Skan { 2511169689Skan if (set_p) 2512169689Skan SET_BIT (bmap[bb_index], indx); 2513169689Skan else 2514169689Skan RESET_BIT (bmap[bb_index], indx); 2515169689Skan break; 2516169689Skan } 2517169689Skan list_entry = XEXP (list_entry, 1); 2518169689Skan } 2519169689Skan } 252090075Sobrien } 252190075Sobrien 252250397Sobrien x = XEXP (x, 0); 252350397Sobrien goto repeat; 252450397Sobrien 252550397Sobrien case PC: 252650397Sobrien case CC0: /*FIXME*/ 252750397Sobrien case CONST: 252850397Sobrien case CONST_INT: 252950397Sobrien case CONST_DOUBLE: 253096263Sobrien case CONST_VECTOR: 253150397Sobrien case SYMBOL_REF: 253250397Sobrien case LABEL_REF: 253350397Sobrien case ADDR_VEC: 253450397Sobrien case ADDR_DIFF_VEC: 253550397Sobrien return; 253650397Sobrien 253750397Sobrien default: 253850397Sobrien break; 253950397Sobrien } 254050397Sobrien 254190075Sobrien for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--) 254250397Sobrien { 254350397Sobrien if (fmt[i] == 'e') 254450397Sobrien { 254550397Sobrien /* If we are about to do the last recursive call 254650397Sobrien needed at this level, change it into iteration. 254750397Sobrien This function is called enough to be worth it. */ 254850397Sobrien if (i == 0) 254950397Sobrien { 255090075Sobrien x = XEXP (x, i); 255150397Sobrien goto repeat; 255250397Sobrien } 255390075Sobrien 255490075Sobrien compute_transp (XEXP (x, i), indx, bmap, set_p); 255550397Sobrien } 255650397Sobrien else if (fmt[i] == 'E') 255790075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 255890075Sobrien compute_transp (XVECEXP (x, i, j), indx, bmap, set_p); 255950397Sobrien } 256050397Sobrien} 256150397Sobrien 256250397Sobrien/* Top level routine to do the dataflow analysis needed by copy/const 256350397Sobrien propagation. */ 256450397Sobrien 256550397Sobrienstatic void 2566132718Skancompute_cprop_data (void) 256750397Sobrien{ 2568117395Skan compute_local_properties (cprop_absaltered, cprop_pavloc, NULL, &set_hash_table); 256990075Sobrien compute_available (cprop_pavloc, cprop_absaltered, 257090075Sobrien cprop_avout, cprop_avin); 257150397Sobrien} 257250397Sobrien 257350397Sobrien/* Copy/constant propagation. */ 257450397Sobrien 257550397Sobrien/* Maximum number of register uses in an insn that we handle. */ 257650397Sobrien#define MAX_USES 8 257750397Sobrien 257850397Sobrien/* Table of uses found in an insn. 257950397Sobrien Allocated statically to avoid alloc/free complexity and overhead. */ 258050397Sobrienstatic struct reg_use reg_use_table[MAX_USES]; 258150397Sobrien 258250397Sobrien/* Index into `reg_use_table' while building it. */ 258350397Sobrienstatic int reg_use_count; 258450397Sobrien 258590075Sobrien/* Set up a list of register numbers used in INSN. The found uses are stored 258690075Sobrien in `reg_use_table'. `reg_use_count' is initialized to zero before entry, 258790075Sobrien and contains the number of uses in the table upon exit. 258850397Sobrien 258990075Sobrien ??? If a register appears multiple times we will record it multiple times. 259090075Sobrien This doesn't hurt anything but it will slow things down. */ 259150397Sobrien 259250397Sobrienstatic void 2593132718Skanfind_used_regs (rtx *xptr, void *data ATTRIBUTE_UNUSED) 259450397Sobrien{ 259590075Sobrien int i, j; 259650397Sobrien enum rtx_code code; 259790075Sobrien const char *fmt; 259890075Sobrien rtx x = *xptr; 259950397Sobrien 260090075Sobrien /* repeat is used to turn tail-recursion into iteration since GCC 260190075Sobrien can't do it when there's no return value. */ 260250397Sobrien repeat: 260350397Sobrien if (x == 0) 260450397Sobrien return; 260550397Sobrien 260650397Sobrien code = GET_CODE (x); 260790075Sobrien if (REG_P (x)) 260850397Sobrien { 260950397Sobrien if (reg_use_count == MAX_USES) 261050397Sobrien return; 261190075Sobrien 261250397Sobrien reg_use_table[reg_use_count].reg_rtx = x; 261350397Sobrien reg_use_count++; 261450397Sobrien } 261550397Sobrien 261650397Sobrien /* Recursively scan the operands of this expression. */ 261750397Sobrien 261890075Sobrien for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--) 261950397Sobrien { 262050397Sobrien if (fmt[i] == 'e') 262150397Sobrien { 262250397Sobrien /* If we are about to do the last recursive call 262350397Sobrien needed at this level, change it into iteration. 262450397Sobrien This function is called enough to be worth it. */ 262550397Sobrien if (i == 0) 262650397Sobrien { 262750397Sobrien x = XEXP (x, 0); 262850397Sobrien goto repeat; 262950397Sobrien } 263090075Sobrien 263190075Sobrien find_used_regs (&XEXP (x, i), data); 263250397Sobrien } 263350397Sobrien else if (fmt[i] == 'E') 263490075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 263590075Sobrien find_used_regs (&XVECEXP (x, i, j), data); 263650397Sobrien } 263750397Sobrien} 263850397Sobrien 263950397Sobrien/* Try to replace all non-SET_DEST occurrences of FROM in INSN with TO. 2640117395Skan Returns nonzero is successful. */ 264150397Sobrien 264250397Sobrienstatic int 2643132718Skantry_replace_reg (rtx from, rtx to, rtx insn) 264450397Sobrien{ 264590075Sobrien rtx note = find_reg_equal_equiv_note (insn); 264690075Sobrien rtx src = 0; 264790075Sobrien int success = 0; 264890075Sobrien rtx set = single_set (insn); 264952284Sobrien 2650117395Skan validate_replace_src_group (from, to, insn); 2651117395Skan if (num_changes_pending () && apply_change_group ()) 2652117395Skan success = 1; 265390075Sobrien 2654117395Skan /* Try to simplify SET_SRC if we have substituted a constant. */ 2655117395Skan if (success && set && CONSTANT_P (to)) 265690075Sobrien { 2657117395Skan src = simplify_rtx (SET_SRC (set)); 2658117395Skan 2659117395Skan if (src) 2660117395Skan validate_change (insn, &SET_SRC (set), src, 0); 2661117395Skan } 2662117395Skan 2663169689Skan /* If there is already a REG_EQUAL note, update the expression in it 2664169689Skan with our replacement. */ 2665169689Skan if (note != 0 && REG_NOTE_KIND (note) == REG_EQUAL) 2666132718Skan XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), from, to); 2667132718Skan 2668117395Skan if (!success && set && reg_mentioned_p (from, SET_SRC (set))) 2669117395Skan { 2670117395Skan /* If above failed and this is a single set, try to simplify the source of 2671117395Skan the set given our substitution. We could perhaps try this for multiple 2672117395Skan SETs, but it probably won't buy us anything. */ 267390075Sobrien src = simplify_replace_rtx (SET_SRC (set), from, to); 267490075Sobrien 267590075Sobrien if (!rtx_equal_p (src, SET_SRC (set)) 267690075Sobrien && validate_change (insn, &SET_SRC (set), src, 0)) 267790075Sobrien success = 1; 2678117395Skan 2679119256Skan /* If we've failed to do replacement, have a single SET, don't already 2680119256Skan have a note, and have no special SET, add a REG_EQUAL note to not 2681119256Skan lose information. */ 2682119256Skan if (!success && note == 0 && set != 0 2683169689Skan && GET_CODE (SET_DEST (set)) != ZERO_EXTRACT 2684169689Skan && GET_CODE (SET_DEST (set)) != STRICT_LOW_PART) 2685117395Skan note = set_unique_reg_note (insn, REG_EQUAL, copy_rtx (src)); 268690075Sobrien } 268790075Sobrien 268890075Sobrien /* REG_EQUAL may get simplified into register. 268990075Sobrien We don't allow that. Remove that note. This code ought 2690132718Skan not to happen, because previous code ought to synthesize 269190075Sobrien reg-reg move, but be on the safe side. */ 2692169689Skan if (note && REG_NOTE_KIND (note) == REG_EQUAL && REG_P (XEXP (note, 0))) 269390075Sobrien remove_note (insn, note); 269490075Sobrien 269590075Sobrien return success; 269650397Sobrien} 269750397Sobrien 269890075Sobrien/* Find a set of REGNOs that are available on entry to INSN's block. Returns 269990075Sobrien NULL no such set is found. */ 270050397Sobrien 270150397Sobrienstatic struct expr * 2702132718Skanfind_avail_set (int regno, rtx insn) 270350397Sobrien{ 270490075Sobrien /* SET1 contains the last set found that can be returned to the caller for 270590075Sobrien use in a substitution. */ 270690075Sobrien struct expr *set1 = 0; 2707117395Skan 270890075Sobrien /* Loops are not possible here. To get a loop we would need two sets 2709169689Skan available at the start of the block containing INSN. i.e. we would 271090075Sobrien need two sets like this available at the start of the block: 271150397Sobrien 271290075Sobrien (set (reg X) (reg Y)) 271390075Sobrien (set (reg Y) (reg X)) 271490075Sobrien 271590075Sobrien This can not happen since the set of (reg Y) would have killed the 271690075Sobrien set of (reg X) making it unavailable at the start of this block. */ 271790075Sobrien while (1) 271850397Sobrien { 271990075Sobrien rtx src; 2720132718Skan struct expr *set = lookup_set (regno, &set_hash_table); 272190075Sobrien 272290075Sobrien /* Find a set that is available at the start of the block 272390075Sobrien which contains INSN. */ 272490075Sobrien while (set) 272590075Sobrien { 272690075Sobrien if (TEST_BIT (cprop_avin[BLOCK_NUM (insn)], set->bitmap_index)) 272790075Sobrien break; 272890075Sobrien set = next_set (regno, set); 272990075Sobrien } 273090075Sobrien 273190075Sobrien /* If no available set was found we've reached the end of the 273290075Sobrien (possibly empty) copy chain. */ 273390075Sobrien if (set == 0) 2734117395Skan break; 273590075Sobrien 2736169689Skan gcc_assert (GET_CODE (set->expr) == SET); 273790075Sobrien 273890075Sobrien src = SET_SRC (set->expr); 273990075Sobrien 274090075Sobrien /* We know the set is available. 274190075Sobrien Now check that SRC is ANTLOC (i.e. none of the source operands 2742117395Skan have changed since the start of the block). 274390075Sobrien 274490075Sobrien If the source operand changed, we may still use it for the next 274590075Sobrien iteration of this loop, but we may not use it for substitutions. */ 274690075Sobrien 2747132718Skan if (gcse_constant_p (src) || oprs_not_set_p (src, insn)) 274890075Sobrien set1 = set; 274990075Sobrien 275090075Sobrien /* If the source of the set is anything except a register, then 275190075Sobrien we have reached the end of the copy chain. */ 2752169689Skan if (! REG_P (src)) 275350397Sobrien break; 275490075Sobrien 2755169689Skan /* Follow the copy chain, i.e. start another iteration of the loop 275690075Sobrien and see if we have an available copy into SRC. */ 275790075Sobrien regno = REGNO (src); 275850397Sobrien } 275950397Sobrien 276090075Sobrien /* SET1 holds the last set that was available and anticipatable at 276190075Sobrien INSN. */ 276290075Sobrien return set1; 276350397Sobrien} 276450397Sobrien 276590075Sobrien/* Subroutine of cprop_insn that tries to propagate constants into 2766117395Skan JUMP_INSNS. JUMP must be a conditional jump. If SETCC is non-NULL 2767132718Skan it is the instruction that immediately precedes JUMP, and must be a 2768117395Skan single SET of a register. FROM is what we will try to replace, 2769117395Skan SRC is the constant we will try to substitute for it. Returns nonzero 2770117395Skan if a change was made. */ 277190075Sobrien 277290075Sobrienstatic int 2773132718Skancprop_jump (basic_block bb, rtx setcc, rtx jump, rtx from, rtx src) 277490075Sobrien{ 2775132718Skan rtx new, set_src, note_src; 2776117395Skan rtx set = pc_set (jump); 2777132718Skan rtx note = find_reg_equal_equiv_note (jump); 277890075Sobrien 2779132718Skan if (note) 2780132718Skan { 2781132718Skan note_src = XEXP (note, 0); 2782132718Skan if (GET_CODE (note_src) == EXPR_LIST) 2783132718Skan note_src = NULL_RTX; 2784132718Skan } 2785132718Skan else note_src = NULL_RTX; 2786132718Skan 2787132718Skan /* Prefer REG_EQUAL notes except those containing EXPR_LISTs. */ 2788132718Skan set_src = note_src ? note_src : SET_SRC (set); 2789132718Skan 2790132718Skan /* First substitute the SETCC condition into the JUMP instruction, 2791132718Skan then substitute that given values into this expanded JUMP. */ 2792132718Skan if (setcc != NULL_RTX 2793117395Skan && !modified_between_p (from, setcc, jump) 2794117395Skan && !modified_between_p (src, setcc, jump)) 2795117395Skan { 2796132718Skan rtx setcc_src; 2797117395Skan rtx setcc_set = single_set (setcc); 2798132718Skan rtx setcc_note = find_reg_equal_equiv_note (setcc); 2799132718Skan setcc_src = (setcc_note && GET_CODE (XEXP (setcc_note, 0)) != EXPR_LIST) 2800132718Skan ? XEXP (setcc_note, 0) : SET_SRC (setcc_set); 2801132718Skan set_src = simplify_replace_rtx (set_src, SET_DEST (setcc_set), 2802132718Skan setcc_src); 2803117395Skan } 2804117395Skan else 2805132718Skan setcc = NULL_RTX; 2806117395Skan 2807132718Skan new = simplify_replace_rtx (set_src, from, src); 2808117395Skan 2809132718Skan /* If no simplification can be made, then try the next register. */ 2810132718Skan if (rtx_equal_p (new, SET_SRC (set))) 281190075Sobrien return 0; 2812117395Skan 281390075Sobrien /* If this is now a no-op delete it, otherwise this must be a valid insn. */ 281490075Sobrien if (new == pc_rtx) 2815117395Skan delete_insn (jump); 281690075Sobrien else 281790075Sobrien { 2818117395Skan /* Ensure the value computed inside the jump insn to be equivalent 2819117395Skan to one computed by setcc. */ 2820132718Skan if (setcc && modified_in_p (new, setcc)) 282190075Sobrien return 0; 2822117395Skan if (! validate_change (jump, &SET_SRC (set), new, 0)) 2823132718Skan { 2824132718Skan /* When (some) constants are not valid in a comparison, and there 2825132718Skan are two registers to be replaced by constants before the entire 2826132718Skan comparison can be folded into a constant, we need to keep 2827132718Skan intermediate information in REG_EQUAL notes. For targets with 2828132718Skan separate compare insns, such notes are added by try_replace_reg. 2829132718Skan When we have a combined compare-and-branch instruction, however, 2830132718Skan we need to attach a note to the branch itself to make this 2831132718Skan optimization work. */ 283290075Sobrien 2833132718Skan if (!rtx_equal_p (new, note_src)) 2834132718Skan set_unique_reg_note (jump, REG_EQUAL, copy_rtx (new)); 2835132718Skan return 0; 2836132718Skan } 2837132718Skan 2838132718Skan /* Remove REG_EQUAL note after simplification. */ 2839132718Skan if (note_src) 2840132718Skan remove_note (jump, note); 2841132718Skan 284290075Sobrien /* If this has turned into an unconditional jump, 284390075Sobrien then put a barrier after it so that the unreachable 284490075Sobrien code will be deleted. */ 284590075Sobrien if (GET_CODE (SET_SRC (set)) == LABEL_REF) 2846117395Skan emit_barrier_after (jump); 284790075Sobrien } 284890075Sobrien 2849117395Skan#ifdef HAVE_cc0 2850117395Skan /* Delete the cc0 setter. */ 2851117395Skan if (setcc != NULL && CC0_P (SET_DEST (single_set (setcc)))) 2852117395Skan delete_insn (setcc); 2853117395Skan#endif 2854117395Skan 285590075Sobrien run_jump_opt_after_gcse = 1; 285690075Sobrien 2857169689Skan global_const_prop_count++; 2858169689Skan if (dump_file != NULL) 285990075Sobrien { 2860169689Skan fprintf (dump_file, 2861169689Skan "GLOBAL CONST-PROP: Replacing reg %d in jump_insn %d with constant ", 2862117395Skan REGNO (from), INSN_UID (jump)); 2863169689Skan print_rtl (dump_file, src); 2864169689Skan fprintf (dump_file, "\n"); 286590075Sobrien } 286690075Sobrien purge_dead_edges (bb); 286790075Sobrien 286890075Sobrien return 1; 286990075Sobrien} 287090075Sobrien 2871117395Skanstatic bool 2872169689Skanconstprop_register (rtx insn, rtx from, rtx to, bool alter_jumps) 287390075Sobrien{ 2874117395Skan rtx sset; 287590075Sobrien 2876117395Skan /* Check for reg or cc0 setting instructions followed by 2877117395Skan conditional branch instructions first. */ 2878117395Skan if (alter_jumps 2879117395Skan && (sset = single_set (insn)) != NULL 2880117395Skan && NEXT_INSN (insn) 2881117395Skan && any_condjump_p (NEXT_INSN (insn)) && onlyjump_p (NEXT_INSN (insn))) 2882117395Skan { 2883117395Skan rtx dest = SET_DEST (sset); 2884117395Skan if ((REG_P (dest) || CC0_P (dest)) 2885117395Skan && cprop_jump (BLOCK_FOR_INSN (insn), insn, NEXT_INSN (insn), from, to)) 2886117395Skan return 1; 2887117395Skan } 288890075Sobrien 2889117395Skan /* Handle normal insns next. */ 2890169689Skan if (NONJUMP_INSN_P (insn) 2891117395Skan && try_replace_reg (from, to, insn)) 2892117395Skan return 1; 289390075Sobrien 2894117395Skan /* Try to propagate a CONST_INT into a conditional jump. 2895117395Skan We're pretty specific about what we will handle in this 2896117395Skan code, we can extend this as necessary over time. 2897117395Skan 2898117395Skan Right now the insn in question must look like 2899117395Skan (set (pc) (if_then_else ...)) */ 2900117395Skan else if (alter_jumps && any_condjump_p (insn) && onlyjump_p (insn)) 2901117395Skan return cprop_jump (BLOCK_FOR_INSN (insn), NULL, insn, from, to); 2902117395Skan return 0; 290390075Sobrien} 2904117395Skan 290550397Sobrien/* Perform constant and copy propagation on INSN. 2906117395Skan The result is nonzero if a change was made. */ 290750397Sobrien 290850397Sobrienstatic int 2909132718Skancprop_insn (rtx insn, int alter_jumps) 291050397Sobrien{ 291150397Sobrien struct reg_use *reg_used; 291250397Sobrien int changed = 0; 291390075Sobrien rtx note; 291450397Sobrien 291590075Sobrien if (!INSN_P (insn)) 291650397Sobrien return 0; 291750397Sobrien 291850397Sobrien reg_use_count = 0; 291990075Sobrien note_uses (&PATTERN (insn), find_used_regs, NULL); 2920117395Skan 292190075Sobrien note = find_reg_equal_equiv_note (insn); 292250397Sobrien 292390075Sobrien /* We may win even when propagating constants into notes. */ 292490075Sobrien if (note) 292590075Sobrien find_used_regs (&XEXP (note, 0), NULL); 292690075Sobrien 292790075Sobrien for (reg_used = ®_use_table[0]; reg_use_count > 0; 292890075Sobrien reg_used++, reg_use_count--) 292950397Sobrien { 293090075Sobrien unsigned int regno = REGNO (reg_used->reg_rtx); 293150397Sobrien rtx pat, src; 293250397Sobrien struct expr *set; 293350397Sobrien 293450397Sobrien /* Ignore registers created by GCSE. 293590075Sobrien We do this because ... */ 293650397Sobrien if (regno >= max_gcse_regno) 293750397Sobrien continue; 293850397Sobrien 293950397Sobrien /* If the register has already been set in this block, there's 294050397Sobrien nothing we can do. */ 294150397Sobrien if (! oprs_not_set_p (reg_used->reg_rtx, insn)) 294250397Sobrien continue; 294350397Sobrien 294450397Sobrien /* Find an assignment that sets reg_used and is available 294550397Sobrien at the start of the block. */ 294650397Sobrien set = find_avail_set (regno, insn); 294750397Sobrien if (! set) 294850397Sobrien continue; 2949117395Skan 295050397Sobrien pat = set->expr; 295150397Sobrien /* ??? We might be able to handle PARALLELs. Later. */ 2952169689Skan gcc_assert (GET_CODE (pat) == SET); 295390075Sobrien 295450397Sobrien src = SET_SRC (pat); 295550397Sobrien 295652284Sobrien /* Constant propagation. */ 2957132718Skan if (gcse_constant_p (src)) 295850397Sobrien { 2959117395Skan if (constprop_register (insn, reg_used->reg_rtx, src, alter_jumps)) 296050397Sobrien { 296150397Sobrien changed = 1; 2962169689Skan global_const_prop_count++; 2963169689Skan if (dump_file != NULL) 296450397Sobrien { 2965169689Skan fprintf (dump_file, "GLOBAL CONST-PROP: Replacing reg %d in ", regno); 2966169689Skan fprintf (dump_file, "insn %d with constant ", INSN_UID (insn)); 2967169689Skan print_rtl (dump_file, src); 2968169689Skan fprintf (dump_file, "\n"); 296950397Sobrien } 2970132718Skan if (INSN_DELETED_P (insn)) 2971132718Skan return 1; 297250397Sobrien } 297350397Sobrien } 2974169689Skan else if (REG_P (src) 297550397Sobrien && REGNO (src) >= FIRST_PSEUDO_REGISTER 297650397Sobrien && REGNO (src) != regno) 297750397Sobrien { 297890075Sobrien if (try_replace_reg (reg_used->reg_rtx, src, insn)) 297950397Sobrien { 298090075Sobrien changed = 1; 2981169689Skan global_copy_prop_count++; 2982169689Skan if (dump_file != NULL) 298350397Sobrien { 2984169689Skan fprintf (dump_file, "GLOBAL COPY-PROP: Replacing reg %d in insn %d", 298590075Sobrien regno, INSN_UID (insn)); 2986169689Skan fprintf (dump_file, " with reg %d\n", REGNO (src)); 298790075Sobrien } 298850397Sobrien 298990075Sobrien /* The original insn setting reg_used may or may not now be 299090075Sobrien deletable. We leave the deletion to flow. */ 299190075Sobrien /* FIXME: If it turns out that the insn isn't deletable, 299290075Sobrien then we may have unnecessarily extended register lifetimes 299390075Sobrien and made things worse. */ 299450397Sobrien } 299550397Sobrien } 299650397Sobrien } 299750397Sobrien 299850397Sobrien return changed; 299950397Sobrien} 300050397Sobrien 3001117395Skan/* Like find_used_regs, but avoid recording uses that appear in 3002117395Skan input-output contexts such as zero_extract or pre_dec. This 3003117395Skan restricts the cases we consider to those for which local cprop 3004117395Skan can legitimately make replacements. */ 3005117395Skan 3006117395Skanstatic void 3007132718Skanlocal_cprop_find_used_regs (rtx *xptr, void *data) 3008117395Skan{ 3009117395Skan rtx x = *xptr; 3010117395Skan 3011117395Skan if (x == 0) 3012117395Skan return; 3013117395Skan 3014117395Skan switch (GET_CODE (x)) 3015117395Skan { 3016117395Skan case ZERO_EXTRACT: 3017117395Skan case SIGN_EXTRACT: 3018117395Skan case STRICT_LOW_PART: 3019117395Skan return; 3020117395Skan 3021117395Skan case PRE_DEC: 3022117395Skan case PRE_INC: 3023117395Skan case POST_DEC: 3024117395Skan case POST_INC: 3025117395Skan case PRE_MODIFY: 3026117395Skan case POST_MODIFY: 3027117395Skan /* Can only legitimately appear this early in the context of 3028117395Skan stack pushes for function arguments, but handle all of the 3029117395Skan codes nonetheless. */ 3030117395Skan return; 3031117395Skan 3032117395Skan case SUBREG: 3033117395Skan /* Setting a subreg of a register larger than word_mode leaves 3034117395Skan the non-written words unchanged. */ 3035117395Skan if (GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (x))) > BITS_PER_WORD) 3036117395Skan return; 3037117395Skan break; 3038117395Skan 3039117395Skan default: 3040117395Skan break; 3041117395Skan } 3042117395Skan 3043117395Skan find_used_regs (xptr, data); 3044117395Skan} 3045132718Skan 3046117395Skan/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall; 3047117395Skan their REG_EQUAL notes need updating. */ 3048117395Skan 3049117395Skanstatic bool 3050169689Skando_local_cprop (rtx x, rtx insn, bool alter_jumps, rtx *libcall_sp) 3051117395Skan{ 3052117395Skan rtx newreg = NULL, newcnst = NULL; 3053117395Skan 3054117395Skan /* Rule out USE instructions and ASM statements as we don't want to 3055117395Skan change the hard registers mentioned. */ 3056169689Skan if (REG_P (x) 3057117395Skan && (REGNO (x) >= FIRST_PSEUDO_REGISTER 3058117395Skan || (GET_CODE (PATTERN (insn)) != USE 3059117395Skan && asm_noperands (PATTERN (insn)) < 0))) 3060117395Skan { 3061117395Skan cselib_val *val = cselib_lookup (x, GET_MODE (x), 0); 3062117395Skan struct elt_loc_list *l; 3063117395Skan 3064117395Skan if (!val) 3065117395Skan return false; 3066117395Skan for (l = val->locs; l; l = l->next) 3067117395Skan { 3068117395Skan rtx this_rtx = l->loc; 3069117395Skan rtx note; 3070117395Skan 3071146895Skan /* Don't CSE non-constant values out of libcall blocks. */ 3072146895Skan if (l->in_libcall && ! CONSTANT_P (this_rtx)) 3073117395Skan continue; 3074117395Skan 3075132718Skan if (gcse_constant_p (this_rtx)) 3076117395Skan newcnst = this_rtx; 3077117395Skan if (REG_P (this_rtx) && REGNO (this_rtx) >= FIRST_PSEUDO_REGISTER 3078117395Skan /* Don't copy propagate if it has attached REG_EQUIV note. 3079117395Skan At this point this only function parameters should have 3080117395Skan REG_EQUIV notes and if the argument slot is used somewhere 3081117395Skan explicitly, it means address of parameter has been taken, 3082117395Skan so we should not extend the lifetime of the pseudo. */ 3083117395Skan && (!(note = find_reg_note (l->setting_insn, REG_EQUIV, NULL_RTX)) 3084169689Skan || ! MEM_P (XEXP (note, 0)))) 3085117395Skan newreg = this_rtx; 3086117395Skan } 3087117395Skan if (newcnst && constprop_register (insn, x, newcnst, alter_jumps)) 3088117395Skan { 3089117395Skan /* If we find a case where we can't fix the retval REG_EQUAL notes 3090132718Skan match the new register, we either have to abandon this replacement 3091117395Skan or fix delete_trivially_dead_insns to preserve the setting insn, 3092117395Skan or make it delete the REG_EUAQL note, and fix up all passes that 3093117395Skan require the REG_EQUAL note there. */ 3094169689Skan bool adjusted; 3095169689Skan 3096169689Skan adjusted = adjust_libcall_notes (x, newcnst, insn, libcall_sp); 3097169689Skan gcc_assert (adjusted); 3098169689Skan 3099169689Skan if (dump_file != NULL) 3100117395Skan { 3101169689Skan fprintf (dump_file, "LOCAL CONST-PROP: Replacing reg %d in ", 3102117395Skan REGNO (x)); 3103169689Skan fprintf (dump_file, "insn %d with constant ", 3104117395Skan INSN_UID (insn)); 3105169689Skan print_rtl (dump_file, newcnst); 3106169689Skan fprintf (dump_file, "\n"); 3107117395Skan } 3108169689Skan local_const_prop_count++; 3109117395Skan return true; 3110117395Skan } 3111117395Skan else if (newreg && newreg != x && try_replace_reg (x, newreg, insn)) 3112117395Skan { 3113117395Skan adjust_libcall_notes (x, newreg, insn, libcall_sp); 3114169689Skan if (dump_file != NULL) 3115117395Skan { 3116169689Skan fprintf (dump_file, 3117117395Skan "LOCAL COPY-PROP: Replacing reg %d in insn %d", 3118117395Skan REGNO (x), INSN_UID (insn)); 3119169689Skan fprintf (dump_file, " with reg %d\n", REGNO (newreg)); 3120117395Skan } 3121169689Skan local_copy_prop_count++; 3122117395Skan return true; 3123117395Skan } 3124117395Skan } 3125117395Skan return false; 3126117395Skan} 3127117395Skan 3128117395Skan/* LIBCALL_SP is a zero-terminated array of insns at the end of a libcall; 3129117395Skan their REG_EQUAL notes need updating to reflect that OLDREG has been 3130117395Skan replaced with NEWVAL in INSN. Return true if all substitutions could 3131117395Skan be made. */ 3132117395Skanstatic bool 3133132718Skanadjust_libcall_notes (rtx oldreg, rtx newval, rtx insn, rtx *libcall_sp) 3134117395Skan{ 3135117395Skan rtx end; 3136117395Skan 3137117395Skan while ((end = *libcall_sp++)) 3138117395Skan { 3139117395Skan rtx note = find_reg_equal_equiv_note (end); 3140117395Skan 3141117395Skan if (! note) 3142117395Skan continue; 3143117395Skan 3144117395Skan if (REG_P (newval)) 3145117395Skan { 3146117395Skan if (reg_set_between_p (newval, PREV_INSN (insn), end)) 3147117395Skan { 3148117395Skan do 3149117395Skan { 3150117395Skan note = find_reg_equal_equiv_note (end); 3151117395Skan if (! note) 3152117395Skan continue; 3153117395Skan if (reg_mentioned_p (newval, XEXP (note, 0))) 3154117395Skan return false; 3155117395Skan } 3156117395Skan while ((end = *libcall_sp++)); 3157117395Skan return true; 3158117395Skan } 3159117395Skan } 3160146895Skan XEXP (note, 0) = simplify_replace_rtx (XEXP (note, 0), oldreg, newval); 3161117395Skan insn = end; 3162117395Skan } 3163117395Skan return true; 3164117395Skan} 3165117395Skan 3166117395Skan#define MAX_NESTED_LIBCALLS 9 3167117395Skan 3168169689Skan/* Do local const/copy propagation (i.e. within each basic block). 3169169689Skan If ALTER_JUMPS is true, allow propagating into jump insns, which 3170169689Skan could modify the CFG. */ 3171169689Skan 3172117395Skanstatic void 3173169689Skanlocal_cprop_pass (bool alter_jumps) 3174117395Skan{ 3175169689Skan basic_block bb; 3176117395Skan rtx insn; 3177117395Skan struct reg_use *reg_used; 3178117395Skan rtx libcall_stack[MAX_NESTED_LIBCALLS + 1], *libcall_sp; 3179117395Skan bool changed = false; 3180117395Skan 3181169689Skan cselib_init (false); 3182117395Skan libcall_sp = &libcall_stack[MAX_NESTED_LIBCALLS]; 3183117395Skan *libcall_sp = 0; 3184169689Skan FOR_EACH_BB (bb) 3185117395Skan { 3186169689Skan FOR_BB_INSNS (bb, insn) 3187117395Skan { 3188169689Skan if (INSN_P (insn)) 3189169689Skan { 3190169689Skan rtx note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); 3191117395Skan 3192117395Skan if (note) 3193169689Skan { 3194169689Skan gcc_assert (libcall_sp != libcall_stack); 3195169689Skan *--libcall_sp = XEXP (note, 0); 3196169689Skan } 3197169689Skan note = find_reg_note (insn, REG_RETVAL, NULL_RTX); 3198169689Skan if (note) 3199169689Skan libcall_sp++; 3200169689Skan note = find_reg_equal_equiv_note (insn); 3201169689Skan do 3202169689Skan { 3203169689Skan reg_use_count = 0; 3204169689Skan note_uses (&PATTERN (insn), local_cprop_find_used_regs, 3205169689Skan NULL); 3206169689Skan if (note) 3207169689Skan local_cprop_find_used_regs (&XEXP (note, 0), NULL); 3208117395Skan 3209169689Skan for (reg_used = ®_use_table[0]; reg_use_count > 0; 3210169689Skan reg_used++, reg_use_count--) 3211169689Skan if (do_local_cprop (reg_used->reg_rtx, insn, alter_jumps, 3212169689Skan libcall_sp)) 3213169689Skan { 3214169689Skan changed = true; 3215169689Skan break; 3216169689Skan } 3217169689Skan if (INSN_DELETED_P (insn)) 3218117395Skan break; 3219169689Skan } 3220169689Skan while (reg_use_count); 3221117395Skan } 3222169689Skan cselib_process_insn (insn); 3223117395Skan } 3224169689Skan 3225169689Skan /* Forget everything at the end of a basic block. Make sure we are 3226169689Skan not inside a libcall, they should never cross basic blocks. */ 3227169689Skan cselib_clear_table (); 3228169689Skan gcc_assert (libcall_sp == &libcall_stack[MAX_NESTED_LIBCALLS]); 3229117395Skan } 3230169689Skan 3231117395Skan cselib_finish (); 3232169689Skan 3233117395Skan /* Global analysis may get into infinite loops for unreachable blocks. */ 3234117395Skan if (changed && alter_jumps) 3235117395Skan { 3236117395Skan delete_unreachable_blocks (); 3237117395Skan free_reg_set_mem (); 3238117395Skan alloc_reg_set_mem (max_reg_num ()); 3239169689Skan compute_sets (); 3240117395Skan } 3241117395Skan} 3242117395Skan 324390075Sobrien/* Forward propagate copies. This includes copies and constants. Return 3244117395Skan nonzero if a change was made. */ 324550397Sobrien 324650397Sobrienstatic int 3247132718Skancprop (int alter_jumps) 324850397Sobrien{ 3249117395Skan int changed; 3250117395Skan basic_block bb; 325150397Sobrien rtx insn; 325250397Sobrien 325350397Sobrien /* Note we start at block 1. */ 3254117395Skan if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR) 3255117395Skan { 3256169689Skan if (dump_file != NULL) 3257169689Skan fprintf (dump_file, "\n"); 3258117395Skan return 0; 3259117395Skan } 326050397Sobrien 326150397Sobrien changed = 0; 3262117395Skan FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, EXIT_BLOCK_PTR, next_bb) 326350397Sobrien { 326450397Sobrien /* Reset tables used to keep track of what's still valid [since the 326550397Sobrien start of the block]. */ 326650397Sobrien reset_opr_set_tables (); 326750397Sobrien 3268169689Skan FOR_BB_INSNS (bb, insn) 326990075Sobrien if (INSN_P (insn)) 327090075Sobrien { 3271117395Skan changed |= cprop_insn (insn, alter_jumps); 327250397Sobrien 327390075Sobrien /* Keep track of everything modified by this insn. */ 327490075Sobrien /* ??? Need to be careful w.r.t. mods done to INSN. Don't 327590075Sobrien call mark_oprs_set if we turned the insn into a NOTE. */ 3276169689Skan if (! NOTE_P (insn)) 327750397Sobrien mark_oprs_set (insn); 327890075Sobrien } 327950397Sobrien } 328050397Sobrien 3281169689Skan if (dump_file != NULL) 3282169689Skan fprintf (dump_file, "\n"); 328350397Sobrien 328450397Sobrien return changed; 328550397Sobrien} 328650397Sobrien 3287132718Skan/* Similar to get_condition, only the resulting condition must be 3288132718Skan valid at JUMP, instead of at EARLIEST. 3289132718Skan 3290132718Skan This differs from noce_get_condition in ifcvt.c in that we prefer not to 3291132718Skan settle for the condition variable in the jump instruction being integral. 3292132718Skan We prefer to be able to record the value of a user variable, rather than 3293132718Skan the value of a temporary used in a condition. This could be solved by 3294169689Skan recording the value of *every* register scanned by canonicalize_condition, 3295132718Skan but this would require some code reorganization. */ 3296132718Skan 3297132718Skanrtx 3298132718Skanfis_get_condition (rtx jump) 3299132718Skan{ 3300169689Skan return get_condition (jump, NULL, false, true); 3301132718Skan} 3302132718Skan 3303132718Skan/* Check the comparison COND to see if we can safely form an implicit set from 3304132718Skan it. COND is either an EQ or NE comparison. */ 3305132718Skan 3306132718Skanstatic bool 3307132718Skanimplicit_set_cond_p (rtx cond) 3308132718Skan{ 3309132718Skan enum machine_mode mode = GET_MODE (XEXP (cond, 0)); 3310132718Skan rtx cst = XEXP (cond, 1); 3311132718Skan 3312132718Skan /* We can't perform this optimization if either operand might be or might 3313132718Skan contain a signed zero. */ 3314132718Skan if (HONOR_SIGNED_ZEROS (mode)) 3315132718Skan { 3316132718Skan /* It is sufficient to check if CST is or contains a zero. We must 3317132718Skan handle float, complex, and vector. If any subpart is a zero, then 3318132718Skan the optimization can't be performed. */ 3319132718Skan /* ??? The complex and vector checks are not implemented yet. We just 3320132718Skan always return zero for them. */ 3321132718Skan if (GET_CODE (cst) == CONST_DOUBLE) 3322132718Skan { 3323132718Skan REAL_VALUE_TYPE d; 3324132718Skan REAL_VALUE_FROM_CONST_DOUBLE (d, cst); 3325132718Skan if (REAL_VALUES_EQUAL (d, dconst0)) 3326132718Skan return 0; 3327132718Skan } 3328132718Skan else 3329132718Skan return 0; 3330132718Skan } 3331132718Skan 3332132718Skan return gcse_constant_p (cst); 3333132718Skan} 3334132718Skan 3335132718Skan/* Find the implicit sets of a function. An "implicit set" is a constraint 3336132718Skan on the value of a variable, implied by a conditional jump. For example, 3337132718Skan following "if (x == 2)", the then branch may be optimized as though the 3338132718Skan conditional performed an "explicit set", in this example, "x = 2". This 3339132718Skan function records the set patterns that are implicit at the start of each 3340132718Skan basic block. */ 3341132718Skan 3342132718Skanstatic void 3343132718Skanfind_implicit_sets (void) 3344132718Skan{ 3345132718Skan basic_block bb, dest; 3346132718Skan unsigned int count; 3347132718Skan rtx cond, new; 3348132718Skan 3349132718Skan count = 0; 3350132718Skan FOR_EACH_BB (bb) 3351132718Skan /* Check for more than one successor. */ 3352169689Skan if (EDGE_COUNT (bb->succs) > 1) 3353132718Skan { 3354132718Skan cond = fis_get_condition (BB_END (bb)); 3355132718Skan 3356132718Skan if (cond 3357132718Skan && (GET_CODE (cond) == EQ || GET_CODE (cond) == NE) 3358169689Skan && REG_P (XEXP (cond, 0)) 3359132718Skan && REGNO (XEXP (cond, 0)) >= FIRST_PSEUDO_REGISTER 3360132718Skan && implicit_set_cond_p (cond)) 3361132718Skan { 3362132718Skan dest = GET_CODE (cond) == EQ ? BRANCH_EDGE (bb)->dest 3363132718Skan : FALLTHRU_EDGE (bb)->dest; 3364132718Skan 3365169689Skan if (dest && single_pred_p (dest) 3366132718Skan && dest != EXIT_BLOCK_PTR) 3367132718Skan { 3368132718Skan new = gen_rtx_SET (VOIDmode, XEXP (cond, 0), 3369132718Skan XEXP (cond, 1)); 3370132718Skan implicit_sets[dest->index] = new; 3371169689Skan if (dump_file) 3372132718Skan { 3373169689Skan fprintf(dump_file, "Implicit set of reg %d in ", 3374132718Skan REGNO (XEXP (cond, 0))); 3375169689Skan fprintf(dump_file, "basic block %d\n", dest->index); 3376132718Skan } 3377132718Skan count++; 3378132718Skan } 3379132718Skan } 3380132718Skan } 3381132718Skan 3382169689Skan if (dump_file) 3383169689Skan fprintf (dump_file, "Found %d implicit sets\n", count); 3384132718Skan} 3385132718Skan 338650397Sobrien/* Perform one copy/constant propagation pass. 3387132718Skan PASS is the pass count. If CPROP_JUMPS is true, perform constant 3388132718Skan propagation into conditional jumps. If BYPASS_JUMPS is true, 3389132718Skan perform conditional jump bypassing optimizations. */ 339050397Sobrien 339150397Sobrienstatic int 3392169689Skanone_cprop_pass (int pass, bool cprop_jumps, bool bypass_jumps) 339350397Sobrien{ 339450397Sobrien int changed = 0; 339550397Sobrien 3396169689Skan global_const_prop_count = local_const_prop_count = 0; 3397169689Skan global_copy_prop_count = local_copy_prop_count = 0; 339850397Sobrien 3399132718Skan local_cprop_pass (cprop_jumps); 3400117395Skan 3401132718Skan /* Determine implicit sets. */ 3402169689Skan implicit_sets = XCNEWVEC (rtx, last_basic_block); 3403132718Skan find_implicit_sets (); 3404132718Skan 3405117395Skan alloc_hash_table (max_cuid, &set_hash_table, 1); 3406117395Skan compute_hash_table (&set_hash_table); 3407132718Skan 3408132718Skan /* Free implicit_sets before peak usage. */ 3409132718Skan free (implicit_sets); 3410132718Skan implicit_sets = NULL; 3411132718Skan 3412169689Skan if (dump_file) 3413169689Skan dump_hash_table (dump_file, "SET", &set_hash_table); 3414117395Skan if (set_hash_table.n_elems > 0) 341550397Sobrien { 3416117395Skan alloc_cprop_mem (last_basic_block, set_hash_table.n_elems); 341750397Sobrien compute_cprop_data (); 3418132718Skan changed = cprop (cprop_jumps); 3419132718Skan if (bypass_jumps) 3420117395Skan changed |= bypass_conditional_jumps (); 342150397Sobrien free_cprop_mem (); 342250397Sobrien } 342390075Sobrien 3424117395Skan free_hash_table (&set_hash_table); 342550397Sobrien 3426169689Skan if (dump_file) 342750397Sobrien { 3428169689Skan fprintf (dump_file, "CPROP of %s, pass %d: %d bytes needed, ", 3429132718Skan current_function_name (), pass, bytes_used); 3430169689Skan fprintf (dump_file, "%d local const props, %d local copy props, ", 3431169689Skan local_const_prop_count, local_copy_prop_count); 3432169689Skan fprintf (dump_file, "%d global const props, %d global copy props\n\n", 3433169689Skan global_const_prop_count, global_copy_prop_count); 343450397Sobrien } 3435117395Skan /* Global analysis may get into infinite loops for unreachable blocks. */ 3436132718Skan if (changed && cprop_jumps) 3437117395Skan delete_unreachable_blocks (); 343850397Sobrien 343950397Sobrien return changed; 344050397Sobrien} 344150397Sobrien 3442117395Skan/* Bypass conditional jumps. */ 3443117395Skan 3444132718Skan/* The value of last_basic_block at the beginning of the jump_bypass 3445132718Skan pass. The use of redirect_edge_and_branch_force may introduce new 3446132718Skan basic blocks, but the data flow analysis is only valid for basic 3447132718Skan block indices less than bypass_last_basic_block. */ 3448132718Skan 3449132718Skanstatic int bypass_last_basic_block; 3450132718Skan 3451117395Skan/* Find a set of REGNO to a constant that is available at the end of basic 3452117395Skan block BB. Returns NULL if no such set is found. Based heavily upon 3453117395Skan find_avail_set. */ 3454117395Skan 3455117395Skanstatic struct expr * 3456132718Skanfind_bypass_set (int regno, int bb) 3457117395Skan{ 3458117395Skan struct expr *result = 0; 3459117395Skan 3460117395Skan for (;;) 3461117395Skan { 3462117395Skan rtx src; 3463132718Skan struct expr *set = lookup_set (regno, &set_hash_table); 3464117395Skan 3465117395Skan while (set) 3466117395Skan { 3467117395Skan if (TEST_BIT (cprop_avout[bb], set->bitmap_index)) 3468117395Skan break; 3469117395Skan set = next_set (regno, set); 3470117395Skan } 3471117395Skan 3472117395Skan if (set == 0) 3473117395Skan break; 3474117395Skan 3475169689Skan gcc_assert (GET_CODE (set->expr) == SET); 3476117395Skan 3477117395Skan src = SET_SRC (set->expr); 3478132718Skan if (gcse_constant_p (src)) 3479117395Skan result = set; 3480117395Skan 3481169689Skan if (! REG_P (src)) 3482117395Skan break; 3483117395Skan 3484117395Skan regno = REGNO (src); 3485117395Skan } 3486117395Skan return result; 3487117395Skan} 3488117395Skan 3489117395Skan 3490117395Skan/* Subroutine of bypass_block that checks whether a pseudo is killed by 3491117395Skan any of the instructions inserted on an edge. Jump bypassing places 3492117395Skan condition code setters on CFG edges using insert_insn_on_edge. This 3493117395Skan function is required to check that our data flow analysis is still 3494117395Skan valid prior to commit_edge_insertions. */ 3495117395Skan 3496117395Skanstatic bool 3497132718Skanreg_killed_on_edge (rtx reg, edge e) 3498117395Skan{ 3499117395Skan rtx insn; 3500117395Skan 3501169689Skan for (insn = e->insns.r; insn; insn = NEXT_INSN (insn)) 3502117395Skan if (INSN_P (insn) && reg_set_p (reg, insn)) 3503117395Skan return true; 3504117395Skan 3505117395Skan return false; 3506117395Skan} 3507117395Skan 3508117395Skan/* Subroutine of bypass_conditional_jumps that attempts to bypass the given 3509117395Skan basic block BB which has more than one predecessor. If not NULL, SETCC 3510117395Skan is the first instruction of BB, which is immediately followed by JUMP_INSN 3511117395Skan JUMP. Otherwise, SETCC is NULL, and JUMP is the first insn of BB. 3512117395Skan Returns nonzero if a change was made. 3513117395Skan 3514132718Skan During the jump bypassing pass, we may place copies of SETCC instructions 3515117395Skan on CFG edges. The following routine must be careful to pay attention to 3516117395Skan these inserted insns when performing its transformations. */ 3517117395Skan 3518117395Skanstatic int 3519132718Skanbypass_block (basic_block bb, rtx setcc, rtx jump) 3520117395Skan{ 3521117395Skan rtx insn, note; 3522169689Skan edge e, edest; 3523117395Skan int i, change; 3524132718Skan int may_be_loop_header; 3525169689Skan unsigned removed_p; 3526169689Skan edge_iterator ei; 3527117395Skan 3528117395Skan insn = (setcc != NULL) ? setcc : jump; 3529117395Skan 3530117395Skan /* Determine set of register uses in INSN. */ 3531117395Skan reg_use_count = 0; 3532117395Skan note_uses (&PATTERN (insn), find_used_regs, NULL); 3533117395Skan note = find_reg_equal_equiv_note (insn); 3534117395Skan if (note) 3535117395Skan find_used_regs (&XEXP (note, 0), NULL); 3536117395Skan 3537132718Skan may_be_loop_header = false; 3538169689Skan FOR_EACH_EDGE (e, ei, bb->preds) 3539132718Skan if (e->flags & EDGE_DFS_BACK) 3540132718Skan { 3541132718Skan may_be_loop_header = true; 3542132718Skan break; 3543132718Skan } 3544132718Skan 3545117395Skan change = 0; 3546169689Skan for (ei = ei_start (bb->preds); (e = ei_safe_edge (ei)); ) 3547117395Skan { 3548169689Skan removed_p = 0; 3549169689Skan 3550132718Skan if (e->flags & EDGE_COMPLEX) 3551169689Skan { 3552169689Skan ei_next (&ei); 3553169689Skan continue; 3554169689Skan } 3555132718Skan 3556132718Skan /* We can't redirect edges from new basic blocks. */ 3557132718Skan if (e->src->index >= bypass_last_basic_block) 3558169689Skan { 3559169689Skan ei_next (&ei); 3560169689Skan continue; 3561169689Skan } 3562132718Skan 3563132718Skan /* The irreducible loops created by redirecting of edges entering the 3564132718Skan loop from outside would decrease effectiveness of some of the following 3565132718Skan optimizations, so prevent this. */ 3566132718Skan if (may_be_loop_header 3567132718Skan && !(e->flags & EDGE_DFS_BACK)) 3568169689Skan { 3569169689Skan ei_next (&ei); 3570169689Skan continue; 3571169689Skan } 3572132718Skan 3573117395Skan for (i = 0; i < reg_use_count; i++) 3574117395Skan { 3575117395Skan struct reg_use *reg_used = ®_use_table[i]; 3576117395Skan unsigned int regno = REGNO (reg_used->reg_rtx); 3577117395Skan basic_block dest, old_dest; 3578117395Skan struct expr *set; 3579117395Skan rtx src, new; 3580117395Skan 3581117395Skan if (regno >= max_gcse_regno) 3582117395Skan continue; 3583117395Skan 3584117395Skan set = find_bypass_set (regno, e->src->index); 3585117395Skan 3586117395Skan if (! set) 3587117395Skan continue; 3588117395Skan 3589117395Skan /* Check the data flow is valid after edge insertions. */ 3590169689Skan if (e->insns.r && reg_killed_on_edge (reg_used->reg_rtx, e)) 3591117395Skan continue; 3592117395Skan 3593117395Skan src = SET_SRC (pc_set (jump)); 3594117395Skan 3595117395Skan if (setcc != NULL) 3596117395Skan src = simplify_replace_rtx (src, 3597117395Skan SET_DEST (PATTERN (setcc)), 3598117395Skan SET_SRC (PATTERN (setcc))); 3599117395Skan 3600117395Skan new = simplify_replace_rtx (src, reg_used->reg_rtx, 3601117395Skan SET_SRC (set->expr)); 3602117395Skan 3603132718Skan /* Jump bypassing may have already placed instructions on 3604117395Skan edges of the CFG. We can't bypass an outgoing edge that 3605117395Skan has instructions associated with it, as these insns won't 3606117395Skan get executed if the incoming edge is redirected. */ 3607117395Skan 3608117395Skan if (new == pc_rtx) 3609117395Skan { 3610117395Skan edest = FALLTHRU_EDGE (bb); 3611169689Skan dest = edest->insns.r ? NULL : edest->dest; 3612117395Skan } 3613117395Skan else if (GET_CODE (new) == LABEL_REF) 3614117395Skan { 3615117395Skan dest = BLOCK_FOR_INSN (XEXP (new, 0)); 3616117395Skan /* Don't bypass edges containing instructions. */ 3617169689Skan edest = find_edge (bb, dest); 3618169689Skan if (edest && edest->insns.r) 3619169689Skan dest = NULL; 3620117395Skan } 3621117395Skan else 3622117395Skan dest = NULL; 3623117395Skan 3624132718Skan /* Avoid unification of the edge with other edges from original 3625132718Skan branch. We would end up emitting the instruction on "both" 3626132718Skan edges. */ 3627132718Skan 3628169689Skan if (dest && setcc && !CC0_P (SET_DEST (PATTERN (setcc))) 3629169689Skan && find_edge (e->src, dest)) 3630169689Skan dest = NULL; 3631169689Skan 3632117395Skan old_dest = e->dest; 3633132718Skan if (dest != NULL 3634132718Skan && dest != old_dest 3635132718Skan && dest != EXIT_BLOCK_PTR) 3636132718Skan { 3637132718Skan redirect_edge_and_branch_force (e, dest); 3638132718Skan 3639117395Skan /* Copy the register setter to the redirected edge. 3640117395Skan Don't copy CC0 setters, as CC0 is dead after jump. */ 3641117395Skan if (setcc) 3642117395Skan { 3643117395Skan rtx pat = PATTERN (setcc); 3644117395Skan if (!CC0_P (SET_DEST (pat))) 3645117395Skan insert_insn_on_edge (copy_insn (pat), e); 3646117395Skan } 3647117395Skan 3648169689Skan if (dump_file != NULL) 3649117395Skan { 3650169689Skan fprintf (dump_file, "JUMP-BYPASS: Proved reg %d " 3651169689Skan "in jump_insn %d equals constant ", 3652117395Skan regno, INSN_UID (jump)); 3653169689Skan print_rtl (dump_file, SET_SRC (set->expr)); 3654169689Skan fprintf (dump_file, "\nBypass edge from %d->%d to %d\n", 3655117395Skan e->src->index, old_dest->index, dest->index); 3656117395Skan } 3657117395Skan change = 1; 3658169689Skan removed_p = 1; 3659117395Skan break; 3660117395Skan } 3661117395Skan } 3662169689Skan if (!removed_p) 3663169689Skan ei_next (&ei); 3664117395Skan } 3665117395Skan return change; 3666117395Skan} 3667117395Skan 3668117395Skan/* Find basic blocks with more than one predecessor that only contain a 3669117395Skan single conditional jump. If the result of the comparison is known at 3670117395Skan compile-time from any incoming edge, redirect that edge to the 3671132718Skan appropriate target. Returns nonzero if a change was made. 3672117395Skan 3673132718Skan This function is now mis-named, because we also handle indirect jumps. */ 3674132718Skan 3675117395Skanstatic int 3676132718Skanbypass_conditional_jumps (void) 3677117395Skan{ 3678117395Skan basic_block bb; 3679117395Skan int changed; 3680117395Skan rtx setcc; 3681117395Skan rtx insn; 3682117395Skan rtx dest; 3683117395Skan 3684117395Skan /* Note we start at block 1. */ 3685117395Skan if (ENTRY_BLOCK_PTR->next_bb == EXIT_BLOCK_PTR) 3686117395Skan return 0; 3687117395Skan 3688132718Skan bypass_last_basic_block = last_basic_block; 3689132718Skan mark_dfs_back_edges (); 3690132718Skan 3691117395Skan changed = 0; 3692117395Skan FOR_BB_BETWEEN (bb, ENTRY_BLOCK_PTR->next_bb->next_bb, 3693117395Skan EXIT_BLOCK_PTR, next_bb) 3694117395Skan { 3695117395Skan /* Check for more than one predecessor. */ 3696169689Skan if (!single_pred_p (bb)) 3697117395Skan { 3698117395Skan setcc = NULL_RTX; 3699169689Skan FOR_BB_INSNS (bb, insn) 3700169689Skan if (NONJUMP_INSN_P (insn)) 3701117395Skan { 3702117395Skan if (setcc) 3703117395Skan break; 3704117395Skan if (GET_CODE (PATTERN (insn)) != SET) 3705117395Skan break; 3706117395Skan 3707117395Skan dest = SET_DEST (PATTERN (insn)); 3708117395Skan if (REG_P (dest) || CC0_P (dest)) 3709117395Skan setcc = insn; 3710117395Skan else 3711117395Skan break; 3712117395Skan } 3713169689Skan else if (JUMP_P (insn)) 3714117395Skan { 3715132718Skan if ((any_condjump_p (insn) || computed_jump_p (insn)) 3716132718Skan && onlyjump_p (insn)) 3717117395Skan changed |= bypass_block (bb, setcc, insn); 3718117395Skan break; 3719117395Skan } 3720117395Skan else if (INSN_P (insn)) 3721117395Skan break; 3722117395Skan } 3723117395Skan } 3724117395Skan 3725117395Skan /* If we bypassed any register setting insns, we inserted a 3726132718Skan copy on the redirected edge. These need to be committed. */ 3727117395Skan if (changed) 3728117395Skan commit_edge_insertions(); 3729117395Skan 3730117395Skan return changed; 3731117395Skan} 3732117395Skan 373352284Sobrien/* Compute PRE+LCM working variables. */ 373450397Sobrien 373550397Sobrien/* Local properties of expressions. */ 373650397Sobrien/* Nonzero for expressions that are transparent in the block. */ 373752284Sobrienstatic sbitmap *transp; 373852284Sobrien 373952284Sobrien/* Nonzero for expressions that are transparent at the end of the block. 374052284Sobrien This is only zero for expressions killed by abnormal critical edge 374152284Sobrien created by a calls. */ 374252284Sobrienstatic sbitmap *transpout; 374352284Sobrien 374450397Sobrien/* Nonzero for expressions that are computed (available) in the block. */ 374552284Sobrienstatic sbitmap *comp; 374652284Sobrien 374750397Sobrien/* Nonzero for expressions that are locally anticipatable in the block. */ 374852284Sobrienstatic sbitmap *antloc; 374950397Sobrien 375052284Sobrien/* Nonzero for expressions where this block is an optimal computation 375152284Sobrien point. */ 375252284Sobrienstatic sbitmap *pre_optimal; 375350397Sobrien 375452284Sobrien/* Nonzero for expressions which are redundant in a particular block. */ 375552284Sobrienstatic sbitmap *pre_redundant; 375650397Sobrien 375790075Sobrien/* Nonzero for expressions which should be inserted on a specific edge. */ 375890075Sobrienstatic sbitmap *pre_insert_map; 375952284Sobrien 376090075Sobrien/* Nonzero for expressions which should be deleted in a specific block. */ 376190075Sobrienstatic sbitmap *pre_delete_map; 376290075Sobrien 376390075Sobrien/* Contains the edge_list returned by pre_edge_lcm. */ 376490075Sobrienstatic struct edge_list *edge_list; 376590075Sobrien 376652284Sobrien/* Redundant insns. */ 376752284Sobrienstatic sbitmap pre_redundant_insns; 376852284Sobrien 376950397Sobrien/* Allocate vars used for PRE analysis. */ 377050397Sobrien 377150397Sobrienstatic void 3772132718Skanalloc_pre_mem (int n_blocks, int n_exprs) 377350397Sobrien{ 377452284Sobrien transp = sbitmap_vector_alloc (n_blocks, n_exprs); 377552284Sobrien comp = sbitmap_vector_alloc (n_blocks, n_exprs); 377652284Sobrien antloc = sbitmap_vector_alloc (n_blocks, n_exprs); 377750397Sobrien 377890075Sobrien pre_optimal = NULL; 377990075Sobrien pre_redundant = NULL; 378090075Sobrien pre_insert_map = NULL; 378190075Sobrien pre_delete_map = NULL; 378290075Sobrien ae_kill = sbitmap_vector_alloc (n_blocks, n_exprs); 378390075Sobrien 378490075Sobrien /* pre_insert and pre_delete are allocated later. */ 378550397Sobrien} 378650397Sobrien 378750397Sobrien/* Free vars used for PRE analysis. */ 378850397Sobrien 378950397Sobrienstatic void 3790132718Skanfree_pre_mem (void) 379150397Sobrien{ 379290075Sobrien sbitmap_vector_free (transp); 379390075Sobrien sbitmap_vector_free (comp); 379450397Sobrien 379590075Sobrien /* ANTLOC and AE_KILL are freed just after pre_lcm finishes. */ 379690075Sobrien 379790075Sobrien if (pre_optimal) 379890075Sobrien sbitmap_vector_free (pre_optimal); 379990075Sobrien if (pre_redundant) 380090075Sobrien sbitmap_vector_free (pre_redundant); 380190075Sobrien if (pre_insert_map) 380290075Sobrien sbitmap_vector_free (pre_insert_map); 380390075Sobrien if (pre_delete_map) 380490075Sobrien sbitmap_vector_free (pre_delete_map); 380590075Sobrien 380690075Sobrien transp = comp = NULL; 380790075Sobrien pre_optimal = pre_redundant = pre_insert_map = pre_delete_map = NULL; 380850397Sobrien} 380950397Sobrien 381050397Sobrien/* Top level routine to do the dataflow analysis needed by PRE. */ 381150397Sobrien 381250397Sobrienstatic void 3813132718Skancompute_pre_data (void) 381450397Sobrien{ 381590075Sobrien sbitmap trapping_expr; 3816117395Skan basic_block bb; 381790075Sobrien unsigned int ui; 381890075Sobrien 3819117395Skan compute_local_properties (transp, comp, antloc, &expr_hash_table); 3820117395Skan sbitmap_vector_zero (ae_kill, last_basic_block); 382190075Sobrien 382290075Sobrien /* Collect expressions which might trap. */ 3823117395Skan trapping_expr = sbitmap_alloc (expr_hash_table.n_elems); 382490075Sobrien sbitmap_zero (trapping_expr); 3825117395Skan for (ui = 0; ui < expr_hash_table.size; ui++) 382690075Sobrien { 382790075Sobrien struct expr *e; 3828117395Skan for (e = expr_hash_table.table[ui]; e != NULL; e = e->next_same_hash) 382990075Sobrien if (may_trap_p (e->expr)) 383090075Sobrien SET_BIT (trapping_expr, e->bitmap_index); 383190075Sobrien } 383290075Sobrien 383390075Sobrien /* Compute ae_kill for each basic block using: 383490075Sobrien 383590075Sobrien ~(TRANSP | COMP) 3836169689Skan */ 383790075Sobrien 3838117395Skan FOR_EACH_BB (bb) 383990075Sobrien { 384090075Sobrien edge e; 3841169689Skan edge_iterator ei; 384290075Sobrien 384390075Sobrien /* If the current block is the destination of an abnormal edge, we 384490075Sobrien kill all trapping expressions because we won't be able to properly 384590075Sobrien place the instruction on the edge. So make them neither 384690075Sobrien anticipatable nor transparent. This is fairly conservative. */ 3847169689Skan FOR_EACH_EDGE (e, ei, bb->preds) 384890075Sobrien if (e->flags & EDGE_ABNORMAL) 384990075Sobrien { 3850117395Skan sbitmap_difference (antloc[bb->index], antloc[bb->index], trapping_expr); 3851117395Skan sbitmap_difference (transp[bb->index], transp[bb->index], trapping_expr); 385290075Sobrien break; 385390075Sobrien } 385490075Sobrien 3855117395Skan sbitmap_a_or_b (ae_kill[bb->index], transp[bb->index], comp[bb->index]); 3856117395Skan sbitmap_not (ae_kill[bb->index], ae_kill[bb->index]); 385790075Sobrien } 385890075Sobrien 3859169689Skan edge_list = pre_edge_lcm (expr_hash_table.n_elems, transp, comp, antloc, 386090075Sobrien ae_kill, &pre_insert_map, &pre_delete_map); 386190075Sobrien sbitmap_vector_free (antloc); 386290075Sobrien antloc = NULL; 386390075Sobrien sbitmap_vector_free (ae_kill); 3864117395Skan ae_kill = NULL; 386590075Sobrien sbitmap_free (trapping_expr); 386650397Sobrien} 386750397Sobrien 386850397Sobrien/* PRE utilities */ 386950397Sobrien 3870117395Skan/* Return nonzero if an occurrence of expression EXPR in OCCR_BB would reach 387152284Sobrien block BB. 387250397Sobrien 387350397Sobrien VISITED is a pointer to a working buffer for tracking which BB's have 387450397Sobrien been visited. It is NULL for the top-level call. 387550397Sobrien 387650397Sobrien We treat reaching expressions that go through blocks containing the same 387750397Sobrien reaching expression as "not reaching". E.g. if EXPR is generated in blocks 387850397Sobrien 2 and 3, INSN is in block 4, and 2->3->4, we treat the expression in block 387950397Sobrien 2 as not reaching. The intent is to improve the probability of finding 388050397Sobrien only one reaching expression and to reduce register lifetimes by picking 388150397Sobrien the closest such expression. */ 388250397Sobrien 388350397Sobrienstatic int 3884132718Skanpre_expr_reaches_here_p_work (basic_block occr_bb, struct expr *expr, basic_block bb, char *visited) 388550397Sobrien{ 388690075Sobrien edge pred; 3887169689Skan edge_iterator ei; 3888169689Skan 3889169689Skan FOR_EACH_EDGE (pred, ei, bb->preds) 389050397Sobrien { 389190075Sobrien basic_block pred_bb = pred->src; 389250397Sobrien 389390075Sobrien if (pred->src == ENTRY_BLOCK_PTR 389490075Sobrien /* Has predecessor has already been visited? */ 389590075Sobrien || visited[pred_bb->index]) 389690075Sobrien ;/* Nothing to do. */ 389750397Sobrien 389850397Sobrien /* Does this predecessor generate this expression? */ 389990075Sobrien else if (TEST_BIT (comp[pred_bb->index], expr->bitmap_index)) 390050397Sobrien { 390150397Sobrien /* Is this the occurrence we're looking for? 390250397Sobrien Note that there's only one generating occurrence per block 390350397Sobrien so we just need to check the block number. */ 390452284Sobrien if (occr_bb == pred_bb) 390550397Sobrien return 1; 390690075Sobrien 390790075Sobrien visited[pred_bb->index] = 1; 390850397Sobrien } 390950397Sobrien /* Ignore this predecessor if it kills the expression. */ 391090075Sobrien else if (! TEST_BIT (transp[pred_bb->index], expr->bitmap_index)) 391190075Sobrien visited[pred_bb->index] = 1; 391290075Sobrien 391350397Sobrien /* Neither gen nor kill. */ 391450397Sobrien else 391552284Sobrien { 391690075Sobrien visited[pred_bb->index] = 1; 391790075Sobrien if (pre_expr_reaches_here_p_work (occr_bb, expr, pred_bb, visited)) 391850397Sobrien return 1; 391952284Sobrien } 392050397Sobrien } 392150397Sobrien 392250397Sobrien /* All paths have been checked. */ 392350397Sobrien return 0; 392450397Sobrien} 392590075Sobrien 392690075Sobrien/* The wrapper for pre_expr_reaches_here_work that ensures that any 392790075Sobrien memory allocated for that function is returned. */ 392890075Sobrien 392990075Sobrienstatic int 3930132718Skanpre_expr_reaches_here_p (basic_block occr_bb, struct expr *expr, basic_block bb) 393190075Sobrien{ 393290075Sobrien int rval; 3933169689Skan char *visited = XCNEWVEC (char, last_basic_block); 393490075Sobrien 393590075Sobrien rval = pre_expr_reaches_here_p_work (occr_bb, expr, bb, visited); 393690075Sobrien 393790075Sobrien free (visited); 393890075Sobrien return rval; 393990075Sobrien} 394050397Sobrien 394190075Sobrien 394290075Sobrien/* Given an expr, generate RTL which we can insert at the end of a BB, 3943117395Skan or on an edge. Set the block number of any insns generated to 394490075Sobrien the value of BB. */ 394590075Sobrien 394690075Sobrienstatic rtx 3947132718Skanprocess_insert_insn (struct expr *expr) 394890075Sobrien{ 394990075Sobrien rtx reg = expr->reaching_reg; 395090075Sobrien rtx exp = copy_rtx (expr->expr); 395190075Sobrien rtx pat; 395290075Sobrien 395390075Sobrien start_sequence (); 395490075Sobrien 395590075Sobrien /* If the expression is something that's an operand, like a constant, 395690075Sobrien just copy it to a register. */ 395790075Sobrien if (general_operand (exp, GET_MODE (reg))) 395890075Sobrien emit_move_insn (reg, exp); 395990075Sobrien 396090075Sobrien /* Otherwise, make a new insn to compute this expression and make sure the 396190075Sobrien insn will be recognized (this also adds any needed CLOBBERs). Copy the 396290075Sobrien expression to make sure we don't have any sharing issues. */ 3963169689Skan else 3964169689Skan { 3965169689Skan rtx insn = emit_insn (gen_rtx_SET (VOIDmode, reg, exp)); 3966117395Skan 3967169689Skan if (insn_invalid_p (insn)) 3968169689Skan gcc_unreachable (); 3969169689Skan } 3970169689Skan 3971169689Skan 3972117395Skan pat = get_insns (); 397390075Sobrien end_sequence (); 397490075Sobrien 397590075Sobrien return pat; 397690075Sobrien} 3977117395Skan 397852284Sobrien/* Add EXPR to the end of basic block BB. 397950397Sobrien 398052284Sobrien This is used by both the PRE and code hoisting. 398152284Sobrien 398252284Sobrien For PRE, we want to verify that the expr is either transparent 398352284Sobrien or locally anticipatable in the target block. This check makes 398452284Sobrien no sense for code hoisting. */ 398552284Sobrien 398650397Sobrienstatic void 3987132718Skaninsert_insn_end_bb (struct expr *expr, basic_block bb, int pre) 398850397Sobrien{ 3989132718Skan rtx insn = BB_END (bb); 399050397Sobrien rtx new_insn; 399150397Sobrien rtx reg = expr->reaching_reg; 399250397Sobrien int regno = REGNO (reg); 3993117395Skan rtx pat, pat_end; 399450397Sobrien 399590075Sobrien pat = process_insert_insn (expr); 3996169689Skan gcc_assert (pat && INSN_P (pat)); 399750397Sobrien 3998117395Skan pat_end = pat; 3999117395Skan while (NEXT_INSN (pat_end) != NULL_RTX) 4000117395Skan pat_end = NEXT_INSN (pat_end); 4001117395Skan 400250397Sobrien /* If the last insn is a jump, insert EXPR in front [taking care to 4003132718Skan handle cc0, etc. properly]. Similarly we need to care trapping 400496263Sobrien instructions in presence of non-call exceptions. */ 400550397Sobrien 4006169689Skan if (JUMP_P (insn) 4007169689Skan || (NONJUMP_INSN_P (insn) 4008169689Skan && (!single_succ_p (bb) 4009169689Skan || single_succ_edge (bb)->flags & EDGE_ABNORMAL))) 401050397Sobrien { 401150397Sobrien#ifdef HAVE_cc0 401250397Sobrien rtx note; 401350397Sobrien#endif 401496263Sobrien /* It should always be the case that we can put these instructions 401596263Sobrien anywhere in the basic block with performing PRE optimizations. 401696263Sobrien Check this. */ 4017169689Skan gcc_assert (!NONJUMP_INSN_P (insn) || !pre 4018169689Skan || TEST_BIT (antloc[bb->index], expr->bitmap_index) 4019169689Skan || TEST_BIT (transp[bb->index], expr->bitmap_index)); 402050397Sobrien 402150397Sobrien /* If this is a jump table, then we can't insert stuff here. Since 402250397Sobrien we know the previous real insn must be the tablejump, we insert 402350397Sobrien the new instruction just before the tablejump. */ 402450397Sobrien if (GET_CODE (PATTERN (insn)) == ADDR_VEC 402550397Sobrien || GET_CODE (PATTERN (insn)) == ADDR_DIFF_VEC) 402650397Sobrien insn = prev_real_insn (insn); 402750397Sobrien 402850397Sobrien#ifdef HAVE_cc0 402950397Sobrien /* FIXME: 'twould be nice to call prev_cc0_setter here but it aborts 403050397Sobrien if cc0 isn't set. */ 403150397Sobrien note = find_reg_note (insn, REG_CC_SETTER, NULL_RTX); 403250397Sobrien if (note) 403350397Sobrien insn = XEXP (note, 0); 403450397Sobrien else 403550397Sobrien { 403650397Sobrien rtx maybe_cc0_setter = prev_nonnote_insn (insn); 403750397Sobrien if (maybe_cc0_setter 403890075Sobrien && INSN_P (maybe_cc0_setter) 403950397Sobrien && sets_cc0_p (PATTERN (maybe_cc0_setter))) 404050397Sobrien insn = maybe_cc0_setter; 404150397Sobrien } 404250397Sobrien#endif 404350397Sobrien /* FIXME: What if something in cc0/jump uses value set in new insn? */ 4044132718Skan new_insn = emit_insn_before_noloc (pat, insn); 404550397Sobrien } 404690075Sobrien 404752284Sobrien /* Likewise if the last insn is a call, as will happen in the presence 404852284Sobrien of exception handling. */ 4049169689Skan else if (CALL_P (insn) 4050169689Skan && (!single_succ_p (bb) 4051169689Skan || single_succ_edge (bb)->flags & EDGE_ABNORMAL)) 405252284Sobrien { 405352284Sobrien /* Keeping in mind SMALL_REGISTER_CLASSES and parameters in registers, 405452284Sobrien we search backward and place the instructions before the first 405552284Sobrien parameter is loaded. Do this for everyone for consistency and a 4056132718Skan presumption that we'll get better code elsewhere as well. 405752284Sobrien 405890075Sobrien It should always be the case that we can put these instructions 405952284Sobrien anywhere in the basic block with performing PRE optimizations. 406052284Sobrien Check this. */ 406190075Sobrien 4062169689Skan gcc_assert (!pre 4063169689Skan || TEST_BIT (antloc[bb->index], expr->bitmap_index) 4064169689Skan || TEST_BIT (transp[bb->index], expr->bitmap_index)); 406552284Sobrien 406652284Sobrien /* Since different machines initialize their parameter registers 406752284Sobrien in different orders, assume nothing. Collect the set of all 406852284Sobrien parameter registers. */ 4069132718Skan insn = find_first_parameter_load (insn, BB_HEAD (bb)); 407052284Sobrien 407152284Sobrien /* If we found all the parameter loads, then we want to insert 407252284Sobrien before the first parameter load. 407352284Sobrien 407452284Sobrien If we did not find all the parameter loads, then we might have 407552284Sobrien stopped on the head of the block, which could be a CODE_LABEL. 407652284Sobrien If we inserted before the CODE_LABEL, then we would be putting 407752284Sobrien the insn in the wrong basic block. In that case, put the insn 407890075Sobrien after the CODE_LABEL. Also, respect NOTE_INSN_BASIC_BLOCK. */ 4079169689Skan while (LABEL_P (insn) 408090075Sobrien || NOTE_INSN_BASIC_BLOCK_P (insn)) 408190075Sobrien insn = NEXT_INSN (insn); 408252284Sobrien 4083132718Skan new_insn = emit_insn_before_noloc (pat, insn); 408452284Sobrien } 408550397Sobrien else 4086132718Skan new_insn = emit_insn_after_noloc (pat, insn); 408752284Sobrien 4088117395Skan while (1) 408952284Sobrien { 4090117395Skan if (INSN_P (pat)) 409152284Sobrien { 4092117395Skan add_label_notes (PATTERN (pat), new_insn); 4093117395Skan note_stores (PATTERN (pat), record_set_info, pat); 409452284Sobrien } 4095117395Skan if (pat == pat_end) 4096117395Skan break; 4097117395Skan pat = NEXT_INSN (pat); 409852284Sobrien } 409990075Sobrien 410050397Sobrien gcse_create_count++; 410150397Sobrien 4102169689Skan if (dump_file) 410350397Sobrien { 4104169689Skan fprintf (dump_file, "PRE/HOIST: end of bb %d, insn %d, ", 410590075Sobrien bb->index, INSN_UID (new_insn)); 4106169689Skan fprintf (dump_file, "copying expression %d to reg %d\n", 410790075Sobrien expr->bitmap_index, regno); 410850397Sobrien } 410950397Sobrien} 411050397Sobrien 411190075Sobrien/* Insert partially redundant expressions on edges in the CFG to make 411290075Sobrien the expressions fully redundant. */ 411350397Sobrien 411490075Sobrienstatic int 4115132718Skanpre_edge_insert (struct edge_list *edge_list, struct expr **index_map) 411650397Sobrien{ 411790075Sobrien int e, i, j, num_edges, set_size, did_insert = 0; 411852284Sobrien sbitmap *inserted; 411950397Sobrien 412090075Sobrien /* Where PRE_INSERT_MAP is nonzero, we add the expression on that edge 412190075Sobrien if it reaches any of the deleted expressions. */ 412250397Sobrien 412390075Sobrien set_size = pre_insert_map[0]->size; 412490075Sobrien num_edges = NUM_EDGES (edge_list); 4125117395Skan inserted = sbitmap_vector_alloc (num_edges, expr_hash_table.n_elems); 412690075Sobrien sbitmap_vector_zero (inserted, num_edges); 412752284Sobrien 412890075Sobrien for (e = 0; e < num_edges; e++) 412950397Sobrien { 413050397Sobrien int indx; 413190075Sobrien basic_block bb = INDEX_EDGE_PRED_BB (edge_list, e); 413250397Sobrien 413352284Sobrien for (i = indx = 0; i < set_size; i++, indx += SBITMAP_ELT_BITS) 413450397Sobrien { 413590075Sobrien SBITMAP_ELT_TYPE insert = pre_insert_map[e]->elms[i]; 413650397Sobrien 4137117395Skan for (j = indx; insert && j < (int) expr_hash_table.n_elems; j++, insert >>= 1) 413890075Sobrien if ((insert & 1) != 0 && index_map[j]->reaching_reg != NULL_RTX) 413990075Sobrien { 414090075Sobrien struct expr *expr = index_map[j]; 414190075Sobrien struct occr *occr; 414252284Sobrien 414390075Sobrien /* Now look at each deleted occurrence of this expression. */ 414490075Sobrien for (occr = expr->antic_occr; occr != NULL; occr = occr->next) 414590075Sobrien { 414690075Sobrien if (! occr->deleted_p) 414790075Sobrien continue; 414852284Sobrien 4149169689Skan /* Insert this expression on this edge if it would 415090075Sobrien reach the deleted occurrence in BB. */ 415190075Sobrien if (!TEST_BIT (inserted[e], j)) 415290075Sobrien { 415390075Sobrien rtx insn; 415490075Sobrien edge eg = INDEX_EDGE (edge_list, e); 415590075Sobrien 415690075Sobrien /* We can't insert anything on an abnormal and 415790075Sobrien critical edge, so we insert the insn at the end of 415890075Sobrien the previous block. There are several alternatives 415990075Sobrien detailed in Morgans book P277 (sec 10.5) for 416090075Sobrien handling this situation. This one is easiest for 416190075Sobrien now. */ 416290075Sobrien 4163169689Skan if (eg->flags & EDGE_ABNORMAL) 416490075Sobrien insert_insn_end_bb (index_map[j], bb, 0); 416590075Sobrien else 416690075Sobrien { 416790075Sobrien insn = process_insert_insn (index_map[j]); 416890075Sobrien insert_insn_on_edge (insn, eg); 416990075Sobrien } 417090075Sobrien 4171169689Skan if (dump_file) 417290075Sobrien { 4173169689Skan fprintf (dump_file, "PRE/HOIST: edge (%d,%d), ", 417490075Sobrien bb->index, 417590075Sobrien INDEX_EDGE_SUCC_BB (edge_list, e)->index); 4176169689Skan fprintf (dump_file, "copy expression %d\n", 417790075Sobrien expr->bitmap_index); 417890075Sobrien } 417990075Sobrien 418090075Sobrien update_ld_motion_stores (expr); 418190075Sobrien SET_BIT (inserted[e], j); 418290075Sobrien did_insert = 1; 418390075Sobrien gcse_create_count++; 418490075Sobrien } 418590075Sobrien } 418690075Sobrien } 418750397Sobrien } 418850397Sobrien } 418990075Sobrien 419090075Sobrien sbitmap_vector_free (inserted); 419190075Sobrien return did_insert; 419250397Sobrien} 419350397Sobrien 4194132718Skan/* Copy the result of EXPR->EXPR generated by INSN to EXPR->REACHING_REG. 4195132718Skan Given "old_reg <- expr" (INSN), instead of adding after it 4196132718Skan reaching_reg <- old_reg 4197132718Skan it's better to do the following: 4198132718Skan reaching_reg <- expr 4199132718Skan old_reg <- reaching_reg 4200132718Skan because this way copy propagation can discover additional PRE 4201132718Skan opportunities. But if this fails, we try the old way. 4202132718Skan When "expr" is a store, i.e. 4203132718Skan given "MEM <- old_reg", instead of adding after it 4204132718Skan reaching_reg <- old_reg 4205132718Skan it's better to add it before as follows: 4206132718Skan reaching_reg <- old_reg 4207132718Skan MEM <- reaching_reg. */ 420850397Sobrien 420950397Sobrienstatic void 4210132718Skanpre_insert_copy_insn (struct expr *expr, rtx insn) 421150397Sobrien{ 421250397Sobrien rtx reg = expr->reaching_reg; 421350397Sobrien int regno = REGNO (reg); 421450397Sobrien int indx = expr->bitmap_index; 4215132718Skan rtx pat = PATTERN (insn); 4216169689Skan rtx set, first_set, new_insn; 4217132718Skan rtx old_reg; 4218132718Skan int i; 421950397Sobrien 4220132718Skan /* This block matches the logic in hash_scan_insn. */ 4221169689Skan switch (GET_CODE (pat)) 4222132718Skan { 4223169689Skan case SET: 4224169689Skan set = pat; 4225169689Skan break; 4226169689Skan 4227169689Skan case PARALLEL: 4228132718Skan /* Search through the parallel looking for the set whose 4229132718Skan source was the expression that we're interested in. */ 4230169689Skan first_set = NULL_RTX; 4231132718Skan set = NULL_RTX; 4232132718Skan for (i = 0; i < XVECLEN (pat, 0); i++) 4233132718Skan { 4234132718Skan rtx x = XVECEXP (pat, 0, i); 4235169689Skan if (GET_CODE (x) == SET) 4236132718Skan { 4237169689Skan /* If the source was a REG_EQUAL or REG_EQUIV note, we 4238169689Skan may not find an equivalent expression, but in this 4239169689Skan case the PARALLEL will have a single set. */ 4240169689Skan if (first_set == NULL_RTX) 4241169689Skan first_set = x; 4242169689Skan if (expr_equiv_p (SET_SRC (x), expr->expr)) 4243169689Skan { 4244169689Skan set = x; 4245169689Skan break; 4246169689Skan } 4247132718Skan } 4248132718Skan } 4249169689Skan 4250169689Skan gcc_assert (first_set); 4251169689Skan if (set == NULL_RTX) 4252169689Skan set = first_set; 4253169689Skan break; 4254169689Skan 4255169689Skan default: 4256169689Skan gcc_unreachable (); 4257132718Skan } 425890075Sobrien 4259169689Skan if (REG_P (SET_DEST (set))) 4260132718Skan { 4261132718Skan old_reg = SET_DEST (set); 4262132718Skan /* Check if we can modify the set destination in the original insn. */ 4263132718Skan if (validate_change (insn, &SET_DEST (set), reg, 0)) 4264132718Skan { 4265132718Skan new_insn = gen_move_insn (old_reg, reg); 4266132718Skan new_insn = emit_insn_after (new_insn, insn); 426790075Sobrien 4268132718Skan /* Keep register set table up to date. */ 4269132718Skan record_one_set (regno, insn); 4270132718Skan } 4271132718Skan else 4272132718Skan { 4273132718Skan new_insn = gen_move_insn (reg, old_reg); 4274132718Skan new_insn = emit_insn_after (new_insn, insn); 427550397Sobrien 4276132718Skan /* Keep register set table up to date. */ 4277132718Skan record_one_set (regno, new_insn); 4278132718Skan } 4279132718Skan } 4280132718Skan else /* This is possible only in case of a store to memory. */ 4281132718Skan { 4282132718Skan old_reg = SET_SRC (set); 4283132718Skan new_insn = gen_move_insn (reg, old_reg); 4284132718Skan 4285132718Skan /* Check if we can modify the set source in the original insn. */ 4286132718Skan if (validate_change (insn, &SET_SRC (set), reg, 0)) 4287132718Skan new_insn = emit_insn_before (new_insn, insn); 4288132718Skan else 4289132718Skan new_insn = emit_insn_after (new_insn, insn); 4290132718Skan 4291132718Skan /* Keep register set table up to date. */ 4292132718Skan record_one_set (regno, new_insn); 4293132718Skan } 4294132718Skan 429550397Sobrien gcse_create_count++; 429650397Sobrien 4297169689Skan if (dump_file) 4298169689Skan fprintf (dump_file, 429990075Sobrien "PRE: bb %d, insn %d, copy expression %d in insn %d to reg %d\n", 430090075Sobrien BLOCK_NUM (insn), INSN_UID (new_insn), indx, 430190075Sobrien INSN_UID (insn), regno); 430250397Sobrien} 430350397Sobrien 430450397Sobrien/* Copy available expressions that reach the redundant expression 430550397Sobrien to `reaching_reg'. */ 430650397Sobrien 430750397Sobrienstatic void 4308132718Skanpre_insert_copies (void) 430950397Sobrien{ 4310132718Skan unsigned int i, added_copy; 431190075Sobrien struct expr *expr; 431290075Sobrien struct occr *occr; 431390075Sobrien struct occr *avail; 431450397Sobrien 431550397Sobrien /* For each available expression in the table, copy the result to 431650397Sobrien `reaching_reg' if the expression reaches a deleted one. 431750397Sobrien 431850397Sobrien ??? The current algorithm is rather brute force. 431950397Sobrien Need to do some profiling. */ 432050397Sobrien 4321117395Skan for (i = 0; i < expr_hash_table.size; i++) 4322117395Skan for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) 432390075Sobrien { 432490075Sobrien /* If the basic block isn't reachable, PPOUT will be TRUE. However, 432590075Sobrien we don't want to insert a copy here because the expression may not 432690075Sobrien really be redundant. So only insert an insn if the expression was 432790075Sobrien deleted. This test also avoids further processing if the 432890075Sobrien expression wasn't deleted anywhere. */ 432990075Sobrien if (expr->reaching_reg == NULL) 433090075Sobrien continue; 4331169689Skan 4332132718Skan /* Set when we add a copy for that expression. */ 4333169689Skan added_copy = 0; 433450397Sobrien 433590075Sobrien for (occr = expr->antic_occr; occr != NULL; occr = occr->next) 433690075Sobrien { 433790075Sobrien if (! occr->deleted_p) 433890075Sobrien continue; 433950397Sobrien 434090075Sobrien for (avail = expr->avail_occr; avail != NULL; avail = avail->next) 434190075Sobrien { 434290075Sobrien rtx insn = avail->insn; 434350397Sobrien 434490075Sobrien /* No need to handle this one if handled already. */ 434590075Sobrien if (avail->copied_p) 434690075Sobrien continue; 434750397Sobrien 434890075Sobrien /* Don't handle this one if it's a redundant one. */ 434990075Sobrien if (TEST_BIT (pre_redundant_insns, INSN_CUID (insn))) 435090075Sobrien continue; 435150397Sobrien 435290075Sobrien /* Or if the expression doesn't reach the deleted one. */ 4353117395Skan if (! pre_expr_reaches_here_p (BLOCK_FOR_INSN (avail->insn), 435490075Sobrien expr, 435590075Sobrien BLOCK_FOR_INSN (occr->insn))) 435690075Sobrien continue; 435750397Sobrien 4358132718Skan added_copy = 1; 4359132718Skan 436090075Sobrien /* Copy the result of avail to reaching_reg. */ 436190075Sobrien pre_insert_copy_insn (expr, insn); 436290075Sobrien avail->copied_p = 1; 436390075Sobrien } 436490075Sobrien } 4365132718Skan 4366169689Skan if (added_copy) 4367132718Skan update_ld_motion_stores (expr); 436890075Sobrien } 436950397Sobrien} 437050397Sobrien 4371117395Skan/* Emit move from SRC to DEST noting the equivalence with expression computed 4372117395Skan in INSN. */ 4373117395Skanstatic rtx 4374132718Skangcse_emit_move_after (rtx src, rtx dest, rtx insn) 4375117395Skan{ 4376117395Skan rtx new; 4377117395Skan rtx set = single_set (insn), set2; 4378117395Skan rtx note; 4379117395Skan rtx eqv; 4380117395Skan 4381117395Skan /* This should never fail since we're creating a reg->reg copy 4382117395Skan we've verified to be valid. */ 4383117395Skan 4384117395Skan new = emit_insn_after (gen_move_insn (dest, src), insn); 4385117395Skan 4386117395Skan /* Note the equivalence for local CSE pass. */ 4387117395Skan set2 = single_set (new); 4388117395Skan if (!set2 || !rtx_equal_p (SET_DEST (set2), dest)) 4389117395Skan return new; 4390117395Skan if ((note = find_reg_equal_equiv_note (insn))) 4391117395Skan eqv = XEXP (note, 0); 4392117395Skan else 4393117395Skan eqv = SET_SRC (set); 4394117395Skan 4395117395Skan set_unique_reg_note (new, REG_EQUAL, copy_insn_1 (eqv)); 4396117395Skan 4397117395Skan return new; 4398117395Skan} 4399117395Skan 440050397Sobrien/* Delete redundant computations. 440150397Sobrien Deletion is done by changing the insn to copy the `reaching_reg' of 440250397Sobrien the expression into the result of the SET. It is left to later passes 440350397Sobrien (cprop, cse2, flow, combine, regmove) to propagate the copy or eliminate it. 440450397Sobrien 4405117395Skan Returns nonzero if a change is made. */ 440650397Sobrien 440750397Sobrienstatic int 4408132718Skanpre_delete (void) 440950397Sobrien{ 441090075Sobrien unsigned int i; 441190075Sobrien int changed; 441290075Sobrien struct expr *expr; 441390075Sobrien struct occr *occr; 441450397Sobrien 441550397Sobrien changed = 0; 4416117395Skan for (i = 0; i < expr_hash_table.size; i++) 4417132718Skan for (expr = expr_hash_table.table[i]; 4418132718Skan expr != NULL; 4419132718Skan expr = expr->next_same_hash) 442090075Sobrien { 442190075Sobrien int indx = expr->bitmap_index; 442250397Sobrien 442390075Sobrien /* We only need to search antic_occr since we require 442490075Sobrien ANTLOC != 0. */ 442550397Sobrien 442690075Sobrien for (occr = expr->antic_occr; occr != NULL; occr = occr->next) 442790075Sobrien { 442890075Sobrien rtx insn = occr->insn; 442990075Sobrien rtx set; 443090075Sobrien basic_block bb = BLOCK_FOR_INSN (insn); 443150397Sobrien 4432132718Skan /* We only delete insns that have a single_set. */ 4433132718Skan if (TEST_BIT (pre_delete_map[bb->index], indx) 4434132718Skan && (set = single_set (insn)) != 0) 443590075Sobrien { 443690075Sobrien /* Create a pseudo-reg to store the result of reaching 443790075Sobrien expressions into. Get the mode for the new pseudo from 443890075Sobrien the mode of the original destination pseudo. */ 443990075Sobrien if (expr->reaching_reg == NULL) 444090075Sobrien expr->reaching_reg 444190075Sobrien = gen_reg_rtx (GET_MODE (SET_DEST (set))); 444250397Sobrien 4443117395Skan gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn); 4444117395Skan delete_insn (insn); 4445117395Skan occr->deleted_p = 1; 4446117395Skan SET_BIT (pre_redundant_insns, INSN_CUID (insn)); 4447117395Skan changed = 1; 4448117395Skan gcse_subst_count++; 444950397Sobrien 4450169689Skan if (dump_file) 445190075Sobrien { 4452169689Skan fprintf (dump_file, 445390075Sobrien "PRE: redundant insn %d (expression %d) in ", 445490075Sobrien INSN_UID (insn), indx); 4455169689Skan fprintf (dump_file, "bb %d, reaching reg is %d\n", 445690075Sobrien bb->index, REGNO (expr->reaching_reg)); 445790075Sobrien } 445890075Sobrien } 445990075Sobrien } 446090075Sobrien } 446150397Sobrien 446250397Sobrien return changed; 446350397Sobrien} 446450397Sobrien 446550397Sobrien/* Perform GCSE optimizations using PRE. 446650397Sobrien This is called by one_pre_gcse_pass after all the dataflow analysis 446750397Sobrien has been done. 446850397Sobrien 446990075Sobrien This is based on the original Morel-Renvoise paper Fred Chow's thesis, and 447090075Sobrien lazy code motion from Knoop, Ruthing and Steffen as described in Advanced 447190075Sobrien Compiler Design and Implementation. 447250397Sobrien 447390075Sobrien ??? A new pseudo reg is created to hold the reaching expression. The nice 447490075Sobrien thing about the classical approach is that it would try to use an existing 447590075Sobrien reg. If the register can't be adequately optimized [i.e. we introduce 447690075Sobrien reload problems], one could add a pass here to propagate the new register 447790075Sobrien through the block. 447850397Sobrien 447990075Sobrien ??? We don't handle single sets in PARALLELs because we're [currently] not 448090075Sobrien able to copy the rest of the parallel when we insert copies to create full 448190075Sobrien redundancies from partial redundancies. However, there's no reason why we 448290075Sobrien can't handle PARALLELs in the cases where there are no partial 448350397Sobrien redundancies. */ 448450397Sobrien 448550397Sobrienstatic int 4486132718Skanpre_gcse (void) 448750397Sobrien{ 448890075Sobrien unsigned int i; 448990075Sobrien int did_insert, changed; 449050397Sobrien struct expr **index_map; 449190075Sobrien struct expr *expr; 449250397Sobrien 449350397Sobrien /* Compute a mapping from expression number (`bitmap_index') to 449450397Sobrien hash table entry. */ 449550397Sobrien 4496169689Skan index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems); 4497117395Skan for (i = 0; i < expr_hash_table.size; i++) 4498117395Skan for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) 449990075Sobrien index_map[expr->bitmap_index] = expr; 450050397Sobrien 450150397Sobrien /* Reset bitmap used to track which insns are redundant. */ 450252284Sobrien pre_redundant_insns = sbitmap_alloc (max_cuid); 450352284Sobrien sbitmap_zero (pre_redundant_insns); 450450397Sobrien 450550397Sobrien /* Delete the redundant insns first so that 450650397Sobrien - we know what register to use for the new insns and for the other 450750397Sobrien ones with reaching expressions 450850397Sobrien - we know which insns are redundant when we go to create copies */ 450990075Sobrien 451050397Sobrien changed = pre_delete (); 451150397Sobrien 451290075Sobrien did_insert = pre_edge_insert (edge_list, index_map); 451350397Sobrien 451450397Sobrien /* In other places with reaching expressions, copy the expression to the 451590075Sobrien specially allocated pseudo-reg that reaches the redundant expr. */ 451650397Sobrien pre_insert_copies (); 451790075Sobrien if (did_insert) 451890075Sobrien { 451990075Sobrien commit_edge_insertions (); 452090075Sobrien changed = 1; 452190075Sobrien } 452250397Sobrien 452390075Sobrien free (index_map); 452490075Sobrien sbitmap_free (pre_redundant_insns); 452550397Sobrien return changed; 452650397Sobrien} 452750397Sobrien 452850397Sobrien/* Top level routine to perform one PRE GCSE pass. 452950397Sobrien 4530117395Skan Return nonzero if a change was made. */ 453150397Sobrien 453250397Sobrienstatic int 4533132718Skanone_pre_gcse_pass (int pass) 453450397Sobrien{ 453550397Sobrien int changed = 0; 453650397Sobrien 453750397Sobrien gcse_subst_count = 0; 453850397Sobrien gcse_create_count = 0; 453950397Sobrien 4540117395Skan alloc_hash_table (max_cuid, &expr_hash_table, 0); 454190075Sobrien add_noreturn_fake_exit_edges (); 454290075Sobrien if (flag_gcse_lm) 454390075Sobrien compute_ld_motion_mems (); 454490075Sobrien 4545117395Skan compute_hash_table (&expr_hash_table); 454690075Sobrien trim_ld_motion_mems (); 4547169689Skan if (dump_file) 4548169689Skan dump_hash_table (dump_file, "Expression", &expr_hash_table); 454990075Sobrien 4550117395Skan if (expr_hash_table.n_elems > 0) 455150397Sobrien { 4552117395Skan alloc_pre_mem (last_basic_block, expr_hash_table.n_elems); 455350397Sobrien compute_pre_data (); 455450397Sobrien changed |= pre_gcse (); 455590075Sobrien free_edge_list (edge_list); 455650397Sobrien free_pre_mem (); 455750397Sobrien } 455890075Sobrien 455990075Sobrien free_ldst_mems (); 4560169689Skan remove_fake_exit_edges (); 4561117395Skan free_hash_table (&expr_hash_table); 456250397Sobrien 4563169689Skan if (dump_file) 456450397Sobrien { 4565169689Skan fprintf (dump_file, "\nPRE GCSE of %s, pass %d: %d bytes needed, ", 4566132718Skan current_function_name (), pass, bytes_used); 4567169689Skan fprintf (dump_file, "%d substs, %d insns created\n", 456890075Sobrien gcse_subst_count, gcse_create_count); 456950397Sobrien } 457050397Sobrien 457150397Sobrien return changed; 457250397Sobrien} 457350397Sobrien 457450397Sobrien/* If X contains any LABEL_REF's, add REG_LABEL notes for them to INSN. 457590075Sobrien If notes are added to an insn which references a CODE_LABEL, the 457690075Sobrien LABEL_NUSES count is incremented. We have to add REG_LABEL notes, 457790075Sobrien because the following loop optimization pass requires them. */ 457850397Sobrien 457950397Sobrien/* ??? If there was a jump optimization pass after gcse and before loop, 458050397Sobrien then we would not need to do this here, because jump would add the 458150397Sobrien necessary REG_LABEL notes. */ 458250397Sobrien 458350397Sobrienstatic void 4584132718Skanadd_label_notes (rtx x, rtx insn) 458550397Sobrien{ 458650397Sobrien enum rtx_code code = GET_CODE (x); 458750397Sobrien int i, j; 458890075Sobrien const char *fmt; 458950397Sobrien 459050397Sobrien if (code == LABEL_REF && !LABEL_REF_NONLOCAL_P (x)) 459150397Sobrien { 459250397Sobrien /* This code used to ignore labels that referred to dispatch tables to 4593132718Skan avoid flow generating (slightly) worse code. 459450397Sobrien 459552284Sobrien We no longer ignore such label references (see LABEL_REF handling in 459652284Sobrien mark_jump_label for additional information). */ 459790075Sobrien 459890075Sobrien REG_NOTES (insn) = gen_rtx_INSN_LIST (REG_LABEL, XEXP (x, 0), 459950397Sobrien REG_NOTES (insn)); 460090075Sobrien if (LABEL_P (XEXP (x, 0))) 4601117395Skan LABEL_NUSES (XEXP (x, 0))++; 460250397Sobrien return; 460350397Sobrien } 460450397Sobrien 460590075Sobrien for (i = GET_RTX_LENGTH (code) - 1, fmt = GET_RTX_FORMAT (code); i >= 0; i--) 460650397Sobrien { 460750397Sobrien if (fmt[i] == 'e') 460850397Sobrien add_label_notes (XEXP (x, i), insn); 460950397Sobrien else if (fmt[i] == 'E') 461050397Sobrien for (j = XVECLEN (x, i) - 1; j >= 0; j--) 461150397Sobrien add_label_notes (XVECEXP (x, i, j), insn); 461250397Sobrien } 461350397Sobrien} 461452284Sobrien 461552284Sobrien/* Compute transparent outgoing information for each block. 461652284Sobrien 461752284Sobrien An expression is transparent to an edge unless it is killed by 461852284Sobrien the edge itself. This can only happen with abnormal control flow, 461952284Sobrien when the edge is traversed through a call. This happens with 462052284Sobrien non-local labels and exceptions. 462152284Sobrien 462252284Sobrien This would not be necessary if we split the edge. While this is 462352284Sobrien normally impossible for abnormal critical edges, with some effort 462452284Sobrien it should be possible with exception handling, since we still have 462552284Sobrien control over which handler should be invoked. But due to increased 462652284Sobrien EH table sizes, this may not be worthwhile. */ 462752284Sobrien 462852284Sobrienstatic void 4629132718Skancompute_transpout (void) 463052284Sobrien{ 4631117395Skan basic_block bb; 463290075Sobrien unsigned int i; 463390075Sobrien struct expr *expr; 463452284Sobrien 4635117395Skan sbitmap_vector_ones (transpout, last_basic_block); 463652284Sobrien 4637117395Skan FOR_EACH_BB (bb) 463852284Sobrien { 463952284Sobrien /* Note that flow inserted a nop a the end of basic blocks that 464052284Sobrien end in call instructions for reasons other than abnormal 464152284Sobrien control flow. */ 4642169689Skan if (! CALL_P (BB_END (bb))) 464352284Sobrien continue; 464452284Sobrien 4645117395Skan for (i = 0; i < expr_hash_table.size; i++) 4646117395Skan for (expr = expr_hash_table.table[i]; expr ; expr = expr->next_same_hash) 4647169689Skan if (MEM_P (expr->expr)) 464890075Sobrien { 464990075Sobrien if (GET_CODE (XEXP (expr->expr, 0)) == SYMBOL_REF 465090075Sobrien && CONSTANT_POOL_ADDRESS_P (XEXP (expr->expr, 0))) 465190075Sobrien continue; 4652117395Skan 465390075Sobrien /* ??? Optimally, we would use interprocedural alias 465490075Sobrien analysis to determine if this mem is actually killed 465590075Sobrien by this call. */ 4656117395Skan RESET_BIT (transpout[bb->index], expr->bitmap_index); 465790075Sobrien } 465890075Sobrien } 465990075Sobrien} 466090075Sobrien 466190075Sobrien/* Code Hoisting variables and subroutines. */ 466290075Sobrien 466390075Sobrien/* Very busy expressions. */ 466490075Sobrienstatic sbitmap *hoist_vbein; 466590075Sobrienstatic sbitmap *hoist_vbeout; 466690075Sobrien 466790075Sobrien/* Hoistable expressions. */ 466890075Sobrienstatic sbitmap *hoist_exprs; 466990075Sobrien 467090075Sobrien/* ??? We could compute post dominators and run this algorithm in 4671117395Skan reverse to perform tail merging, doing so would probably be 467290075Sobrien more effective than the tail merging code in jump.c. 467390075Sobrien 467490075Sobrien It's unclear if tail merging could be run in parallel with 467590075Sobrien code hoisting. It would be nice. */ 467690075Sobrien 467790075Sobrien/* Allocate vars used for code hoisting analysis. */ 467890075Sobrien 467990075Sobrienstatic void 4680132718Skanalloc_code_hoist_mem (int n_blocks, int n_exprs) 468190075Sobrien{ 468290075Sobrien antloc = sbitmap_vector_alloc (n_blocks, n_exprs); 468390075Sobrien transp = sbitmap_vector_alloc (n_blocks, n_exprs); 468490075Sobrien comp = sbitmap_vector_alloc (n_blocks, n_exprs); 468590075Sobrien 468690075Sobrien hoist_vbein = sbitmap_vector_alloc (n_blocks, n_exprs); 468790075Sobrien hoist_vbeout = sbitmap_vector_alloc (n_blocks, n_exprs); 468890075Sobrien hoist_exprs = sbitmap_vector_alloc (n_blocks, n_exprs); 468990075Sobrien transpout = sbitmap_vector_alloc (n_blocks, n_exprs); 469090075Sobrien} 469190075Sobrien 469290075Sobrien/* Free vars used for code hoisting analysis. */ 469390075Sobrien 469490075Sobrienstatic void 4695132718Skanfree_code_hoist_mem (void) 469690075Sobrien{ 469790075Sobrien sbitmap_vector_free (antloc); 469890075Sobrien sbitmap_vector_free (transp); 469990075Sobrien sbitmap_vector_free (comp); 470090075Sobrien 470190075Sobrien sbitmap_vector_free (hoist_vbein); 470290075Sobrien sbitmap_vector_free (hoist_vbeout); 470390075Sobrien sbitmap_vector_free (hoist_exprs); 470490075Sobrien sbitmap_vector_free (transpout); 470590075Sobrien 4706132718Skan free_dominance_info (CDI_DOMINATORS); 470790075Sobrien} 470890075Sobrien 470990075Sobrien/* Compute the very busy expressions at entry/exit from each block. 471090075Sobrien 471190075Sobrien An expression is very busy if all paths from a given point 471290075Sobrien compute the expression. */ 471390075Sobrien 471490075Sobrienstatic void 4715132718Skancompute_code_hoist_vbeinout (void) 471690075Sobrien{ 4717117395Skan int changed, passes; 4718117395Skan basic_block bb; 471990075Sobrien 4720117395Skan sbitmap_vector_zero (hoist_vbeout, last_basic_block); 4721117395Skan sbitmap_vector_zero (hoist_vbein, last_basic_block); 472290075Sobrien 472390075Sobrien passes = 0; 472490075Sobrien changed = 1; 472590075Sobrien 472690075Sobrien while (changed) 472790075Sobrien { 472890075Sobrien changed = 0; 472990075Sobrien 473090075Sobrien /* We scan the blocks in the reverse order to speed up 473190075Sobrien the convergence. */ 4732117395Skan FOR_EACH_BB_REVERSE (bb) 473390075Sobrien { 4734117395Skan changed |= sbitmap_a_or_b_and_c_cg (hoist_vbein[bb->index], antloc[bb->index], 4735117395Skan hoist_vbeout[bb->index], transp[bb->index]); 4736117395Skan if (bb->next_bb != EXIT_BLOCK_PTR) 4737117395Skan sbitmap_intersection_of_succs (hoist_vbeout[bb->index], hoist_vbein, bb->index); 473890075Sobrien } 473990075Sobrien 474090075Sobrien passes++; 474190075Sobrien } 474290075Sobrien 4743169689Skan if (dump_file) 4744169689Skan fprintf (dump_file, "hoisting vbeinout computation: %d passes\n", passes); 474590075Sobrien} 474690075Sobrien 474790075Sobrien/* Top level routine to do the dataflow analysis needed by code hoisting. */ 474890075Sobrien 474990075Sobrienstatic void 4750132718Skancompute_code_hoist_data (void) 475190075Sobrien{ 4752117395Skan compute_local_properties (transp, comp, antloc, &expr_hash_table); 475390075Sobrien compute_transpout (); 475490075Sobrien compute_code_hoist_vbeinout (); 4755132718Skan calculate_dominance_info (CDI_DOMINATORS); 4756169689Skan if (dump_file) 4757169689Skan fprintf (dump_file, "\n"); 475890075Sobrien} 475990075Sobrien 476090075Sobrien/* Determine if the expression identified by EXPR_INDEX would 476190075Sobrien reach BB unimpared if it was placed at the end of EXPR_BB. 476290075Sobrien 476390075Sobrien It's unclear exactly what Muchnick meant by "unimpared". It seems 476490075Sobrien to me that the expression must either be computed or transparent in 476590075Sobrien *every* block in the path(s) from EXPR_BB to BB. Any other definition 476690075Sobrien would allow the expression to be hoisted out of loops, even if 476790075Sobrien the expression wasn't a loop invariant. 476890075Sobrien 476990075Sobrien Contrast this to reachability for PRE where an expression is 477090075Sobrien considered reachable if *any* path reaches instead of *all* 477190075Sobrien paths. */ 477290075Sobrien 477390075Sobrienstatic int 4774132718Skanhoist_expr_reaches_here_p (basic_block expr_bb, int expr_index, basic_block bb, char *visited) 477590075Sobrien{ 477690075Sobrien edge pred; 4777169689Skan edge_iterator ei; 477890075Sobrien int visited_allocated_locally = 0; 477990075Sobrien 4780117395Skan 478190075Sobrien if (visited == NULL) 478290075Sobrien { 478390075Sobrien visited_allocated_locally = 1; 4784169689Skan visited = XCNEWVEC (char, last_basic_block); 478590075Sobrien } 478690075Sobrien 4787169689Skan FOR_EACH_EDGE (pred, ei, bb->preds) 478890075Sobrien { 478990075Sobrien basic_block pred_bb = pred->src; 479090075Sobrien 479190075Sobrien if (pred->src == ENTRY_BLOCK_PTR) 479290075Sobrien break; 4793117395Skan else if (pred_bb == expr_bb) 4794117395Skan continue; 479590075Sobrien else if (visited[pred_bb->index]) 479690075Sobrien continue; 479790075Sobrien 479890075Sobrien /* Does this predecessor generate this expression? */ 479990075Sobrien else if (TEST_BIT (comp[pred_bb->index], expr_index)) 480090075Sobrien break; 480190075Sobrien else if (! TEST_BIT (transp[pred_bb->index], expr_index)) 480290075Sobrien break; 480390075Sobrien 480490075Sobrien /* Not killed. */ 480590075Sobrien else 480690075Sobrien { 480790075Sobrien visited[pred_bb->index] = 1; 480890075Sobrien if (! hoist_expr_reaches_here_p (expr_bb, expr_index, 480990075Sobrien pred_bb, visited)) 481090075Sobrien break; 481190075Sobrien } 481290075Sobrien } 4813117395Skan if (visited_allocated_locally) 481490075Sobrien free (visited); 481590075Sobrien 481690075Sobrien return (pred == NULL); 481790075Sobrien} 481890075Sobrien 481990075Sobrien/* Actually perform code hoisting. */ 482090075Sobrien 482190075Sobrienstatic void 4822132718Skanhoist_code (void) 482390075Sobrien{ 4824117395Skan basic_block bb, dominated; 4825117395Skan basic_block *domby; 4826117395Skan unsigned int domby_len; 4827117395Skan unsigned int i,j; 482890075Sobrien struct expr **index_map; 482990075Sobrien struct expr *expr; 483090075Sobrien 4831117395Skan sbitmap_vector_zero (hoist_exprs, last_basic_block); 483290075Sobrien 483390075Sobrien /* Compute a mapping from expression number (`bitmap_index') to 483490075Sobrien hash table entry. */ 483590075Sobrien 4836169689Skan index_map = XCNEWVEC (struct expr *, expr_hash_table.n_elems); 4837117395Skan for (i = 0; i < expr_hash_table.size; i++) 4838117395Skan for (expr = expr_hash_table.table[i]; expr != NULL; expr = expr->next_same_hash) 483990075Sobrien index_map[expr->bitmap_index] = expr; 484090075Sobrien 484190075Sobrien /* Walk over each basic block looking for potentially hoistable 484290075Sobrien expressions, nothing gets hoisted from the entry block. */ 4843117395Skan FOR_EACH_BB (bb) 484490075Sobrien { 484590075Sobrien int found = 0; 484690075Sobrien int insn_inserted_p; 484790075Sobrien 4848132718Skan domby_len = get_dominated_by (CDI_DOMINATORS, bb, &domby); 484990075Sobrien /* Examine each expression that is very busy at the exit of this 485090075Sobrien block. These are the potentially hoistable expressions. */ 4851117395Skan for (i = 0; i < hoist_vbeout[bb->index]->n_bits; i++) 485290075Sobrien { 485390075Sobrien int hoistable = 0; 485490075Sobrien 4855117395Skan if (TEST_BIT (hoist_vbeout[bb->index], i) 4856117395Skan && TEST_BIT (transpout[bb->index], i)) 485790075Sobrien { 485890075Sobrien /* We've found a potentially hoistable expression, now 485990075Sobrien we look at every block BB dominates to see if it 486090075Sobrien computes the expression. */ 4861117395Skan for (j = 0; j < domby_len; j++) 486290075Sobrien { 4863117395Skan dominated = domby[j]; 486490075Sobrien /* Ignore self dominance. */ 4865117395Skan if (bb == dominated) 486690075Sobrien continue; 486790075Sobrien /* We've found a dominated block, now see if it computes 486890075Sobrien the busy expression and whether or not moving that 486990075Sobrien expression to the "beginning" of that block is safe. */ 4870117395Skan if (!TEST_BIT (antloc[dominated->index], i)) 487190075Sobrien continue; 487290075Sobrien 487390075Sobrien /* Note if the expression would reach the dominated block 4874117395Skan unimpared if it was placed at the end of BB. 487590075Sobrien 487690075Sobrien Keep track of how many times this expression is hoistable 487790075Sobrien from a dominated block into BB. */ 4878117395Skan if (hoist_expr_reaches_here_p (bb, i, dominated, NULL)) 487990075Sobrien hoistable++; 488090075Sobrien } 488190075Sobrien 488290075Sobrien /* If we found more than one hoistable occurrence of this 488390075Sobrien expression, then note it in the bitmap of expressions to 488490075Sobrien hoist. It makes no sense to hoist things which are computed 488590075Sobrien in only one BB, and doing so tends to pessimize register 488690075Sobrien allocation. One could increase this value to try harder 488790075Sobrien to avoid any possible code expansion due to register 488890075Sobrien allocation issues; however experiments have shown that 488990075Sobrien the vast majority of hoistable expressions are only movable 4890132718Skan from two successors, so raising this threshold is likely 489190075Sobrien to nullify any benefit we get from code hoisting. */ 489290075Sobrien if (hoistable > 1) 489390075Sobrien { 4894117395Skan SET_BIT (hoist_exprs[bb->index], i); 489590075Sobrien found = 1; 489690075Sobrien } 489790075Sobrien } 489890075Sobrien } 489990075Sobrien /* If we found nothing to hoist, then quit now. */ 490090075Sobrien if (! found) 4901117395Skan { 4902132718Skan free (domby); 490390075Sobrien continue; 4904117395Skan } 490590075Sobrien 490690075Sobrien /* Loop over all the hoistable expressions. */ 4907117395Skan for (i = 0; i < hoist_exprs[bb->index]->n_bits; i++) 490890075Sobrien { 490990075Sobrien /* We want to insert the expression into BB only once, so 491090075Sobrien note when we've inserted it. */ 491190075Sobrien insn_inserted_p = 0; 491290075Sobrien 491390075Sobrien /* These tests should be the same as the tests above. */ 4914161651Skan if (TEST_BIT (hoist_exprs[bb->index], i)) 491590075Sobrien { 491690075Sobrien /* We've found a potentially hoistable expression, now 491790075Sobrien we look at every block BB dominates to see if it 491890075Sobrien computes the expression. */ 4919117395Skan for (j = 0; j < domby_len; j++) 492090075Sobrien { 4921117395Skan dominated = domby[j]; 492290075Sobrien /* Ignore self dominance. */ 4923117395Skan if (bb == dominated) 492490075Sobrien continue; 492590075Sobrien 492690075Sobrien /* We've found a dominated block, now see if it computes 492790075Sobrien the busy expression and whether or not moving that 492890075Sobrien expression to the "beginning" of that block is safe. */ 4929117395Skan if (!TEST_BIT (antloc[dominated->index], i)) 493090075Sobrien continue; 493190075Sobrien 493290075Sobrien /* The expression is computed in the dominated block and 493390075Sobrien it would be safe to compute it at the start of the 493490075Sobrien dominated block. Now we have to determine if the 493590075Sobrien expression would reach the dominated block if it was 493690075Sobrien placed at the end of BB. */ 4937117395Skan if (hoist_expr_reaches_here_p (bb, i, dominated, NULL)) 493890075Sobrien { 493990075Sobrien struct expr *expr = index_map[i]; 494090075Sobrien struct occr *occr = expr->antic_occr; 494190075Sobrien rtx insn; 494290075Sobrien rtx set; 494390075Sobrien 494490075Sobrien /* Find the right occurrence of this expression. */ 4945117395Skan while (BLOCK_FOR_INSN (occr->insn) != dominated && occr) 494690075Sobrien occr = occr->next; 494790075Sobrien 4948169689Skan gcc_assert (occr); 494990075Sobrien insn = occr->insn; 495090075Sobrien set = single_set (insn); 4951169689Skan gcc_assert (set); 495290075Sobrien 495390075Sobrien /* Create a pseudo-reg to store the result of reaching 495490075Sobrien expressions into. Get the mode for the new pseudo 495590075Sobrien from the mode of the original destination pseudo. */ 495690075Sobrien if (expr->reaching_reg == NULL) 495790075Sobrien expr->reaching_reg 495890075Sobrien = gen_reg_rtx (GET_MODE (SET_DEST (set))); 495990075Sobrien 4960117395Skan gcse_emit_move_after (expr->reaching_reg, SET_DEST (set), insn); 4961117395Skan delete_insn (insn); 4962117395Skan occr->deleted_p = 1; 4963117395Skan if (!insn_inserted_p) 496490075Sobrien { 4965117395Skan insert_insn_end_bb (index_map[i], bb, 0); 4966117395Skan insn_inserted_p = 1; 496790075Sobrien } 496890075Sobrien } 496990075Sobrien } 497090075Sobrien } 497152284Sobrien } 4972117395Skan free (domby); 497352284Sobrien } 497490075Sobrien 497590075Sobrien free (index_map); 497652284Sobrien} 497790075Sobrien 497890075Sobrien/* Top level routine to perform one code hoisting (aka unification) pass 497990075Sobrien 4980117395Skan Return nonzero if a change was made. */ 498190075Sobrien 498290075Sobrienstatic int 4983132718Skanone_code_hoisting_pass (void) 498490075Sobrien{ 498590075Sobrien int changed = 0; 498690075Sobrien 4987117395Skan alloc_hash_table (max_cuid, &expr_hash_table, 0); 4988117395Skan compute_hash_table (&expr_hash_table); 4989169689Skan if (dump_file) 4990169689Skan dump_hash_table (dump_file, "Code Hosting Expressions", &expr_hash_table); 499190075Sobrien 4992117395Skan if (expr_hash_table.n_elems > 0) 499390075Sobrien { 4994117395Skan alloc_code_hoist_mem (last_basic_block, expr_hash_table.n_elems); 499590075Sobrien compute_code_hoist_data (); 499690075Sobrien hoist_code (); 499790075Sobrien free_code_hoist_mem (); 499890075Sobrien } 499990075Sobrien 5000117395Skan free_hash_table (&expr_hash_table); 500190075Sobrien 500290075Sobrien return changed; 500390075Sobrien} 500490075Sobrien 500590075Sobrien/* Here we provide the things required to do store motion towards 500690075Sobrien the exit. In order for this to be effective, gcse also needed to 500790075Sobrien be taught how to move a load when it is kill only by a store to itself. 500890075Sobrien 500990075Sobrien int i; 501090075Sobrien float a[10]; 501190075Sobrien 501290075Sobrien void foo(float scale) 501390075Sobrien { 501490075Sobrien for (i=0; i<10; i++) 501590075Sobrien a[i] *= scale; 501690075Sobrien } 501790075Sobrien 501890075Sobrien 'i' is both loaded and stored to in the loop. Normally, gcse cannot move 5019117395Skan the load out since its live around the loop, and stored at the bottom 5020117395Skan of the loop. 502190075Sobrien 5022117395Skan The 'Load Motion' referred to and implemented in this file is 502390075Sobrien an enhancement to gcse which when using edge based lcm, recognizes 502490075Sobrien this situation and allows gcse to move the load out of the loop. 502590075Sobrien 502690075Sobrien Once gcse has hoisted the load, store motion can then push this 502790075Sobrien load towards the exit, and we end up with no loads or stores of 'i' 502890075Sobrien in the loop. */ 502990075Sobrien 5030169689Skanstatic hashval_t 5031169689Skanpre_ldst_expr_hash (const void *p) 5032169689Skan{ 5033169689Skan int do_not_record_p = 0; 5034169689Skan const struct ls_expr *x = p; 5035169689Skan return hash_rtx (x->pattern, GET_MODE (x->pattern), &do_not_record_p, NULL, false); 5036169689Skan} 5037169689Skan 5038169689Skanstatic int 5039169689Skanpre_ldst_expr_eq (const void *p1, const void *p2) 5040169689Skan{ 5041169689Skan const struct ls_expr *ptr1 = p1, *ptr2 = p2; 5042169689Skan return expr_equiv_p (ptr1->pattern, ptr2->pattern); 5043169689Skan} 5044169689Skan 504590075Sobrien/* This will search the ldst list for a matching expression. If it 504690075Sobrien doesn't find one, we create one and initialize it. */ 504790075Sobrien 504890075Sobrienstatic struct ls_expr * 5049132718Skanldst_entry (rtx x) 505090075Sobrien{ 5051132718Skan int do_not_record_p = 0; 505290075Sobrien struct ls_expr * ptr; 5053132718Skan unsigned int hash; 5054169689Skan void **slot; 5055169689Skan struct ls_expr e; 505690075Sobrien 5057169689Skan hash = hash_rtx (x, GET_MODE (x), &do_not_record_p, 5058169689Skan NULL, /*have_reg_qty=*/false); 505990075Sobrien 5060169689Skan e.pattern = x; 5061169689Skan slot = htab_find_slot_with_hash (pre_ldst_table, &e, hash, INSERT); 5062169689Skan if (*slot) 5063169689Skan return (struct ls_expr *)*slot; 506490075Sobrien 5065169689Skan ptr = XNEW (struct ls_expr); 5066117395Skan 5067132718Skan ptr->next = pre_ldst_mems; 5068132718Skan ptr->expr = NULL; 5069132718Skan ptr->pattern = x; 5070132718Skan ptr->pattern_regs = NULL_RTX; 5071132718Skan ptr->loads = NULL_RTX; 5072132718Skan ptr->stores = NULL_RTX; 5073132718Skan ptr->reaching_reg = NULL_RTX; 5074132718Skan ptr->invalid = 0; 5075132718Skan ptr->index = 0; 5076132718Skan ptr->hash_index = hash; 5077132718Skan pre_ldst_mems = ptr; 5078169689Skan *slot = ptr; 5079132718Skan 508090075Sobrien return ptr; 508190075Sobrien} 508290075Sobrien 508390075Sobrien/* Free up an individual ldst entry. */ 508490075Sobrien 5085117395Skanstatic void 5086132718Skanfree_ldst_entry (struct ls_expr * ptr) 508790075Sobrien{ 508890075Sobrien free_INSN_LIST_list (& ptr->loads); 508990075Sobrien free_INSN_LIST_list (& ptr->stores); 509090075Sobrien 509190075Sobrien free (ptr); 509290075Sobrien} 509390075Sobrien 509490075Sobrien/* Free up all memory associated with the ldst list. */ 509590075Sobrien 509690075Sobrienstatic void 5097132718Skanfree_ldst_mems (void) 509890075Sobrien{ 5099169689Skan if (pre_ldst_table) 5100169689Skan htab_delete (pre_ldst_table); 5101169689Skan pre_ldst_table = NULL; 5102169689Skan 5103117395Skan while (pre_ldst_mems) 510490075Sobrien { 510590075Sobrien struct ls_expr * tmp = pre_ldst_mems; 510690075Sobrien 510790075Sobrien pre_ldst_mems = pre_ldst_mems->next; 510890075Sobrien 510990075Sobrien free_ldst_entry (tmp); 511090075Sobrien } 511190075Sobrien 511290075Sobrien pre_ldst_mems = NULL; 511390075Sobrien} 511490075Sobrien 511590075Sobrien/* Dump debugging info about the ldst list. */ 511690075Sobrien 511790075Sobrienstatic void 5118132718Skanprint_ldst_list (FILE * file) 511990075Sobrien{ 512090075Sobrien struct ls_expr * ptr; 512190075Sobrien 512290075Sobrien fprintf (file, "LDST list: \n"); 512390075Sobrien 512490075Sobrien for (ptr = first_ls_expr(); ptr != NULL; ptr = next_ls_expr (ptr)) 512590075Sobrien { 512690075Sobrien fprintf (file, " Pattern (%3d): ", ptr->index); 512790075Sobrien 512890075Sobrien print_rtl (file, ptr->pattern); 512990075Sobrien 513090075Sobrien fprintf (file, "\n Loads : "); 513190075Sobrien 513290075Sobrien if (ptr->loads) 513390075Sobrien print_rtl (file, ptr->loads); 513490075Sobrien else 513590075Sobrien fprintf (file, "(nil)"); 513690075Sobrien 513790075Sobrien fprintf (file, "\n Stores : "); 513890075Sobrien 513990075Sobrien if (ptr->stores) 514090075Sobrien print_rtl (file, ptr->stores); 514190075Sobrien else 514290075Sobrien fprintf (file, "(nil)"); 514390075Sobrien 514490075Sobrien fprintf (file, "\n\n"); 514590075Sobrien } 514690075Sobrien 514790075Sobrien fprintf (file, "\n"); 514890075Sobrien} 514990075Sobrien 515090075Sobrien/* Returns 1 if X is in the list of ldst only expressions. */ 515190075Sobrien 515290075Sobrienstatic struct ls_expr * 5153132718Skanfind_rtx_in_ldst (rtx x) 515490075Sobrien{ 5155169689Skan struct ls_expr e; 5156169689Skan void **slot; 5157169689Skan if (!pre_ldst_table) 5158169689Skan return NULL; 5159169689Skan e.pattern = x; 5160169689Skan slot = htab_find_slot (pre_ldst_table, &e, NO_INSERT); 5161169689Skan if (!slot || ((struct ls_expr *)*slot)->invalid) 5162169689Skan return NULL; 5163169689Skan return *slot; 516490075Sobrien} 516590075Sobrien 516690075Sobrien/* Assign each element of the list of mems a monotonically increasing value. */ 516790075Sobrien 516890075Sobrienstatic int 5169132718Skanenumerate_ldsts (void) 517090075Sobrien{ 517190075Sobrien struct ls_expr * ptr; 517290075Sobrien int n = 0; 517390075Sobrien 517490075Sobrien for (ptr = pre_ldst_mems; ptr != NULL; ptr = ptr->next) 517590075Sobrien ptr->index = n++; 517690075Sobrien 517790075Sobrien return n; 517890075Sobrien} 517990075Sobrien 518090075Sobrien/* Return first item in the list. */ 518190075Sobrien 518290075Sobrienstatic inline struct ls_expr * 5183132718Skanfirst_ls_expr (void) 518490075Sobrien{ 518590075Sobrien return pre_ldst_mems; 518690075Sobrien} 518790075Sobrien 5188132718Skan/* Return the next item in the list after the specified one. */ 518990075Sobrien 519090075Sobrienstatic inline struct ls_expr * 5191132718Skannext_ls_expr (struct ls_expr * ptr) 519290075Sobrien{ 519390075Sobrien return ptr->next; 519490075Sobrien} 519590075Sobrien 519690075Sobrien/* Load Motion for loads which only kill themselves. */ 519790075Sobrien 519890075Sobrien/* Return true if x is a simple MEM operation, with no registers or 519990075Sobrien side effects. These are the types of loads we consider for the 520090075Sobrien ld_motion list, otherwise we let the usual aliasing take care of it. */ 520190075Sobrien 5202117395Skanstatic int 5203132718Skansimple_mem (rtx x) 520490075Sobrien{ 5205169689Skan if (! MEM_P (x)) 520690075Sobrien return 0; 5207117395Skan 520890075Sobrien if (MEM_VOLATILE_P (x)) 520990075Sobrien return 0; 5210117395Skan 521190075Sobrien if (GET_MODE (x) == BLKmode) 521290075Sobrien return 0; 521390075Sobrien 5214132718Skan /* If we are handling exceptions, we must be careful with memory references 5215132718Skan that may trap. If we are not, the behavior is undefined, so we may just 5216132718Skan continue. */ 5217132718Skan if (flag_non_call_exceptions && may_trap_p (x)) 5218132718Skan return 0; 5219117395Skan 5220132718Skan if (side_effects_p (x)) 5221132718Skan return 0; 5222132718Skan 5223132718Skan /* Do not consider function arguments passed on stack. */ 5224132718Skan if (reg_mentioned_p (stack_pointer_rtx, x)) 5225132718Skan return 0; 5226132718Skan 5227132718Skan if (flag_float_store && FLOAT_MODE_P (GET_MODE (x))) 5228132718Skan return 0; 5229132718Skan 5230132718Skan return 1; 523190075Sobrien} 523290075Sobrien 5233117395Skan/* Make sure there isn't a buried reference in this pattern anywhere. 5234117395Skan If there is, invalidate the entry for it since we're not capable 5235117395Skan of fixing it up just yet.. We have to be sure we know about ALL 523690075Sobrien loads since the aliasing code will allow all entries in the 523790075Sobrien ld_motion list to not-alias itself. If we miss a load, we will get 5238117395Skan the wrong value since gcse might common it and we won't know to 523990075Sobrien fix it up. */ 524090075Sobrien 524190075Sobrienstatic void 5242132718Skaninvalidate_any_buried_refs (rtx x) 524390075Sobrien{ 524490075Sobrien const char * fmt; 524590075Sobrien int i, j; 524690075Sobrien struct ls_expr * ptr; 524790075Sobrien 524890075Sobrien /* Invalidate it in the list. */ 5249169689Skan if (MEM_P (x) && simple_mem (x)) 525090075Sobrien { 525190075Sobrien ptr = ldst_entry (x); 525290075Sobrien ptr->invalid = 1; 525390075Sobrien } 525490075Sobrien 525590075Sobrien /* Recursively process the insn. */ 525690075Sobrien fmt = GET_RTX_FORMAT (GET_CODE (x)); 5257117395Skan 525890075Sobrien for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0; i--) 525990075Sobrien { 526090075Sobrien if (fmt[i] == 'e') 526190075Sobrien invalidate_any_buried_refs (XEXP (x, i)); 526290075Sobrien else if (fmt[i] == 'E') 526390075Sobrien for (j = XVECLEN (x, i) - 1; j >= 0; j--) 526490075Sobrien invalidate_any_buried_refs (XVECEXP (x, i, j)); 526590075Sobrien } 526690075Sobrien} 526790075Sobrien 5268132718Skan/* Find all the 'simple' MEMs which are used in LOADs and STORES. Simple 5269132718Skan being defined as MEM loads and stores to symbols, with no side effects 5270132718Skan and no registers in the expression. For a MEM destination, we also 5271132718Skan check that the insn is still valid if we replace the destination with a 5272132718Skan REG, as is done in update_ld_motion_stores. If there are any uses/defs 5273132718Skan which don't match this criteria, they are invalidated and trimmed out 5274132718Skan later. */ 527590075Sobrien 5276117395Skanstatic void 5277132718Skancompute_ld_motion_mems (void) 527890075Sobrien{ 527990075Sobrien struct ls_expr * ptr; 5280117395Skan basic_block bb; 528190075Sobrien rtx insn; 5282117395Skan 528390075Sobrien pre_ldst_mems = NULL; 5284169689Skan pre_ldst_table = htab_create (13, pre_ldst_expr_hash, 5285169689Skan pre_ldst_expr_eq, NULL); 528690075Sobrien 5287117395Skan FOR_EACH_BB (bb) 528890075Sobrien { 5289169689Skan FOR_BB_INSNS (bb, insn) 529090075Sobrien { 5291132718Skan if (INSN_P (insn)) 529290075Sobrien { 529390075Sobrien if (GET_CODE (PATTERN (insn)) == SET) 529490075Sobrien { 529590075Sobrien rtx src = SET_SRC (PATTERN (insn)); 529690075Sobrien rtx dest = SET_DEST (PATTERN (insn)); 529790075Sobrien 529890075Sobrien /* Check for a simple LOAD... */ 5299169689Skan if (MEM_P (src) && simple_mem (src)) 530090075Sobrien { 530190075Sobrien ptr = ldst_entry (src); 5302169689Skan if (REG_P (dest)) 530390075Sobrien ptr->loads = alloc_INSN_LIST (insn, ptr->loads); 530490075Sobrien else 530590075Sobrien ptr->invalid = 1; 530690075Sobrien } 530790075Sobrien else 530890075Sobrien { 530990075Sobrien /* Make sure there isn't a buried load somewhere. */ 531090075Sobrien invalidate_any_buried_refs (src); 531190075Sobrien } 5312117395Skan 531390075Sobrien /* Check for stores. Don't worry about aliased ones, they 531490075Sobrien will block any movement we might do later. We only care 531590075Sobrien about this exact pattern since those are the only 531690075Sobrien circumstance that we will ignore the aliasing info. */ 5317169689Skan if (MEM_P (dest) && simple_mem (dest)) 531890075Sobrien { 531990075Sobrien ptr = ldst_entry (dest); 5320117395Skan 5321169689Skan if (! MEM_P (src) 5322132718Skan && GET_CODE (src) != ASM_OPERANDS 5323132718Skan /* Check for REG manually since want_to_gcse_p 5324132718Skan returns 0 for all REGs. */ 5325169689Skan && can_assign_to_reg_p (src)) 532690075Sobrien ptr->stores = alloc_INSN_LIST (insn, ptr->stores); 532790075Sobrien else 532890075Sobrien ptr->invalid = 1; 532990075Sobrien } 533090075Sobrien } 533190075Sobrien else 533290075Sobrien invalidate_any_buried_refs (PATTERN (insn)); 533390075Sobrien } 533490075Sobrien } 533590075Sobrien } 533690075Sobrien} 533790075Sobrien 5338117395Skan/* Remove any references that have been either invalidated or are not in the 533990075Sobrien expression list for pre gcse. */ 534090075Sobrien 534190075Sobrienstatic void 5342132718Skantrim_ld_motion_mems (void) 534390075Sobrien{ 5344132718Skan struct ls_expr * * last = & pre_ldst_mems; 5345132718Skan struct ls_expr * ptr = pre_ldst_mems; 534690075Sobrien 534790075Sobrien while (ptr != NULL) 534890075Sobrien { 5349132718Skan struct expr * expr; 5350117395Skan 535190075Sobrien /* Delete if entry has been made invalid. */ 5352132718Skan if (! ptr->invalid) 535390075Sobrien { 535490075Sobrien /* Delete if we cannot find this mem in the expression list. */ 5355132718Skan unsigned int hash = ptr->hash_index % expr_hash_table.size; 5356117395Skan 5357132718Skan for (expr = expr_hash_table.table[hash]; 5358132718Skan expr != NULL; 5359132718Skan expr = expr->next_same_hash) 5360132718Skan if (expr_equiv_p (expr->expr, ptr->pattern)) 5361132718Skan break; 536290075Sobrien } 536390075Sobrien else 5364132718Skan expr = (struct expr *) 0; 5365132718Skan 5366132718Skan if (expr) 536790075Sobrien { 536890075Sobrien /* Set the expression field if we are keeping it. */ 536990075Sobrien ptr->expr = expr; 5370132718Skan last = & ptr->next; 537190075Sobrien ptr = ptr->next; 537290075Sobrien } 5373132718Skan else 5374132718Skan { 5375132718Skan *last = ptr->next; 5376169689Skan htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index); 5377132718Skan free_ldst_entry (ptr); 5378132718Skan ptr = * last; 5379132718Skan } 538090075Sobrien } 538190075Sobrien 538290075Sobrien /* Show the world what we've found. */ 5383169689Skan if (dump_file && pre_ldst_mems != NULL) 5384169689Skan print_ldst_list (dump_file); 538590075Sobrien} 538690075Sobrien 538790075Sobrien/* This routine will take an expression which we are replacing with 538890075Sobrien a reaching register, and update any stores that are needed if 538990075Sobrien that expression is in the ld_motion list. Stores are updated by 5390132718Skan copying their SRC to the reaching register, and then storing 539190075Sobrien the reaching register into the store location. These keeps the 539290075Sobrien correct value in the reaching register for the loads. */ 539390075Sobrien 539490075Sobrienstatic void 5395132718Skanupdate_ld_motion_stores (struct expr * expr) 539690075Sobrien{ 539790075Sobrien struct ls_expr * mem_ptr; 539890075Sobrien 539990075Sobrien if ((mem_ptr = find_rtx_in_ldst (expr->expr))) 540090075Sobrien { 5401117395Skan /* We can try to find just the REACHED stores, but is shouldn't 5402117395Skan matter to set the reaching reg everywhere... some might be 540390075Sobrien dead and should be eliminated later. */ 540490075Sobrien 5405132718Skan /* We replace (set mem expr) with (set reg expr) (set mem reg) 5406132718Skan where reg is the reaching reg used in the load. We checked in 5407132718Skan compute_ld_motion_mems that we can replace (set mem expr) with 5408132718Skan (set reg expr) in that insn. */ 540990075Sobrien rtx list = mem_ptr->stores; 5410117395Skan 541190075Sobrien for ( ; list != NULL_RTX; list = XEXP (list, 1)) 541290075Sobrien { 541390075Sobrien rtx insn = XEXP (list, 0); 541490075Sobrien rtx pat = PATTERN (insn); 541590075Sobrien rtx src = SET_SRC (pat); 541690075Sobrien rtx reg = expr->reaching_reg; 541790075Sobrien rtx copy, new; 541890075Sobrien 541990075Sobrien /* If we've already copied it, continue. */ 542090075Sobrien if (expr->reaching_reg == src) 542190075Sobrien continue; 5422117395Skan 5423169689Skan if (dump_file) 542490075Sobrien { 5425169689Skan fprintf (dump_file, "PRE: store updated with reaching reg "); 5426169689Skan print_rtl (dump_file, expr->reaching_reg); 5427169689Skan fprintf (dump_file, ":\n "); 5428169689Skan print_inline_rtx (dump_file, insn, 8); 5429169689Skan fprintf (dump_file, "\n"); 543090075Sobrien } 5431117395Skan 5432132718Skan copy = gen_move_insn ( reg, copy_rtx (SET_SRC (pat))); 543390075Sobrien new = emit_insn_before (copy, insn); 543490075Sobrien record_one_set (REGNO (reg), new); 543590075Sobrien SET_SRC (pat) = reg; 543690075Sobrien 543790075Sobrien /* un-recognize this pattern since it's probably different now. */ 543890075Sobrien INSN_CODE (insn) = -1; 543990075Sobrien gcse_create_count++; 544090075Sobrien } 544190075Sobrien } 544290075Sobrien} 544390075Sobrien 544490075Sobrien/* Store motion code. */ 544590075Sobrien 5446132718Skan#define ANTIC_STORE_LIST(x) ((x)->loads) 5447132718Skan#define AVAIL_STORE_LIST(x) ((x)->stores) 5448132718Skan#define LAST_AVAIL_CHECK_FAILURE(x) ((x)->reaching_reg) 5449132718Skan 5450117395Skan/* This is used to communicate the target bitvector we want to use in the 545190075Sobrien reg_set_info routine when called via the note_stores mechanism. */ 5452132718Skanstatic int * regvec; 545390075Sobrien 5454132718Skan/* And current insn, for the same routine. */ 5455132718Skanstatic rtx compute_store_table_current_insn; 5456132718Skan 545790075Sobrien/* Used in computing the reverse edge graph bit vectors. */ 545890075Sobrienstatic sbitmap * st_antloc; 545990075Sobrien 546090075Sobrien/* Global holding the number of store expressions we are dealing with. */ 546190075Sobrienstatic int num_stores; 546290075Sobrien 5463132718Skan/* Checks to set if we need to mark a register set. Called from 5464132718Skan note_stores. */ 546590075Sobrien 546690075Sobrienstatic void 5467132718Skanreg_set_info (rtx dest, rtx setter ATTRIBUTE_UNUSED, 5468132718Skan void *data) 546990075Sobrien{ 5470132718Skan sbitmap bb_reg = data; 5471132718Skan 547290075Sobrien if (GET_CODE (dest) == SUBREG) 547390075Sobrien dest = SUBREG_REG (dest); 547490075Sobrien 5475169689Skan if (REG_P (dest)) 5476132718Skan { 5477132718Skan regvec[REGNO (dest)] = INSN_UID (compute_store_table_current_insn); 5478132718Skan if (bb_reg) 5479132718Skan SET_BIT (bb_reg, REGNO (dest)); 5480132718Skan } 548190075Sobrien} 548290075Sobrien 5483132718Skan/* Clear any mark that says that this insn sets dest. Called from 5484132718Skan note_stores. */ 548590075Sobrien 5486132718Skanstatic void 5487132718Skanreg_clear_last_set (rtx dest, rtx setter ATTRIBUTE_UNUSED, 5488132718Skan void *data) 548990075Sobrien{ 5490132718Skan int *dead_vec = data; 5491132718Skan 5492132718Skan if (GET_CODE (dest) == SUBREG) 5493132718Skan dest = SUBREG_REG (dest); 5494132718Skan 5495169689Skan if (REG_P (dest) && 5496132718Skan dead_vec[REGNO (dest)] == INSN_UID (compute_store_table_current_insn)) 5497132718Skan dead_vec[REGNO (dest)] = 0; 5498132718Skan} 5499132718Skan 5500132718Skan/* Return zero if some of the registers in list X are killed 5501132718Skan due to set of registers in bitmap REGS_SET. */ 5502132718Skan 5503132718Skanstatic bool 5504132718Skanstore_ops_ok (rtx x, int *regs_set) 5505132718Skan{ 5506132718Skan rtx reg; 5507132718Skan 5508132718Skan for (; x; x = XEXP (x, 1)) 5509132718Skan { 5510132718Skan reg = XEXP (x, 0); 5511132718Skan if (regs_set[REGNO(reg)]) 5512132718Skan return false; 5513132718Skan } 5514132718Skan 5515132718Skan return true; 5516132718Skan} 5517132718Skan 5518132718Skan/* Returns a list of registers mentioned in X. */ 5519132718Skanstatic rtx 5520132718Skanextract_mentioned_regs (rtx x) 5521132718Skan{ 5522132718Skan return extract_mentioned_regs_helper (x, NULL_RTX); 5523132718Skan} 5524132718Skan 5525132718Skan/* Helper for extract_mentioned_regs; ACCUM is used to accumulate used 5526132718Skan registers. */ 5527132718Skanstatic rtx 5528132718Skanextract_mentioned_regs_helper (rtx x, rtx accum) 5529132718Skan{ 553090075Sobrien int i; 553190075Sobrien enum rtx_code code; 553290075Sobrien const char * fmt; 553390075Sobrien 553490075Sobrien /* Repeat is used to turn tail-recursion into iteration. */ 553590075Sobrien repeat: 553690075Sobrien 553790075Sobrien if (x == 0) 5538132718Skan return accum; 553990075Sobrien 554090075Sobrien code = GET_CODE (x); 554190075Sobrien switch (code) 554290075Sobrien { 554390075Sobrien case REG: 5544132718Skan return alloc_EXPR_LIST (0, x, accum); 554590075Sobrien 554690075Sobrien case MEM: 554790075Sobrien x = XEXP (x, 0); 554890075Sobrien goto repeat; 554990075Sobrien 555090075Sobrien case PRE_DEC: 555190075Sobrien case PRE_INC: 555290075Sobrien case POST_DEC: 555390075Sobrien case POST_INC: 5554132718Skan /* We do not run this function with arguments having side effects. */ 5555169689Skan gcc_unreachable (); 555690075Sobrien 555790075Sobrien case PC: 555890075Sobrien case CC0: /*FIXME*/ 555990075Sobrien case CONST: 556090075Sobrien case CONST_INT: 556190075Sobrien case CONST_DOUBLE: 556296263Sobrien case CONST_VECTOR: 556390075Sobrien case SYMBOL_REF: 556490075Sobrien case LABEL_REF: 556590075Sobrien case ADDR_VEC: 556690075Sobrien case ADDR_DIFF_VEC: 5567132718Skan return accum; 556890075Sobrien 556990075Sobrien default: 557090075Sobrien break; 557190075Sobrien } 557290075Sobrien 557390075Sobrien i = GET_RTX_LENGTH (code) - 1; 557490075Sobrien fmt = GET_RTX_FORMAT (code); 5575117395Skan 557690075Sobrien for (; i >= 0; i--) 557790075Sobrien { 557890075Sobrien if (fmt[i] == 'e') 557990075Sobrien { 558090075Sobrien rtx tem = XEXP (x, i); 558190075Sobrien 558290075Sobrien /* If we are about to do the last recursive call 5583132718Skan needed at this level, change it into iteration. */ 558490075Sobrien if (i == 0) 558590075Sobrien { 558690075Sobrien x = tem; 558790075Sobrien goto repeat; 558890075Sobrien } 5589117395Skan 5590132718Skan accum = extract_mentioned_regs_helper (tem, accum); 559190075Sobrien } 559290075Sobrien else if (fmt[i] == 'E') 559390075Sobrien { 559490075Sobrien int j; 5595117395Skan 559690075Sobrien for (j = 0; j < XVECLEN (x, i); j++) 5597132718Skan accum = extract_mentioned_regs_helper (XVECEXP (x, i, j), accum); 559890075Sobrien } 559990075Sobrien } 560090075Sobrien 5601132718Skan return accum; 560290075Sobrien} 560390075Sobrien 5604132718Skan/* Determine whether INSN is MEM store pattern that we will consider moving. 5605132718Skan REGS_SET_BEFORE is bitmap of registers set before (and including) the 5606132718Skan current insn, REGS_SET_AFTER is bitmap of registers set after (and 5607132718Skan including) the insn in this basic block. We must be passing through BB from 5608132718Skan head to end, as we are using this fact to speed things up. 560990075Sobrien 5610132718Skan The results are stored this way: 5611132718Skan 5612132718Skan -- the first anticipatable expression is added into ANTIC_STORE_LIST 5613132718Skan -- if the processed expression is not anticipatable, NULL_RTX is added 5614132718Skan there instead, so that we can use it as indicator that no further 5615132718Skan expression of this type may be anticipatable 5616132718Skan -- if the expression is available, it is added as head of AVAIL_STORE_LIST; 5617132718Skan consequently, all of them but this head are dead and may be deleted. 5618132718Skan -- if the expression is not available, the insn due to that it fails to be 5619132718Skan available is stored in reaching_reg. 5620132718Skan 5621132718Skan The things are complicated a bit by fact that there already may be stores 5622132718Skan to the same MEM from other blocks; also caller must take care of the 5623132718Skan necessary cleanup of the temporary markers after end of the basic block. 5624132718Skan */ 5625132718Skan 562690075Sobrienstatic void 5627132718Skanfind_moveable_store (rtx insn, int *regs_set_before, int *regs_set_after) 562890075Sobrien{ 562990075Sobrien struct ls_expr * ptr; 5630132718Skan rtx dest, set, tmp; 5631132718Skan int check_anticipatable, check_available; 5632132718Skan basic_block bb = BLOCK_FOR_INSN (insn); 563390075Sobrien 5634132718Skan set = single_set (insn); 5635132718Skan if (!set) 563690075Sobrien return; 563790075Sobrien 5638132718Skan dest = SET_DEST (set); 5639117395Skan 5640169689Skan if (! MEM_P (dest) || MEM_VOLATILE_P (dest) 564190075Sobrien || GET_MODE (dest) == BLKmode) 564290075Sobrien return; 564390075Sobrien 5644132718Skan if (side_effects_p (dest)) 5645132718Skan return; 564690075Sobrien 5647132718Skan /* If we are handling exceptions, we must be careful with memory references 5648132718Skan that may trap. If we are not, the behavior is undefined, so we may just 5649132718Skan continue. */ 5650132718Skan if (flag_non_call_exceptions && may_trap_p (dest)) 565190075Sobrien return; 565290075Sobrien 5653169689Skan /* Even if the destination cannot trap, the source may. In this case we'd 5654169689Skan need to handle updating the REG_EH_REGION note. */ 5655169689Skan if (find_reg_note (insn, REG_EH_REGION, NULL_RTX)) 5656169689Skan return; 5657169689Skan 5658169689Skan /* Make sure that the SET_SRC of this store insns can be assigned to 5659169689Skan a register, or we will fail later on in replace_store_insn, which 5660169689Skan assumes that we can do this. But sometimes the target machine has 5661169689Skan oddities like MEM read-modify-write instruction. See for example 5662169689Skan PR24257. */ 5663169689Skan if (!can_assign_to_reg_p (SET_SRC (set))) 5664169689Skan return; 5665169689Skan 566690075Sobrien ptr = ldst_entry (dest); 5667132718Skan if (!ptr->pattern_regs) 5668132718Skan ptr->pattern_regs = extract_mentioned_regs (dest); 5669132718Skan 5670132718Skan /* Do not check for anticipatability if we either found one anticipatable 5671132718Skan store already, or tested for one and found out that it was killed. */ 5672132718Skan check_anticipatable = 0; 5673132718Skan if (!ANTIC_STORE_LIST (ptr)) 5674132718Skan check_anticipatable = 1; 5675132718Skan else 5676132718Skan { 5677132718Skan tmp = XEXP (ANTIC_STORE_LIST (ptr), 0); 5678132718Skan if (tmp != NULL_RTX 5679132718Skan && BLOCK_FOR_INSN (tmp) != bb) 5680132718Skan check_anticipatable = 1; 5681132718Skan } 5682132718Skan if (check_anticipatable) 5683132718Skan { 5684132718Skan if (store_killed_before (dest, ptr->pattern_regs, insn, bb, regs_set_before)) 5685132718Skan tmp = NULL_RTX; 5686132718Skan else 5687132718Skan tmp = insn; 5688132718Skan ANTIC_STORE_LIST (ptr) = alloc_INSN_LIST (tmp, 5689132718Skan ANTIC_STORE_LIST (ptr)); 5690132718Skan } 5691132718Skan 5692132718Skan /* It is not necessary to check whether store is available if we did 5693132718Skan it successfully before; if we failed before, do not bother to check 5694132718Skan until we reach the insn that caused us to fail. */ 5695132718Skan check_available = 0; 5696132718Skan if (!AVAIL_STORE_LIST (ptr)) 5697132718Skan check_available = 1; 5698132718Skan else 5699132718Skan { 5700132718Skan tmp = XEXP (AVAIL_STORE_LIST (ptr), 0); 5701132718Skan if (BLOCK_FOR_INSN (tmp) != bb) 5702132718Skan check_available = 1; 5703132718Skan } 5704132718Skan if (check_available) 5705132718Skan { 5706132718Skan /* Check that we have already reached the insn at that the check 5707132718Skan failed last time. */ 5708132718Skan if (LAST_AVAIL_CHECK_FAILURE (ptr)) 5709132718Skan { 5710132718Skan for (tmp = BB_END (bb); 5711132718Skan tmp != insn && tmp != LAST_AVAIL_CHECK_FAILURE (ptr); 5712132718Skan tmp = PREV_INSN (tmp)) 5713132718Skan continue; 5714132718Skan if (tmp == insn) 5715132718Skan check_available = 0; 5716132718Skan } 5717132718Skan else 5718132718Skan check_available = store_killed_after (dest, ptr->pattern_regs, insn, 5719132718Skan bb, regs_set_after, 5720132718Skan &LAST_AVAIL_CHECK_FAILURE (ptr)); 5721132718Skan } 5722132718Skan if (!check_available) 5723132718Skan AVAIL_STORE_LIST (ptr) = alloc_INSN_LIST (insn, AVAIL_STORE_LIST (ptr)); 572490075Sobrien} 572590075Sobrien 5726132718Skan/* Find available and anticipatable stores. */ 572790075Sobrien 572890075Sobrienstatic int 5729132718Skancompute_store_table (void) 573090075Sobrien{ 5731117395Skan int ret; 5732117395Skan basic_block bb; 573390075Sobrien unsigned regno; 5734132718Skan rtx insn, pat, tmp; 5735132718Skan int *last_set_in, *already_set; 5736132718Skan struct ls_expr * ptr, **prev_next_ptr_ptr; 573790075Sobrien 573890075Sobrien max_gcse_regno = max_reg_num (); 573990075Sobrien 5740132718Skan reg_set_in_block = sbitmap_vector_alloc (last_basic_block, 574190075Sobrien max_gcse_regno); 5742117395Skan sbitmap_vector_zero (reg_set_in_block, last_basic_block); 574390075Sobrien pre_ldst_mems = 0; 5744169689Skan pre_ldst_table = htab_create (13, pre_ldst_expr_hash, 5745169689Skan pre_ldst_expr_eq, NULL); 5746169689Skan last_set_in = XCNEWVEC (int, max_gcse_regno); 5747169689Skan already_set = XNEWVEC (int, max_gcse_regno); 574890075Sobrien 574990075Sobrien /* Find all the stores we care about. */ 5750117395Skan FOR_EACH_BB (bb) 575190075Sobrien { 5752132718Skan /* First compute the registers set in this block. */ 5753132718Skan regvec = last_set_in; 5754132718Skan 5755169689Skan FOR_BB_INSNS (bb, insn) 575690075Sobrien { 575790075Sobrien if (! INSN_P (insn)) 575890075Sobrien continue; 575990075Sobrien 5760169689Skan if (CALL_P (insn)) 576190075Sobrien { 576290075Sobrien for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 5763169689Skan if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) 5764132718Skan { 5765132718Skan last_set_in[regno] = INSN_UID (insn); 5766132718Skan SET_BIT (reg_set_in_block[bb->index], regno); 5767132718Skan } 576890075Sobrien } 5769117395Skan 577090075Sobrien pat = PATTERN (insn); 5771132718Skan compute_store_table_current_insn = insn; 5772132718Skan note_stores (pat, reg_set_info, reg_set_in_block[bb->index]); 5773132718Skan } 5774132718Skan 5775132718Skan /* Now find the stores. */ 5776132718Skan memset (already_set, 0, sizeof (int) * max_gcse_regno); 5777132718Skan regvec = already_set; 5778169689Skan FOR_BB_INSNS (bb, insn) 5779132718Skan { 5780132718Skan if (! INSN_P (insn)) 5781132718Skan continue; 5782132718Skan 5783169689Skan if (CALL_P (insn)) 5784132718Skan { 5785132718Skan for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 5786169689Skan if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno)) 5787132718Skan already_set[regno] = 1; 5788132718Skan } 5789132718Skan 5790132718Skan pat = PATTERN (insn); 579190075Sobrien note_stores (pat, reg_set_info, NULL); 5792117395Skan 579390075Sobrien /* Now that we've marked regs, look for stores. */ 5794132718Skan find_moveable_store (insn, already_set, last_set_in); 5795132718Skan 5796132718Skan /* Unmark regs that are no longer set. */ 5797132718Skan compute_store_table_current_insn = insn; 5798132718Skan note_stores (pat, reg_clear_last_set, last_set_in); 5799169689Skan if (CALL_P (insn)) 5800132718Skan { 5801132718Skan for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++) 5802169689Skan if (TEST_HARD_REG_BIT (regs_invalidated_by_call, regno) 5803132718Skan && last_set_in[regno] == INSN_UID (insn)) 5804132718Skan last_set_in[regno] = 0; 5805132718Skan } 580690075Sobrien } 5807132718Skan 5808132718Skan#ifdef ENABLE_CHECKING 5809132718Skan /* last_set_in should now be all-zero. */ 5810132718Skan for (regno = 0; regno < max_gcse_regno; regno++) 5811169689Skan gcc_assert (!last_set_in[regno]); 5812132718Skan#endif 5813132718Skan 5814132718Skan /* Clear temporary marks. */ 5815132718Skan for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr)) 5816132718Skan { 5817132718Skan LAST_AVAIL_CHECK_FAILURE(ptr) = NULL_RTX; 5818132718Skan if (ANTIC_STORE_LIST (ptr) 5819132718Skan && (tmp = XEXP (ANTIC_STORE_LIST (ptr), 0)) == NULL_RTX) 5820132718Skan ANTIC_STORE_LIST (ptr) = XEXP (ANTIC_STORE_LIST (ptr), 1); 5821132718Skan } 582290075Sobrien } 582390075Sobrien 5824132718Skan /* Remove the stores that are not available anywhere, as there will 5825132718Skan be no opportunity to optimize them. */ 5826132718Skan for (ptr = pre_ldst_mems, prev_next_ptr_ptr = &pre_ldst_mems; 5827132718Skan ptr != NULL; 5828132718Skan ptr = *prev_next_ptr_ptr) 5829132718Skan { 5830132718Skan if (!AVAIL_STORE_LIST (ptr)) 5831132718Skan { 5832132718Skan *prev_next_ptr_ptr = ptr->next; 5833169689Skan htab_remove_elt_with_hash (pre_ldst_table, ptr, ptr->hash_index); 5834132718Skan free_ldst_entry (ptr); 5835132718Skan } 5836132718Skan else 5837132718Skan prev_next_ptr_ptr = &ptr->next; 5838132718Skan } 5839132718Skan 584090075Sobrien ret = enumerate_ldsts (); 5841117395Skan 5842169689Skan if (dump_file) 584390075Sobrien { 5844169689Skan fprintf (dump_file, "ST_avail and ST_antic (shown under loads..)\n"); 5845169689Skan print_ldst_list (dump_file); 584690075Sobrien } 5847117395Skan 5848132718Skan free (last_set_in); 5849132718Skan free (already_set); 585090075Sobrien return ret; 585190075Sobrien} 585290075Sobrien 5853132718Skan/* Check to see if the load X is aliased with STORE_PATTERN. 5854132718Skan AFTER is true if we are checking the case when STORE_PATTERN occurs 5855132718Skan after the X. */ 585690075Sobrien 5857132718Skanstatic bool 5858132718Skanload_kills_store (rtx x, rtx store_pattern, int after) 585990075Sobrien{ 5860132718Skan if (after) 5861132718Skan return anti_dependence (x, store_pattern); 5862132718Skan else 5863132718Skan return true_dependence (store_pattern, GET_MODE (store_pattern), x, 5864132718Skan rtx_addr_varies_p); 586590075Sobrien} 586690075Sobrien 5867117395Skan/* Go through the entire insn X, looking for any loads which might alias 5868132718Skan STORE_PATTERN. Return true if found. 5869132718Skan AFTER is true if we are checking the case when STORE_PATTERN occurs 5870132718Skan after the insn X. */ 587190075Sobrien 5872132718Skanstatic bool 5873132718Skanfind_loads (rtx x, rtx store_pattern, int after) 587490075Sobrien{ 587590075Sobrien const char * fmt; 587690075Sobrien int i, j; 5877132718Skan int ret = false; 587890075Sobrien 587990075Sobrien if (!x) 5880132718Skan return false; 588190075Sobrien 5882117395Skan if (GET_CODE (x) == SET) 588390075Sobrien x = SET_SRC (x); 588490075Sobrien 5885169689Skan if (MEM_P (x)) 588690075Sobrien { 5887132718Skan if (load_kills_store (x, store_pattern, after)) 5888132718Skan return true; 588990075Sobrien } 589090075Sobrien 589190075Sobrien /* Recursively process the insn. */ 589290075Sobrien fmt = GET_RTX_FORMAT (GET_CODE (x)); 5893117395Skan 589490075Sobrien for (i = GET_RTX_LENGTH (GET_CODE (x)) - 1; i >= 0 && !ret; i--) 589590075Sobrien { 589690075Sobrien if (fmt[i] == 'e') 5897132718Skan ret |= find_loads (XEXP (x, i), store_pattern, after); 589890075Sobrien else if (fmt[i] == 'E') 589990075Sobrien for (j = XVECLEN (x, i) - 1; j >= 0; j--) 5900132718Skan ret |= find_loads (XVECEXP (x, i, j), store_pattern, after); 590190075Sobrien } 590290075Sobrien return ret; 590390075Sobrien} 590490075Sobrien 5905117395Skan/* Check if INSN kills the store pattern X (is aliased with it). 5906132718Skan AFTER is true if we are checking the case when store X occurs 5907169689Skan after the insn. Return true if it does. */ 590890075Sobrien 5909132718Skanstatic bool 5910132718Skanstore_killed_in_insn (rtx x, rtx x_regs, rtx insn, int after) 591190075Sobrien{ 5912132718Skan rtx reg, base, note; 5913117395Skan 5914132718Skan if (!INSN_P (insn)) 5915132718Skan return false; 5916132718Skan 5917169689Skan if (CALL_P (insn)) 591890075Sobrien { 591990075Sobrien /* A normal or pure call might read from pattern, 592090075Sobrien but a const call will not. */ 5921132718Skan if (! CONST_OR_PURE_CALL_P (insn) || pure_call_p (insn)) 5922132718Skan return true; 5923132718Skan 5924132718Skan /* But even a const call reads its parameters. Check whether the 5925132718Skan base of some of registers used in mem is stack pointer. */ 5926132718Skan for (reg = x_regs; reg; reg = XEXP (reg, 1)) 5927132718Skan { 5928132718Skan base = find_base_term (XEXP (reg, 0)); 5929132718Skan if (!base 5930132718Skan || (GET_CODE (base) == ADDRESS 5931132718Skan && GET_MODE (base) == Pmode 5932132718Skan && XEXP (base, 0) == stack_pointer_rtx)) 5933132718Skan return true; 5934132718Skan } 5935132718Skan 5936132718Skan return false; 593790075Sobrien } 5938117395Skan 593990075Sobrien if (GET_CODE (PATTERN (insn)) == SET) 594090075Sobrien { 594190075Sobrien rtx pat = PATTERN (insn); 5942132718Skan rtx dest = SET_DEST (pat); 5943132718Skan 5944169689Skan if (GET_CODE (dest) == ZERO_EXTRACT) 5945132718Skan dest = XEXP (dest, 0); 5946132718Skan 594790075Sobrien /* Check for memory stores to aliased objects. */ 5948169689Skan if (MEM_P (dest) 5949132718Skan && !expr_equiv_p (dest, x)) 5950132718Skan { 5951132718Skan if (after) 5952132718Skan { 5953132718Skan if (output_dependence (dest, x)) 5954132718Skan return true; 5955132718Skan } 5956132718Skan else 5957132718Skan { 5958132718Skan if (output_dependence (x, dest)) 5959132718Skan return true; 5960132718Skan } 5961132718Skan } 5962132718Skan if (find_loads (SET_SRC (pat), x, after)) 5963132718Skan return true; 596490075Sobrien } 5965132718Skan else if (find_loads (PATTERN (insn), x, after)) 5966132718Skan return true; 5967132718Skan 5968132718Skan /* If this insn has a REG_EQUAL or REG_EQUIV note referencing a memory 5969132718Skan location aliased with X, then this insn kills X. */ 5970132718Skan note = find_reg_equal_equiv_note (insn); 5971132718Skan if (! note) 5972132718Skan return false; 5973132718Skan note = XEXP (note, 0); 5974132718Skan 5975132718Skan /* However, if the note represents a must alias rather than a may 5976132718Skan alias relationship, then it does not kill X. */ 5977132718Skan if (expr_equiv_p (note, x)) 5978132718Skan return false; 5979132718Skan 5980132718Skan /* See if there are any aliased loads in the note. */ 5981132718Skan return find_loads (note, x, after); 598290075Sobrien} 598390075Sobrien 5984132718Skan/* Returns true if the expression X is loaded or clobbered on or after INSN 5985132718Skan within basic block BB. REGS_SET_AFTER is bitmap of registers set in 5986132718Skan or after the insn. X_REGS is list of registers mentioned in X. If the store 5987132718Skan is killed, return the last insn in that it occurs in FAIL_INSN. */ 598890075Sobrien 5989132718Skanstatic bool 5990132718Skanstore_killed_after (rtx x, rtx x_regs, rtx insn, basic_block bb, 5991132718Skan int *regs_set_after, rtx *fail_insn) 599290075Sobrien{ 5993132718Skan rtx last = BB_END (bb), act; 5994117395Skan 5995132718Skan if (!store_ops_ok (x_regs, regs_set_after)) 5996132718Skan { 5997132718Skan /* We do not know where it will happen. */ 5998132718Skan if (fail_insn) 5999132718Skan *fail_insn = NULL_RTX; 6000132718Skan return true; 6001132718Skan } 600290075Sobrien 6003132718Skan /* Scan from the end, so that fail_insn is determined correctly. */ 6004132718Skan for (act = last; act != PREV_INSN (insn); act = PREV_INSN (act)) 6005132718Skan if (store_killed_in_insn (x, x_regs, act, false)) 6006132718Skan { 6007132718Skan if (fail_insn) 6008132718Skan *fail_insn = act; 6009132718Skan return true; 6010132718Skan } 601190075Sobrien 6012132718Skan return false; 601390075Sobrien} 601490075Sobrien 6015132718Skan/* Returns true if the expression X is loaded or clobbered on or before INSN 6016132718Skan within basic block BB. X_REGS is list of registers mentioned in X. 6017132718Skan REGS_SET_BEFORE is bitmap of registers set before or in this insn. */ 6018132718Skanstatic bool 6019132718Skanstore_killed_before (rtx x, rtx x_regs, rtx insn, basic_block bb, 6020132718Skan int *regs_set_before) 602190075Sobrien{ 6022132718Skan rtx first = BB_HEAD (bb); 602390075Sobrien 6024132718Skan if (!store_ops_ok (x_regs, regs_set_before)) 6025132718Skan return true; 6026117395Skan 6027132718Skan for ( ; insn != PREV_INSN (first); insn = PREV_INSN (insn)) 6028132718Skan if (store_killed_in_insn (x, x_regs, insn, true)) 6029132718Skan return true; 603090075Sobrien 6031132718Skan return false; 603290075Sobrien} 603390075Sobrien 6034132718Skan/* Fill in available, anticipatable, transparent and kill vectors in 6035132718Skan STORE_DATA, based on lists of available and anticipatable stores. */ 603690075Sobrienstatic void 6037132718Skanbuild_store_vectors (void) 603890075Sobrien{ 6039132718Skan basic_block bb; 6040132718Skan int *regs_set_in_block; 604190075Sobrien rtx insn, st; 604290075Sobrien struct ls_expr * ptr; 6043132718Skan unsigned regno; 604490075Sobrien 604590075Sobrien /* Build the gen_vector. This is any store in the table which is not killed 604690075Sobrien by aliasing later in its block. */ 6047132718Skan ae_gen = sbitmap_vector_alloc (last_basic_block, num_stores); 6048117395Skan sbitmap_vector_zero (ae_gen, last_basic_block); 604990075Sobrien 6050132718Skan st_antloc = sbitmap_vector_alloc (last_basic_block, num_stores); 6051117395Skan sbitmap_vector_zero (st_antloc, last_basic_block); 605290075Sobrien 605390075Sobrien for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr)) 6054117395Skan { 6055132718Skan for (st = AVAIL_STORE_LIST (ptr); st != NULL; st = XEXP (st, 1)) 605690075Sobrien { 605790075Sobrien insn = XEXP (st, 0); 605890075Sobrien bb = BLOCK_FOR_INSN (insn); 6059117395Skan 6060132718Skan /* If we've already seen an available expression in this block, 6061132718Skan we can delete this one (It occurs earlier in the block). We'll 6062132718Skan copy the SRC expression to an unused register in case there 6063132718Skan are any side effects. */ 6064132718Skan if (TEST_BIT (ae_gen[bb->index], ptr->index)) 606590075Sobrien { 6066132718Skan rtx r = gen_reg_rtx (GET_MODE (ptr->pattern)); 6067169689Skan if (dump_file) 6068169689Skan fprintf (dump_file, "Removing redundant store:\n"); 6069132718Skan replace_store_insn (r, XEXP (st, 0), bb, ptr); 6070132718Skan continue; 607190075Sobrien } 6072132718Skan SET_BIT (ae_gen[bb->index], ptr->index); 6073132718Skan } 6074117395Skan 6075132718Skan for (st = ANTIC_STORE_LIST (ptr); st != NULL; st = XEXP (st, 1)) 6076132718Skan { 6077132718Skan insn = XEXP (st, 0); 6078132718Skan bb = BLOCK_FOR_INSN (insn); 6079132718Skan SET_BIT (st_antloc[bb->index], ptr->index); 608090075Sobrien } 608190075Sobrien } 608290075Sobrien 6083132718Skan ae_kill = sbitmap_vector_alloc (last_basic_block, num_stores); 6084117395Skan sbitmap_vector_zero (ae_kill, last_basic_block); 608590075Sobrien 6086132718Skan transp = sbitmap_vector_alloc (last_basic_block, num_stores); 6087117395Skan sbitmap_vector_zero (transp, last_basic_block); 6088169689Skan regs_set_in_block = XNEWVEC (int, max_gcse_regno); 6089117395Skan 6090132718Skan FOR_EACH_BB (bb) 6091132718Skan { 6092132718Skan for (regno = 0; regno < max_gcse_regno; regno++) 6093132718Skan regs_set_in_block[regno] = TEST_BIT (reg_set_in_block[bb->index], regno); 609490075Sobrien 6095132718Skan for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr)) 6096132718Skan { 6097132718Skan if (store_killed_after (ptr->pattern, ptr->pattern_regs, BB_HEAD (bb), 6098132718Skan bb, regs_set_in_block, NULL)) 6099132718Skan { 6100132718Skan /* It should not be necessary to consider the expression 6101132718Skan killed if it is both anticipatable and available. */ 6102132718Skan if (!TEST_BIT (st_antloc[bb->index], ptr->index) 6103132718Skan || !TEST_BIT (ae_gen[bb->index], ptr->index)) 6104132718Skan SET_BIT (ae_kill[bb->index], ptr->index); 6105132718Skan } 6106132718Skan else 6107132718Skan SET_BIT (transp[bb->index], ptr->index); 6108132718Skan } 6109132718Skan } 6110132718Skan 6111132718Skan free (regs_set_in_block); 6112132718Skan 6113169689Skan if (dump_file) 611490075Sobrien { 6115169689Skan dump_sbitmap_vector (dump_file, "st_antloc", "", st_antloc, last_basic_block); 6116169689Skan dump_sbitmap_vector (dump_file, "st_kill", "", ae_kill, last_basic_block); 6117169689Skan dump_sbitmap_vector (dump_file, "Transpt", "", transp, last_basic_block); 6118169689Skan dump_sbitmap_vector (dump_file, "st_avloc", "", ae_gen, last_basic_block); 611990075Sobrien } 612090075Sobrien} 612190075Sobrien 6122132718Skan/* Insert an instruction at the beginning of a basic block, and update 6123132718Skan the BB_HEAD if needed. */ 612490075Sobrien 6125117395Skanstatic void 6126132718Skaninsert_insn_start_bb (rtx insn, basic_block bb) 612790075Sobrien{ 612890075Sobrien /* Insert at start of successor block. */ 6129132718Skan rtx prev = PREV_INSN (BB_HEAD (bb)); 6130132718Skan rtx before = BB_HEAD (bb); 613190075Sobrien while (before != 0) 613290075Sobrien { 6133169689Skan if (! LABEL_P (before) 6134169689Skan && (! NOTE_P (before) 613590075Sobrien || NOTE_LINE_NUMBER (before) != NOTE_INSN_BASIC_BLOCK)) 613690075Sobrien break; 613790075Sobrien prev = before; 6138132718Skan if (prev == BB_END (bb)) 613990075Sobrien break; 614090075Sobrien before = NEXT_INSN (before); 614190075Sobrien } 614290075Sobrien 6143132718Skan insn = emit_insn_after_noloc (insn, prev); 614490075Sobrien 6145169689Skan if (dump_file) 614690075Sobrien { 6147169689Skan fprintf (dump_file, "STORE_MOTION insert store at start of BB %d:\n", 614890075Sobrien bb->index); 6149169689Skan print_inline_rtx (dump_file, insn, 6); 6150169689Skan fprintf (dump_file, "\n"); 615190075Sobrien } 615290075Sobrien} 615390075Sobrien 615490075Sobrien/* This routine will insert a store on an edge. EXPR is the ldst entry for 6155117395Skan the memory reference, and E is the edge to insert it on. Returns nonzero 615690075Sobrien if an edge insertion was performed. */ 615790075Sobrien 615890075Sobrienstatic int 6159132718Skaninsert_store (struct ls_expr * expr, edge e) 616090075Sobrien{ 616190075Sobrien rtx reg, insn; 616290075Sobrien basic_block bb; 616390075Sobrien edge tmp; 6164169689Skan edge_iterator ei; 616590075Sobrien 616690075Sobrien /* We did all the deleted before this insert, so if we didn't delete a 616790075Sobrien store, then we haven't set the reaching reg yet either. */ 616890075Sobrien if (expr->reaching_reg == NULL_RTX) 616990075Sobrien return 0; 617090075Sobrien 6171132718Skan if (e->flags & EDGE_FAKE) 6172132718Skan return 0; 6173132718Skan 617490075Sobrien reg = expr->reaching_reg; 6175132718Skan insn = gen_move_insn (copy_rtx (expr->pattern), reg); 6176117395Skan 617790075Sobrien /* If we are inserting this expression on ALL predecessor edges of a BB, 617890075Sobrien insert it at the start of the BB, and reset the insert bits on the other 617990075Sobrien edges so we don't try to insert it on the other edges. */ 618090075Sobrien bb = e->dest; 6181169689Skan FOR_EACH_EDGE (tmp, ei, e->dest->preds) 6182132718Skan if (!(tmp->flags & EDGE_FAKE)) 6183132718Skan { 6184132718Skan int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest); 6185169689Skan 6186169689Skan gcc_assert (index != EDGE_INDEX_NO_EDGE); 6187132718Skan if (! TEST_BIT (pre_insert_map[index], expr->index)) 6188132718Skan break; 6189132718Skan } 619090075Sobrien 619190075Sobrien /* If tmp is NULL, we found an insertion on every edge, blank the 619290075Sobrien insertion vector for these edges, and insert at the start of the BB. */ 619390075Sobrien if (!tmp && bb != EXIT_BLOCK_PTR) 619490075Sobrien { 6195169689Skan FOR_EACH_EDGE (tmp, ei, e->dest->preds) 619690075Sobrien { 619790075Sobrien int index = EDGE_INDEX (edge_list, tmp->src, tmp->dest); 619890075Sobrien RESET_BIT (pre_insert_map[index], expr->index); 619990075Sobrien } 620090075Sobrien insert_insn_start_bb (insn, bb); 620190075Sobrien return 0; 620290075Sobrien } 6203117395Skan 6204169689Skan /* We can't put stores in the front of blocks pointed to by abnormal 6205169689Skan edges since that may put a store where one didn't used to be. */ 6206169689Skan gcc_assert (!(e->flags & EDGE_ABNORMAL)); 620790075Sobrien 620890075Sobrien insert_insn_on_edge (insn, e); 6209117395Skan 6210169689Skan if (dump_file) 621190075Sobrien { 6212169689Skan fprintf (dump_file, "STORE_MOTION insert insn on edge (%d, %d):\n", 621390075Sobrien e->src->index, e->dest->index); 6214169689Skan print_inline_rtx (dump_file, insn, 6); 6215169689Skan fprintf (dump_file, "\n"); 621690075Sobrien } 6217117395Skan 621890075Sobrien return 1; 621990075Sobrien} 622090075Sobrien 6221132718Skan/* Remove any REG_EQUAL or REG_EQUIV notes containing a reference to the 6222132718Skan memory location in SMEXPR set in basic block BB. 6223132718Skan 6224132718Skan This could be rather expensive. */ 6225132718Skan 6226132718Skanstatic void 6227132718Skanremove_reachable_equiv_notes (basic_block bb, struct ls_expr *smexpr) 6228132718Skan{ 6229169689Skan edge_iterator *stack, ei; 6230169689Skan int sp; 6231169689Skan edge act; 6232132718Skan sbitmap visited = sbitmap_alloc (last_basic_block); 6233132718Skan rtx last, insn, note; 6234132718Skan rtx mem = smexpr->pattern; 6235132718Skan 6236169689Skan stack = XNEWVEC (edge_iterator, n_basic_blocks); 6237169689Skan sp = 0; 6238169689Skan ei = ei_start (bb->succs); 6239169689Skan 6240132718Skan sbitmap_zero (visited); 6241132718Skan 6242169689Skan act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL); 6243132718Skan while (1) 6244132718Skan { 6245132718Skan if (!act) 6246132718Skan { 6247169689Skan if (!sp) 6248132718Skan { 6249132718Skan free (stack); 6250132718Skan sbitmap_free (visited); 6251132718Skan return; 6252132718Skan } 6253169689Skan act = ei_edge (stack[--sp]); 6254132718Skan } 6255132718Skan bb = act->dest; 6256169689Skan 6257132718Skan if (bb == EXIT_BLOCK_PTR 6258146895Skan || TEST_BIT (visited, bb->index)) 6259132718Skan { 6260169689Skan if (!ei_end_p (ei)) 6261169689Skan ei_next (&ei); 6262169689Skan act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL; 6263132718Skan continue; 6264132718Skan } 6265132718Skan SET_BIT (visited, bb->index); 6266132718Skan 6267132718Skan if (TEST_BIT (st_antloc[bb->index], smexpr->index)) 6268132718Skan { 6269132718Skan for (last = ANTIC_STORE_LIST (smexpr); 6270132718Skan BLOCK_FOR_INSN (XEXP (last, 0)) != bb; 6271132718Skan last = XEXP (last, 1)) 6272132718Skan continue; 6273132718Skan last = XEXP (last, 0); 6274132718Skan } 6275132718Skan else 6276132718Skan last = NEXT_INSN (BB_END (bb)); 6277169689Skan 6278132718Skan for (insn = BB_HEAD (bb); insn != last; insn = NEXT_INSN (insn)) 6279132718Skan if (INSN_P (insn)) 6280132718Skan { 6281132718Skan note = find_reg_equal_equiv_note (insn); 6282132718Skan if (!note || !expr_equiv_p (XEXP (note, 0), mem)) 6283132718Skan continue; 6284132718Skan 6285169689Skan if (dump_file) 6286169689Skan fprintf (dump_file, "STORE_MOTION drop REG_EQUAL note at insn %d:\n", 6287132718Skan INSN_UID (insn)); 6288132718Skan remove_note (insn, note); 6289132718Skan } 6290169689Skan 6291169689Skan if (!ei_end_p (ei)) 6292169689Skan ei_next (&ei); 6293169689Skan act = (! ei_end_p (ei)) ? ei_edge (ei) : NULL; 6294169689Skan 6295169689Skan if (EDGE_COUNT (bb->succs) > 0) 6296132718Skan { 6297132718Skan if (act) 6298169689Skan stack[sp++] = ei; 6299169689Skan ei = ei_start (bb->succs); 6300169689Skan act = (EDGE_COUNT (ei_container (ei)) > 0 ? EDGE_I (ei_container (ei), 0) : NULL); 6301132718Skan } 6302132718Skan } 6303132718Skan} 6304132718Skan 630590075Sobrien/* This routine will replace a store with a SET to a specified register. */ 630690075Sobrien 630790075Sobrienstatic void 6308132718Skanreplace_store_insn (rtx reg, rtx del, basic_block bb, struct ls_expr *smexpr) 630990075Sobrien{ 6310146895Skan rtx insn, mem, note, set, ptr, pair; 6311117395Skan 6312132718Skan mem = smexpr->pattern; 6313132718Skan insn = gen_move_insn (reg, SET_SRC (single_set (del))); 631490075Sobrien insn = emit_insn_after (insn, del); 6315117395Skan 6316169689Skan if (dump_file) 631790075Sobrien { 6318169689Skan fprintf (dump_file, 631990075Sobrien "STORE_MOTION delete insn in BB %d:\n ", bb->index); 6320169689Skan print_inline_rtx (dump_file, del, 6); 6321169689Skan fprintf (dump_file, "\nSTORE MOTION replaced with insn:\n "); 6322169689Skan print_inline_rtx (dump_file, insn, 6); 6323169689Skan fprintf (dump_file, "\n"); 632490075Sobrien } 6325117395Skan 6326132718Skan for (ptr = ANTIC_STORE_LIST (smexpr); ptr; ptr = XEXP (ptr, 1)) 6327132718Skan if (XEXP (ptr, 0) == del) 6328132718Skan { 6329132718Skan XEXP (ptr, 0) = insn; 6330132718Skan break; 6331132718Skan } 6332146895Skan 6333146895Skan /* Move the notes from the deleted insn to its replacement, and patch 6334146895Skan up the LIBCALL notes. */ 6335146895Skan REG_NOTES (insn) = REG_NOTES (del); 6336146895Skan 6337146895Skan note = find_reg_note (insn, REG_RETVAL, NULL_RTX); 6338146895Skan if (note) 6339146895Skan { 6340146895Skan pair = XEXP (note, 0); 6341146895Skan note = find_reg_note (pair, REG_LIBCALL, NULL_RTX); 6342146895Skan XEXP (note, 0) = insn; 6343146895Skan } 6344146895Skan note = find_reg_note (insn, REG_LIBCALL, NULL_RTX); 6345146895Skan if (note) 6346146895Skan { 6347146895Skan pair = XEXP (note, 0); 6348146895Skan note = find_reg_note (pair, REG_RETVAL, NULL_RTX); 6349146895Skan XEXP (note, 0) = insn; 6350146895Skan } 6351146895Skan 635290075Sobrien delete_insn (del); 6353132718Skan 6354132718Skan /* Now we must handle REG_EQUAL notes whose contents is equal to the mem; 6355132718Skan they are no longer accurate provided that they are reached by this 6356132718Skan definition, so drop them. */ 6357132718Skan for (; insn != NEXT_INSN (BB_END (bb)); insn = NEXT_INSN (insn)) 6358132718Skan if (INSN_P (insn)) 6359132718Skan { 6360132718Skan set = single_set (insn); 6361132718Skan if (!set) 6362132718Skan continue; 6363132718Skan if (expr_equiv_p (SET_DEST (set), mem)) 6364132718Skan return; 6365132718Skan note = find_reg_equal_equiv_note (insn); 6366132718Skan if (!note || !expr_equiv_p (XEXP (note, 0), mem)) 6367132718Skan continue; 6368132718Skan 6369169689Skan if (dump_file) 6370169689Skan fprintf (dump_file, "STORE_MOTION drop REG_EQUAL note at insn %d:\n", 6371132718Skan INSN_UID (insn)); 6372132718Skan remove_note (insn, note); 6373132718Skan } 6374132718Skan remove_reachable_equiv_notes (bb, smexpr); 637590075Sobrien} 637690075Sobrien 637790075Sobrien 637890075Sobrien/* Delete a store, but copy the value that would have been stored into 637990075Sobrien the reaching_reg for later storing. */ 638090075Sobrien 638190075Sobrienstatic void 6382132718Skandelete_store (struct ls_expr * expr, basic_block bb) 638390075Sobrien{ 638490075Sobrien rtx reg, i, del; 638590075Sobrien 638690075Sobrien if (expr->reaching_reg == NULL_RTX) 638790075Sobrien expr->reaching_reg = gen_reg_rtx (GET_MODE (expr->pattern)); 638890075Sobrien 638990075Sobrien reg = expr->reaching_reg; 6390117395Skan 639190075Sobrien for (i = AVAIL_STORE_LIST (expr); i; i = XEXP (i, 1)) 639290075Sobrien { 639390075Sobrien del = XEXP (i, 0); 639490075Sobrien if (BLOCK_FOR_INSN (del) == bb) 639590075Sobrien { 6396117395Skan /* We know there is only one since we deleted redundant 639790075Sobrien ones during the available computation. */ 6398132718Skan replace_store_insn (reg, del, bb, expr); 639990075Sobrien break; 640090075Sobrien } 640190075Sobrien } 640290075Sobrien} 640390075Sobrien 640490075Sobrien/* Free memory used by store motion. */ 640590075Sobrien 6406117395Skanstatic void 6407132718Skanfree_store_memory (void) 640890075Sobrien{ 640990075Sobrien free_ldst_mems (); 6410117395Skan 641190075Sobrien if (ae_gen) 641290075Sobrien sbitmap_vector_free (ae_gen); 641390075Sobrien if (ae_kill) 641490075Sobrien sbitmap_vector_free (ae_kill); 641590075Sobrien if (transp) 641690075Sobrien sbitmap_vector_free (transp); 641790075Sobrien if (st_antloc) 641890075Sobrien sbitmap_vector_free (st_antloc); 641990075Sobrien if (pre_insert_map) 642090075Sobrien sbitmap_vector_free (pre_insert_map); 642190075Sobrien if (pre_delete_map) 642290075Sobrien sbitmap_vector_free (pre_delete_map); 642390075Sobrien if (reg_set_in_block) 642490075Sobrien sbitmap_vector_free (reg_set_in_block); 6425117395Skan 642690075Sobrien ae_gen = ae_kill = transp = st_antloc = NULL; 642790075Sobrien pre_insert_map = pre_delete_map = reg_set_in_block = NULL; 642890075Sobrien} 642990075Sobrien 643090075Sobrien/* Perform store motion. Much like gcse, except we move expressions the 643190075Sobrien other way by looking at the flowgraph in reverse. */ 643290075Sobrien 643390075Sobrienstatic void 6434132718Skanstore_motion (void) 643590075Sobrien{ 6436117395Skan basic_block bb; 643790075Sobrien int x; 643890075Sobrien struct ls_expr * ptr; 643990075Sobrien int update_flow = 0; 644090075Sobrien 6441169689Skan if (dump_file) 644290075Sobrien { 6443169689Skan fprintf (dump_file, "before store motion\n"); 6444169689Skan print_rtl (dump_file, get_insns ()); 644590075Sobrien } 644690075Sobrien 644790075Sobrien init_alias_analysis (); 644890075Sobrien 6449132718Skan /* Find all the available and anticipatable stores. */ 645090075Sobrien num_stores = compute_store_table (); 645190075Sobrien if (num_stores == 0) 645290075Sobrien { 6453169689Skan htab_delete (pre_ldst_table); 6454169689Skan pre_ldst_table = NULL; 645590075Sobrien sbitmap_vector_free (reg_set_in_block); 645690075Sobrien end_alias_analysis (); 645790075Sobrien return; 645890075Sobrien } 645990075Sobrien 6460132718Skan /* Now compute kill & transp vectors. */ 6461132718Skan build_store_vectors (); 646290075Sobrien add_noreturn_fake_exit_edges (); 6463132718Skan connect_infinite_loops_to_exit (); 646490075Sobrien 6465169689Skan edge_list = pre_edge_rev_lcm (num_stores, transp, ae_gen, 6466117395Skan st_antloc, ae_kill, &pre_insert_map, 646790075Sobrien &pre_delete_map); 646890075Sobrien 646990075Sobrien /* Now we want to insert the new stores which are going to be needed. */ 647090075Sobrien for (ptr = first_ls_expr (); ptr != NULL; ptr = next_ls_expr (ptr)) 647190075Sobrien { 6472169689Skan /* If any of the edges we have above are abnormal, we can't move this 6473169689Skan store. */ 6474169689Skan for (x = NUM_EDGES (edge_list) - 1; x >= 0; x--) 6475169689Skan if (TEST_BIT (pre_insert_map[x], ptr->index) 6476169689Skan && (INDEX_EDGE (edge_list, x)->flags & EDGE_ABNORMAL)) 6477169689Skan break; 6478169689Skan 6479169689Skan if (x >= 0) 6480169689Skan { 6481169689Skan if (dump_file != NULL) 6482169689Skan fprintf (dump_file, 6483169689Skan "Can't replace store %d: abnormal edge from %d to %d\n", 6484169689Skan ptr->index, INDEX_EDGE (edge_list, x)->src->index, 6485169689Skan INDEX_EDGE (edge_list, x)->dest->index); 6486169689Skan continue; 6487169689Skan } 6488169689Skan 6489169689Skan /* Now we want to insert the new stores which are going to be needed. */ 6490169689Skan 6491117395Skan FOR_EACH_BB (bb) 6492117395Skan if (TEST_BIT (pre_delete_map[bb->index], ptr->index)) 6493117395Skan delete_store (ptr, bb); 649490075Sobrien 649590075Sobrien for (x = 0; x < NUM_EDGES (edge_list); x++) 649690075Sobrien if (TEST_BIT (pre_insert_map[x], ptr->index)) 649790075Sobrien update_flow |= insert_store (ptr, INDEX_EDGE (edge_list, x)); 649890075Sobrien } 649990075Sobrien 650090075Sobrien if (update_flow) 650190075Sobrien commit_edge_insertions (); 650290075Sobrien 650390075Sobrien free_store_memory (); 650490075Sobrien free_edge_list (edge_list); 6505169689Skan remove_fake_exit_edges (); 650690075Sobrien end_alias_analysis (); 650790075Sobrien} 6508117395Skan 6509132718Skan 6510132718Skan/* Entry point for jump bypassing optimization pass. */ 6511132718Skan 6512169689Skanstatic int 6513169689Skanbypass_jumps (void) 6514132718Skan{ 6515132718Skan int changed; 6516132718Skan 6517132718Skan /* We do not construct an accurate cfg in functions which call 6518132718Skan setjmp, so just punt to be safe. */ 6519132718Skan if (current_function_calls_setjmp) 6520132718Skan return 0; 6521132718Skan 6522132718Skan /* Identify the basic block information for this function, including 6523132718Skan successors and predecessors. */ 6524132718Skan max_gcse_regno = max_reg_num (); 6525132718Skan 6526169689Skan if (dump_file) 6527169689Skan dump_flow_info (dump_file, dump_flags); 6528132718Skan 6529132718Skan /* Return if there's nothing to do, or it is too expensive. */ 6530169689Skan if (n_basic_blocks <= NUM_FIXED_BLOCKS + 1 6531169689Skan || is_too_expensive (_ ("jump bypassing disabled"))) 6532132718Skan return 0; 6533132718Skan 6534132718Skan gcc_obstack_init (&gcse_obstack); 6535132718Skan bytes_used = 0; 6536132718Skan 6537132718Skan /* We need alias. */ 6538132718Skan init_alias_analysis (); 6539132718Skan 6540132718Skan /* Record where pseudo-registers are set. This data is kept accurate 6541132718Skan during each pass. ??? We could also record hard-reg information here 6542132718Skan [since it's unchanging], however it is currently done during hash table 6543132718Skan computation. 6544132718Skan 6545132718Skan It may be tempting to compute MEM set information here too, but MEM sets 6546132718Skan will be subject to code motion one day and thus we need to compute 6547132718Skan information about memory sets when we build the hash tables. */ 6548132718Skan 6549132718Skan alloc_reg_set_mem (max_gcse_regno); 6550169689Skan compute_sets (); 6551132718Skan 6552132718Skan max_gcse_regno = max_reg_num (); 6553169689Skan alloc_gcse_mem (); 6554169689Skan changed = one_cprop_pass (MAX_GCSE_PASSES + 2, true, true); 6555132718Skan free_gcse_mem (); 6556132718Skan 6557169689Skan if (dump_file) 6558132718Skan { 6559169689Skan fprintf (dump_file, "BYPASS of %s: %d basic blocks, ", 6560132718Skan current_function_name (), n_basic_blocks); 6561169689Skan fprintf (dump_file, "%d bytes\n\n", bytes_used); 6562132718Skan } 6563132718Skan 6564132718Skan obstack_free (&gcse_obstack, NULL); 6565132718Skan free_reg_set_mem (); 6566132718Skan 6567132718Skan /* We are finished with alias. */ 6568132718Skan end_alias_analysis (); 6569132718Skan allocate_reg_info (max_reg_num (), FALSE, FALSE); 6570132718Skan 6571132718Skan return changed; 6572132718Skan} 6573132718Skan 6574132718Skan/* Return true if the graph is too expensive to optimize. PASS is the 6575132718Skan optimization about to be performed. */ 6576132718Skan 6577132718Skanstatic bool 6578132718Skanis_too_expensive (const char *pass) 6579132718Skan{ 6580132718Skan /* Trying to perform global optimizations on flow graphs which have 6581132718Skan a high connectivity will take a long time and is unlikely to be 6582132718Skan particularly useful. 6583169689Skan 6584132718Skan In normal circumstances a cfg should have about twice as many 6585132718Skan edges as blocks. But we do not want to punish small functions 6586132718Skan which have a couple switch statements. Rather than simply 6587132718Skan threshold the number of blocks, uses something with a more 6588132718Skan graceful degradation. */ 6589132718Skan if (n_edges > 20000 + n_basic_blocks * 4) 6590132718Skan { 6591169689Skan warning (OPT_Wdisabled_optimization, 6592169689Skan "%s: %d basic blocks and %d edges/basic block", 6593169689Skan pass, n_basic_blocks, n_edges / n_basic_blocks); 6594169689Skan 6595132718Skan return true; 6596132718Skan } 6597132718Skan 6598132718Skan /* If allocating memory for the cprop bitmap would take up too much 6599132718Skan storage it's better just to disable the optimization. */ 6600132718Skan if ((n_basic_blocks 6601132718Skan * SBITMAP_SET_SIZE (max_reg_num ()) 6602132718Skan * sizeof (SBITMAP_ELT_TYPE)) > MAX_GCSE_MEMORY) 6603132718Skan { 6604169689Skan warning (OPT_Wdisabled_optimization, 6605169689Skan "%s: %d basic blocks and %d registers", 6606169689Skan pass, n_basic_blocks, max_reg_num ()); 6607132718Skan 6608132718Skan return true; 6609132718Skan } 6610132718Skan 6611132718Skan return false; 6612132718Skan} 6613169689Skan 6614169689Skanstatic bool 6615169689Skangate_handle_jump_bypass (void) 6616169689Skan{ 6617169689Skan return optimize > 0 && flag_gcse; 6618169689Skan} 6619132718Skan 6620169689Skan/* Perform jump bypassing and control flow optimizations. */ 6621169689Skanstatic unsigned int 6622169689Skanrest_of_handle_jump_bypass (void) 6623169689Skan{ 6624169689Skan cleanup_cfg (CLEANUP_EXPENSIVE); 6625169689Skan reg_scan (get_insns (), max_reg_num ()); 6626169689Skan 6627169689Skan if (bypass_jumps ()) 6628169689Skan { 6629169689Skan rebuild_jump_labels (get_insns ()); 6630169689Skan cleanup_cfg (CLEANUP_EXPENSIVE); 6631169689Skan delete_trivially_dead_insns (get_insns (), max_reg_num ()); 6632169689Skan } 6633169689Skan return 0; 6634169689Skan} 6635169689Skan 6636169689Skanstruct tree_opt_pass pass_jump_bypass = 6637169689Skan{ 6638169689Skan "bypass", /* name */ 6639169689Skan gate_handle_jump_bypass, /* gate */ 6640169689Skan rest_of_handle_jump_bypass, /* execute */ 6641169689Skan NULL, /* sub */ 6642169689Skan NULL, /* next */ 6643169689Skan 0, /* static_pass_number */ 6644169689Skan TV_BYPASS, /* tv_id */ 6645169689Skan 0, /* properties_required */ 6646169689Skan 0, /* properties_provided */ 6647169689Skan 0, /* properties_destroyed */ 6648169689Skan 0, /* todo_flags_start */ 6649169689Skan TODO_dump_func | 6650169689Skan TODO_ggc_collect | TODO_verify_flow, /* todo_flags_finish */ 6651169689Skan 'G' /* letter */ 6652169689Skan}; 6653169689Skan 6654169689Skan 6655169689Skanstatic bool 6656169689Skangate_handle_gcse (void) 6657169689Skan{ 6658169689Skan return optimize > 0 && flag_gcse; 6659169689Skan} 6660169689Skan 6661169689Skan 6662169689Skanstatic unsigned int 6663169689Skanrest_of_handle_gcse (void) 6664169689Skan{ 6665169689Skan int save_csb, save_cfj; 6666169689Skan int tem2 = 0, tem; 6667169689Skan 6668169689Skan tem = gcse_main (get_insns ()); 6669169689Skan rebuild_jump_labels (get_insns ()); 6670169689Skan delete_trivially_dead_insns (get_insns (), max_reg_num ()); 6671169689Skan 6672169689Skan save_csb = flag_cse_skip_blocks; 6673169689Skan save_cfj = flag_cse_follow_jumps; 6674169689Skan flag_cse_skip_blocks = flag_cse_follow_jumps = 0; 6675169689Skan 6676169689Skan /* If -fexpensive-optimizations, re-run CSE to clean up things done 6677169689Skan by gcse. */ 6678169689Skan if (flag_expensive_optimizations) 6679169689Skan { 6680169689Skan timevar_push (TV_CSE); 6681169689Skan reg_scan (get_insns (), max_reg_num ()); 6682169689Skan tem2 = cse_main (get_insns (), max_reg_num ()); 6683169689Skan purge_all_dead_edges (); 6684169689Skan delete_trivially_dead_insns (get_insns (), max_reg_num ()); 6685169689Skan timevar_pop (TV_CSE); 6686169689Skan cse_not_expected = !flag_rerun_cse_after_loop; 6687169689Skan } 6688169689Skan 6689169689Skan /* If gcse or cse altered any jumps, rerun jump optimizations to clean 6690169689Skan things up. */ 6691169689Skan if (tem || tem2) 6692169689Skan { 6693169689Skan timevar_push (TV_JUMP); 6694169689Skan rebuild_jump_labels (get_insns ()); 6695169689Skan delete_dead_jumptables (); 6696169689Skan cleanup_cfg (CLEANUP_EXPENSIVE); 6697169689Skan timevar_pop (TV_JUMP); 6698169689Skan } 6699169689Skan 6700169689Skan flag_cse_skip_blocks = save_csb; 6701169689Skan flag_cse_follow_jumps = save_cfj; 6702169689Skan return 0; 6703169689Skan} 6704169689Skan 6705169689Skanstruct tree_opt_pass pass_gcse = 6706169689Skan{ 6707169689Skan "gcse1", /* name */ 6708169689Skan gate_handle_gcse, /* gate */ 6709169689Skan rest_of_handle_gcse, /* execute */ 6710169689Skan NULL, /* sub */ 6711169689Skan NULL, /* next */ 6712169689Skan 0, /* static_pass_number */ 6713169689Skan TV_GCSE, /* tv_id */ 6714169689Skan 0, /* properties_required */ 6715169689Skan 0, /* properties_provided */ 6716169689Skan 0, /* properties_destroyed */ 6717169689Skan 0, /* todo_flags_start */ 6718169689Skan TODO_dump_func | 6719169689Skan TODO_verify_flow | TODO_ggc_collect, /* todo_flags_finish */ 6720169689Skan 'G' /* letter */ 6721169689Skan}; 6722169689Skan 6723169689Skan 6724117395Skan#include "gt-gcse.h" 6725