Import GCC-8 to a new vendor branch
[dragonfly.git] / contrib / gcc-8.0 / gcc / gimple-laddress.c
1 /* Lower and optimize address expressions.
2    Copyright (C) 2015-2018 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   pass_laddress (gcc::context *ctxt)
65     : gimple_opt_pass (pass_data_laddress, ctxt)
66   {}
67
68   /* opt_pass methods: */
69   opt_pass * clone () { return new pass_laddress (m_ctxt); }
70   virtual bool gate (function *) { return optimize != 0; }
71   virtual unsigned int execute (function *);
72
73 }; // class pass_laddress
74
75 unsigned int
76 pass_laddress::execute (function *fun)
77 {
78   basic_block bb;
79
80   FOR_EACH_BB_FN (bb, fun)
81     {
82       for (gimple_stmt_iterator gsi = gsi_start_bb (bb); !gsi_end_p (gsi);)
83         {
84           gimple *stmt = gsi_stmt (gsi);
85           if (!is_gimple_assign (stmt)
86               || gimple_assign_rhs_code (stmt) != ADDR_EXPR
87               || is_gimple_invariant_address (gimple_assign_rhs1 (stmt)))
88             {
89               gsi_next (&gsi);
90               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           tree expr = gimple_assign_rhs1 (stmt);
103           poly_int64 bitsize, bitpos;
104           tree base, offset;
105           machine_mode mode;
106           int volatilep = 0, reversep, unsignedp = 0;
107           base = get_inner_reference (TREE_OPERAND (expr, 0), &bitsize,
108                                       &bitpos, &offset, &mode, &unsignedp,
109                                       &reversep, &volatilep);
110           gcc_assert (base != NULL_TREE);
111           poly_int64 bytepos = exact_div (bitpos, BITS_PER_UNIT);
112           if (offset != NULL_TREE)
113             {
114               if (maybe_ne (bytepos, 0))
115                 offset = size_binop (PLUS_EXPR, offset, size_int (bytepos));
116               offset = force_gimple_operand_gsi (&gsi, offset, true, NULL,
117                                                  true, GSI_SAME_STMT);
118               base = build_fold_addr_expr (base);
119               base = force_gimple_operand_gsi (&gsi, base, true, NULL,
120                                                true, GSI_SAME_STMT);
121               gimple *g = gimple_build_assign (gimple_assign_lhs (stmt),
122                                               POINTER_PLUS_EXPR, base, offset);
123               gsi_replace (&gsi, g, false);
124             }
125           gsi_next (&gsi);
126         }
127     }
128
129   return 0;
130 }
131
132 } // anon namespace
133
134 gimple_opt_pass *
135 make_pass_laddress (gcc::context *ctxt)
136 {
137   return new pass_laddress (ctxt);
138 }