Line data Source code
1 : /* Lower and optimize address expressions.
2 : Copyright (C) 2015-2026 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 285722 : pass_laddress (gcc::context *ctxt)
65 571444 : : 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 1041484 : 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 1041419 : pass_laddress::execute (function *fun)
77 : {
78 1041419 : basic_block bb;
79 :
80 10457396 : FOR_EACH_BB_FN (bb, fun)
81 : {
82 100845385 : for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
83 : {
84 82013431 : gimple *stmt = gsi_stmt (gsi);
85 82013431 : if (!is_gimple_assign (stmt)
86 21941899 : || gimple_assign_rhs_code (stmt) != ADDR_EXPR
87 83229942 : || is_gimple_invariant_address (gimple_assign_rhs1 (stmt)))
88 : {
89 81708012 : gsi_next (&gsi);
90 81708012 : 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 305419 : tree expr = gimple_assign_rhs1 (stmt);
103 305419 : poly_int64 bitsize, bitpos;
104 305419 : tree base, offset;
105 305419 : machine_mode mode;
106 305419 : int volatilep = 0, reversep, unsignedp = 0;
107 305419 : base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
108 : &bitpos, &offset, &mode, &unsignedp,
109 : &reversep, &volatilep);
110 305419 : gcc_assert (base != NULL_TREE);
111 305419 : poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
112 305419 : if (offset != NULL_TREE)
113 : {
114 40672 : if (maybe_ne (bytepos, 0))
115 3194 : offset = size_binop (PLUS_EXPR, offset, size_int (bytepos));
116 40672 : offset = force_gimple_operand_gsi (&gsi, offset, true, NULL,
117 : true, GSI_SAME_STMT);
118 40672 : base = build_fold_addr_expr (base);
119 40672 : base = force_gimple_operand_gsi (&gsi, base, true, NULL,
120 : true, GSI_SAME_STMT);
121 40672 : gimple *g = gimple_build_assign (gimple_assign_lhs (stmt),
122 : POINTER_PLUS_EXPR, base, offset);
123 40672 : gsi_replace (&gsi, g, false);
124 : }
125 305419 : gsi_next (&gsi);
126 : }
127 : }
128 :
129 1041419 : return 0;
130 : }
131 :
132 : } // anon namespace
133 :
134 : gimple_opt_pass *
135 285722 : make_pass_laddress (gcc::context *ctxt)
136 : {
137 285722 : return new pass_laddress (ctxt);
138 : }
|