11debfc3dSmrg /* Rtl-level induction variable analysis.
2*8feb0f0bSmrg Copyright (C) 2004-2020 Free Software Foundation, Inc.
31debfc3dSmrg
41debfc3dSmrg This file is part of GCC.
51debfc3dSmrg
61debfc3dSmrg GCC is free software; you can redistribute it and/or modify it
71debfc3dSmrg under the terms of the GNU General Public License as published by the
81debfc3dSmrg Free Software Foundation; either version 3, or (at your option) any
91debfc3dSmrg later version.
101debfc3dSmrg
111debfc3dSmrg GCC is distributed in the hope that it will be useful, but WITHOUT
121debfc3dSmrg ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
131debfc3dSmrg FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
141debfc3dSmrg for more details.
151debfc3dSmrg
161debfc3dSmrg You should have received a copy of the GNU General Public License
171debfc3dSmrg along with GCC; see the file COPYING3. If not see
181debfc3dSmrg <http://www.gnu.org/licenses/>. */
191debfc3dSmrg
201debfc3dSmrg /* This is a simple analysis of induction variables of the loop. The major use
211debfc3dSmrg is for determining the number of iterations of a loop for loop unrolling,
221debfc3dSmrg doloop optimization and branch prediction. The iv information is computed
231debfc3dSmrg on demand.
241debfc3dSmrg
251debfc3dSmrg Induction variables are analyzed by walking the use-def chains. When
261debfc3dSmrg a basic induction variable (biv) is found, it is cached in the bivs
271debfc3dSmrg hash table. When register is proved to be a biv, its description
281debfc3dSmrg is stored to DF_REF_DATA of the def reference.
291debfc3dSmrg
301debfc3dSmrg The analysis works always with one loop -- you must call
311debfc3dSmrg iv_analysis_loop_init (loop) for it. All the other functions then work with
321debfc3dSmrg this loop. When you need to work with another loop, just call
331debfc3dSmrg iv_analysis_loop_init for it. When you no longer need iv analysis, call
341debfc3dSmrg iv_analysis_done () to clean up the memory.
351debfc3dSmrg
361debfc3dSmrg The available functions are:
371debfc3dSmrg
38a2dc1f3fSmrg iv_analyze (insn, mode, reg, iv): Stores the description of the induction
39a2dc1f3fSmrg variable corresponding to the use of register REG in INSN to IV, given
40a2dc1f3fSmrg that REG has mode MODE. Returns true if REG is an induction variable
41a2dc1f3fSmrg in INSN. false otherwise. If a use of REG is not found in INSN,
42a2dc1f3fSmrg the following insns are scanned (so that we may call this function
43a2dc1f3fSmrg on insns returned by get_condition).
441debfc3dSmrg iv_analyze_result (insn, def, iv): Stores to IV the description of the iv
451debfc3dSmrg corresponding to DEF, which is a register defined in INSN.
46a2dc1f3fSmrg iv_analyze_expr (insn, mode, expr, iv): Stores to IV the description of iv
471debfc3dSmrg corresponding to expression EXPR evaluated at INSN. All registers used bu
48a2dc1f3fSmrg EXPR must also be used in INSN. MODE is the mode of EXPR.
491debfc3dSmrg */
501debfc3dSmrg
511debfc3dSmrg #include "config.h"
521debfc3dSmrg #include "system.h"
531debfc3dSmrg #include "coretypes.h"
541debfc3dSmrg #include "backend.h"
551debfc3dSmrg #include "rtl.h"
561debfc3dSmrg #include "df.h"
571debfc3dSmrg #include "memmodel.h"
581debfc3dSmrg #include "emit-rtl.h"
591debfc3dSmrg #include "diagnostic-core.h"
601debfc3dSmrg #include "cfgloop.h"
611debfc3dSmrg #include "intl.h"
621debfc3dSmrg #include "dumpfile.h"
631debfc3dSmrg #include "rtl-iter.h"
64*8feb0f0bSmrg #include "tree-ssa-loop-niter.h"
65*8feb0f0bSmrg #include "regs.h"
66*8feb0f0bSmrg #include "function-abi.h"
671debfc3dSmrg
681debfc3dSmrg /* Possible return values of iv_get_reaching_def. */
691debfc3dSmrg
701debfc3dSmrg enum iv_grd_result
711debfc3dSmrg {
721debfc3dSmrg /* More than one reaching def, or reaching def that does not
731debfc3dSmrg dominate the use. */
741debfc3dSmrg GRD_INVALID,
751debfc3dSmrg
761debfc3dSmrg /* The use is trivial invariant of the loop, i.e. is not changed
771debfc3dSmrg inside the loop. */
781debfc3dSmrg GRD_INVARIANT,
791debfc3dSmrg
801debfc3dSmrg /* The use is reached by initial value and a value from the
811debfc3dSmrg previous iteration. */
821debfc3dSmrg GRD_MAYBE_BIV,
831debfc3dSmrg
841debfc3dSmrg /* The use has single dominating def. */
851debfc3dSmrg GRD_SINGLE_DOM
861debfc3dSmrg };
871debfc3dSmrg
881debfc3dSmrg /* Information about a biv. */
891debfc3dSmrg
90*8feb0f0bSmrg class biv_entry
911debfc3dSmrg {
92*8feb0f0bSmrg public:
931debfc3dSmrg unsigned regno; /* The register of the biv. */
94*8feb0f0bSmrg class rtx_iv iv; /* Value of the biv. */
951debfc3dSmrg };
961debfc3dSmrg
971debfc3dSmrg static bool clean_slate = true;
981debfc3dSmrg
991debfc3dSmrg static unsigned int iv_ref_table_size = 0;
1001debfc3dSmrg
1011debfc3dSmrg /* Table of rtx_ivs indexed by the df_ref uid field. */
102*8feb0f0bSmrg static class rtx_iv ** iv_ref_table;
1031debfc3dSmrg
1041debfc3dSmrg /* Induction variable stored at the reference. */
1051debfc3dSmrg #define DF_REF_IV(REF) iv_ref_table[DF_REF_ID (REF)]
1061debfc3dSmrg #define DF_REF_IV_SET(REF, IV) iv_ref_table[DF_REF_ID (REF)] = (IV)
1071debfc3dSmrg
1081debfc3dSmrg /* The current loop. */
1091debfc3dSmrg
110*8feb0f0bSmrg static class loop *current_loop;
1111debfc3dSmrg
1121debfc3dSmrg /* Hashtable helper. */
1131debfc3dSmrg
1141debfc3dSmrg struct biv_entry_hasher : free_ptr_hash <biv_entry>
1151debfc3dSmrg {
1161debfc3dSmrg typedef rtx_def *compare_type;
1171debfc3dSmrg static inline hashval_t hash (const biv_entry *);
1181debfc3dSmrg static inline bool equal (const biv_entry *, const rtx_def *);
1191debfc3dSmrg };
1201debfc3dSmrg
1211debfc3dSmrg /* Returns hash value for biv B. */
1221debfc3dSmrg
1231debfc3dSmrg inline hashval_t
hash(const biv_entry * b)1241debfc3dSmrg biv_entry_hasher::hash (const biv_entry *b)
1251debfc3dSmrg {
1261debfc3dSmrg return b->regno;
1271debfc3dSmrg }
1281debfc3dSmrg
1291debfc3dSmrg /* Compares biv B and register R. */
1301debfc3dSmrg
1311debfc3dSmrg inline bool
equal(const biv_entry * b,const rtx_def * r)1321debfc3dSmrg biv_entry_hasher::equal (const biv_entry *b, const rtx_def *r)
1331debfc3dSmrg {
1341debfc3dSmrg return b->regno == REGNO (r);
1351debfc3dSmrg }
1361debfc3dSmrg
1371debfc3dSmrg /* Bivs of the current loop. */
1381debfc3dSmrg
1391debfc3dSmrg static hash_table<biv_entry_hasher> *bivs;
1401debfc3dSmrg
141*8feb0f0bSmrg static bool iv_analyze_op (rtx_insn *, scalar_int_mode, rtx, class rtx_iv *);
1421debfc3dSmrg
1431debfc3dSmrg /* Return the RTX code corresponding to the IV extend code EXTEND. */
1441debfc3dSmrg static inline enum rtx_code
iv_extend_to_rtx_code(enum iv_extend_code extend)1451debfc3dSmrg iv_extend_to_rtx_code (enum iv_extend_code extend)
1461debfc3dSmrg {
1471debfc3dSmrg switch (extend)
1481debfc3dSmrg {
1491debfc3dSmrg case IV_SIGN_EXTEND:
1501debfc3dSmrg return SIGN_EXTEND;
1511debfc3dSmrg case IV_ZERO_EXTEND:
1521debfc3dSmrg return ZERO_EXTEND;
1531debfc3dSmrg case IV_UNKNOWN_EXTEND:
1541debfc3dSmrg return UNKNOWN;
1551debfc3dSmrg }
1561debfc3dSmrg gcc_unreachable ();
1571debfc3dSmrg }
1581debfc3dSmrg
1591debfc3dSmrg /* Dumps information about IV to FILE. */
1601debfc3dSmrg
161*8feb0f0bSmrg extern void dump_iv_info (FILE *, class rtx_iv *);
1621debfc3dSmrg void
dump_iv_info(FILE * file,class rtx_iv * iv)163*8feb0f0bSmrg dump_iv_info (FILE *file, class rtx_iv *iv)
1641debfc3dSmrg {
1651debfc3dSmrg if (!iv->base)
1661debfc3dSmrg {
1671debfc3dSmrg fprintf (file, "not simple");
1681debfc3dSmrg return;
1691debfc3dSmrg }
1701debfc3dSmrg
1711debfc3dSmrg if (iv->step == const0_rtx
1721debfc3dSmrg && !iv->first_special)
1731debfc3dSmrg fprintf (file, "invariant ");
1741debfc3dSmrg
1751debfc3dSmrg print_rtl (file, iv->base);
1761debfc3dSmrg if (iv->step != const0_rtx)
1771debfc3dSmrg {
1781debfc3dSmrg fprintf (file, " + ");
1791debfc3dSmrg print_rtl (file, iv->step);
1801debfc3dSmrg fprintf (file, " * iteration");
1811debfc3dSmrg }
1821debfc3dSmrg fprintf (file, " (in %s)", GET_MODE_NAME (iv->mode));
1831debfc3dSmrg
1841debfc3dSmrg if (iv->mode != iv->extend_mode)
1851debfc3dSmrg fprintf (file, " %s to %s",
1861debfc3dSmrg rtx_name[iv_extend_to_rtx_code (iv->extend)],
1871debfc3dSmrg GET_MODE_NAME (iv->extend_mode));
1881debfc3dSmrg
1891debfc3dSmrg if (iv->mult != const1_rtx)
1901debfc3dSmrg {
1911debfc3dSmrg fprintf (file, " * ");
1921debfc3dSmrg print_rtl (file, iv->mult);
1931debfc3dSmrg }
1941debfc3dSmrg if (iv->delta != const0_rtx)
1951debfc3dSmrg {
1961debfc3dSmrg fprintf (file, " + ");
1971debfc3dSmrg print_rtl (file, iv->delta);
1981debfc3dSmrg }
1991debfc3dSmrg if (iv->first_special)
2001debfc3dSmrg fprintf (file, " (first special)");
2011debfc3dSmrg }
2021debfc3dSmrg
2031debfc3dSmrg static void
check_iv_ref_table_size(void)2041debfc3dSmrg check_iv_ref_table_size (void)
2051debfc3dSmrg {
2061debfc3dSmrg if (iv_ref_table_size < DF_DEFS_TABLE_SIZE ())
2071debfc3dSmrg {
2081debfc3dSmrg unsigned int new_size = DF_DEFS_TABLE_SIZE () + (DF_DEFS_TABLE_SIZE () / 4);
209*8feb0f0bSmrg iv_ref_table = XRESIZEVEC (class rtx_iv *, iv_ref_table, new_size);
2101debfc3dSmrg memset (&iv_ref_table[iv_ref_table_size], 0,
211*8feb0f0bSmrg (new_size - iv_ref_table_size) * sizeof (class rtx_iv *));
2121debfc3dSmrg iv_ref_table_size = new_size;
2131debfc3dSmrg }
2141debfc3dSmrg }
2151debfc3dSmrg
2161debfc3dSmrg
2171debfc3dSmrg /* Checks whether REG is a well-behaved register. */
2181debfc3dSmrg
2191debfc3dSmrg static bool
simple_reg_p(rtx reg)2201debfc3dSmrg simple_reg_p (rtx reg)
2211debfc3dSmrg {
2221debfc3dSmrg unsigned r;
2231debfc3dSmrg
2241debfc3dSmrg if (GET_CODE (reg) == SUBREG)
2251debfc3dSmrg {
2261debfc3dSmrg if (!subreg_lowpart_p (reg))
2271debfc3dSmrg return false;
2281debfc3dSmrg reg = SUBREG_REG (reg);
2291debfc3dSmrg }
2301debfc3dSmrg
2311debfc3dSmrg if (!REG_P (reg))
2321debfc3dSmrg return false;
2331debfc3dSmrg
2341debfc3dSmrg r = REGNO (reg);
2351debfc3dSmrg if (HARD_REGISTER_NUM_P (r))
2361debfc3dSmrg return false;
2371debfc3dSmrg
2381debfc3dSmrg if (GET_MODE_CLASS (GET_MODE (reg)) != MODE_INT)
2391debfc3dSmrg return false;
2401debfc3dSmrg
2411debfc3dSmrg return true;
2421debfc3dSmrg }
2431debfc3dSmrg
2441debfc3dSmrg /* Clears the information about ivs stored in df. */
2451debfc3dSmrg
2461debfc3dSmrg static void
clear_iv_info(void)2471debfc3dSmrg clear_iv_info (void)
2481debfc3dSmrg {
2491debfc3dSmrg unsigned i, n_defs = DF_DEFS_TABLE_SIZE ();
250*8feb0f0bSmrg class rtx_iv *iv;
2511debfc3dSmrg
2521debfc3dSmrg check_iv_ref_table_size ();
2531debfc3dSmrg for (i = 0; i < n_defs; i++)
2541debfc3dSmrg {
2551debfc3dSmrg iv = iv_ref_table[i];
2561debfc3dSmrg if (iv)
2571debfc3dSmrg {
2581debfc3dSmrg free (iv);
2591debfc3dSmrg iv_ref_table[i] = NULL;
2601debfc3dSmrg }
2611debfc3dSmrg }
2621debfc3dSmrg
2631debfc3dSmrg bivs->empty ();
2641debfc3dSmrg }
2651debfc3dSmrg
2661debfc3dSmrg
2671debfc3dSmrg /* Prepare the data for an induction variable analysis of a LOOP. */
2681debfc3dSmrg
2691debfc3dSmrg void
iv_analysis_loop_init(class loop * loop)270*8feb0f0bSmrg iv_analysis_loop_init (class loop *loop)
2711debfc3dSmrg {
2721debfc3dSmrg current_loop = loop;
2731debfc3dSmrg
2741debfc3dSmrg /* Clear the information from the analysis of the previous loop. */
2751debfc3dSmrg if (clean_slate)
2761debfc3dSmrg {
2771debfc3dSmrg df_set_flags (DF_EQ_NOTES + DF_DEFER_INSN_RESCAN);
2781debfc3dSmrg bivs = new hash_table<biv_entry_hasher> (10);
2791debfc3dSmrg clean_slate = false;
2801debfc3dSmrg }
2811debfc3dSmrg else
2821debfc3dSmrg clear_iv_info ();
2831debfc3dSmrg
2841debfc3dSmrg /* Get rid of the ud chains before processing the rescans. Then add
2851debfc3dSmrg the problem back. */
2861debfc3dSmrg df_remove_problem (df_chain);
2871debfc3dSmrg df_process_deferred_rescans ();
2881debfc3dSmrg df_set_flags (DF_RD_PRUNE_DEAD_DEFS);
2891debfc3dSmrg df_chain_add_problem (DF_UD_CHAIN);
2901debfc3dSmrg df_note_add_problem ();
2911debfc3dSmrg df_analyze_loop (loop);
2921debfc3dSmrg if (dump_file)
2931debfc3dSmrg df_dump_region (dump_file);
2941debfc3dSmrg
2951debfc3dSmrg check_iv_ref_table_size ();
2961debfc3dSmrg }
2971debfc3dSmrg
2981debfc3dSmrg /* Finds the definition of REG that dominates loop latch and stores
2991debfc3dSmrg it to DEF. Returns false if there is not a single definition
3001debfc3dSmrg dominating the latch. If REG has no definition in loop, DEF
3011debfc3dSmrg is set to NULL and true is returned. */
3021debfc3dSmrg
3031debfc3dSmrg static bool
latch_dominating_def(rtx reg,df_ref * def)3041debfc3dSmrg latch_dominating_def (rtx reg, df_ref *def)
3051debfc3dSmrg {
3061debfc3dSmrg df_ref single_rd = NULL, adef;
3071debfc3dSmrg unsigned regno = REGNO (reg);
308*8feb0f0bSmrg class df_rd_bb_info *bb_info = DF_RD_BB_INFO (current_loop->latch);
3091debfc3dSmrg
3101debfc3dSmrg for (adef = DF_REG_DEF_CHAIN (regno); adef; adef = DF_REF_NEXT_REG (adef))
3111debfc3dSmrg {
3121debfc3dSmrg if (!bitmap_bit_p (df->blocks_to_analyze, DF_REF_BBNO (adef))
3131debfc3dSmrg || !bitmap_bit_p (&bb_info->out, DF_REF_ID (adef)))
3141debfc3dSmrg continue;
3151debfc3dSmrg
3161debfc3dSmrg /* More than one reaching definition. */
3171debfc3dSmrg if (single_rd)
3181debfc3dSmrg return false;
3191debfc3dSmrg
3201debfc3dSmrg if (!just_once_each_iteration_p (current_loop, DF_REF_BB (adef)))
3211debfc3dSmrg return false;
3221debfc3dSmrg
3231debfc3dSmrg single_rd = adef;
3241debfc3dSmrg }
3251debfc3dSmrg
3261debfc3dSmrg *def = single_rd;
3271debfc3dSmrg return true;
3281debfc3dSmrg }
3291debfc3dSmrg
3301debfc3dSmrg /* Gets definition of REG reaching its use in INSN and stores it to DEF. */
3311debfc3dSmrg
3321debfc3dSmrg static enum iv_grd_result
iv_get_reaching_def(rtx_insn * insn,rtx reg,df_ref * def)3331debfc3dSmrg iv_get_reaching_def (rtx_insn *insn, rtx reg, df_ref *def)
3341debfc3dSmrg {
3351debfc3dSmrg df_ref use, adef;
3361debfc3dSmrg basic_block def_bb, use_bb;
3371debfc3dSmrg rtx_insn *def_insn;
3381debfc3dSmrg bool dom_p;
3391debfc3dSmrg
3401debfc3dSmrg *def = NULL;
3411debfc3dSmrg if (!simple_reg_p (reg))
3421debfc3dSmrg return GRD_INVALID;
3431debfc3dSmrg if (GET_CODE (reg) == SUBREG)
3441debfc3dSmrg reg = SUBREG_REG (reg);
3451debfc3dSmrg gcc_assert (REG_P (reg));
3461debfc3dSmrg
3471debfc3dSmrg use = df_find_use (insn, reg);
3481debfc3dSmrg gcc_assert (use != NULL);
3491debfc3dSmrg
3501debfc3dSmrg if (!DF_REF_CHAIN (use))
3511debfc3dSmrg return GRD_INVARIANT;
3521debfc3dSmrg
3531debfc3dSmrg /* More than one reaching def. */
3541debfc3dSmrg if (DF_REF_CHAIN (use)->next)
3551debfc3dSmrg return GRD_INVALID;
3561debfc3dSmrg
3571debfc3dSmrg adef = DF_REF_CHAIN (use)->ref;
3581debfc3dSmrg
3591debfc3dSmrg /* We do not handle setting only part of the register. */
3601debfc3dSmrg if (DF_REF_FLAGS (adef) & DF_REF_READ_WRITE)
3611debfc3dSmrg return GRD_INVALID;
3621debfc3dSmrg
3631debfc3dSmrg def_insn = DF_REF_INSN (adef);
3641debfc3dSmrg def_bb = DF_REF_BB (adef);
3651debfc3dSmrg use_bb = BLOCK_FOR_INSN (insn);
3661debfc3dSmrg
3671debfc3dSmrg if (use_bb == def_bb)
3681debfc3dSmrg dom_p = (DF_INSN_LUID (def_insn) < DF_INSN_LUID (insn));
3691debfc3dSmrg else
3701debfc3dSmrg dom_p = dominated_by_p (CDI_DOMINATORS, use_bb, def_bb);
3711debfc3dSmrg
3721debfc3dSmrg if (dom_p)
3731debfc3dSmrg {
3741debfc3dSmrg *def = adef;
3751debfc3dSmrg return GRD_SINGLE_DOM;
3761debfc3dSmrg }
3771debfc3dSmrg
3781debfc3dSmrg /* The definition does not dominate the use. This is still OK if
3791debfc3dSmrg this may be a use of a biv, i.e. if the def_bb dominates loop
3801debfc3dSmrg latch. */
3811debfc3dSmrg if (just_once_each_iteration_p (current_loop, def_bb))
3821debfc3dSmrg return GRD_MAYBE_BIV;
3831debfc3dSmrg
3841debfc3dSmrg return GRD_INVALID;
3851debfc3dSmrg }
3861debfc3dSmrg
3871debfc3dSmrg /* Sets IV to invariant CST in MODE. Always returns true (just for
3881debfc3dSmrg consistency with other iv manipulation functions that may fail). */
3891debfc3dSmrg
3901debfc3dSmrg static bool
iv_constant(class rtx_iv * iv,scalar_int_mode mode,rtx cst)391*8feb0f0bSmrg iv_constant (class rtx_iv *iv, scalar_int_mode mode, rtx cst)
3921debfc3dSmrg {
3931debfc3dSmrg iv->mode = mode;
3941debfc3dSmrg iv->base = cst;
3951debfc3dSmrg iv->step = const0_rtx;
3961debfc3dSmrg iv->first_special = false;
3971debfc3dSmrg iv->extend = IV_UNKNOWN_EXTEND;
3981debfc3dSmrg iv->extend_mode = iv->mode;
3991debfc3dSmrg iv->delta = const0_rtx;
4001debfc3dSmrg iv->mult = const1_rtx;
4011debfc3dSmrg
4021debfc3dSmrg return true;
4031debfc3dSmrg }
4041debfc3dSmrg
4051debfc3dSmrg /* Evaluates application of subreg to MODE on IV. */
4061debfc3dSmrg
4071debfc3dSmrg static bool
iv_subreg(class rtx_iv * iv,scalar_int_mode mode)408*8feb0f0bSmrg iv_subreg (class rtx_iv *iv, scalar_int_mode mode)
4091debfc3dSmrg {
4101debfc3dSmrg /* If iv is invariant, just calculate the new value. */
4111debfc3dSmrg if (iv->step == const0_rtx
4121debfc3dSmrg && !iv->first_special)
4131debfc3dSmrg {
4141debfc3dSmrg rtx val = get_iv_value (iv, const0_rtx);
4151debfc3dSmrg val = lowpart_subreg (mode, val,
4161debfc3dSmrg iv->extend == IV_UNKNOWN_EXTEND
4171debfc3dSmrg ? iv->mode : iv->extend_mode);
4181debfc3dSmrg
4191debfc3dSmrg iv->base = val;
4201debfc3dSmrg iv->extend = IV_UNKNOWN_EXTEND;
4211debfc3dSmrg iv->mode = iv->extend_mode = mode;
4221debfc3dSmrg iv->delta = const0_rtx;
4231debfc3dSmrg iv->mult = const1_rtx;
4241debfc3dSmrg return true;
4251debfc3dSmrg }
4261debfc3dSmrg
4271debfc3dSmrg if (iv->extend_mode == mode)
4281debfc3dSmrg return true;
4291debfc3dSmrg
4301debfc3dSmrg if (GET_MODE_BITSIZE (mode) > GET_MODE_BITSIZE (iv->mode))
4311debfc3dSmrg return false;
4321debfc3dSmrg
4331debfc3dSmrg iv->extend = IV_UNKNOWN_EXTEND;
4341debfc3dSmrg iv->mode = mode;
4351debfc3dSmrg
4361debfc3dSmrg iv->base = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta,
4371debfc3dSmrg simplify_gen_binary (MULT, iv->extend_mode,
4381debfc3dSmrg iv->base, iv->mult));
4391debfc3dSmrg iv->step = simplify_gen_binary (MULT, iv->extend_mode, iv->step, iv->mult);
4401debfc3dSmrg iv->mult = const1_rtx;
4411debfc3dSmrg iv->delta = const0_rtx;
4421debfc3dSmrg iv->first_special = false;
4431debfc3dSmrg
4441debfc3dSmrg return true;
4451debfc3dSmrg }
4461debfc3dSmrg
4471debfc3dSmrg /* Evaluates application of EXTEND to MODE on IV. */
4481debfc3dSmrg
4491debfc3dSmrg static bool
iv_extend(class rtx_iv * iv,enum iv_extend_code extend,scalar_int_mode mode)450*8feb0f0bSmrg iv_extend (class rtx_iv *iv, enum iv_extend_code extend, scalar_int_mode mode)
4511debfc3dSmrg {
4521debfc3dSmrg /* If iv is invariant, just calculate the new value. */
4531debfc3dSmrg if (iv->step == const0_rtx
4541debfc3dSmrg && !iv->first_special)
4551debfc3dSmrg {
4561debfc3dSmrg rtx val = get_iv_value (iv, const0_rtx);
4571debfc3dSmrg if (iv->extend_mode != iv->mode
4581debfc3dSmrg && iv->extend != IV_UNKNOWN_EXTEND
4591debfc3dSmrg && iv->extend != extend)
4601debfc3dSmrg val = lowpart_subreg (iv->mode, val, iv->extend_mode);
4611debfc3dSmrg val = simplify_gen_unary (iv_extend_to_rtx_code (extend), mode,
4621debfc3dSmrg val,
4631debfc3dSmrg iv->extend == extend
4641debfc3dSmrg ? iv->extend_mode : iv->mode);
4651debfc3dSmrg iv->base = val;
4661debfc3dSmrg iv->extend = IV_UNKNOWN_EXTEND;
4671debfc3dSmrg iv->mode = iv->extend_mode = mode;
4681debfc3dSmrg iv->delta = const0_rtx;
4691debfc3dSmrg iv->mult = const1_rtx;
4701debfc3dSmrg return true;
4711debfc3dSmrg }
4721debfc3dSmrg
4731debfc3dSmrg if (mode != iv->extend_mode)
4741debfc3dSmrg return false;
4751debfc3dSmrg
4761debfc3dSmrg if (iv->extend != IV_UNKNOWN_EXTEND
4771debfc3dSmrg && iv->extend != extend)
4781debfc3dSmrg return false;
4791debfc3dSmrg
4801debfc3dSmrg iv->extend = extend;
4811debfc3dSmrg
4821debfc3dSmrg return true;
4831debfc3dSmrg }
4841debfc3dSmrg
4851debfc3dSmrg /* Evaluates negation of IV. */
4861debfc3dSmrg
4871debfc3dSmrg static bool
iv_neg(class rtx_iv * iv)488*8feb0f0bSmrg iv_neg (class rtx_iv *iv)
4891debfc3dSmrg {
4901debfc3dSmrg if (iv->extend == IV_UNKNOWN_EXTEND)
4911debfc3dSmrg {
4921debfc3dSmrg iv->base = simplify_gen_unary (NEG, iv->extend_mode,
4931debfc3dSmrg iv->base, iv->extend_mode);
4941debfc3dSmrg iv->step = simplify_gen_unary (NEG, iv->extend_mode,
4951debfc3dSmrg iv->step, iv->extend_mode);
4961debfc3dSmrg }
4971debfc3dSmrg else
4981debfc3dSmrg {
4991debfc3dSmrg iv->delta = simplify_gen_unary (NEG, iv->extend_mode,
5001debfc3dSmrg iv->delta, iv->extend_mode);
5011debfc3dSmrg iv->mult = simplify_gen_unary (NEG, iv->extend_mode,
5021debfc3dSmrg iv->mult, iv->extend_mode);
5031debfc3dSmrg }
5041debfc3dSmrg
5051debfc3dSmrg return true;
5061debfc3dSmrg }
5071debfc3dSmrg
5081debfc3dSmrg /* Evaluates addition or subtraction (according to OP) of IV1 to IV0. */
5091debfc3dSmrg
5101debfc3dSmrg static bool
iv_add(class rtx_iv * iv0,class rtx_iv * iv1,enum rtx_code op)511*8feb0f0bSmrg iv_add (class rtx_iv *iv0, class rtx_iv *iv1, enum rtx_code op)
5121debfc3dSmrg {
513a2dc1f3fSmrg scalar_int_mode mode;
5141debfc3dSmrg rtx arg;
5151debfc3dSmrg
5161debfc3dSmrg /* Extend the constant to extend_mode of the other operand if necessary. */
5171debfc3dSmrg if (iv0->extend == IV_UNKNOWN_EXTEND
5181debfc3dSmrg && iv0->mode == iv0->extend_mode
5191debfc3dSmrg && iv0->step == const0_rtx
5201debfc3dSmrg && GET_MODE_SIZE (iv0->extend_mode) < GET_MODE_SIZE (iv1->extend_mode))
5211debfc3dSmrg {
5221debfc3dSmrg iv0->extend_mode = iv1->extend_mode;
5231debfc3dSmrg iv0->base = simplify_gen_unary (ZERO_EXTEND, iv0->extend_mode,
5241debfc3dSmrg iv0->base, iv0->mode);
5251debfc3dSmrg }
5261debfc3dSmrg if (iv1->extend == IV_UNKNOWN_EXTEND
5271debfc3dSmrg && iv1->mode == iv1->extend_mode
5281debfc3dSmrg && iv1->step == const0_rtx
5291debfc3dSmrg && GET_MODE_SIZE (iv1->extend_mode) < GET_MODE_SIZE (iv0->extend_mode))
5301debfc3dSmrg {
5311debfc3dSmrg iv1->extend_mode = iv0->extend_mode;
5321debfc3dSmrg iv1->base = simplify_gen_unary (ZERO_EXTEND, iv1->extend_mode,
5331debfc3dSmrg iv1->base, iv1->mode);
5341debfc3dSmrg }
5351debfc3dSmrg
5361debfc3dSmrg mode = iv0->extend_mode;
5371debfc3dSmrg if (mode != iv1->extend_mode)
5381debfc3dSmrg return false;
5391debfc3dSmrg
5401debfc3dSmrg if (iv0->extend == IV_UNKNOWN_EXTEND
5411debfc3dSmrg && iv1->extend == IV_UNKNOWN_EXTEND)
5421debfc3dSmrg {
5431debfc3dSmrg if (iv0->mode != iv1->mode)
5441debfc3dSmrg return false;
5451debfc3dSmrg
5461debfc3dSmrg iv0->base = simplify_gen_binary (op, mode, iv0->base, iv1->base);
5471debfc3dSmrg iv0->step = simplify_gen_binary (op, mode, iv0->step, iv1->step);
5481debfc3dSmrg
5491debfc3dSmrg return true;
5501debfc3dSmrg }
5511debfc3dSmrg
5521debfc3dSmrg /* Handle addition of constant. */
5531debfc3dSmrg if (iv1->extend == IV_UNKNOWN_EXTEND
5541debfc3dSmrg && iv1->mode == mode
5551debfc3dSmrg && iv1->step == const0_rtx)
5561debfc3dSmrg {
5571debfc3dSmrg iv0->delta = simplify_gen_binary (op, mode, iv0->delta, iv1->base);
5581debfc3dSmrg return true;
5591debfc3dSmrg }
5601debfc3dSmrg
5611debfc3dSmrg if (iv0->extend == IV_UNKNOWN_EXTEND
5621debfc3dSmrg && iv0->mode == mode
5631debfc3dSmrg && iv0->step == const0_rtx)
5641debfc3dSmrg {
5651debfc3dSmrg arg = iv0->base;
5661debfc3dSmrg *iv0 = *iv1;
5671debfc3dSmrg if (op == MINUS
5681debfc3dSmrg && !iv_neg (iv0))
5691debfc3dSmrg return false;
5701debfc3dSmrg
5711debfc3dSmrg iv0->delta = simplify_gen_binary (PLUS, mode, iv0->delta, arg);
5721debfc3dSmrg return true;
5731debfc3dSmrg }
5741debfc3dSmrg
5751debfc3dSmrg return false;
5761debfc3dSmrg }
5771debfc3dSmrg
5781debfc3dSmrg /* Evaluates multiplication of IV by constant CST. */
5791debfc3dSmrg
5801debfc3dSmrg static bool
iv_mult(class rtx_iv * iv,rtx mby)581*8feb0f0bSmrg iv_mult (class rtx_iv *iv, rtx mby)
5821debfc3dSmrg {
583a2dc1f3fSmrg scalar_int_mode mode = iv->extend_mode;
5841debfc3dSmrg
5851debfc3dSmrg if (GET_MODE (mby) != VOIDmode
5861debfc3dSmrg && GET_MODE (mby) != mode)
5871debfc3dSmrg return false;
5881debfc3dSmrg
5891debfc3dSmrg if (iv->extend == IV_UNKNOWN_EXTEND)
5901debfc3dSmrg {
5911debfc3dSmrg iv->base = simplify_gen_binary (MULT, mode, iv->base, mby);
5921debfc3dSmrg iv->step = simplify_gen_binary (MULT, mode, iv->step, mby);
5931debfc3dSmrg }
5941debfc3dSmrg else
5951debfc3dSmrg {
5961debfc3dSmrg iv->delta = simplify_gen_binary (MULT, mode, iv->delta, mby);
5971debfc3dSmrg iv->mult = simplify_gen_binary (MULT, mode, iv->mult, mby);
5981debfc3dSmrg }
5991debfc3dSmrg
6001debfc3dSmrg return true;
6011debfc3dSmrg }
6021debfc3dSmrg
6031debfc3dSmrg /* Evaluates shift of IV by constant CST. */
6041debfc3dSmrg
6051debfc3dSmrg static bool
iv_shift(class rtx_iv * iv,rtx mby)606*8feb0f0bSmrg iv_shift (class rtx_iv *iv, rtx mby)
6071debfc3dSmrg {
608a2dc1f3fSmrg scalar_int_mode mode = iv->extend_mode;
6091debfc3dSmrg
6101debfc3dSmrg if (GET_MODE (mby) != VOIDmode
6111debfc3dSmrg && GET_MODE (mby) != mode)
6121debfc3dSmrg return false;
6131debfc3dSmrg
6141debfc3dSmrg if (iv->extend == IV_UNKNOWN_EXTEND)
6151debfc3dSmrg {
6161debfc3dSmrg iv->base = simplify_gen_binary (ASHIFT, mode, iv->base, mby);
6171debfc3dSmrg iv->step = simplify_gen_binary (ASHIFT, mode, iv->step, mby);
6181debfc3dSmrg }
6191debfc3dSmrg else
6201debfc3dSmrg {
6211debfc3dSmrg iv->delta = simplify_gen_binary (ASHIFT, mode, iv->delta, mby);
6221debfc3dSmrg iv->mult = simplify_gen_binary (ASHIFT, mode, iv->mult, mby);
6231debfc3dSmrg }
6241debfc3dSmrg
6251debfc3dSmrg return true;
6261debfc3dSmrg }
6271debfc3dSmrg
6281debfc3dSmrg /* The recursive part of get_biv_step. Gets the value of the single value
6291debfc3dSmrg defined by DEF wrto initial value of REG inside loop, in shape described
6301debfc3dSmrg at get_biv_step. */
6311debfc3dSmrg
6321debfc3dSmrg static bool
get_biv_step_1(df_ref def,scalar_int_mode outer_mode,rtx reg,rtx * inner_step,scalar_int_mode * inner_mode,enum iv_extend_code * extend,rtx * outer_step)633a2dc1f3fSmrg get_biv_step_1 (df_ref def, scalar_int_mode outer_mode, rtx reg,
634a2dc1f3fSmrg rtx *inner_step, scalar_int_mode *inner_mode,
635a2dc1f3fSmrg enum iv_extend_code *extend,
6361debfc3dSmrg rtx *outer_step)
6371debfc3dSmrg {
6381debfc3dSmrg rtx set, rhs, op0 = NULL_RTX, op1 = NULL_RTX;
6391debfc3dSmrg rtx next, nextr;
6401debfc3dSmrg enum rtx_code code;
6411debfc3dSmrg rtx_insn *insn = DF_REF_INSN (def);
6421debfc3dSmrg df_ref next_def;
6431debfc3dSmrg enum iv_grd_result res;
6441debfc3dSmrg
6451debfc3dSmrg set = single_set (insn);
6461debfc3dSmrg if (!set)
6471debfc3dSmrg return false;
6481debfc3dSmrg
6491debfc3dSmrg rhs = find_reg_equal_equiv_note (insn);
6501debfc3dSmrg if (rhs)
6511debfc3dSmrg rhs = XEXP (rhs, 0);
6521debfc3dSmrg else
6531debfc3dSmrg rhs = SET_SRC (set);
6541debfc3dSmrg
6551debfc3dSmrg code = GET_CODE (rhs);
6561debfc3dSmrg switch (code)
6571debfc3dSmrg {
6581debfc3dSmrg case SUBREG:
6591debfc3dSmrg case REG:
6601debfc3dSmrg next = rhs;
6611debfc3dSmrg break;
6621debfc3dSmrg
6631debfc3dSmrg case PLUS:
6641debfc3dSmrg case MINUS:
6651debfc3dSmrg op0 = XEXP (rhs, 0);
6661debfc3dSmrg op1 = XEXP (rhs, 1);
6671debfc3dSmrg
6681debfc3dSmrg if (code == PLUS && CONSTANT_P (op0))
6691debfc3dSmrg std::swap (op0, op1);
6701debfc3dSmrg
6711debfc3dSmrg if (!simple_reg_p (op0)
6721debfc3dSmrg || !CONSTANT_P (op1))
6731debfc3dSmrg return false;
6741debfc3dSmrg
6751debfc3dSmrg if (GET_MODE (rhs) != outer_mode)
6761debfc3dSmrg {
6771debfc3dSmrg /* ppc64 uses expressions like
6781debfc3dSmrg
6791debfc3dSmrg (set x:SI (plus:SI (subreg:SI y:DI) 1)).
6801debfc3dSmrg
6811debfc3dSmrg this is equivalent to
6821debfc3dSmrg
6831debfc3dSmrg (set x':DI (plus:DI y:DI 1))
6841debfc3dSmrg (set x:SI (subreg:SI (x':DI)). */
6851debfc3dSmrg if (GET_CODE (op0) != SUBREG)
6861debfc3dSmrg return false;
6871debfc3dSmrg if (GET_MODE (SUBREG_REG (op0)) != outer_mode)
6881debfc3dSmrg return false;
6891debfc3dSmrg }
6901debfc3dSmrg
6911debfc3dSmrg next = op0;
6921debfc3dSmrg break;
6931debfc3dSmrg
6941debfc3dSmrg case SIGN_EXTEND:
6951debfc3dSmrg case ZERO_EXTEND:
6961debfc3dSmrg if (GET_MODE (rhs) != outer_mode)
6971debfc3dSmrg return false;
6981debfc3dSmrg
6991debfc3dSmrg op0 = XEXP (rhs, 0);
7001debfc3dSmrg if (!simple_reg_p (op0))
7011debfc3dSmrg return false;
7021debfc3dSmrg
7031debfc3dSmrg next = op0;
7041debfc3dSmrg break;
7051debfc3dSmrg
7061debfc3dSmrg default:
7071debfc3dSmrg return false;
7081debfc3dSmrg }
7091debfc3dSmrg
7101debfc3dSmrg if (GET_CODE (next) == SUBREG)
7111debfc3dSmrg {
7121debfc3dSmrg if (!subreg_lowpart_p (next))
7131debfc3dSmrg return false;
7141debfc3dSmrg
7151debfc3dSmrg nextr = SUBREG_REG (next);
7161debfc3dSmrg if (GET_MODE (nextr) != outer_mode)
7171debfc3dSmrg return false;
7181debfc3dSmrg }
7191debfc3dSmrg else
7201debfc3dSmrg nextr = next;
7211debfc3dSmrg
7221debfc3dSmrg res = iv_get_reaching_def (insn, nextr, &next_def);
7231debfc3dSmrg
7241debfc3dSmrg if (res == GRD_INVALID || res == GRD_INVARIANT)
7251debfc3dSmrg return false;
7261debfc3dSmrg
7271debfc3dSmrg if (res == GRD_MAYBE_BIV)
7281debfc3dSmrg {
7291debfc3dSmrg if (!rtx_equal_p (nextr, reg))
7301debfc3dSmrg return false;
7311debfc3dSmrg
7321debfc3dSmrg *inner_step = const0_rtx;
7331debfc3dSmrg *extend = IV_UNKNOWN_EXTEND;
7341debfc3dSmrg *inner_mode = outer_mode;
7351debfc3dSmrg *outer_step = const0_rtx;
7361debfc3dSmrg }
737a2dc1f3fSmrg else if (!get_biv_step_1 (next_def, outer_mode, reg,
738a2dc1f3fSmrg inner_step, inner_mode, extend,
7391debfc3dSmrg outer_step))
7401debfc3dSmrg return false;
7411debfc3dSmrg
7421debfc3dSmrg if (GET_CODE (next) == SUBREG)
7431debfc3dSmrg {
744a2dc1f3fSmrg scalar_int_mode amode;
745a2dc1f3fSmrg if (!is_a <scalar_int_mode> (GET_MODE (next), &amode)
746a2dc1f3fSmrg || GET_MODE_SIZE (amode) > GET_MODE_SIZE (*inner_mode))
7471debfc3dSmrg return false;
7481debfc3dSmrg
7491debfc3dSmrg *inner_mode = amode;
7501debfc3dSmrg *inner_step = simplify_gen_binary (PLUS, outer_mode,
7511debfc3dSmrg *inner_step, *outer_step);
7521debfc3dSmrg *outer_step = const0_rtx;
7531debfc3dSmrg *extend = IV_UNKNOWN_EXTEND;
7541debfc3dSmrg }
7551debfc3dSmrg
7561debfc3dSmrg switch (code)
7571debfc3dSmrg {
7581debfc3dSmrg case REG:
7591debfc3dSmrg case SUBREG:
7601debfc3dSmrg break;
7611debfc3dSmrg
7621debfc3dSmrg case PLUS:
7631debfc3dSmrg case MINUS:
7641debfc3dSmrg if (*inner_mode == outer_mode
7651debfc3dSmrg /* See comment in previous switch. */
7661debfc3dSmrg || GET_MODE (rhs) != outer_mode)
7671debfc3dSmrg *inner_step = simplify_gen_binary (code, outer_mode,
7681debfc3dSmrg *inner_step, op1);
7691debfc3dSmrg else
7701debfc3dSmrg *outer_step = simplify_gen_binary (code, outer_mode,
7711debfc3dSmrg *outer_step, op1);
7721debfc3dSmrg break;
7731debfc3dSmrg
7741debfc3dSmrg case SIGN_EXTEND:
7751debfc3dSmrg case ZERO_EXTEND:
7761debfc3dSmrg gcc_assert (GET_MODE (op0) == *inner_mode
7771debfc3dSmrg && *extend == IV_UNKNOWN_EXTEND
7781debfc3dSmrg && *outer_step == const0_rtx);
7791debfc3dSmrg
7801debfc3dSmrg *extend = (code == SIGN_EXTEND) ? IV_SIGN_EXTEND : IV_ZERO_EXTEND;
7811debfc3dSmrg break;
7821debfc3dSmrg
7831debfc3dSmrg default:
7841debfc3dSmrg return false;
7851debfc3dSmrg }
7861debfc3dSmrg
7871debfc3dSmrg return true;
7881debfc3dSmrg }
7891debfc3dSmrg
7901debfc3dSmrg /* Gets the operation on register REG inside loop, in shape
7911debfc3dSmrg
7921debfc3dSmrg OUTER_STEP + EXTEND_{OUTER_MODE} (SUBREG_{INNER_MODE} (REG + INNER_STEP))
7931debfc3dSmrg
7941debfc3dSmrg If the operation cannot be described in this shape, return false.
7951debfc3dSmrg LAST_DEF is the definition of REG that dominates loop latch. */
7961debfc3dSmrg
7971debfc3dSmrg static bool
get_biv_step(df_ref last_def,scalar_int_mode outer_mode,rtx reg,rtx * inner_step,scalar_int_mode * inner_mode,enum iv_extend_code * extend,rtx * outer_step)798a2dc1f3fSmrg get_biv_step (df_ref last_def, scalar_int_mode outer_mode, rtx reg,
799a2dc1f3fSmrg rtx *inner_step, scalar_int_mode *inner_mode,
800a2dc1f3fSmrg enum iv_extend_code *extend, rtx *outer_step)
8011debfc3dSmrg {
802a2dc1f3fSmrg if (!get_biv_step_1 (last_def, outer_mode, reg,
803a2dc1f3fSmrg inner_step, inner_mode, extend,
8041debfc3dSmrg outer_step))
8051debfc3dSmrg return false;
8061debfc3dSmrg
807a2dc1f3fSmrg gcc_assert ((*inner_mode == outer_mode) != (*extend != IV_UNKNOWN_EXTEND));
808a2dc1f3fSmrg gcc_assert (*inner_mode != outer_mode || *outer_step == const0_rtx);
8091debfc3dSmrg
8101debfc3dSmrg return true;
8111debfc3dSmrg }
8121debfc3dSmrg
8131debfc3dSmrg /* Records information that DEF is induction variable IV. */
8141debfc3dSmrg
8151debfc3dSmrg static void
record_iv(df_ref def,class rtx_iv * iv)816*8feb0f0bSmrg record_iv (df_ref def, class rtx_iv *iv)
8171debfc3dSmrg {
818*8feb0f0bSmrg class rtx_iv *recorded_iv = XNEW (class rtx_iv);
8191debfc3dSmrg
8201debfc3dSmrg *recorded_iv = *iv;
8211debfc3dSmrg check_iv_ref_table_size ();
8221debfc3dSmrg DF_REF_IV_SET (def, recorded_iv);
8231debfc3dSmrg }
8241debfc3dSmrg
8251debfc3dSmrg /* If DEF was already analyzed for bivness, store the description of the biv to
8261debfc3dSmrg IV and return true. Otherwise return false. */
8271debfc3dSmrg
8281debfc3dSmrg static bool
analyzed_for_bivness_p(rtx def,class rtx_iv * iv)829*8feb0f0bSmrg analyzed_for_bivness_p (rtx def, class rtx_iv *iv)
8301debfc3dSmrg {
831*8feb0f0bSmrg class biv_entry *biv = bivs->find_with_hash (def, REGNO (def));
8321debfc3dSmrg
8331debfc3dSmrg if (!biv)
8341debfc3dSmrg return false;
8351debfc3dSmrg
8361debfc3dSmrg *iv = biv->iv;
8371debfc3dSmrg return true;
8381debfc3dSmrg }
8391debfc3dSmrg
8401debfc3dSmrg static void
record_biv(rtx def,class rtx_iv * iv)841*8feb0f0bSmrg record_biv (rtx def, class rtx_iv *iv)
8421debfc3dSmrg {
843*8feb0f0bSmrg class biv_entry *biv = XNEW (class biv_entry);
8441debfc3dSmrg biv_entry **slot = bivs->find_slot_with_hash (def, REGNO (def), INSERT);
8451debfc3dSmrg
8461debfc3dSmrg biv->regno = REGNO (def);
8471debfc3dSmrg biv->iv = *iv;
8481debfc3dSmrg gcc_assert (!*slot);
8491debfc3dSmrg *slot = biv;
8501debfc3dSmrg }
8511debfc3dSmrg
8521debfc3dSmrg /* Determines whether DEF is a biv and if so, stores its description
853a2dc1f3fSmrg to *IV. OUTER_MODE is the mode of DEF. */
8541debfc3dSmrg
8551debfc3dSmrg static bool
iv_analyze_biv(scalar_int_mode outer_mode,rtx def,class rtx_iv * iv)856*8feb0f0bSmrg iv_analyze_biv (scalar_int_mode outer_mode, rtx def, class rtx_iv *iv)
8571debfc3dSmrg {
8581debfc3dSmrg rtx inner_step, outer_step;
859a2dc1f3fSmrg scalar_int_mode inner_mode;
8601debfc3dSmrg enum iv_extend_code extend;
8611debfc3dSmrg df_ref last_def;
8621debfc3dSmrg
8631debfc3dSmrg if (dump_file)
8641debfc3dSmrg {
8651debfc3dSmrg fprintf (dump_file, "Analyzing ");
8661debfc3dSmrg print_rtl (dump_file, def);
8671debfc3dSmrg fprintf (dump_file, " for bivness.\n");
8681debfc3dSmrg }
8691debfc3dSmrg
8701debfc3dSmrg if (!REG_P (def))
8711debfc3dSmrg {
8721debfc3dSmrg if (!CONSTANT_P (def))
8731debfc3dSmrg return false;
8741debfc3dSmrg
875a2dc1f3fSmrg return iv_constant (iv, outer_mode, def);
8761debfc3dSmrg }
8771debfc3dSmrg
8781debfc3dSmrg if (!latch_dominating_def (def, &last_def))
8791debfc3dSmrg {
8801debfc3dSmrg if (dump_file)
8811debfc3dSmrg fprintf (dump_file, " not simple.\n");
8821debfc3dSmrg return false;
8831debfc3dSmrg }
8841debfc3dSmrg
8851debfc3dSmrg if (!last_def)
886a2dc1f3fSmrg return iv_constant (iv, outer_mode, def);
8871debfc3dSmrg
8881debfc3dSmrg if (analyzed_for_bivness_p (def, iv))
8891debfc3dSmrg {
8901debfc3dSmrg if (dump_file)
8911debfc3dSmrg fprintf (dump_file, " already analysed.\n");
8921debfc3dSmrg return iv->base != NULL_RTX;
8931debfc3dSmrg }
8941debfc3dSmrg
895a2dc1f3fSmrg if (!get_biv_step (last_def, outer_mode, def, &inner_step, &inner_mode,
896a2dc1f3fSmrg &extend, &outer_step))
8971debfc3dSmrg {
8981debfc3dSmrg iv->base = NULL_RTX;
8991debfc3dSmrg goto end;
9001debfc3dSmrg }
9011debfc3dSmrg
9021debfc3dSmrg /* Loop transforms base to es (base + inner_step) + outer_step,
9031debfc3dSmrg where es means extend of subreg between inner_mode and outer_mode.
9041debfc3dSmrg The corresponding induction variable is
9051debfc3dSmrg
9061debfc3dSmrg es ((base - outer_step) + i * (inner_step + outer_step)) + outer_step */
9071debfc3dSmrg
9081debfc3dSmrg iv->base = simplify_gen_binary (MINUS, outer_mode, def, outer_step);
9091debfc3dSmrg iv->step = simplify_gen_binary (PLUS, outer_mode, inner_step, outer_step);
9101debfc3dSmrg iv->mode = inner_mode;
9111debfc3dSmrg iv->extend_mode = outer_mode;
9121debfc3dSmrg iv->extend = extend;
9131debfc3dSmrg iv->mult = const1_rtx;
9141debfc3dSmrg iv->delta = outer_step;
9151debfc3dSmrg iv->first_special = inner_mode != outer_mode;
9161debfc3dSmrg
9171debfc3dSmrg end:
9181debfc3dSmrg if (dump_file)
9191debfc3dSmrg {
9201debfc3dSmrg fprintf (dump_file, " ");
9211debfc3dSmrg dump_iv_info (dump_file, iv);
9221debfc3dSmrg fprintf (dump_file, "\n");
9231debfc3dSmrg }
9241debfc3dSmrg
9251debfc3dSmrg record_biv (def, iv);
9261debfc3dSmrg return iv->base != NULL_RTX;
9271debfc3dSmrg }
9281debfc3dSmrg
9291debfc3dSmrg /* Analyzes expression RHS used at INSN and stores the result to *IV.
9301debfc3dSmrg The mode of the induction variable is MODE. */
9311debfc3dSmrg
9321debfc3dSmrg bool
iv_analyze_expr(rtx_insn * insn,scalar_int_mode mode,rtx rhs,class rtx_iv * iv)933a2dc1f3fSmrg iv_analyze_expr (rtx_insn *insn, scalar_int_mode mode, rtx rhs,
934*8feb0f0bSmrg class rtx_iv *iv)
9351debfc3dSmrg {
9361debfc3dSmrg rtx mby = NULL_RTX;
9371debfc3dSmrg rtx op0 = NULL_RTX, op1 = NULL_RTX;
938*8feb0f0bSmrg class rtx_iv iv0, iv1;
9391debfc3dSmrg enum rtx_code code = GET_CODE (rhs);
940a2dc1f3fSmrg scalar_int_mode omode = mode;
9411debfc3dSmrg
9421debfc3dSmrg iv->base = NULL_RTX;
9431debfc3dSmrg iv->step = NULL_RTX;
9441debfc3dSmrg
9451debfc3dSmrg gcc_assert (GET_MODE (rhs) == mode || GET_MODE (rhs) == VOIDmode);
9461debfc3dSmrg
9471debfc3dSmrg if (CONSTANT_P (rhs)
9481debfc3dSmrg || REG_P (rhs)
9491debfc3dSmrg || code == SUBREG)
950a2dc1f3fSmrg return iv_analyze_op (insn, mode, rhs, iv);
9511debfc3dSmrg
9521debfc3dSmrg switch (code)
9531debfc3dSmrg {
9541debfc3dSmrg case REG:
9551debfc3dSmrg op0 = rhs;
9561debfc3dSmrg break;
9571debfc3dSmrg
9581debfc3dSmrg case SIGN_EXTEND:
9591debfc3dSmrg case ZERO_EXTEND:
9601debfc3dSmrg case NEG:
9611debfc3dSmrg op0 = XEXP (rhs, 0);
962a2dc1f3fSmrg /* We don't know how many bits there are in a sign-extended constant. */
963a2dc1f3fSmrg if (!is_a <scalar_int_mode> (GET_MODE (op0), &omode))
964a2dc1f3fSmrg return false;
9651debfc3dSmrg break;
9661debfc3dSmrg
9671debfc3dSmrg case PLUS:
9681debfc3dSmrg case MINUS:
9691debfc3dSmrg op0 = XEXP (rhs, 0);
9701debfc3dSmrg op1 = XEXP (rhs, 1);
9711debfc3dSmrg break;
9721debfc3dSmrg
9731debfc3dSmrg case MULT:
9741debfc3dSmrg op0 = XEXP (rhs, 0);
9751debfc3dSmrg mby = XEXP (rhs, 1);
9761debfc3dSmrg if (!CONSTANT_P (mby))
9771debfc3dSmrg std::swap (op0, mby);
9781debfc3dSmrg if (!CONSTANT_P (mby))
9791debfc3dSmrg return false;
9801debfc3dSmrg break;
9811debfc3dSmrg
9821debfc3dSmrg case ASHIFT:
9831debfc3dSmrg op0 = XEXP (rhs, 0);
9841debfc3dSmrg mby = XEXP (rhs, 1);
9851debfc3dSmrg if (!CONSTANT_P (mby))
9861debfc3dSmrg return false;
9871debfc3dSmrg break;
9881debfc3dSmrg
9891debfc3dSmrg default:
9901debfc3dSmrg return false;
9911debfc3dSmrg }
9921debfc3dSmrg
9931debfc3dSmrg if (op0
994a2dc1f3fSmrg && !iv_analyze_expr (insn, omode, op0, &iv0))
9951debfc3dSmrg return false;
9961debfc3dSmrg
9971debfc3dSmrg if (op1
998a2dc1f3fSmrg && !iv_analyze_expr (insn, omode, op1, &iv1))
9991debfc3dSmrg return false;
10001debfc3dSmrg
10011debfc3dSmrg switch (code)
10021debfc3dSmrg {
10031debfc3dSmrg case SIGN_EXTEND:
10041debfc3dSmrg if (!iv_extend (&iv0, IV_SIGN_EXTEND, mode))
10051debfc3dSmrg return false;
10061debfc3dSmrg break;
10071debfc3dSmrg
10081debfc3dSmrg case ZERO_EXTEND:
10091debfc3dSmrg if (!iv_extend (&iv0, IV_ZERO_EXTEND, mode))
10101debfc3dSmrg return false;
10111debfc3dSmrg break;
10121debfc3dSmrg
10131debfc3dSmrg case NEG:
10141debfc3dSmrg if (!iv_neg (&iv0))
10151debfc3dSmrg return false;
10161debfc3dSmrg break;
10171debfc3dSmrg
10181debfc3dSmrg case PLUS:
10191debfc3dSmrg case MINUS:
10201debfc3dSmrg if (!iv_add (&iv0, &iv1, code))
10211debfc3dSmrg return false;
10221debfc3dSmrg break;
10231debfc3dSmrg
10241debfc3dSmrg case MULT:
10251debfc3dSmrg if (!iv_mult (&iv0, mby))
10261debfc3dSmrg return false;
10271debfc3dSmrg break;
10281debfc3dSmrg
10291debfc3dSmrg case ASHIFT:
10301debfc3dSmrg if (!iv_shift (&iv0, mby))
10311debfc3dSmrg return false;
10321debfc3dSmrg break;
10331debfc3dSmrg
10341debfc3dSmrg default:
10351debfc3dSmrg break;
10361debfc3dSmrg }
10371debfc3dSmrg
10381debfc3dSmrg *iv = iv0;
10391debfc3dSmrg return iv->base != NULL_RTX;
10401debfc3dSmrg }
10411debfc3dSmrg
10421debfc3dSmrg /* Analyzes iv DEF and stores the result to *IV. */
10431debfc3dSmrg
10441debfc3dSmrg static bool
iv_analyze_def(df_ref def,class rtx_iv * iv)1045*8feb0f0bSmrg iv_analyze_def (df_ref def, class rtx_iv *iv)
10461debfc3dSmrg {
10471debfc3dSmrg rtx_insn *insn = DF_REF_INSN (def);
10481debfc3dSmrg rtx reg = DF_REF_REG (def);
10491debfc3dSmrg rtx set, rhs;
10501debfc3dSmrg
10511debfc3dSmrg if (dump_file)
10521debfc3dSmrg {
10531debfc3dSmrg fprintf (dump_file, "Analyzing def of ");
10541debfc3dSmrg print_rtl (dump_file, reg);
10551debfc3dSmrg fprintf (dump_file, " in insn ");
10561debfc3dSmrg print_rtl_single (dump_file, insn);
10571debfc3dSmrg }
10581debfc3dSmrg
10591debfc3dSmrg check_iv_ref_table_size ();
10601debfc3dSmrg if (DF_REF_IV (def))
10611debfc3dSmrg {
10621debfc3dSmrg if (dump_file)
10631debfc3dSmrg fprintf (dump_file, " already analysed.\n");
10641debfc3dSmrg *iv = *DF_REF_IV (def);
10651debfc3dSmrg return iv->base != NULL_RTX;
10661debfc3dSmrg }
10671debfc3dSmrg
10681debfc3dSmrg iv->base = NULL_RTX;
10691debfc3dSmrg iv->step = NULL_RTX;
10701debfc3dSmrg
1071a2dc1f3fSmrg scalar_int_mode mode;
1072a2dc1f3fSmrg if (!REG_P (reg) || !is_a <scalar_int_mode> (GET_MODE (reg), &mode))
10731debfc3dSmrg return false;
10741debfc3dSmrg
10751debfc3dSmrg set = single_set (insn);
10761debfc3dSmrg if (!set)
10771debfc3dSmrg return false;
10781debfc3dSmrg
10791debfc3dSmrg if (!REG_P (SET_DEST (set)))
10801debfc3dSmrg return false;
10811debfc3dSmrg
10821debfc3dSmrg gcc_assert (SET_DEST (set) == reg);
10831debfc3dSmrg rhs = find_reg_equal_equiv_note (insn);
10841debfc3dSmrg if (rhs)
10851debfc3dSmrg rhs = XEXP (rhs, 0);
10861debfc3dSmrg else
10871debfc3dSmrg rhs = SET_SRC (set);
10881debfc3dSmrg
1089a2dc1f3fSmrg iv_analyze_expr (insn, mode, rhs, iv);
10901debfc3dSmrg record_iv (def, iv);
10911debfc3dSmrg
10921debfc3dSmrg if (dump_file)
10931debfc3dSmrg {
10941debfc3dSmrg print_rtl (dump_file, reg);
10951debfc3dSmrg fprintf (dump_file, " in insn ");
10961debfc3dSmrg print_rtl_single (dump_file, insn);
10971debfc3dSmrg fprintf (dump_file, " is ");
10981debfc3dSmrg dump_iv_info (dump_file, iv);
10991debfc3dSmrg fprintf (dump_file, "\n");
11001debfc3dSmrg }
11011debfc3dSmrg
11021debfc3dSmrg return iv->base != NULL_RTX;
11031debfc3dSmrg }
11041debfc3dSmrg
1105a2dc1f3fSmrg /* Analyzes operand OP of INSN and stores the result to *IV. MODE is the
1106a2dc1f3fSmrg mode of OP. */
11071debfc3dSmrg
11081debfc3dSmrg static bool
iv_analyze_op(rtx_insn * insn,scalar_int_mode mode,rtx op,class rtx_iv * iv)1109*8feb0f0bSmrg iv_analyze_op (rtx_insn *insn, scalar_int_mode mode, rtx op, class rtx_iv *iv)
11101debfc3dSmrg {
11111debfc3dSmrg df_ref def = NULL;
11121debfc3dSmrg enum iv_grd_result res;
11131debfc3dSmrg
11141debfc3dSmrg if (dump_file)
11151debfc3dSmrg {
11161debfc3dSmrg fprintf (dump_file, "Analyzing operand ");
11171debfc3dSmrg print_rtl (dump_file, op);
11181debfc3dSmrg fprintf (dump_file, " of insn ");
11191debfc3dSmrg print_rtl_single (dump_file, insn);
11201debfc3dSmrg }
11211debfc3dSmrg
11221debfc3dSmrg if (function_invariant_p (op))
11231debfc3dSmrg res = GRD_INVARIANT;
11241debfc3dSmrg else if (GET_CODE (op) == SUBREG)
11251debfc3dSmrg {
1126a2dc1f3fSmrg scalar_int_mode inner_mode;
1127a2dc1f3fSmrg if (!subreg_lowpart_p (op)
1128a2dc1f3fSmrg || !is_a <scalar_int_mode> (GET_MODE (SUBREG_REG (op)), &inner_mode))
11291debfc3dSmrg return false;
11301debfc3dSmrg
1131a2dc1f3fSmrg if (!iv_analyze_op (insn, inner_mode, SUBREG_REG (op), iv))
11321debfc3dSmrg return false;
11331debfc3dSmrg
1134a2dc1f3fSmrg return iv_subreg (iv, mode);
11351debfc3dSmrg }
11361debfc3dSmrg else
11371debfc3dSmrg {
11381debfc3dSmrg res = iv_get_reaching_def (insn, op, &def);
11391debfc3dSmrg if (res == GRD_INVALID)
11401debfc3dSmrg {
11411debfc3dSmrg if (dump_file)
11421debfc3dSmrg fprintf (dump_file, " not simple.\n");
11431debfc3dSmrg return false;
11441debfc3dSmrg }
11451debfc3dSmrg }
11461debfc3dSmrg
11471debfc3dSmrg if (res == GRD_INVARIANT)
11481debfc3dSmrg {
1149a2dc1f3fSmrg iv_constant (iv, mode, op);
11501debfc3dSmrg
11511debfc3dSmrg if (dump_file)
11521debfc3dSmrg {
11531debfc3dSmrg fprintf (dump_file, " ");
11541debfc3dSmrg dump_iv_info (dump_file, iv);
11551debfc3dSmrg fprintf (dump_file, "\n");
11561debfc3dSmrg }
11571debfc3dSmrg return true;
11581debfc3dSmrg }
11591debfc3dSmrg
11601debfc3dSmrg if (res == GRD_MAYBE_BIV)
1161a2dc1f3fSmrg return iv_analyze_biv (mode, op, iv);
11621debfc3dSmrg
11631debfc3dSmrg return iv_analyze_def (def, iv);
11641debfc3dSmrg }
11651debfc3dSmrg
1166a2dc1f3fSmrg /* Analyzes value VAL at INSN and stores the result to *IV. MODE is the
1167a2dc1f3fSmrg mode of VAL. */
11681debfc3dSmrg
11691debfc3dSmrg bool
iv_analyze(rtx_insn * insn,scalar_int_mode mode,rtx val,class rtx_iv * iv)1170*8feb0f0bSmrg iv_analyze (rtx_insn *insn, scalar_int_mode mode, rtx val, class rtx_iv *iv)
11711debfc3dSmrg {
11721debfc3dSmrg rtx reg;
11731debfc3dSmrg
11741debfc3dSmrg /* We must find the insn in that val is used, so that we get to UD chains.
11751debfc3dSmrg Since the function is sometimes called on result of get_condition,
11761debfc3dSmrg this does not necessarily have to be directly INSN; scan also the
11771debfc3dSmrg following insns. */
11781debfc3dSmrg if (simple_reg_p (val))
11791debfc3dSmrg {
11801debfc3dSmrg if (GET_CODE (val) == SUBREG)
11811debfc3dSmrg reg = SUBREG_REG (val);
11821debfc3dSmrg else
11831debfc3dSmrg reg = val;
11841debfc3dSmrg
11851debfc3dSmrg while (!df_find_use (insn, reg))
11861debfc3dSmrg insn = NEXT_INSN (insn);
11871debfc3dSmrg }
11881debfc3dSmrg
1189a2dc1f3fSmrg return iv_analyze_op (insn, mode, val, iv);
11901debfc3dSmrg }
11911debfc3dSmrg
11921debfc3dSmrg /* Analyzes definition of DEF in INSN and stores the result to IV. */
11931debfc3dSmrg
11941debfc3dSmrg bool
iv_analyze_result(rtx_insn * insn,rtx def,class rtx_iv * iv)1195*8feb0f0bSmrg iv_analyze_result (rtx_insn *insn, rtx def, class rtx_iv *iv)
11961debfc3dSmrg {
11971debfc3dSmrg df_ref adef;
11981debfc3dSmrg
11991debfc3dSmrg adef = df_find_def (insn, def);
12001debfc3dSmrg if (!adef)
12011debfc3dSmrg return false;
12021debfc3dSmrg
12031debfc3dSmrg return iv_analyze_def (adef, iv);
12041debfc3dSmrg }
12051debfc3dSmrg
12061debfc3dSmrg /* Checks whether definition of register REG in INSN is a basic induction
1207a2dc1f3fSmrg variable. MODE is the mode of REG.
1208a2dc1f3fSmrg
1209a2dc1f3fSmrg IV analysis must have been initialized (via a call to
12101debfc3dSmrg iv_analysis_loop_init) for this function to produce a result. */
12111debfc3dSmrg
12121debfc3dSmrg bool
biv_p(rtx_insn * insn,scalar_int_mode mode,rtx reg)1213a2dc1f3fSmrg biv_p (rtx_insn *insn, scalar_int_mode mode, rtx reg)
12141debfc3dSmrg {
1215*8feb0f0bSmrg class rtx_iv iv;
12161debfc3dSmrg df_ref def, last_def;
12171debfc3dSmrg
12181debfc3dSmrg if (!simple_reg_p (reg))
12191debfc3dSmrg return false;
12201debfc3dSmrg
12211debfc3dSmrg def = df_find_def (insn, reg);
12221debfc3dSmrg gcc_assert (def != NULL);
12231debfc3dSmrg if (!latch_dominating_def (reg, &last_def))
12241debfc3dSmrg return false;
12251debfc3dSmrg if (last_def != def)
12261debfc3dSmrg return false;
12271debfc3dSmrg
1228a2dc1f3fSmrg if (!iv_analyze_biv (mode, reg, &iv))
12291debfc3dSmrg return false;
12301debfc3dSmrg
12311debfc3dSmrg return iv.step != const0_rtx;
12321debfc3dSmrg }
12331debfc3dSmrg
12341debfc3dSmrg /* Calculates value of IV at ITERATION-th iteration. */
12351debfc3dSmrg
12361debfc3dSmrg rtx
get_iv_value(class rtx_iv * iv,rtx iteration)1237*8feb0f0bSmrg get_iv_value (class rtx_iv *iv, rtx iteration)
12381debfc3dSmrg {
12391debfc3dSmrg rtx val;
12401debfc3dSmrg
12411debfc3dSmrg /* We would need to generate some if_then_else patterns, and so far
12421debfc3dSmrg it is not needed anywhere. */
12431debfc3dSmrg gcc_assert (!iv->first_special);
12441debfc3dSmrg
12451debfc3dSmrg if (iv->step != const0_rtx && iteration != const0_rtx)
12461debfc3dSmrg val = simplify_gen_binary (PLUS, iv->extend_mode, iv->base,
12471debfc3dSmrg simplify_gen_binary (MULT, iv->extend_mode,
12481debfc3dSmrg iv->step, iteration));
12491debfc3dSmrg else
12501debfc3dSmrg val = iv->base;
12511debfc3dSmrg
12521debfc3dSmrg if (iv->extend_mode == iv->mode)
12531debfc3dSmrg return val;
12541debfc3dSmrg
12551debfc3dSmrg val = lowpart_subreg (iv->mode, val, iv->extend_mode);
12561debfc3dSmrg
12571debfc3dSmrg if (iv->extend == IV_UNKNOWN_EXTEND)
12581debfc3dSmrg return val;
12591debfc3dSmrg
12601debfc3dSmrg val = simplify_gen_unary (iv_extend_to_rtx_code (iv->extend),
12611debfc3dSmrg iv->extend_mode, val, iv->mode);
12621debfc3dSmrg val = simplify_gen_binary (PLUS, iv->extend_mode, iv->delta,
12631debfc3dSmrg simplify_gen_binary (MULT, iv->extend_mode,
12641debfc3dSmrg iv->mult, val));
12651debfc3dSmrg
12661debfc3dSmrg return val;
12671debfc3dSmrg }
12681debfc3dSmrg
12691debfc3dSmrg /* Free the data for an induction variable analysis. */
12701debfc3dSmrg
12711debfc3dSmrg void
iv_analysis_done(void)12721debfc3dSmrg iv_analysis_done (void)
12731debfc3dSmrg {
12741debfc3dSmrg if (!clean_slate)
12751debfc3dSmrg {
12761debfc3dSmrg clear_iv_info ();
12771debfc3dSmrg clean_slate = true;
12781debfc3dSmrg df_finish_pass (true);
12791debfc3dSmrg delete bivs;
12801debfc3dSmrg bivs = NULL;
12811debfc3dSmrg free (iv_ref_table);
12821debfc3dSmrg iv_ref_table = NULL;
12831debfc3dSmrg iv_ref_table_size = 0;
12841debfc3dSmrg }
12851debfc3dSmrg }
12861debfc3dSmrg
12871debfc3dSmrg /* Computes inverse to X modulo (1 << MOD). */
12881debfc3dSmrg
12891debfc3dSmrg static uint64_t
inverse(uint64_t x,int mod)12901debfc3dSmrg inverse (uint64_t x, int mod)
12911debfc3dSmrg {
12921debfc3dSmrg uint64_t mask =
12931debfc3dSmrg ((uint64_t) 1 << (mod - 1) << 1) - 1;
12941debfc3dSmrg uint64_t rslt = 1;
12951debfc3dSmrg int i;
12961debfc3dSmrg
12971debfc3dSmrg for (i = 0; i < mod - 1; i++)
12981debfc3dSmrg {
12991debfc3dSmrg rslt = (rslt * x) & mask;
13001debfc3dSmrg x = (x * x) & mask;
13011debfc3dSmrg }
13021debfc3dSmrg
13031debfc3dSmrg return rslt;
13041debfc3dSmrg }
13051debfc3dSmrg
13061debfc3dSmrg /* Checks whether any register in X is in set ALT. */
13071debfc3dSmrg
13081debfc3dSmrg static bool
altered_reg_used(const_rtx x,bitmap alt)13091debfc3dSmrg altered_reg_used (const_rtx x, bitmap alt)
13101debfc3dSmrg {
13111debfc3dSmrg subrtx_iterator::array_type array;
13121debfc3dSmrg FOR_EACH_SUBRTX (iter, array, x, NONCONST)
13131debfc3dSmrg {
13141debfc3dSmrg const_rtx x = *iter;
13151debfc3dSmrg if (REG_P (x) && REGNO_REG_SET_P (alt, REGNO (x)))
13161debfc3dSmrg return true;
13171debfc3dSmrg }
13181debfc3dSmrg return false;
13191debfc3dSmrg }
13201debfc3dSmrg
13211debfc3dSmrg /* Marks registers altered by EXPR in set ALT. */
13221debfc3dSmrg
13231debfc3dSmrg static void
mark_altered(rtx expr,const_rtx by ATTRIBUTE_UNUSED,void * alt)13241debfc3dSmrg mark_altered (rtx expr, const_rtx by ATTRIBUTE_UNUSED, void *alt)
13251debfc3dSmrg {
13261debfc3dSmrg if (GET_CODE (expr) == SUBREG)
13271debfc3dSmrg expr = SUBREG_REG (expr);
13281debfc3dSmrg if (!REG_P (expr))
13291debfc3dSmrg return;
13301debfc3dSmrg
13311debfc3dSmrg SET_REGNO_REG_SET ((bitmap) alt, REGNO (expr));
13321debfc3dSmrg }
13331debfc3dSmrg
13341debfc3dSmrg /* Checks whether RHS is simple enough to process. */
13351debfc3dSmrg
13361debfc3dSmrg static bool
simple_rhs_p(rtx rhs)13371debfc3dSmrg simple_rhs_p (rtx rhs)
13381debfc3dSmrg {
13391debfc3dSmrg rtx op0, op1;
13401debfc3dSmrg
13411debfc3dSmrg if (function_invariant_p (rhs)
13421debfc3dSmrg || (REG_P (rhs) && !HARD_REGISTER_P (rhs)))
13431debfc3dSmrg return true;
13441debfc3dSmrg
13451debfc3dSmrg switch (GET_CODE (rhs))
13461debfc3dSmrg {
13471debfc3dSmrg case PLUS:
13481debfc3dSmrg case MINUS:
13491debfc3dSmrg case AND:
13501debfc3dSmrg op0 = XEXP (rhs, 0);
13511debfc3dSmrg op1 = XEXP (rhs, 1);
13521debfc3dSmrg /* Allow reg OP const and reg OP reg. */
13531debfc3dSmrg if (!(REG_P (op0) && !HARD_REGISTER_P (op0))
13541debfc3dSmrg && !function_invariant_p (op0))
13551debfc3dSmrg return false;
13561debfc3dSmrg if (!(REG_P (op1) && !HARD_REGISTER_P (op1))
13571debfc3dSmrg && !function_invariant_p (op1))
13581debfc3dSmrg return false;
13591debfc3dSmrg
13601debfc3dSmrg return true;
13611debfc3dSmrg
13621debfc3dSmrg case ASHIFT:
13631debfc3dSmrg case ASHIFTRT:
13641debfc3dSmrg case LSHIFTRT:
13651debfc3dSmrg case MULT:
13661debfc3dSmrg op0 = XEXP (rhs, 0);
13671debfc3dSmrg op1 = XEXP (rhs, 1);
13681debfc3dSmrg /* Allow reg OP const. */
13691debfc3dSmrg if (!(REG_P (op0) && !HARD_REGISTER_P (op0)))
13701debfc3dSmrg return false;
13711debfc3dSmrg if (!function_invariant_p (op1))
13721debfc3dSmrg return false;
13731debfc3dSmrg
13741debfc3dSmrg return true;
13751debfc3dSmrg
13761debfc3dSmrg default:
13771debfc3dSmrg return false;
13781debfc3dSmrg }
13791debfc3dSmrg }
13801debfc3dSmrg
13811debfc3dSmrg /* If REGNO has a single definition, return its known value, otherwise return
13821debfc3dSmrg null. */
13831debfc3dSmrg
13841debfc3dSmrg static rtx
find_single_def_src(unsigned int regno)13851debfc3dSmrg find_single_def_src (unsigned int regno)
13861debfc3dSmrg {
1387a2dc1f3fSmrg rtx src = NULL_RTX;
13881debfc3dSmrg
1389a2dc1f3fSmrg /* Don't look through unbounded number of single definition REG copies,
1390a2dc1f3fSmrg there might be loops for sources with uninitialized variables. */
1391a2dc1f3fSmrg for (int cnt = 0; cnt < 128; cnt++)
13921debfc3dSmrg {
1393a2dc1f3fSmrg df_ref adef = DF_REG_DEF_CHAIN (regno);
13941debfc3dSmrg if (adef == NULL || DF_REF_NEXT_REG (adef) != NULL
13951debfc3dSmrg || DF_REF_IS_ARTIFICIAL (adef))
13961debfc3dSmrg return NULL_RTX;
13971debfc3dSmrg
1398a2dc1f3fSmrg rtx set = single_set (DF_REF_INSN (adef));
13991debfc3dSmrg if (set == NULL || !REG_P (SET_DEST (set))
14001debfc3dSmrg || REGNO (SET_DEST (set)) != regno)
14011debfc3dSmrg return NULL_RTX;
14021debfc3dSmrg
1403a2dc1f3fSmrg rtx note = find_reg_equal_equiv_note (DF_REF_INSN (adef));
14041debfc3dSmrg if (note && function_invariant_p (XEXP (note, 0)))
14051debfc3dSmrg {
14061debfc3dSmrg src = XEXP (note, 0);
14071debfc3dSmrg break;
14081debfc3dSmrg }
14091debfc3dSmrg src = SET_SRC (set);
14101debfc3dSmrg
14111debfc3dSmrg if (REG_P (src))
14121debfc3dSmrg {
14131debfc3dSmrg regno = REGNO (src);
14141debfc3dSmrg continue;
14151debfc3dSmrg }
14161debfc3dSmrg break;
14171debfc3dSmrg }
14181debfc3dSmrg if (!function_invariant_p (src))
14191debfc3dSmrg return NULL_RTX;
14201debfc3dSmrg
14211debfc3dSmrg return src;
14221debfc3dSmrg }
14231debfc3dSmrg
14241debfc3dSmrg /* If any registers in *EXPR that have a single definition, try to replace
14251debfc3dSmrg them with the known-equivalent values. */
14261debfc3dSmrg
14271debfc3dSmrg static void
replace_single_def_regs(rtx * expr)14281debfc3dSmrg replace_single_def_regs (rtx *expr)
14291debfc3dSmrg {
14301debfc3dSmrg subrtx_var_iterator::array_type array;
14311debfc3dSmrg repeat:
14321debfc3dSmrg FOR_EACH_SUBRTX_VAR (iter, array, *expr, NONCONST)
14331debfc3dSmrg {
14341debfc3dSmrg rtx x = *iter;
14351debfc3dSmrg if (REG_P (x))
14361debfc3dSmrg if (rtx new_x = find_single_def_src (REGNO (x)))
14371debfc3dSmrg {
14381debfc3dSmrg *expr = simplify_replace_rtx (*expr, x, new_x);
14391debfc3dSmrg goto repeat;
14401debfc3dSmrg }
14411debfc3dSmrg }
14421debfc3dSmrg }
14431debfc3dSmrg
14441debfc3dSmrg /* A subroutine of simplify_using_initial_values, this function examines INSN
14451debfc3dSmrg to see if it contains a suitable set that we can use to make a replacement.
14461debfc3dSmrg If it is suitable, return true and set DEST and SRC to the lhs and rhs of
14471debfc3dSmrg the set; return false otherwise. */
14481debfc3dSmrg
14491debfc3dSmrg static bool
suitable_set_for_replacement(rtx_insn * insn,rtx * dest,rtx * src)14501debfc3dSmrg suitable_set_for_replacement (rtx_insn *insn, rtx *dest, rtx *src)
14511debfc3dSmrg {
14521debfc3dSmrg rtx set = single_set (insn);
14531debfc3dSmrg rtx lhs = NULL_RTX, rhs;
14541debfc3dSmrg
14551debfc3dSmrg if (!set)
14561debfc3dSmrg return false;
14571debfc3dSmrg
14581debfc3dSmrg lhs = SET_DEST (set);
14591debfc3dSmrg if (!REG_P (lhs))
14601debfc3dSmrg return false;
14611debfc3dSmrg
14621debfc3dSmrg rhs = find_reg_equal_equiv_note (insn);
14631debfc3dSmrg if (rhs)
14641debfc3dSmrg rhs = XEXP (rhs, 0);
14651debfc3dSmrg else
14661debfc3dSmrg rhs = SET_SRC (set);
14671debfc3dSmrg
14681debfc3dSmrg if (!simple_rhs_p (rhs))
14691debfc3dSmrg return false;
14701debfc3dSmrg
14711debfc3dSmrg *dest = lhs;
14721debfc3dSmrg *src = rhs;
14731debfc3dSmrg return true;
14741debfc3dSmrg }
14751debfc3dSmrg
14761debfc3dSmrg /* Using the data returned by suitable_set_for_replacement, replace DEST
14771debfc3dSmrg with SRC in *EXPR and return the new expression. Also call
14781debfc3dSmrg replace_single_def_regs if the replacement changed something. */
14791debfc3dSmrg static void
replace_in_expr(rtx * expr,rtx dest,rtx src)14801debfc3dSmrg replace_in_expr (rtx *expr, rtx dest, rtx src)
14811debfc3dSmrg {
14821debfc3dSmrg rtx old = *expr;
14831debfc3dSmrg *expr = simplify_replace_rtx (*expr, dest, src);
14841debfc3dSmrg if (old == *expr)
14851debfc3dSmrg return;
14861debfc3dSmrg replace_single_def_regs (expr);
14871debfc3dSmrg }
14881debfc3dSmrg
14891debfc3dSmrg /* Checks whether A implies B. */
14901debfc3dSmrg
14911debfc3dSmrg static bool
implies_p(rtx a,rtx b)14921debfc3dSmrg implies_p (rtx a, rtx b)
14931debfc3dSmrg {
14941debfc3dSmrg rtx op0, op1, opb0, opb1;
14951debfc3dSmrg machine_mode mode;
14961debfc3dSmrg
14971debfc3dSmrg if (rtx_equal_p (a, b))
14981debfc3dSmrg return true;
14991debfc3dSmrg
15001debfc3dSmrg if (GET_CODE (a) == EQ)
15011debfc3dSmrg {
15021debfc3dSmrg op0 = XEXP (a, 0);
15031debfc3dSmrg op1 = XEXP (a, 1);
15041debfc3dSmrg
15051debfc3dSmrg if (REG_P (op0)
15061debfc3dSmrg || (GET_CODE (op0) == SUBREG
15071debfc3dSmrg && REG_P (SUBREG_REG (op0))))
15081debfc3dSmrg {
15091debfc3dSmrg rtx r = simplify_replace_rtx (b, op0, op1);
15101debfc3dSmrg if (r == const_true_rtx)
15111debfc3dSmrg return true;
15121debfc3dSmrg }
15131debfc3dSmrg
15141debfc3dSmrg if (REG_P (op1)
15151debfc3dSmrg || (GET_CODE (op1) == SUBREG
15161debfc3dSmrg && REG_P (SUBREG_REG (op1))))
15171debfc3dSmrg {
15181debfc3dSmrg rtx r = simplify_replace_rtx (b, op1, op0);
15191debfc3dSmrg if (r == const_true_rtx)
15201debfc3dSmrg return true;
15211debfc3dSmrg }
15221debfc3dSmrg }
15231debfc3dSmrg
15241debfc3dSmrg if (b == const_true_rtx)
15251debfc3dSmrg return true;
15261debfc3dSmrg
15271debfc3dSmrg if ((GET_RTX_CLASS (GET_CODE (a)) != RTX_COMM_COMPARE
15281debfc3dSmrg && GET_RTX_CLASS (GET_CODE (a)) != RTX_COMPARE)
15291debfc3dSmrg || (GET_RTX_CLASS (GET_CODE (b)) != RTX_COMM_COMPARE
15301debfc3dSmrg && GET_RTX_CLASS (GET_CODE (b)) != RTX_COMPARE))
15311debfc3dSmrg return false;
15321debfc3dSmrg
15331debfc3dSmrg op0 = XEXP (a, 0);
15341debfc3dSmrg op1 = XEXP (a, 1);
15351debfc3dSmrg opb0 = XEXP (b, 0);
15361debfc3dSmrg opb1 = XEXP (b, 1);
15371debfc3dSmrg
15381debfc3dSmrg mode = GET_MODE (op0);
15391debfc3dSmrg if (mode != GET_MODE (opb0))
15401debfc3dSmrg mode = VOIDmode;
15411debfc3dSmrg else if (mode == VOIDmode)
15421debfc3dSmrg {
15431debfc3dSmrg mode = GET_MODE (op1);
15441debfc3dSmrg if (mode != GET_MODE (opb1))
15451debfc3dSmrg mode = VOIDmode;
15461debfc3dSmrg }
15471debfc3dSmrg
15481debfc3dSmrg /* A < B implies A + 1 <= B. */
15491debfc3dSmrg if ((GET_CODE (a) == GT || GET_CODE (a) == LT)
15501debfc3dSmrg && (GET_CODE (b) == GE || GET_CODE (b) == LE))
15511debfc3dSmrg {
15521debfc3dSmrg
15531debfc3dSmrg if (GET_CODE (a) == GT)
15541debfc3dSmrg std::swap (op0, op1);
15551debfc3dSmrg
15561debfc3dSmrg if (GET_CODE (b) == GE)
15571debfc3dSmrg std::swap (opb0, opb1);
15581debfc3dSmrg
15591debfc3dSmrg if (SCALAR_INT_MODE_P (mode)
15601debfc3dSmrg && rtx_equal_p (op1, opb1)
15611debfc3dSmrg && simplify_gen_binary (MINUS, mode, opb0, op0) == const1_rtx)
15621debfc3dSmrg return true;
15631debfc3dSmrg return false;
15641debfc3dSmrg }
15651debfc3dSmrg
15661debfc3dSmrg /* A < B or A > B imply A != B. TODO: Likewise
15671debfc3dSmrg A + n < B implies A != B + n if neither wraps. */
15681debfc3dSmrg if (GET_CODE (b) == NE
15691debfc3dSmrg && (GET_CODE (a) == GT || GET_CODE (a) == GTU
15701debfc3dSmrg || GET_CODE (a) == LT || GET_CODE (a) == LTU))
15711debfc3dSmrg {
15721debfc3dSmrg if (rtx_equal_p (op0, opb0)
15731debfc3dSmrg && rtx_equal_p (op1, opb1))
15741debfc3dSmrg return true;
15751debfc3dSmrg }
15761debfc3dSmrg
15771debfc3dSmrg /* For unsigned comparisons, A != 0 implies A > 0 and A >= 1. */
15781debfc3dSmrg if (GET_CODE (a) == NE
15791debfc3dSmrg && op1 == const0_rtx)
15801debfc3dSmrg {
15811debfc3dSmrg if ((GET_CODE (b) == GTU
15821debfc3dSmrg && opb1 == const0_rtx)
15831debfc3dSmrg || (GET_CODE (b) == GEU
15841debfc3dSmrg && opb1 == const1_rtx))
15851debfc3dSmrg return rtx_equal_p (op0, opb0);
15861debfc3dSmrg }
15871debfc3dSmrg
15881debfc3dSmrg /* A != N is equivalent to A - (N + 1) <u -1. */
15891debfc3dSmrg if (GET_CODE (a) == NE
15901debfc3dSmrg && CONST_INT_P (op1)
15911debfc3dSmrg && GET_CODE (b) == LTU
15921debfc3dSmrg && opb1 == constm1_rtx
15931debfc3dSmrg && GET_CODE (opb0) == PLUS
15941debfc3dSmrg && CONST_INT_P (XEXP (opb0, 1))
15951debfc3dSmrg /* Avoid overflows. */
15961debfc3dSmrg && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
15971debfc3dSmrg != ((unsigned HOST_WIDE_INT)1
15981debfc3dSmrg << (HOST_BITS_PER_WIDE_INT - 1)) - 1)
15991debfc3dSmrg && INTVAL (XEXP (opb0, 1)) + 1 == -INTVAL (op1))
16001debfc3dSmrg return rtx_equal_p (op0, XEXP (opb0, 0));
16011debfc3dSmrg
16021debfc3dSmrg /* Likewise, A != N implies A - N > 0. */
16031debfc3dSmrg if (GET_CODE (a) == NE
16041debfc3dSmrg && CONST_INT_P (op1))
16051debfc3dSmrg {
16061debfc3dSmrg if (GET_CODE (b) == GTU
16071debfc3dSmrg && GET_CODE (opb0) == PLUS
16081debfc3dSmrg && opb1 == const0_rtx
16091debfc3dSmrg && CONST_INT_P (XEXP (opb0, 1))
16101debfc3dSmrg /* Avoid overflows. */
16111debfc3dSmrg && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
16121debfc3dSmrg != (HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1)))
16131debfc3dSmrg && rtx_equal_p (XEXP (opb0, 0), op0))
16141debfc3dSmrg return INTVAL (op1) == -INTVAL (XEXP (opb0, 1));
16151debfc3dSmrg if (GET_CODE (b) == GEU
16161debfc3dSmrg && GET_CODE (opb0) == PLUS
16171debfc3dSmrg && opb1 == const1_rtx
16181debfc3dSmrg && CONST_INT_P (XEXP (opb0, 1))
16191debfc3dSmrg /* Avoid overflows. */
16201debfc3dSmrg && ((unsigned HOST_WIDE_INT) INTVAL (XEXP (opb0, 1))
16211debfc3dSmrg != (HOST_WIDE_INT_1U << (HOST_BITS_PER_WIDE_INT - 1)))
16221debfc3dSmrg && rtx_equal_p (XEXP (opb0, 0), op0))
16231debfc3dSmrg return INTVAL (op1) == -INTVAL (XEXP (opb0, 1));
16241debfc3dSmrg }
16251debfc3dSmrg
16261debfc3dSmrg /* A >s X, where X is positive, implies A <u Y, if Y is negative. */
16271debfc3dSmrg if ((GET_CODE (a) == GT || GET_CODE (a) == GE)
16281debfc3dSmrg && CONST_INT_P (op1)
16291debfc3dSmrg && ((GET_CODE (a) == GT && op1 == constm1_rtx)
16301debfc3dSmrg || INTVAL (op1) >= 0)
16311debfc3dSmrg && GET_CODE (b) == LTU
16321debfc3dSmrg && CONST_INT_P (opb1)
16331debfc3dSmrg && rtx_equal_p (op0, opb0))
16341debfc3dSmrg return INTVAL (opb1) < 0;
16351debfc3dSmrg
16361debfc3dSmrg return false;
16371debfc3dSmrg }
16381debfc3dSmrg
16391debfc3dSmrg /* Canonicalizes COND so that
16401debfc3dSmrg
16411debfc3dSmrg (1) Ensure that operands are ordered according to
16421debfc3dSmrg swap_commutative_operands_p.
16431debfc3dSmrg (2) (LE x const) will be replaced with (LT x <const+1>) and similarly
16441debfc3dSmrg for GE, GEU, and LEU. */
16451debfc3dSmrg
16461debfc3dSmrg rtx
canon_condition(rtx cond)16471debfc3dSmrg canon_condition (rtx cond)
16481debfc3dSmrg {
16491debfc3dSmrg rtx op0, op1;
16501debfc3dSmrg enum rtx_code code;
16511debfc3dSmrg machine_mode mode;
16521debfc3dSmrg
16531debfc3dSmrg code = GET_CODE (cond);
16541debfc3dSmrg op0 = XEXP (cond, 0);
16551debfc3dSmrg op1 = XEXP (cond, 1);
16561debfc3dSmrg
16571debfc3dSmrg if (swap_commutative_operands_p (op0, op1))
16581debfc3dSmrg {
16591debfc3dSmrg code = swap_condition (code);
16601debfc3dSmrg std::swap (op0, op1);
16611debfc3dSmrg }
16621debfc3dSmrg
16631debfc3dSmrg mode = GET_MODE (op0);
16641debfc3dSmrg if (mode == VOIDmode)
16651debfc3dSmrg mode = GET_MODE (op1);
16661debfc3dSmrg gcc_assert (mode != VOIDmode);
16671debfc3dSmrg
16681debfc3dSmrg if (CONST_SCALAR_INT_P (op1) && GET_MODE_CLASS (mode) != MODE_CC)
16691debfc3dSmrg {
16701debfc3dSmrg rtx_mode_t const_val (op1, mode);
16711debfc3dSmrg
16721debfc3dSmrg switch (code)
16731debfc3dSmrg {
16741debfc3dSmrg case LE:
16751debfc3dSmrg if (wi::ne_p (const_val, wi::max_value (mode, SIGNED)))
16761debfc3dSmrg {
16771debfc3dSmrg code = LT;
16781debfc3dSmrg op1 = immed_wide_int_const (wi::add (const_val, 1), mode);
16791debfc3dSmrg }
16801debfc3dSmrg break;
16811debfc3dSmrg
16821debfc3dSmrg case GE:
16831debfc3dSmrg if (wi::ne_p (const_val, wi::min_value (mode, SIGNED)))
16841debfc3dSmrg {
16851debfc3dSmrg code = GT;
16861debfc3dSmrg op1 = immed_wide_int_const (wi::sub (const_val, 1), mode);
16871debfc3dSmrg }
16881debfc3dSmrg break;
16891debfc3dSmrg
16901debfc3dSmrg case LEU:
16911debfc3dSmrg if (wi::ne_p (const_val, -1))
16921debfc3dSmrg {
16931debfc3dSmrg code = LTU;
16941debfc3dSmrg op1 = immed_wide_int_const (wi::add (const_val, 1), mode);
16951debfc3dSmrg }
16961debfc3dSmrg break;
16971debfc3dSmrg
16981debfc3dSmrg case GEU:
16991debfc3dSmrg if (wi::ne_p (const_val, 0))
17001debfc3dSmrg {
17011debfc3dSmrg code = GTU;
17021debfc3dSmrg op1 = immed_wide_int_const (wi::sub (const_val, 1), mode);
17031debfc3dSmrg }
17041debfc3dSmrg break;
17051debfc3dSmrg
17061debfc3dSmrg default:
17071debfc3dSmrg break;
17081debfc3dSmrg }
17091debfc3dSmrg }
17101debfc3dSmrg
17111debfc3dSmrg if (op0 != XEXP (cond, 0)
17121debfc3dSmrg || op1 != XEXP (cond, 1)
17131debfc3dSmrg || code != GET_CODE (cond)
17141debfc3dSmrg || GET_MODE (cond) != SImode)
17151debfc3dSmrg cond = gen_rtx_fmt_ee (code, SImode, op0, op1);
17161debfc3dSmrg
17171debfc3dSmrg return cond;
17181debfc3dSmrg }
17191debfc3dSmrg
17201debfc3dSmrg /* Reverses CONDition; returns NULL if we cannot. */
17211debfc3dSmrg
17221debfc3dSmrg static rtx
reversed_condition(rtx cond)17231debfc3dSmrg reversed_condition (rtx cond)
17241debfc3dSmrg {
17251debfc3dSmrg enum rtx_code reversed;
17261debfc3dSmrg reversed = reversed_comparison_code (cond, NULL);
17271debfc3dSmrg if (reversed == UNKNOWN)
17281debfc3dSmrg return NULL_RTX;
17291debfc3dSmrg else
17301debfc3dSmrg return gen_rtx_fmt_ee (reversed,
17311debfc3dSmrg GET_MODE (cond), XEXP (cond, 0),
17321debfc3dSmrg XEXP (cond, 1));
17331debfc3dSmrg }
17341debfc3dSmrg
17351debfc3dSmrg /* Tries to use the fact that COND holds to simplify EXPR. ALTERED is the
17361debfc3dSmrg set of altered regs. */
17371debfc3dSmrg
17381debfc3dSmrg void
simplify_using_condition(rtx cond,rtx * expr,regset altered)17391debfc3dSmrg simplify_using_condition (rtx cond, rtx *expr, regset altered)
17401debfc3dSmrg {
17411debfc3dSmrg rtx rev, reve, exp = *expr;
17421debfc3dSmrg
17431debfc3dSmrg /* If some register gets altered later, we do not really speak about its
17441debfc3dSmrg value at the time of comparison. */
17451debfc3dSmrg if (altered && altered_reg_used (cond, altered))
17461debfc3dSmrg return;
17471debfc3dSmrg
17481debfc3dSmrg if (GET_CODE (cond) == EQ
17491debfc3dSmrg && REG_P (XEXP (cond, 0)) && CONSTANT_P (XEXP (cond, 1)))
17501debfc3dSmrg {
17511debfc3dSmrg *expr = simplify_replace_rtx (*expr, XEXP (cond, 0), XEXP (cond, 1));
17521debfc3dSmrg return;
17531debfc3dSmrg }
17541debfc3dSmrg
17551debfc3dSmrg if (!COMPARISON_P (exp))
17561debfc3dSmrg return;
17571debfc3dSmrg
17581debfc3dSmrg rev = reversed_condition (cond);
17591debfc3dSmrg reve = reversed_condition (exp);
17601debfc3dSmrg
17611debfc3dSmrg cond = canon_condition (cond);
17621debfc3dSmrg exp = canon_condition (exp);
17631debfc3dSmrg if (rev)
17641debfc3dSmrg rev = canon_condition (rev);
17651debfc3dSmrg if (reve)
17661debfc3dSmrg reve = canon_condition (reve);
17671debfc3dSmrg
17681debfc3dSmrg if (rtx_equal_p (exp, cond))
17691debfc3dSmrg {
17701debfc3dSmrg *expr = const_true_rtx;
17711debfc3dSmrg return;
17721debfc3dSmrg }
17731debfc3dSmrg
17741debfc3dSmrg if (rev && rtx_equal_p (exp, rev))
17751debfc3dSmrg {
17761debfc3dSmrg *expr = const0_rtx;
17771debfc3dSmrg return;
17781debfc3dSmrg }
17791debfc3dSmrg
17801debfc3dSmrg if (implies_p (cond, exp))
17811debfc3dSmrg {
17821debfc3dSmrg *expr = const_true_rtx;
17831debfc3dSmrg return;
17841debfc3dSmrg }
17851debfc3dSmrg
17861debfc3dSmrg if (reve && implies_p (cond, reve))
17871debfc3dSmrg {
17881debfc3dSmrg *expr = const0_rtx;
17891debfc3dSmrg return;
17901debfc3dSmrg }
17911debfc3dSmrg
17921debfc3dSmrg /* A proof by contradiction. If *EXPR implies (not cond), *EXPR must
17931debfc3dSmrg be false. */
17941debfc3dSmrg if (rev && implies_p (exp, rev))
17951debfc3dSmrg {
17961debfc3dSmrg *expr = const0_rtx;
17971debfc3dSmrg return;
17981debfc3dSmrg }
17991debfc3dSmrg
18001debfc3dSmrg /* Similarly, If (not *EXPR) implies (not cond), *EXPR must be true. */
18011debfc3dSmrg if (rev && reve && implies_p (reve, rev))
18021debfc3dSmrg {
18031debfc3dSmrg *expr = const_true_rtx;
18041debfc3dSmrg return;
18051debfc3dSmrg }
18061debfc3dSmrg
18071debfc3dSmrg /* We would like to have some other tests here. TODO. */
18081debfc3dSmrg
18091debfc3dSmrg return;
18101debfc3dSmrg }
18111debfc3dSmrg
18121debfc3dSmrg /* Use relationship between A and *B to eventually eliminate *B.
18131debfc3dSmrg OP is the operation we consider. */
18141debfc3dSmrg
18151debfc3dSmrg static void
eliminate_implied_condition(enum rtx_code op,rtx a,rtx * b)18161debfc3dSmrg eliminate_implied_condition (enum rtx_code op, rtx a, rtx *b)
18171debfc3dSmrg {
18181debfc3dSmrg switch (op)
18191debfc3dSmrg {
18201debfc3dSmrg case AND:
18211debfc3dSmrg /* If A implies *B, we may replace *B by true. */
18221debfc3dSmrg if (implies_p (a, *b))
18231debfc3dSmrg *b = const_true_rtx;
18241debfc3dSmrg break;
18251debfc3dSmrg
18261debfc3dSmrg case IOR:
18271debfc3dSmrg /* If *B implies A, we may replace *B by false. */
18281debfc3dSmrg if (implies_p (*b, a))
18291debfc3dSmrg *b = const0_rtx;
18301debfc3dSmrg break;
18311debfc3dSmrg
18321debfc3dSmrg default:
18331debfc3dSmrg gcc_unreachable ();
18341debfc3dSmrg }
18351debfc3dSmrg }
18361debfc3dSmrg
18371debfc3dSmrg /* Eliminates the conditions in TAIL that are implied by HEAD. OP is the
18381debfc3dSmrg operation we consider. */
18391debfc3dSmrg
18401debfc3dSmrg static void
eliminate_implied_conditions(enum rtx_code op,rtx * head,rtx tail)18411debfc3dSmrg eliminate_implied_conditions (enum rtx_code op, rtx *head, rtx tail)
18421debfc3dSmrg {
18431debfc3dSmrg rtx elt;
18441debfc3dSmrg
18451debfc3dSmrg for (elt = tail; elt; elt = XEXP (elt, 1))
18461debfc3dSmrg eliminate_implied_condition (op, *head, &XEXP (elt, 0));
18471debfc3dSmrg for (elt = tail; elt; elt = XEXP (elt, 1))
18481debfc3dSmrg eliminate_implied_condition (op, XEXP (elt, 0), head);
18491debfc3dSmrg }
18501debfc3dSmrg
18511debfc3dSmrg /* Simplifies *EXPR using initial values at the start of the LOOP. If *EXPR
18521debfc3dSmrg is a list, its elements are assumed to be combined using OP. */
18531debfc3dSmrg
18541debfc3dSmrg static void
simplify_using_initial_values(class loop * loop,enum rtx_code op,rtx * expr)1855*8feb0f0bSmrg simplify_using_initial_values (class loop *loop, enum rtx_code op, rtx *expr)
18561debfc3dSmrg {
18571debfc3dSmrg bool expression_valid;
18581debfc3dSmrg rtx head, tail, last_valid_expr;
18591debfc3dSmrg rtx_expr_list *cond_list;
18601debfc3dSmrg rtx_insn *insn;
18611debfc3dSmrg rtx neutral, aggr;
18621debfc3dSmrg regset altered, this_altered;
18631debfc3dSmrg edge e;
18641debfc3dSmrg
18651debfc3dSmrg if (!*expr)
18661debfc3dSmrg return;
18671debfc3dSmrg
18681debfc3dSmrg if (CONSTANT_P (*expr))
18691debfc3dSmrg return;
18701debfc3dSmrg
18711debfc3dSmrg if (GET_CODE (*expr) == EXPR_LIST)
18721debfc3dSmrg {
18731debfc3dSmrg head = XEXP (*expr, 0);
18741debfc3dSmrg tail = XEXP (*expr, 1);
18751debfc3dSmrg
18761debfc3dSmrg eliminate_implied_conditions (op, &head, tail);
18771debfc3dSmrg
18781debfc3dSmrg switch (op)
18791debfc3dSmrg {
18801debfc3dSmrg case AND:
18811debfc3dSmrg neutral = const_true_rtx;
18821debfc3dSmrg aggr = const0_rtx;
18831debfc3dSmrg break;
18841debfc3dSmrg
18851debfc3dSmrg case IOR:
18861debfc3dSmrg neutral = const0_rtx;
18871debfc3dSmrg aggr = const_true_rtx;
18881debfc3dSmrg break;
18891debfc3dSmrg
18901debfc3dSmrg default:
18911debfc3dSmrg gcc_unreachable ();
18921debfc3dSmrg }
18931debfc3dSmrg
18941debfc3dSmrg simplify_using_initial_values (loop, UNKNOWN, &head);
18951debfc3dSmrg if (head == aggr)
18961debfc3dSmrg {
18971debfc3dSmrg XEXP (*expr, 0) = aggr;
18981debfc3dSmrg XEXP (*expr, 1) = NULL_RTX;
18991debfc3dSmrg return;
19001debfc3dSmrg }
19011debfc3dSmrg else if (head == neutral)
19021debfc3dSmrg {
19031debfc3dSmrg *expr = tail;
19041debfc3dSmrg simplify_using_initial_values (loop, op, expr);
19051debfc3dSmrg return;
19061debfc3dSmrg }
19071debfc3dSmrg simplify_using_initial_values (loop, op, &tail);
19081debfc3dSmrg
19091debfc3dSmrg if (tail && XEXP (tail, 0) == aggr)
19101debfc3dSmrg {
19111debfc3dSmrg *expr = tail;
19121debfc3dSmrg return;
19131debfc3dSmrg }
19141debfc3dSmrg
19151debfc3dSmrg XEXP (*expr, 0) = head;
19161debfc3dSmrg XEXP (*expr, 1) = tail;
19171debfc3dSmrg return;
19181debfc3dSmrg }
19191debfc3dSmrg
19201debfc3dSmrg gcc_assert (op == UNKNOWN);
19211debfc3dSmrg
19221debfc3dSmrg replace_single_def_regs (expr);
19231debfc3dSmrg if (CONSTANT_P (*expr))
19241debfc3dSmrg return;
19251debfc3dSmrg
19261debfc3dSmrg e = loop_preheader_edge (loop);
19271debfc3dSmrg if (e->src == ENTRY_BLOCK_PTR_FOR_FN (cfun))
19281debfc3dSmrg return;
19291debfc3dSmrg
19301debfc3dSmrg altered = ALLOC_REG_SET (®_obstack);
19311debfc3dSmrg this_altered = ALLOC_REG_SET (®_obstack);
19321debfc3dSmrg
19331debfc3dSmrg expression_valid = true;
19341debfc3dSmrg last_valid_expr = *expr;
19351debfc3dSmrg cond_list = NULL;
19361debfc3dSmrg while (1)
19371debfc3dSmrg {
19381debfc3dSmrg insn = BB_END (e->src);
19391debfc3dSmrg if (any_condjump_p (insn))
19401debfc3dSmrg {
19411debfc3dSmrg rtx cond = get_condition (BB_END (e->src), NULL, false, true);
19421debfc3dSmrg
19431debfc3dSmrg if (cond && (e->flags & EDGE_FALLTHRU))
19441debfc3dSmrg cond = reversed_condition (cond);
19451debfc3dSmrg if (cond)
19461debfc3dSmrg {
19471debfc3dSmrg rtx old = *expr;
19481debfc3dSmrg simplify_using_condition (cond, expr, altered);
19491debfc3dSmrg if (old != *expr)
19501debfc3dSmrg {
19511debfc3dSmrg rtx note;
19521debfc3dSmrg if (CONSTANT_P (*expr))
19531debfc3dSmrg goto out;
19541debfc3dSmrg for (note = cond_list; note; note = XEXP (note, 1))
19551debfc3dSmrg {
19561debfc3dSmrg simplify_using_condition (XEXP (note, 0), expr, altered);
19571debfc3dSmrg if (CONSTANT_P (*expr))
19581debfc3dSmrg goto out;
19591debfc3dSmrg }
19601debfc3dSmrg }
19611debfc3dSmrg cond_list = alloc_EXPR_LIST (0, cond, cond_list);
19621debfc3dSmrg }
19631debfc3dSmrg }
19641debfc3dSmrg
19651debfc3dSmrg FOR_BB_INSNS_REVERSE (e->src, insn)
19661debfc3dSmrg {
19671debfc3dSmrg rtx src, dest;
19681debfc3dSmrg rtx old = *expr;
19691debfc3dSmrg
19701debfc3dSmrg if (!INSN_P (insn))
19711debfc3dSmrg continue;
19721debfc3dSmrg
19731debfc3dSmrg CLEAR_REG_SET (this_altered);
1974*8feb0f0bSmrg note_stores (insn, mark_altered, this_altered);
19751debfc3dSmrg if (CALL_P (insn))
19761debfc3dSmrg {
1977*8feb0f0bSmrg /* Kill all registers that might be clobbered by the call.
1978*8feb0f0bSmrg We don't track modes of hard registers, so we need to be
1979*8feb0f0bSmrg conservative and assume that partial kills are full kills. */
1980*8feb0f0bSmrg function_abi callee_abi = insn_callee_abi (insn);
1981*8feb0f0bSmrg IOR_REG_SET_HRS (this_altered,
1982*8feb0f0bSmrg callee_abi.full_and_partial_reg_clobbers ());
19831debfc3dSmrg }
19841debfc3dSmrg
19851debfc3dSmrg if (suitable_set_for_replacement (insn, &dest, &src))
19861debfc3dSmrg {
19871debfc3dSmrg rtx_expr_list **pnote, **pnote_next;
19881debfc3dSmrg
19891debfc3dSmrg replace_in_expr (expr, dest, src);
19901debfc3dSmrg if (CONSTANT_P (*expr))
19911debfc3dSmrg goto out;
19921debfc3dSmrg
19931debfc3dSmrg for (pnote = &cond_list; *pnote; pnote = pnote_next)
19941debfc3dSmrg {
19951debfc3dSmrg rtx_expr_list *note = *pnote;
19961debfc3dSmrg rtx old_cond = XEXP (note, 0);
19971debfc3dSmrg
19981debfc3dSmrg pnote_next = (rtx_expr_list **)&XEXP (note, 1);
19991debfc3dSmrg replace_in_expr (&XEXP (note, 0), dest, src);
20001debfc3dSmrg
20011debfc3dSmrg /* We can no longer use a condition that has been simplified
20021debfc3dSmrg to a constant, and simplify_using_condition will abort if
20031debfc3dSmrg we try. */
20041debfc3dSmrg if (CONSTANT_P (XEXP (note, 0)))
20051debfc3dSmrg {
20061debfc3dSmrg *pnote = *pnote_next;
20071debfc3dSmrg pnote_next = pnote;
20081debfc3dSmrg free_EXPR_LIST_node (note);
20091debfc3dSmrg }
20101debfc3dSmrg /* Retry simplifications with this condition if either the
20111debfc3dSmrg expression or the condition changed. */
20121debfc3dSmrg else if (old_cond != XEXP (note, 0) || old != *expr)
20131debfc3dSmrg simplify_using_condition (XEXP (note, 0), expr, altered);
20141debfc3dSmrg }
20151debfc3dSmrg }
20161debfc3dSmrg else
20171debfc3dSmrg {
20181debfc3dSmrg rtx_expr_list **pnote, **pnote_next;
20191debfc3dSmrg
20201debfc3dSmrg /* If we did not use this insn to make a replacement, any overlap
20211debfc3dSmrg between stores in this insn and our expression will cause the
20221debfc3dSmrg expression to become invalid. */
20231debfc3dSmrg if (altered_reg_used (*expr, this_altered))
20241debfc3dSmrg goto out;
20251debfc3dSmrg
20261debfc3dSmrg /* Likewise for the conditions. */
20271debfc3dSmrg for (pnote = &cond_list; *pnote; pnote = pnote_next)
20281debfc3dSmrg {
20291debfc3dSmrg rtx_expr_list *note = *pnote;
20301debfc3dSmrg rtx old_cond = XEXP (note, 0);
20311debfc3dSmrg
20321debfc3dSmrg pnote_next = (rtx_expr_list **)&XEXP (note, 1);
20331debfc3dSmrg if (altered_reg_used (old_cond, this_altered))
20341debfc3dSmrg {
20351debfc3dSmrg *pnote = *pnote_next;
20361debfc3dSmrg pnote_next = pnote;
20371debfc3dSmrg free_EXPR_LIST_node (note);
20381debfc3dSmrg }
20391debfc3dSmrg }
20401debfc3dSmrg }
20411debfc3dSmrg
20421debfc3dSmrg if (CONSTANT_P (*expr))
20431debfc3dSmrg goto out;
20441debfc3dSmrg
20451debfc3dSmrg IOR_REG_SET (altered, this_altered);
20461debfc3dSmrg
20471debfc3dSmrg /* If the expression now contains regs that have been altered, we
20481debfc3dSmrg can't return it to the caller. However, it is still valid for
20491debfc3dSmrg further simplification, so keep searching to see if we can
20501debfc3dSmrg eventually turn it into a constant. */
20511debfc3dSmrg if (altered_reg_used (*expr, altered))
20521debfc3dSmrg expression_valid = false;
20531debfc3dSmrg if (expression_valid)
20541debfc3dSmrg last_valid_expr = *expr;
20551debfc3dSmrg }
20561debfc3dSmrg
20571debfc3dSmrg if (!single_pred_p (e->src)
20581debfc3dSmrg || single_pred (e->src) == ENTRY_BLOCK_PTR_FOR_FN (cfun))
20591debfc3dSmrg break;
20601debfc3dSmrg e = single_pred_edge (e->src);
20611debfc3dSmrg }
20621debfc3dSmrg
20631debfc3dSmrg out:
20641debfc3dSmrg free_EXPR_LIST_list (&cond_list);
20651debfc3dSmrg if (!CONSTANT_P (*expr))
20661debfc3dSmrg *expr = last_valid_expr;
20671debfc3dSmrg FREE_REG_SET (altered);
20681debfc3dSmrg FREE_REG_SET (this_altered);
20691debfc3dSmrg }
20701debfc3dSmrg
20711debfc3dSmrg /* Transforms invariant IV into MODE. Adds assumptions based on the fact
20721debfc3dSmrg that IV occurs as left operands of comparison COND and its signedness
20731debfc3dSmrg is SIGNED_P to DESC. */
20741debfc3dSmrg
20751debfc3dSmrg static void
shorten_into_mode(class rtx_iv * iv,scalar_int_mode mode,enum rtx_code cond,bool signed_p,class niter_desc * desc)2076*8feb0f0bSmrg shorten_into_mode (class rtx_iv *iv, scalar_int_mode mode,
2077*8feb0f0bSmrg enum rtx_code cond, bool signed_p, class niter_desc *desc)
20781debfc3dSmrg {
20791debfc3dSmrg rtx mmin, mmax, cond_over, cond_under;
20801debfc3dSmrg
20811debfc3dSmrg get_mode_bounds (mode, signed_p, iv->extend_mode, &mmin, &mmax);
20821debfc3dSmrg cond_under = simplify_gen_relational (LT, SImode, iv->extend_mode,
20831debfc3dSmrg iv->base, mmin);
20841debfc3dSmrg cond_over = simplify_gen_relational (GT, SImode, iv->extend_mode,
20851debfc3dSmrg iv->base, mmax);
20861debfc3dSmrg
20871debfc3dSmrg switch (cond)
20881debfc3dSmrg {
20891debfc3dSmrg case LE:
20901debfc3dSmrg case LT:
20911debfc3dSmrg case LEU:
20921debfc3dSmrg case LTU:
20931debfc3dSmrg if (cond_under != const0_rtx)
20941debfc3dSmrg desc->infinite =
20951debfc3dSmrg alloc_EXPR_LIST (0, cond_under, desc->infinite);
20961debfc3dSmrg if (cond_over != const0_rtx)
20971debfc3dSmrg desc->noloop_assumptions =
20981debfc3dSmrg alloc_EXPR_LIST (0, cond_over, desc->noloop_assumptions);
20991debfc3dSmrg break;
21001debfc3dSmrg
21011debfc3dSmrg case GE:
21021debfc3dSmrg case GT:
21031debfc3dSmrg case GEU:
21041debfc3dSmrg case GTU:
21051debfc3dSmrg if (cond_over != const0_rtx)
21061debfc3dSmrg desc->infinite =
21071debfc3dSmrg alloc_EXPR_LIST (0, cond_over, desc->infinite);
21081debfc3dSmrg if (cond_under != const0_rtx)
21091debfc3dSmrg desc->noloop_assumptions =
21101debfc3dSmrg alloc_EXPR_LIST (0, cond_under, desc->noloop_assumptions);
21111debfc3dSmrg break;
21121debfc3dSmrg
21131debfc3dSmrg case NE:
21141debfc3dSmrg if (cond_over != const0_rtx)
21151debfc3dSmrg desc->infinite =
21161debfc3dSmrg alloc_EXPR_LIST (0, cond_over, desc->infinite);
21171debfc3dSmrg if (cond_under != const0_rtx)
21181debfc3dSmrg desc->infinite =
21191debfc3dSmrg alloc_EXPR_LIST (0, cond_under, desc->infinite);
21201debfc3dSmrg break;
21211debfc3dSmrg
21221debfc3dSmrg default:
21231debfc3dSmrg gcc_unreachable ();
21241debfc3dSmrg }
21251debfc3dSmrg
21261debfc3dSmrg iv->mode = mode;
21271debfc3dSmrg iv->extend = signed_p ? IV_SIGN_EXTEND : IV_ZERO_EXTEND;
21281debfc3dSmrg }
21291debfc3dSmrg
21301debfc3dSmrg /* Transforms IV0 and IV1 compared by COND so that they are both compared as
21311debfc3dSmrg subregs of the same mode if possible (sometimes it is necessary to add
21321debfc3dSmrg some assumptions to DESC). */
21331debfc3dSmrg
21341debfc3dSmrg static bool
canonicalize_iv_subregs(class rtx_iv * iv0,class rtx_iv * iv1,enum rtx_code cond,class niter_desc * desc)2135*8feb0f0bSmrg canonicalize_iv_subregs (class rtx_iv *iv0, class rtx_iv *iv1,
2136*8feb0f0bSmrg enum rtx_code cond, class niter_desc *desc)
21371debfc3dSmrg {
2138a2dc1f3fSmrg scalar_int_mode comp_mode;
21391debfc3dSmrg bool signed_p;
21401debfc3dSmrg
21411debfc3dSmrg /* If the ivs behave specially in the first iteration, or are
21421debfc3dSmrg added/multiplied after extending, we ignore them. */
21431debfc3dSmrg if (iv0->first_special || iv0->mult != const1_rtx || iv0->delta != const0_rtx)
21441debfc3dSmrg return false;
21451debfc3dSmrg if (iv1->first_special || iv1->mult != const1_rtx || iv1->delta != const0_rtx)
21461debfc3dSmrg return false;
21471debfc3dSmrg
21481debfc3dSmrg /* If there is some extend, it must match signedness of the comparison. */
21491debfc3dSmrg switch (cond)
21501debfc3dSmrg {
21511debfc3dSmrg case LE:
21521debfc3dSmrg case LT:
21531debfc3dSmrg if (iv0->extend == IV_ZERO_EXTEND
21541debfc3dSmrg || iv1->extend == IV_ZERO_EXTEND)
21551debfc3dSmrg return false;
21561debfc3dSmrg signed_p = true;
21571debfc3dSmrg break;
21581debfc3dSmrg
21591debfc3dSmrg case LEU:
21601debfc3dSmrg case LTU:
21611debfc3dSmrg if (iv0->extend == IV_SIGN_EXTEND
21621debfc3dSmrg || iv1->extend == IV_SIGN_EXTEND)
21631debfc3dSmrg return false;
21641debfc3dSmrg signed_p = false;
21651debfc3dSmrg break;
21661debfc3dSmrg
21671debfc3dSmrg case NE:
21681debfc3dSmrg if (iv0->extend != IV_UNKNOWN_EXTEND
21691debfc3dSmrg && iv1->extend != IV_UNKNOWN_EXTEND
21701debfc3dSmrg && iv0->extend != iv1->extend)
21711debfc3dSmrg return false;
21721debfc3dSmrg
21731debfc3dSmrg signed_p = false;
21741debfc3dSmrg if (iv0->extend != IV_UNKNOWN_EXTEND)
21751debfc3dSmrg signed_p = iv0->extend == IV_SIGN_EXTEND;
21761debfc3dSmrg if (iv1->extend != IV_UNKNOWN_EXTEND)
21771debfc3dSmrg signed_p = iv1->extend == IV_SIGN_EXTEND;
21781debfc3dSmrg break;
21791debfc3dSmrg
21801debfc3dSmrg default:
21811debfc3dSmrg gcc_unreachable ();
21821debfc3dSmrg }
21831debfc3dSmrg
21841debfc3dSmrg /* Values of both variables should be computed in the same mode. These
21851debfc3dSmrg might indeed be different, if we have comparison like
21861debfc3dSmrg
21871debfc3dSmrg (compare (subreg:SI (iv0)) (subreg:SI (iv1)))
21881debfc3dSmrg
21891debfc3dSmrg and iv0 and iv1 are both ivs iterating in SI mode, but calculated
21901debfc3dSmrg in different modes. This does not seem impossible to handle, but
21911debfc3dSmrg it hardly ever occurs in practice.
21921debfc3dSmrg
21931debfc3dSmrg The only exception is the case when one of operands is invariant.
21941debfc3dSmrg For example pentium 3 generates comparisons like
21951debfc3dSmrg (lt (subreg:HI (reg:SI)) 100). Here we assign HImode to 100, but we
21961debfc3dSmrg definitely do not want this prevent the optimization. */
21971debfc3dSmrg comp_mode = iv0->extend_mode;
21981debfc3dSmrg if (GET_MODE_BITSIZE (comp_mode) < GET_MODE_BITSIZE (iv1->extend_mode))
21991debfc3dSmrg comp_mode = iv1->extend_mode;
22001debfc3dSmrg
22011debfc3dSmrg if (iv0->extend_mode != comp_mode)
22021debfc3dSmrg {
22031debfc3dSmrg if (iv0->mode != iv0->extend_mode
22041debfc3dSmrg || iv0->step != const0_rtx)
22051debfc3dSmrg return false;
22061debfc3dSmrg
22071debfc3dSmrg iv0->base = simplify_gen_unary (signed_p ? SIGN_EXTEND : ZERO_EXTEND,
22081debfc3dSmrg comp_mode, iv0->base, iv0->mode);
22091debfc3dSmrg iv0->extend_mode = comp_mode;
22101debfc3dSmrg }
22111debfc3dSmrg
22121debfc3dSmrg if (iv1->extend_mode != comp_mode)
22131debfc3dSmrg {
22141debfc3dSmrg if (iv1->mode != iv1->extend_mode
22151debfc3dSmrg || iv1->step != const0_rtx)
22161debfc3dSmrg return false;
22171debfc3dSmrg
22181debfc3dSmrg iv1->base = simplify_gen_unary (signed_p ? SIGN_EXTEND : ZERO_EXTEND,
22191debfc3dSmrg comp_mode, iv1->base, iv1->mode);
22201debfc3dSmrg iv1->extend_mode = comp_mode;
22211debfc3dSmrg }
22221debfc3dSmrg
22231debfc3dSmrg /* Check that both ivs belong to a range of a single mode. If one of the
22241debfc3dSmrg operands is an invariant, we may need to shorten it into the common
22251debfc3dSmrg mode. */
22261debfc3dSmrg if (iv0->mode == iv0->extend_mode
22271debfc3dSmrg && iv0->step == const0_rtx
22281debfc3dSmrg && iv0->mode != iv1->mode)
22291debfc3dSmrg shorten_into_mode (iv0, iv1->mode, cond, signed_p, desc);
22301debfc3dSmrg
22311debfc3dSmrg if (iv1->mode == iv1->extend_mode
22321debfc3dSmrg && iv1->step == const0_rtx
22331debfc3dSmrg && iv0->mode != iv1->mode)
22341debfc3dSmrg shorten_into_mode (iv1, iv0->mode, swap_condition (cond), signed_p, desc);
22351debfc3dSmrg
22361debfc3dSmrg if (iv0->mode != iv1->mode)
22371debfc3dSmrg return false;
22381debfc3dSmrg
22391debfc3dSmrg desc->mode = iv0->mode;
22401debfc3dSmrg desc->signed_p = signed_p;
22411debfc3dSmrg
22421debfc3dSmrg return true;
22431debfc3dSmrg }
22441debfc3dSmrg
22451debfc3dSmrg /* Tries to estimate the maximum number of iterations in LOOP, and return the
22461debfc3dSmrg result. This function is called from iv_number_of_iterations with
22471debfc3dSmrg a number of fields in DESC already filled in. OLD_NITER is the original
22481debfc3dSmrg expression for the number of iterations, before we tried to simplify it. */
22491debfc3dSmrg
22501debfc3dSmrg static uint64_t
determine_max_iter(class loop * loop,class niter_desc * desc,rtx old_niter)2251*8feb0f0bSmrg determine_max_iter (class loop *loop, class niter_desc *desc, rtx old_niter)
22521debfc3dSmrg {
22531debfc3dSmrg rtx niter = desc->niter_expr;
22541debfc3dSmrg rtx mmin, mmax, cmp;
22551debfc3dSmrg uint64_t nmax, inc;
22561debfc3dSmrg uint64_t andmax = 0;
22571debfc3dSmrg
22581debfc3dSmrg /* We used to look for constant operand 0 of AND,
22591debfc3dSmrg but canonicalization should always make this impossible. */
22601debfc3dSmrg gcc_checking_assert (GET_CODE (niter) != AND
22611debfc3dSmrg || !CONST_INT_P (XEXP (niter, 0)));
22621debfc3dSmrg
22631debfc3dSmrg if (GET_CODE (niter) == AND
22641debfc3dSmrg && CONST_INT_P (XEXP (niter, 1)))
22651debfc3dSmrg {
22661debfc3dSmrg andmax = UINTVAL (XEXP (niter, 1));
22671debfc3dSmrg niter = XEXP (niter, 0);
22681debfc3dSmrg }
22691debfc3dSmrg
22701debfc3dSmrg get_mode_bounds (desc->mode, desc->signed_p, desc->mode, &mmin, &mmax);
22711debfc3dSmrg nmax = UINTVAL (mmax) - UINTVAL (mmin);
22721debfc3dSmrg
22731debfc3dSmrg if (GET_CODE (niter) == UDIV)
22741debfc3dSmrg {
22751debfc3dSmrg if (!CONST_INT_P (XEXP (niter, 1)))
22761debfc3dSmrg return nmax;
22771debfc3dSmrg inc = INTVAL (XEXP (niter, 1));
22781debfc3dSmrg niter = XEXP (niter, 0);
22791debfc3dSmrg }
22801debfc3dSmrg else
22811debfc3dSmrg inc = 1;
22821debfc3dSmrg
22831debfc3dSmrg /* We could use a binary search here, but for now improving the upper
22841debfc3dSmrg bound by just one eliminates one important corner case. */
22851debfc3dSmrg cmp = simplify_gen_relational (desc->signed_p ? LT : LTU, VOIDmode,
22861debfc3dSmrg desc->mode, old_niter, mmax);
22871debfc3dSmrg simplify_using_initial_values (loop, UNKNOWN, &cmp);
22881debfc3dSmrg if (cmp == const_true_rtx)
22891debfc3dSmrg {
22901debfc3dSmrg nmax--;
22911debfc3dSmrg
22921debfc3dSmrg if (dump_file)
22931debfc3dSmrg fprintf (dump_file, ";; improved upper bound by one.\n");
22941debfc3dSmrg }
22951debfc3dSmrg nmax /= inc;
22961debfc3dSmrg if (andmax)
22971debfc3dSmrg nmax = MIN (nmax, andmax);
22981debfc3dSmrg if (dump_file)
22991debfc3dSmrg fprintf (dump_file, ";; Determined upper bound %" PRId64".\n",
23001debfc3dSmrg nmax);
23011debfc3dSmrg return nmax;
23021debfc3dSmrg }
23031debfc3dSmrg
23041debfc3dSmrg /* Computes number of iterations of the CONDITION in INSN in LOOP and stores
23051debfc3dSmrg the result into DESC. Very similar to determine_number_of_iterations
23061debfc3dSmrg (basically its rtl version), complicated by things like subregs. */
23071debfc3dSmrg
23081debfc3dSmrg static void
iv_number_of_iterations(class loop * loop,rtx_insn * insn,rtx condition,class niter_desc * desc)2309*8feb0f0bSmrg iv_number_of_iterations (class loop *loop, rtx_insn *insn, rtx condition,
2310*8feb0f0bSmrg class niter_desc *desc)
23111debfc3dSmrg {
23121debfc3dSmrg rtx op0, op1, delta, step, bound, may_xform, tmp, tmp0, tmp1;
2313*8feb0f0bSmrg class rtx_iv iv0, iv1;
23141debfc3dSmrg rtx assumption, may_not_xform;
23151debfc3dSmrg enum rtx_code cond;
2316a2dc1f3fSmrg machine_mode nonvoid_mode;
2317a2dc1f3fSmrg scalar_int_mode comp_mode;
23181debfc3dSmrg rtx mmin, mmax, mode_mmin, mode_mmax;
23191debfc3dSmrg uint64_t s, size, d, inv, max, up, down;
23201debfc3dSmrg int64_t inc, step_val;
23211debfc3dSmrg int was_sharp = false;
23221debfc3dSmrg rtx old_niter;
23231debfc3dSmrg bool step_is_pow2;
23241debfc3dSmrg
23251debfc3dSmrg /* The meaning of these assumptions is this:
23261debfc3dSmrg if !assumptions
23271debfc3dSmrg then the rest of information does not have to be valid
23281debfc3dSmrg if noloop_assumptions then the loop does not roll
23291debfc3dSmrg if infinite then this exit is never used */
23301debfc3dSmrg
23311debfc3dSmrg desc->assumptions = NULL_RTX;
23321debfc3dSmrg desc->noloop_assumptions = NULL_RTX;
23331debfc3dSmrg desc->infinite = NULL_RTX;
23341debfc3dSmrg desc->simple_p = true;
23351debfc3dSmrg
23361debfc3dSmrg desc->const_iter = false;
23371debfc3dSmrg desc->niter_expr = NULL_RTX;
23381debfc3dSmrg
23391debfc3dSmrg cond = GET_CODE (condition);
23401debfc3dSmrg gcc_assert (COMPARISON_P (condition));
23411debfc3dSmrg
2342a2dc1f3fSmrg nonvoid_mode = GET_MODE (XEXP (condition, 0));
2343a2dc1f3fSmrg if (nonvoid_mode == VOIDmode)
2344a2dc1f3fSmrg nonvoid_mode = GET_MODE (XEXP (condition, 1));
23451debfc3dSmrg /* The constant comparisons should be folded. */
2346a2dc1f3fSmrg gcc_assert (nonvoid_mode != VOIDmode);
23471debfc3dSmrg
23481debfc3dSmrg /* We only handle integers or pointers. */
2349a2dc1f3fSmrg scalar_int_mode mode;
2350a2dc1f3fSmrg if (!is_a <scalar_int_mode> (nonvoid_mode, &mode))
23511debfc3dSmrg goto fail;
23521debfc3dSmrg
23531debfc3dSmrg op0 = XEXP (condition, 0);
2354a2dc1f3fSmrg if (!iv_analyze (insn, mode, op0, &iv0))
23551debfc3dSmrg goto fail;
23561debfc3dSmrg
23571debfc3dSmrg op1 = XEXP (condition, 1);
2358a2dc1f3fSmrg if (!iv_analyze (insn, mode, op1, &iv1))
23591debfc3dSmrg goto fail;
23601debfc3dSmrg
23611debfc3dSmrg if (GET_MODE_BITSIZE (iv0.extend_mode) > HOST_BITS_PER_WIDE_INT
23621debfc3dSmrg || GET_MODE_BITSIZE (iv1.extend_mode) > HOST_BITS_PER_WIDE_INT)
23631debfc3dSmrg goto fail;
23641debfc3dSmrg
23651debfc3dSmrg /* Check condition and normalize it. */
23661debfc3dSmrg
23671debfc3dSmrg switch (cond)
23681debfc3dSmrg {
23691debfc3dSmrg case GE:
23701debfc3dSmrg case GT:
23711debfc3dSmrg case GEU:
23721debfc3dSmrg case GTU:
23731debfc3dSmrg std::swap (iv0, iv1);
23741debfc3dSmrg cond = swap_condition (cond);
23751debfc3dSmrg break;
23761debfc3dSmrg case NE:
23771debfc3dSmrg case LE:
23781debfc3dSmrg case LEU:
23791debfc3dSmrg case LT:
23801debfc3dSmrg case LTU:
23811debfc3dSmrg break;
23821debfc3dSmrg default:
23831debfc3dSmrg goto fail;
23841debfc3dSmrg }
23851debfc3dSmrg
23861debfc3dSmrg /* Handle extends. This is relatively nontrivial, so we only try in some
23871debfc3dSmrg easy cases, when we can canonicalize the ivs (possibly by adding some
23881debfc3dSmrg assumptions) to shape subreg (base + i * step). This function also fills
23891debfc3dSmrg in desc->mode and desc->signed_p. */
23901debfc3dSmrg
23911debfc3dSmrg if (!canonicalize_iv_subregs (&iv0, &iv1, cond, desc))
23921debfc3dSmrg goto fail;
23931debfc3dSmrg
23941debfc3dSmrg comp_mode = iv0.extend_mode;
23951debfc3dSmrg mode = iv0.mode;
23961debfc3dSmrg size = GET_MODE_PRECISION (mode);
23971debfc3dSmrg get_mode_bounds (mode, (cond == LE || cond == LT), comp_mode, &mmin, &mmax);
23981debfc3dSmrg mode_mmin = lowpart_subreg (mode, mmin, comp_mode);
23991debfc3dSmrg mode_mmax = lowpart_subreg (mode, mmax, comp_mode);
24001debfc3dSmrg
24011debfc3dSmrg if (!CONST_INT_P (iv0.step) || !CONST_INT_P (iv1.step))
24021debfc3dSmrg goto fail;
24031debfc3dSmrg
24041debfc3dSmrg /* We can take care of the case of two induction variables chasing each other
24051debfc3dSmrg if the test is NE. I have never seen a loop using it, but still it is
24061debfc3dSmrg cool. */
24071debfc3dSmrg if (iv0.step != const0_rtx && iv1.step != const0_rtx)
24081debfc3dSmrg {
24091debfc3dSmrg if (cond != NE)
24101debfc3dSmrg goto fail;
24111debfc3dSmrg
24121debfc3dSmrg iv0.step = simplify_gen_binary (MINUS, comp_mode, iv0.step, iv1.step);
24131debfc3dSmrg iv1.step = const0_rtx;
24141debfc3dSmrg }
24151debfc3dSmrg
24161debfc3dSmrg iv0.step = lowpart_subreg (mode, iv0.step, comp_mode);
24171debfc3dSmrg iv1.step = lowpart_subreg (mode, iv1.step, comp_mode);
24181debfc3dSmrg
24191debfc3dSmrg /* This is either infinite loop or the one that ends immediately, depending
24201debfc3dSmrg on initial values. Unswitching should remove this kind of conditions. */
24211debfc3dSmrg if (iv0.step == const0_rtx && iv1.step == const0_rtx)
24221debfc3dSmrg goto fail;
24231debfc3dSmrg
24241debfc3dSmrg if (cond != NE)
24251debfc3dSmrg {
24261debfc3dSmrg if (iv0.step == const0_rtx)
24271debfc3dSmrg step_val = -INTVAL (iv1.step);
24281debfc3dSmrg else
24291debfc3dSmrg step_val = INTVAL (iv0.step);
24301debfc3dSmrg
24311debfc3dSmrg /* Ignore loops of while (i-- < 10) type. */
24321debfc3dSmrg if (step_val < 0)
24331debfc3dSmrg goto fail;
24341debfc3dSmrg
24351debfc3dSmrg step_is_pow2 = !(step_val & (step_val - 1));
24361debfc3dSmrg }
24371debfc3dSmrg else
24381debfc3dSmrg {
24391debfc3dSmrg /* We do not care about whether the step is power of two in this
24401debfc3dSmrg case. */
24411debfc3dSmrg step_is_pow2 = false;
24421debfc3dSmrg step_val = 0;
24431debfc3dSmrg }
24441debfc3dSmrg
24451debfc3dSmrg /* Some more condition normalization. We must record some assumptions
24461debfc3dSmrg due to overflows. */
24471debfc3dSmrg switch (cond)
24481debfc3dSmrg {
24491debfc3dSmrg case LT:
24501debfc3dSmrg case LTU:
24511debfc3dSmrg /* We want to take care only of non-sharp relationals; this is easy,
24521debfc3dSmrg as in cases the overflow would make the transformation unsafe
24531debfc3dSmrg the loop does not roll. Seemingly it would make more sense to want
24541debfc3dSmrg to take care of sharp relationals instead, as NE is more similar to
24551debfc3dSmrg them, but the problem is that here the transformation would be more
24561debfc3dSmrg difficult due to possibly infinite loops. */
24571debfc3dSmrg if (iv0.step == const0_rtx)
24581debfc3dSmrg {
24591debfc3dSmrg tmp = lowpart_subreg (mode, iv0.base, comp_mode);
24601debfc3dSmrg assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
24611debfc3dSmrg mode_mmax);
24621debfc3dSmrg if (assumption == const_true_rtx)
24631debfc3dSmrg goto zero_iter_simplify;
24641debfc3dSmrg iv0.base = simplify_gen_binary (PLUS, comp_mode,
24651debfc3dSmrg iv0.base, const1_rtx);
24661debfc3dSmrg }
24671debfc3dSmrg else
24681debfc3dSmrg {
24691debfc3dSmrg tmp = lowpart_subreg (mode, iv1.base, comp_mode);
24701debfc3dSmrg assumption = simplify_gen_relational (EQ, SImode, mode, tmp,
24711debfc3dSmrg mode_mmin);
24721debfc3dSmrg if (assumption == const_true_rtx)
24731debfc3dSmrg goto zero_iter_simplify;
24741debfc3dSmrg iv1.base = simplify_gen_binary (PLUS, comp_mode,
24751debfc3dSmrg iv1.base, constm1_rtx);
24761debfc3dSmrg }
24771debfc3dSmrg
24781debfc3dSmrg if (assumption != const0_rtx)
24791debfc3dSmrg desc->noloop_assumptions =
24801debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->noloop_assumptions);
24811debfc3dSmrg cond = (cond == LT) ? LE : LEU;
24821debfc3dSmrg
24831debfc3dSmrg /* It will be useful to be able to tell the difference once more in
24841debfc3dSmrg LE -> NE reduction. */
24851debfc3dSmrg was_sharp = true;
24861debfc3dSmrg break;
24871debfc3dSmrg default: ;
24881debfc3dSmrg }
24891debfc3dSmrg
24901debfc3dSmrg /* Take care of trivially infinite loops. */
24911debfc3dSmrg if (cond != NE)
24921debfc3dSmrg {
24931debfc3dSmrg if (iv0.step == const0_rtx)
24941debfc3dSmrg {
24951debfc3dSmrg tmp = lowpart_subreg (mode, iv0.base, comp_mode);
24961debfc3dSmrg if (rtx_equal_p (tmp, mode_mmin))
24971debfc3dSmrg {
24981debfc3dSmrg desc->infinite =
24991debfc3dSmrg alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
25001debfc3dSmrg /* Fill in the remaining fields somehow. */
25011debfc3dSmrg goto zero_iter_simplify;
25021debfc3dSmrg }
25031debfc3dSmrg }
25041debfc3dSmrg else
25051debfc3dSmrg {
25061debfc3dSmrg tmp = lowpart_subreg (mode, iv1.base, comp_mode);
25071debfc3dSmrg if (rtx_equal_p (tmp, mode_mmax))
25081debfc3dSmrg {
25091debfc3dSmrg desc->infinite =
25101debfc3dSmrg alloc_EXPR_LIST (0, const_true_rtx, NULL_RTX);
25111debfc3dSmrg /* Fill in the remaining fields somehow. */
25121debfc3dSmrg goto zero_iter_simplify;
25131debfc3dSmrg }
25141debfc3dSmrg }
25151debfc3dSmrg }
25161debfc3dSmrg
25171debfc3dSmrg /* If we can we want to take care of NE conditions instead of size
25181debfc3dSmrg comparisons, as they are much more friendly (most importantly
25191debfc3dSmrg this takes care of special handling of loops with step 1). We can
25201debfc3dSmrg do it if we first check that upper bound is greater or equal to
25211debfc3dSmrg lower bound, their difference is constant c modulo step and that
25221debfc3dSmrg there is not an overflow. */
25231debfc3dSmrg if (cond != NE)
25241debfc3dSmrg {
25251debfc3dSmrg if (iv0.step == const0_rtx)
25261debfc3dSmrg step = simplify_gen_unary (NEG, comp_mode, iv1.step, comp_mode);
25271debfc3dSmrg else
25281debfc3dSmrg step = iv0.step;
25291debfc3dSmrg step = lowpart_subreg (mode, step, comp_mode);
25301debfc3dSmrg delta = simplify_gen_binary (MINUS, comp_mode, iv1.base, iv0.base);
25311debfc3dSmrg delta = lowpart_subreg (mode, delta, comp_mode);
25321debfc3dSmrg delta = simplify_gen_binary (UMOD, mode, delta, step);
25331debfc3dSmrg may_xform = const0_rtx;
25341debfc3dSmrg may_not_xform = const_true_rtx;
25351debfc3dSmrg
25361debfc3dSmrg if (CONST_INT_P (delta))
25371debfc3dSmrg {
25381debfc3dSmrg if (was_sharp && INTVAL (delta) == INTVAL (step) - 1)
25391debfc3dSmrg {
25401debfc3dSmrg /* A special case. We have transformed condition of type
25411debfc3dSmrg for (i = 0; i < 4; i += 4)
25421debfc3dSmrg into
25431debfc3dSmrg for (i = 0; i <= 3; i += 4)
25441debfc3dSmrg obviously if the test for overflow during that transformation
25451debfc3dSmrg passed, we cannot overflow here. Most importantly any
25461debfc3dSmrg loop with sharp end condition and step 1 falls into this
25471debfc3dSmrg category, so handling this case specially is definitely
25481debfc3dSmrg worth the troubles. */
25491debfc3dSmrg may_xform = const_true_rtx;
25501debfc3dSmrg }
25511debfc3dSmrg else if (iv0.step == const0_rtx)
25521debfc3dSmrg {
25531debfc3dSmrg bound = simplify_gen_binary (PLUS, comp_mode, mmin, step);
25541debfc3dSmrg bound = simplify_gen_binary (MINUS, comp_mode, bound, delta);
25551debfc3dSmrg bound = lowpart_subreg (mode, bound, comp_mode);
25561debfc3dSmrg tmp = lowpart_subreg (mode, iv0.base, comp_mode);
25571debfc3dSmrg may_xform = simplify_gen_relational (cond, SImode, mode,
25581debfc3dSmrg bound, tmp);
25591debfc3dSmrg may_not_xform = simplify_gen_relational (reverse_condition (cond),
25601debfc3dSmrg SImode, mode,
25611debfc3dSmrg bound, tmp);
25621debfc3dSmrg }
25631debfc3dSmrg else
25641debfc3dSmrg {
25651debfc3dSmrg bound = simplify_gen_binary (MINUS, comp_mode, mmax, step);
25661debfc3dSmrg bound = simplify_gen_binary (PLUS, comp_mode, bound, delta);
25671debfc3dSmrg bound = lowpart_subreg (mode, bound, comp_mode);
25681debfc3dSmrg tmp = lowpart_subreg (mode, iv1.base, comp_mode);
25691debfc3dSmrg may_xform = simplify_gen_relational (cond, SImode, mode,
25701debfc3dSmrg tmp, bound);
25711debfc3dSmrg may_not_xform = simplify_gen_relational (reverse_condition (cond),
25721debfc3dSmrg SImode, mode,
25731debfc3dSmrg tmp, bound);
25741debfc3dSmrg }
25751debfc3dSmrg }
25761debfc3dSmrg
25771debfc3dSmrg if (may_xform != const0_rtx)
25781debfc3dSmrg {
25791debfc3dSmrg /* We perform the transformation always provided that it is not
25801debfc3dSmrg completely senseless. This is OK, as we would need this assumption
25811debfc3dSmrg to determine the number of iterations anyway. */
25821debfc3dSmrg if (may_xform != const_true_rtx)
25831debfc3dSmrg {
25841debfc3dSmrg /* If the step is a power of two and the final value we have
25851debfc3dSmrg computed overflows, the cycle is infinite. Otherwise it
25861debfc3dSmrg is nontrivial to compute the number of iterations. */
25871debfc3dSmrg if (step_is_pow2)
25881debfc3dSmrg desc->infinite = alloc_EXPR_LIST (0, may_not_xform,
25891debfc3dSmrg desc->infinite);
25901debfc3dSmrg else
25911debfc3dSmrg desc->assumptions = alloc_EXPR_LIST (0, may_xform,
25921debfc3dSmrg desc->assumptions);
25931debfc3dSmrg }
25941debfc3dSmrg
25951debfc3dSmrg /* We are going to lose some information about upper bound on
25961debfc3dSmrg number of iterations in this step, so record the information
25971debfc3dSmrg here. */
25981debfc3dSmrg inc = INTVAL (iv0.step) - INTVAL (iv1.step);
25991debfc3dSmrg if (CONST_INT_P (iv1.base))
26001debfc3dSmrg up = INTVAL (iv1.base);
26011debfc3dSmrg else
26021debfc3dSmrg up = INTVAL (mode_mmax) - inc;
26031debfc3dSmrg down = INTVAL (CONST_INT_P (iv0.base)
26041debfc3dSmrg ? iv0.base
26051debfc3dSmrg : mode_mmin);
26061debfc3dSmrg max = (up - down) / inc + 1;
26071debfc3dSmrg if (!desc->infinite
26081debfc3dSmrg && !desc->assumptions)
26091debfc3dSmrg record_niter_bound (loop, max, false, true);
26101debfc3dSmrg
26111debfc3dSmrg if (iv0.step == const0_rtx)
26121debfc3dSmrg {
26131debfc3dSmrg iv0.base = simplify_gen_binary (PLUS, comp_mode, iv0.base, delta);
26141debfc3dSmrg iv0.base = simplify_gen_binary (MINUS, comp_mode, iv0.base, step);
26151debfc3dSmrg }
26161debfc3dSmrg else
26171debfc3dSmrg {
26181debfc3dSmrg iv1.base = simplify_gen_binary (MINUS, comp_mode, iv1.base, delta);
26191debfc3dSmrg iv1.base = simplify_gen_binary (PLUS, comp_mode, iv1.base, step);
26201debfc3dSmrg }
26211debfc3dSmrg
26221debfc3dSmrg tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
26231debfc3dSmrg tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
26241debfc3dSmrg assumption = simplify_gen_relational (reverse_condition (cond),
26251debfc3dSmrg SImode, mode, tmp0, tmp1);
26261debfc3dSmrg if (assumption == const_true_rtx)
26271debfc3dSmrg goto zero_iter_simplify;
26281debfc3dSmrg else if (assumption != const0_rtx)
26291debfc3dSmrg desc->noloop_assumptions =
26301debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->noloop_assumptions);
26311debfc3dSmrg cond = NE;
26321debfc3dSmrg }
26331debfc3dSmrg }
26341debfc3dSmrg
26351debfc3dSmrg /* Count the number of iterations. */
26361debfc3dSmrg if (cond == NE)
26371debfc3dSmrg {
26381debfc3dSmrg /* Everything we do here is just arithmetics modulo size of mode. This
26391debfc3dSmrg makes us able to do more involved computations of number of iterations
26401debfc3dSmrg than in other cases. First transform the condition into shape
26411debfc3dSmrg s * i <> c, with s positive. */
26421debfc3dSmrg iv1.base = simplify_gen_binary (MINUS, comp_mode, iv1.base, iv0.base);
26431debfc3dSmrg iv0.base = const0_rtx;
26441debfc3dSmrg iv0.step = simplify_gen_binary (MINUS, comp_mode, iv0.step, iv1.step);
26451debfc3dSmrg iv1.step = const0_rtx;
26461debfc3dSmrg if (INTVAL (iv0.step) < 0)
26471debfc3dSmrg {
26481debfc3dSmrg iv0.step = simplify_gen_unary (NEG, comp_mode, iv0.step, comp_mode);
26491debfc3dSmrg iv1.base = simplify_gen_unary (NEG, comp_mode, iv1.base, comp_mode);
26501debfc3dSmrg }
26511debfc3dSmrg iv0.step = lowpart_subreg (mode, iv0.step, comp_mode);
26521debfc3dSmrg
26531debfc3dSmrg /* Let nsd (s, size of mode) = d. If d does not divide c, the loop
26541debfc3dSmrg is infinite. Otherwise, the number of iterations is
26551debfc3dSmrg (inverse(s/d) * (c/d)) mod (size of mode/d). */
26561debfc3dSmrg s = INTVAL (iv0.step); d = 1;
26571debfc3dSmrg while (s % 2 != 1)
26581debfc3dSmrg {
26591debfc3dSmrg s /= 2;
26601debfc3dSmrg d *= 2;
26611debfc3dSmrg size--;
26621debfc3dSmrg }
26631debfc3dSmrg bound = GEN_INT (((uint64_t) 1 << (size - 1 ) << 1) - 1);
26641debfc3dSmrg
26651debfc3dSmrg tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
26661debfc3dSmrg tmp = simplify_gen_binary (UMOD, mode, tmp1, gen_int_mode (d, mode));
26671debfc3dSmrg assumption = simplify_gen_relational (NE, SImode, mode, tmp, const0_rtx);
26681debfc3dSmrg desc->infinite = alloc_EXPR_LIST (0, assumption, desc->infinite);
26691debfc3dSmrg
26701debfc3dSmrg tmp = simplify_gen_binary (UDIV, mode, tmp1, gen_int_mode (d, mode));
26711debfc3dSmrg inv = inverse (s, size);
26721debfc3dSmrg tmp = simplify_gen_binary (MULT, mode, tmp, gen_int_mode (inv, mode));
26731debfc3dSmrg desc->niter_expr = simplify_gen_binary (AND, mode, tmp, bound);
26741debfc3dSmrg }
26751debfc3dSmrg else
26761debfc3dSmrg {
26771debfc3dSmrg if (iv1.step == const0_rtx)
26781debfc3dSmrg /* Condition in shape a + s * i <= b
26791debfc3dSmrg We must know that b + s does not overflow and a <= b + s and then we
26801debfc3dSmrg can compute number of iterations as (b + s - a) / s. (It might
26811debfc3dSmrg seem that we in fact could be more clever about testing the b + s
26821debfc3dSmrg overflow condition using some information about b - a mod s,
26831debfc3dSmrg but it was already taken into account during LE -> NE transform). */
26841debfc3dSmrg {
26851debfc3dSmrg step = iv0.step;
26861debfc3dSmrg tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
26871debfc3dSmrg tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
26881debfc3dSmrg
26891debfc3dSmrg bound = simplify_gen_binary (MINUS, mode, mode_mmax,
26901debfc3dSmrg lowpart_subreg (mode, step,
26911debfc3dSmrg comp_mode));
26921debfc3dSmrg if (step_is_pow2)
26931debfc3dSmrg {
26941debfc3dSmrg rtx t0, t1;
26951debfc3dSmrg
26961debfc3dSmrg /* If s is power of 2, we know that the loop is infinite if
26971debfc3dSmrg a % s <= b % s and b + s overflows. */
26981debfc3dSmrg assumption = simplify_gen_relational (reverse_condition (cond),
26991debfc3dSmrg SImode, mode,
27001debfc3dSmrg tmp1, bound);
27011debfc3dSmrg
27021debfc3dSmrg t0 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp0), step);
27031debfc3dSmrg t1 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp1), step);
27041debfc3dSmrg tmp = simplify_gen_relational (cond, SImode, mode, t0, t1);
27051debfc3dSmrg assumption = simplify_gen_binary (AND, SImode, assumption, tmp);
27061debfc3dSmrg desc->infinite =
27071debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->infinite);
27081debfc3dSmrg }
27091debfc3dSmrg else
27101debfc3dSmrg {
27111debfc3dSmrg assumption = simplify_gen_relational (cond, SImode, mode,
27121debfc3dSmrg tmp1, bound);
27131debfc3dSmrg desc->assumptions =
27141debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->assumptions);
27151debfc3dSmrg }
27161debfc3dSmrg
27171debfc3dSmrg tmp = simplify_gen_binary (PLUS, comp_mode, iv1.base, iv0.step);
27181debfc3dSmrg tmp = lowpart_subreg (mode, tmp, comp_mode);
27191debfc3dSmrg assumption = simplify_gen_relational (reverse_condition (cond),
27201debfc3dSmrg SImode, mode, tmp0, tmp);
27211debfc3dSmrg
27221debfc3dSmrg delta = simplify_gen_binary (PLUS, mode, tmp1, step);
27231debfc3dSmrg delta = simplify_gen_binary (MINUS, mode, delta, tmp0);
27241debfc3dSmrg }
27251debfc3dSmrg else
27261debfc3dSmrg {
27271debfc3dSmrg /* Condition in shape a <= b - s * i
27281debfc3dSmrg We must know that a - s does not overflow and a - s <= b and then
27291debfc3dSmrg we can again compute number of iterations as (b - (a - s)) / s. */
27301debfc3dSmrg step = simplify_gen_unary (NEG, mode, iv1.step, mode);
27311debfc3dSmrg tmp0 = lowpart_subreg (mode, iv0.base, comp_mode);
27321debfc3dSmrg tmp1 = lowpart_subreg (mode, iv1.base, comp_mode);
27331debfc3dSmrg
27341debfc3dSmrg bound = simplify_gen_binary (PLUS, mode, mode_mmin,
27351debfc3dSmrg lowpart_subreg (mode, step, comp_mode));
27361debfc3dSmrg if (step_is_pow2)
27371debfc3dSmrg {
27381debfc3dSmrg rtx t0, t1;
27391debfc3dSmrg
27401debfc3dSmrg /* If s is power of 2, we know that the loop is infinite if
27411debfc3dSmrg a % s <= b % s and a - s overflows. */
27421debfc3dSmrg assumption = simplify_gen_relational (reverse_condition (cond),
27431debfc3dSmrg SImode, mode,
27441debfc3dSmrg bound, tmp0);
27451debfc3dSmrg
27461debfc3dSmrg t0 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp0), step);
27471debfc3dSmrg t1 = simplify_gen_binary (UMOD, mode, copy_rtx (tmp1), step);
27481debfc3dSmrg tmp = simplify_gen_relational (cond, SImode, mode, t0, t1);
27491debfc3dSmrg assumption = simplify_gen_binary (AND, SImode, assumption, tmp);
27501debfc3dSmrg desc->infinite =
27511debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->infinite);
27521debfc3dSmrg }
27531debfc3dSmrg else
27541debfc3dSmrg {
27551debfc3dSmrg assumption = simplify_gen_relational (cond, SImode, mode,
27561debfc3dSmrg bound, tmp0);
27571debfc3dSmrg desc->assumptions =
27581debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->assumptions);
27591debfc3dSmrg }
27601debfc3dSmrg
27611debfc3dSmrg tmp = simplify_gen_binary (PLUS, comp_mode, iv0.base, iv1.step);
27621debfc3dSmrg tmp = lowpart_subreg (mode, tmp, comp_mode);
27631debfc3dSmrg assumption = simplify_gen_relational (reverse_condition (cond),
27641debfc3dSmrg SImode, mode,
27651debfc3dSmrg tmp, tmp1);
27661debfc3dSmrg delta = simplify_gen_binary (MINUS, mode, tmp0, step);
27671debfc3dSmrg delta = simplify_gen_binary (MINUS, mode, tmp1, delta);
27681debfc3dSmrg }
27691debfc3dSmrg if (assumption == const_true_rtx)
27701debfc3dSmrg goto zero_iter_simplify;
27711debfc3dSmrg else if (assumption != const0_rtx)
27721debfc3dSmrg desc->noloop_assumptions =
27731debfc3dSmrg alloc_EXPR_LIST (0, assumption, desc->noloop_assumptions);
27741debfc3dSmrg delta = simplify_gen_binary (UDIV, mode, delta, step);
27751debfc3dSmrg desc->niter_expr = delta;
27761debfc3dSmrg }
27771debfc3dSmrg
27781debfc3dSmrg old_niter = desc->niter_expr;
27791debfc3dSmrg
27801debfc3dSmrg simplify_using_initial_values (loop, AND, &desc->assumptions);
27811debfc3dSmrg if (desc->assumptions
27821debfc3dSmrg && XEXP (desc->assumptions, 0) == const0_rtx)
27831debfc3dSmrg goto fail;
27841debfc3dSmrg simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
27851debfc3dSmrg simplify_using_initial_values (loop, IOR, &desc->infinite);
27861debfc3dSmrg simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
27871debfc3dSmrg
27881debfc3dSmrg /* Rerun the simplification. Consider code (created by copying loop headers)
27891debfc3dSmrg
27901debfc3dSmrg i = 0;
27911debfc3dSmrg
27921debfc3dSmrg if (0 < n)
27931debfc3dSmrg {
27941debfc3dSmrg do
27951debfc3dSmrg {
27961debfc3dSmrg i++;
27971debfc3dSmrg } while (i < n);
27981debfc3dSmrg }
27991debfc3dSmrg
28001debfc3dSmrg The first pass determines that i = 0, the second pass uses it to eliminate
28011debfc3dSmrg noloop assumption. */
28021debfc3dSmrg
28031debfc3dSmrg simplify_using_initial_values (loop, AND, &desc->assumptions);
28041debfc3dSmrg if (desc->assumptions
28051debfc3dSmrg && XEXP (desc->assumptions, 0) == const0_rtx)
28061debfc3dSmrg goto fail;
28071debfc3dSmrg simplify_using_initial_values (loop, IOR, &desc->noloop_assumptions);
28081debfc3dSmrg simplify_using_initial_values (loop, IOR, &desc->infinite);
28091debfc3dSmrg simplify_using_initial_values (loop, UNKNOWN, &desc->niter_expr);
28101debfc3dSmrg
28111debfc3dSmrg if (desc->noloop_assumptions
28121debfc3dSmrg && XEXP (desc->noloop_assumptions, 0) == const_true_rtx)
28131debfc3dSmrg goto zero_iter;
28141debfc3dSmrg
28151debfc3dSmrg if (CONST_INT_P (desc->niter_expr))
28161debfc3dSmrg {
28171debfc3dSmrg uint64_t val = INTVAL (desc->niter_expr);
28181debfc3dSmrg
28191debfc3dSmrg desc->const_iter = true;
28201debfc3dSmrg desc->niter = val & GET_MODE_MASK (desc->mode);
28211debfc3dSmrg if (!desc->infinite
28221debfc3dSmrg && !desc->assumptions)
28231debfc3dSmrg record_niter_bound (loop, desc->niter, false, true);
28241debfc3dSmrg }
28251debfc3dSmrg else
28261debfc3dSmrg {
28271debfc3dSmrg max = determine_max_iter (loop, desc, old_niter);
28281debfc3dSmrg if (!max)
28291debfc3dSmrg goto zero_iter_simplify;
28301debfc3dSmrg if (!desc->infinite
28311debfc3dSmrg && !desc->assumptions)
28321debfc3dSmrg record_niter_bound (loop, max, false, true);
28331debfc3dSmrg
28341debfc3dSmrg /* simplify_using_initial_values does a copy propagation on the registers
28351debfc3dSmrg in the expression for the number of iterations. This prolongs life
28361debfc3dSmrg ranges of registers and increases register pressure, and usually
28371debfc3dSmrg brings no gain (and if it happens to do, the cse pass will take care
28381debfc3dSmrg of it anyway). So prevent this behavior, unless it enabled us to
28391debfc3dSmrg derive that the number of iterations is a constant. */
28401debfc3dSmrg desc->niter_expr = old_niter;
28411debfc3dSmrg }
28421debfc3dSmrg
28431debfc3dSmrg return;
28441debfc3dSmrg
28451debfc3dSmrg zero_iter_simplify:
28461debfc3dSmrg /* Simplify the assumptions. */
28471debfc3dSmrg simplify_using_initial_values (loop, AND, &desc->assumptions);
28481debfc3dSmrg if (desc->assumptions
28491debfc3dSmrg && XEXP (desc->assumptions, 0) == const0_rtx)
28501debfc3dSmrg goto fail;
28511debfc3dSmrg simplify_using_initial_values (loop, IOR, &desc->infinite);
28521debfc3dSmrg
28531debfc3dSmrg /* Fallthru. */
28541debfc3dSmrg zero_iter:
28551debfc3dSmrg desc->const_iter = true;
28561debfc3dSmrg desc->niter = 0;
28571debfc3dSmrg record_niter_bound (loop, 0, true, true);
28581debfc3dSmrg desc->noloop_assumptions = NULL_RTX;
28591debfc3dSmrg desc->niter_expr = const0_rtx;
28601debfc3dSmrg return;
28611debfc3dSmrg
28621debfc3dSmrg fail:
28631debfc3dSmrg desc->simple_p = false;
28641debfc3dSmrg return;
28651debfc3dSmrg }
28661debfc3dSmrg
28671debfc3dSmrg /* Checks whether E is a simple exit from LOOP and stores its description
28681debfc3dSmrg into DESC. */
28691debfc3dSmrg
28701debfc3dSmrg static void
check_simple_exit(class loop * loop,edge e,class niter_desc * desc)2871*8feb0f0bSmrg check_simple_exit (class loop *loop, edge e, class niter_desc *desc)
28721debfc3dSmrg {
28731debfc3dSmrg basic_block exit_bb;
28741debfc3dSmrg rtx condition;
28751debfc3dSmrg rtx_insn *at;
28761debfc3dSmrg edge ein;
28771debfc3dSmrg
28781debfc3dSmrg exit_bb = e->src;
28791debfc3dSmrg desc->simple_p = false;
28801debfc3dSmrg
28811debfc3dSmrg /* It must belong directly to the loop. */
28821debfc3dSmrg if (exit_bb->loop_father != loop)
28831debfc3dSmrg return;
28841debfc3dSmrg
28851debfc3dSmrg /* It must be tested (at least) once during any iteration. */
28861debfc3dSmrg if (!dominated_by_p (CDI_DOMINATORS, loop->latch, exit_bb))
28871debfc3dSmrg return;
28881debfc3dSmrg
28891debfc3dSmrg /* It must end in a simple conditional jump. */
28901debfc3dSmrg if (!any_condjump_p (BB_END (exit_bb)))
28911debfc3dSmrg return;
28921debfc3dSmrg
28931debfc3dSmrg ein = EDGE_SUCC (exit_bb, 0);
28941debfc3dSmrg if (ein == e)
28951debfc3dSmrg ein = EDGE_SUCC (exit_bb, 1);
28961debfc3dSmrg
28971debfc3dSmrg desc->out_edge = e;
28981debfc3dSmrg desc->in_edge = ein;
28991debfc3dSmrg
29001debfc3dSmrg /* Test whether the condition is suitable. */
29011debfc3dSmrg if (!(condition = get_condition (BB_END (ein->src), &at, false, false)))
29021debfc3dSmrg return;
29031debfc3dSmrg
29041debfc3dSmrg if (ein->flags & EDGE_FALLTHRU)
29051debfc3dSmrg {
29061debfc3dSmrg condition = reversed_condition (condition);
29071debfc3dSmrg if (!condition)
29081debfc3dSmrg return;
29091debfc3dSmrg }
29101debfc3dSmrg
29111debfc3dSmrg /* Check that we are able to determine number of iterations and fill
29121debfc3dSmrg in information about it. */
29131debfc3dSmrg iv_number_of_iterations (loop, at, condition, desc);
29141debfc3dSmrg }
29151debfc3dSmrg
29161debfc3dSmrg /* Finds a simple exit of LOOP and stores its description into DESC. */
29171debfc3dSmrg
2918*8feb0f0bSmrg static void
find_simple_exit(class loop * loop,class niter_desc * desc)2919*8feb0f0bSmrg find_simple_exit (class loop *loop, class niter_desc *desc)
29201debfc3dSmrg {
29211debfc3dSmrg unsigned i;
29221debfc3dSmrg basic_block *body;
29231debfc3dSmrg edge e;
2924*8feb0f0bSmrg class niter_desc act;
29251debfc3dSmrg bool any = false;
29261debfc3dSmrg edge_iterator ei;
29271debfc3dSmrg
29281debfc3dSmrg desc->simple_p = false;
29291debfc3dSmrg body = get_loop_body (loop);
29301debfc3dSmrg
29311debfc3dSmrg for (i = 0; i < loop->num_nodes; i++)
29321debfc3dSmrg {
29331debfc3dSmrg FOR_EACH_EDGE (e, ei, body[i]->succs)
29341debfc3dSmrg {
29351debfc3dSmrg if (flow_bb_inside_loop_p (loop, e->dest))
29361debfc3dSmrg continue;
29371debfc3dSmrg
29381debfc3dSmrg check_simple_exit (loop, e, &act);
29391debfc3dSmrg if (!act.simple_p)
29401debfc3dSmrg continue;
29411debfc3dSmrg
29421debfc3dSmrg if (!any)
29431debfc3dSmrg any = true;
29441debfc3dSmrg else
29451debfc3dSmrg {
29461debfc3dSmrg /* Prefer constant iterations; the less the better. */
29471debfc3dSmrg if (!act.const_iter
29481debfc3dSmrg || (desc->const_iter && act.niter >= desc->niter))
29491debfc3dSmrg continue;
29501debfc3dSmrg
29511debfc3dSmrg /* Also if the actual exit may be infinite, while the old one
29521debfc3dSmrg not, prefer the old one. */
29531debfc3dSmrg if (act.infinite && !desc->infinite)
29541debfc3dSmrg continue;
29551debfc3dSmrg }
29561debfc3dSmrg
29571debfc3dSmrg *desc = act;
29581debfc3dSmrg }
29591debfc3dSmrg }
29601debfc3dSmrg
29611debfc3dSmrg if (dump_file)
29621debfc3dSmrg {
29631debfc3dSmrg if (desc->simple_p)
29641debfc3dSmrg {
29651debfc3dSmrg fprintf (dump_file, "Loop %d is simple:\n", loop->num);
29661debfc3dSmrg fprintf (dump_file, " simple exit %d -> %d\n",
29671debfc3dSmrg desc->out_edge->src->index,
29681debfc3dSmrg desc->out_edge->dest->index);
29691debfc3dSmrg if (desc->assumptions)
29701debfc3dSmrg {
29711debfc3dSmrg fprintf (dump_file, " assumptions: ");
29721debfc3dSmrg print_rtl (dump_file, desc->assumptions);
29731debfc3dSmrg fprintf (dump_file, "\n");
29741debfc3dSmrg }
29751debfc3dSmrg if (desc->noloop_assumptions)
29761debfc3dSmrg {
29771debfc3dSmrg fprintf (dump_file, " does not roll if: ");
29781debfc3dSmrg print_rtl (dump_file, desc->noloop_assumptions);
29791debfc3dSmrg fprintf (dump_file, "\n");
29801debfc3dSmrg }
29811debfc3dSmrg if (desc->infinite)
29821debfc3dSmrg {
29831debfc3dSmrg fprintf (dump_file, " infinite if: ");
29841debfc3dSmrg print_rtl (dump_file, desc->infinite);
29851debfc3dSmrg fprintf (dump_file, "\n");
29861debfc3dSmrg }
29871debfc3dSmrg
29881debfc3dSmrg fprintf (dump_file, " number of iterations: ");
29891debfc3dSmrg print_rtl (dump_file, desc->niter_expr);
29901debfc3dSmrg fprintf (dump_file, "\n");
29911debfc3dSmrg
29921debfc3dSmrg fprintf (dump_file, " upper bound: %li\n",
29931debfc3dSmrg (long)get_max_loop_iterations_int (loop));
29941debfc3dSmrg fprintf (dump_file, " likely upper bound: %li\n",
29951debfc3dSmrg (long)get_likely_max_loop_iterations_int (loop));
29961debfc3dSmrg fprintf (dump_file, " realistic bound: %li\n",
29971debfc3dSmrg (long)get_estimated_loop_iterations_int (loop));
29981debfc3dSmrg }
29991debfc3dSmrg else
30001debfc3dSmrg fprintf (dump_file, "Loop %d is not simple.\n", loop->num);
30011debfc3dSmrg }
30021debfc3dSmrg
3003*8feb0f0bSmrg /* Fix up the finiteness if possible. We can only do it for single exit,
3004*8feb0f0bSmrg since the loop is finite, but it's possible that we predicate one loop
3005*8feb0f0bSmrg exit to be finite which can not be determined as finite in middle-end as
3006*8feb0f0bSmrg well. It results in incorrect predicate information on the exit condition
3007*8feb0f0bSmrg expression. For example, if says [(int) _1 + -8, + , -8] != 0 finite,
3008*8feb0f0bSmrg it means _1 can exactly divide -8. */
3009*8feb0f0bSmrg if (desc->infinite && single_exit (loop) && finite_loop_p (loop))
3010*8feb0f0bSmrg {
3011*8feb0f0bSmrg desc->infinite = NULL_RTX;
3012*8feb0f0bSmrg if (dump_file)
3013*8feb0f0bSmrg fprintf (dump_file, " infinite updated to finite.\n");
3014*8feb0f0bSmrg }
3015*8feb0f0bSmrg
30161debfc3dSmrg free (body);
30171debfc3dSmrg }
30181debfc3dSmrg
30191debfc3dSmrg /* Creates a simple loop description of LOOP if it was not computed
30201debfc3dSmrg already. */
30211debfc3dSmrg
3022*8feb0f0bSmrg class niter_desc *
get_simple_loop_desc(class loop * loop)3023*8feb0f0bSmrg get_simple_loop_desc (class loop *loop)
30241debfc3dSmrg {
3025*8feb0f0bSmrg class niter_desc *desc = simple_loop_desc (loop);
30261debfc3dSmrg
30271debfc3dSmrg if (desc)
30281debfc3dSmrg return desc;
30291debfc3dSmrg
30301debfc3dSmrg /* At least desc->infinite is not always initialized by
30311debfc3dSmrg find_simple_loop_exit. */
30321debfc3dSmrg desc = ggc_cleared_alloc<niter_desc> ();
30331debfc3dSmrg iv_analysis_loop_init (loop);
30341debfc3dSmrg find_simple_exit (loop, desc);
30351debfc3dSmrg loop->simple_loop_desc = desc;
30361debfc3dSmrg return desc;
30371debfc3dSmrg }
30381debfc3dSmrg
30391debfc3dSmrg /* Releases simple loop description for LOOP. */
30401debfc3dSmrg
30411debfc3dSmrg void
free_simple_loop_desc(class loop * loop)3042*8feb0f0bSmrg free_simple_loop_desc (class loop *loop)
30431debfc3dSmrg {
3044*8feb0f0bSmrg class niter_desc *desc = simple_loop_desc (loop);
30451debfc3dSmrg
30461debfc3dSmrg if (!desc)
30471debfc3dSmrg return;
30481debfc3dSmrg
30491debfc3dSmrg ggc_free (desc);
30501debfc3dSmrg loop->simple_loop_desc = NULL;
30511debfc3dSmrg }
3052