Branch data Line data Source code
1 : : /* Lower and optimize address expressions.
2 : : Copyright (C) 2015-2024 Free Software Foundation, Inc.
3 : : Contributed by Marek Polacek <polacek@redhat.com>
4 : :
5 : : This file is part of GCC.
6 : :
7 : : GCC is free software; you can redistribute it and/or modify it under
8 : : the terms of the GNU General Public License as published by the Free
9 : : Software Foundation; either version 3, or (at your option) any later
10 : : version.
11 : :
12 : : GCC is distributed in the hope that it will be useful, but WITHOUT ANY
13 : : WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 : : FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15 : : for more details.
16 : :
17 : : You should have received a copy of the GNU General Public License
18 : : along with GCC; see the file COPYING3. If not see
19 : : <http://www.gnu.org/licenses/>. */
20 : :
21 : : #include "config.h"
22 : : #include "system.h"
23 : : #include "coretypes.h"
24 : : #include "alias.h"
25 : : #include "predict.h"
26 : : #include "tm.h"
27 : : #include "function.h"
28 : : #include "dominance.h"
29 : : #include "cfg.h"
30 : : #include "basic-block.h"
31 : : #include "tree-ssa-alias.h"
32 : : #include "symtab.h"
33 : : #include "tree.h"
34 : : #include "stringpool.h"
35 : : #include "tree-vrp.h"
36 : : #include "tree-ssanames.h"
37 : : #include "fold-const.h"
38 : : #include "gimple-expr.h"
39 : : #include "gimple.h"
40 : : #include "gimplify.h"
41 : : #include "gimple-iterator.h"
42 : : #include "gimplify-me.h"
43 : : #include "tree-pass.h"
44 : :
45 : :
46 : : namespace {
47 : :
48 : : const pass_data pass_data_laddress =
49 : : {
50 : : GIMPLE_PASS, /* type */
51 : : "laddress", /* name */
52 : : OPTGROUP_NONE, /* optinfo_flags */
53 : : TV_GIMPLE_LADDRESS, /* tv_id */
54 : : ( PROP_cfg | PROP_ssa ), /* properties_required */
55 : : 0, /* properties_provided */
56 : : 0, /* properties_destroyed */
57 : : 0, /* todo_flags_start */
58 : : 0, /* todo_flags_finish */
59 : : };
60 : :
61 : : class pass_laddress : public gimple_opt_pass
62 : : {
63 : : public:
64 : 280114 : pass_laddress (gcc::context *ctxt)
65 : 560228 : : gimple_opt_pass (pass_data_laddress, ctxt)
66 : : {}
67 : :
68 : : /* opt_pass methods: */
69 : 0 : opt_pass * clone () final override { return new pass_laddress (m_ctxt); }
70 : 996137 : bool gate (function *) final override { return optimize != 0; }
71 : : unsigned int execute (function *) final override;
72 : :
73 : : }; // class pass_laddress
74 : :
75 : : unsigned int
76 : 996089 : pass_laddress::execute (function *fun)
77 : : {
78 : 996089 : basic_block bb;
79 : :
80 : 9785537 : FOR_EACH_BB_FN (bb, fun)
81 : : {
82 : 89408057 : for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
83 : : {
84 : 71829161 : gimple *stmt = gsi_stmt (gsi);
85 : 71829161 : if (!is_gimple_assign (stmt)
86 : 20926188 : || gimple_assign_rhs_code (stmt) != ADDR_EXPR
87 : 72974705 : || is_gimple_invariant_address (gimple_assign_rhs1 (stmt)))
88 : : {
89 : 71534442 : gsi_next (&gsi);
90 : 71534442 : continue;
91 : : }
92 : :
93 : : /* Lower ADDR_EXPR assignments:
94 : : _4 = &b[i_9];
95 : : into
96 : : _1 = (sizetype) i_9;
97 : : _7 = _1 * 4;
98 : : _4 = &b + _7;
99 : : This ought to aid the vectorizer and expose CSE opportunities.
100 : : */
101 : :
102 : 294719 : tree expr = gimple_assign_rhs1 (stmt);
103 : 294719 : poly_int64 bitsize, bitpos;
104 : 294719 : tree base, offset;
105 : 294719 : machine_mode mode;
106 : 294719 : int volatilep = 0, reversep, unsignedp = 0;
107 : 294719 : base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
108 : : &bitpos, &offset, &mode, &unsignedp,
109 : : &reversep, &volatilep);
110 : 294719 : gcc_assert (base != NULL_TREE);
111 : 294719 : poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
112 : 294719 : if (offset != NULL_TREE)
113 : : {
114 : 38092 : if (maybe_ne (bytepos, 0))
115 : 3176 : offset = size_binop (PLUS_EXPR, offset, size_int (bytepos));
116 : 38092 : offset = force_gimple_operand_gsi (&gsi, offset, true, NULL,
117 : : true, GSI_SAME_STMT);
118 : 38092 : base = build_fold_addr_expr (base);
119 : 38092 : base = force_gimple_operand_gsi (&gsi, base, true, NULL,
120 : : true, GSI_SAME_STMT);
121 : 38092 : gimple *g = gimple_build_assign (gimple_assign_lhs (stmt),
122 : : POINTER_PLUS_EXPR, base, offset);
123 : 38092 : gsi_replace (&gsi, g, false);
124 : : }
125 : 294719 : gsi_next (&gsi);
126 : : }
127 : : }
128 : :
129 : 996089 : return 0;
130 : : }
131 : :
132 : : } // anon namespace
133 : :
134 : : gimple_opt_pass *
135 : 280114 : make_pass_laddress (gcc::context *ctxt)
136 : : {
137 : 280114 : return new pass_laddress (ctxt);
138 : : }
|