This patch suppresses the messages printed when the primary module is not found.
[official-gcc.git] / gcc-4_7 / gcc / simplify-got.c
blob22a776ee8545c582c242d5d71e5acab0ba84ad8a
1 /* Simplify the code to load global variable's address from GOT.
2 Copyright (C) 2011
3 Free Software Foundation, Inc.
4 Contributed by Wei Guozhi <carrot@google.com>.
6 This file is part of GCC.
8 GCC is free software; you can redistribute it and/or modify it under
9 the terms of the GNU General Public License as published by the Free
10 Software Foundation; either version 3, or (at your option) any later
11 version.
13 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
14 WARRANTY; without even the implied warranty of MERCHANTABILITY or
15 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
16 for more details.
18 You should have received a copy of the GNU General Public License
19 along with GCC; see the file COPYING3. If not see
20 <http://www.gnu.org/licenses/>. */
22 /* This file contains optimization for global variable's address loading
23 from GOT.
25 When generating PIC code, we need to load global variable's address from
26 GOT. Many targets do this as following:
28 (set pic_reg ...) # load the base address of GOT into pic_reg.
29 ...
30 (set off_set ...) # load the offset from the base of GOT to
31 # a global variable's GOT entry.
32 (set address # load the address from GOT.
33 (mem (plus pic_reg off_set)))
34 ...
36 If the target has an alternative method (usually uses a different
37 relocation) to load the global address and in some cases it has less
38 cost and avoid the pic_reg, we can use this pass to improve it.
40 In order to employ this optimization the target must satisfy the
41 following constraints:
43 1. There should be at least 2 methods to load a global variable's
44 address from GOT.
46 2. By default all global variables accesses use the method described
47 above.
49 3. There is a target dependent situation that the alternative method is
50 better when considering the number of global variable accesses and
51 the number of accessed variables.
53 4. The alternative method doesn't use the base of GOT (pic_reg).
56 #include "config.h"
57 #include "system.h"
58 #include "coretypes.h"
59 #include "tm.h"
60 #include "rtl.h"
61 #include "flags.h"
62 #include "target.h"
63 #include "tree-pass.h"
64 #include "df.h"
65 #include "timevar.h"
67 #define VAR_TABLE_SIZE 10
69 /* Information needed when rewrite the GOT access insns. */
70 struct got_access_info
72 rtx symbol; /* The global variable. */
73 rtx offset_reg; /* Register contains the GOT entry offset. */
74 rtx address_reg; /* Register contains the final global address. */
75 rtx offset_insn; /* The insn loads the offset. */
76 rtx load_insn; /* The insn which loads the address from GOT. */
79 /* This optimization is enabled only when the pic_reg is actually used. */
80 static bool
81 gate_handle_simplify_got (void)
83 return optimize && targetm.got_access.get_pic_reg ();
86 static unsigned int
87 rest_of_handle_simplify_got (void)
89 df_ref ref;
90 rtx use = NULL_RTX;
91 int i, n_symbol, n_access = 0;
92 struct got_access_info* got_accesses;
93 htab_t var_table = htab_create (VAR_TABLE_SIZE,
94 htab_hash_pointer,
95 htab_eq_pointer,
96 NULL);
97 rtx pic_reg = targetm.got_access.get_pic_reg ();
98 gcc_assert (pic_reg);
100 ref = DF_REG_USE_CHAIN (REGNO (pic_reg));
101 got_accesses = XNEWVEC(struct got_access_info,
102 DF_REG_USE_COUNT (REGNO (pic_reg)));
104 /* Check if all uses of pic_reg are loading global address through the
105 default method. */
106 while (ref)
108 rtx insn = DF_REF_INSN (ref);
110 /* Check for the special USE insn, it is not a real usage of pic_reg. */
111 if (GET_CODE (PATTERN (insn)) == USE)
112 use = insn;
113 else
115 /* If an insn both set and use pic_reg, it is in the process of
116 constructing the value of pic_reg. We should also ignore it. */
117 rtx set = single_set (insn);
118 if (!(set && SET_DEST (set) == pic_reg))
120 rtx offset_reg;
121 rtx offset_insn;
122 rtx symbol = targetm.got_access.loaded_global_var (insn,
123 &offset_reg,
124 &offset_insn);
125 if (symbol)
127 rtx* slot = (rtx*) htab_find_slot (var_table, symbol, INSERT);
128 if (*slot == HTAB_EMPTY_ENTRY)
129 *slot = symbol;
131 gcc_assert (set);
132 got_accesses[n_access].symbol = symbol;
133 got_accesses[n_access].offset_reg = offset_reg;
134 got_accesses[n_access].address_reg = SET_DEST (set);
135 got_accesses[n_access].load_insn = insn;
136 got_accesses[n_access].offset_insn = offset_insn;
137 n_access++;
139 else
141 /* This insn doesn't load a global address, but it has
142 other unexpected usage of pic_reg, give up. */
143 free (got_accesses);
144 htab_delete (var_table);
145 return 0;
149 ref = DF_REF_NEXT_REG(ref);
152 /* Check if we can simplify it. */
153 n_symbol = htab_elements (var_table);
154 gcc_assert (n_symbol <= n_access);
155 if (!targetm.got_access.can_simplify_got_access (n_symbol, n_access))
157 free (got_accesses);
158 htab_delete (var_table);
159 return 0;
162 /* Rewrite the global address loading insns. */
163 for (i=0; i<n_access; i++)
164 targetm.got_access.load_global_address (got_accesses[i].symbol,
165 got_accesses[i].offset_reg,
166 got_accesses[i].address_reg,
167 got_accesses[i].load_insn,
168 got_accesses[i].offset_insn);
170 /* Since there is no usage of pic_reg now, we can remove it. */
171 if (use)
172 remove_insn (use);
173 targetm.got_access.clear_pic_reg ();
174 free (got_accesses);
175 htab_delete (var_table);
176 return 0;
179 struct rtl_opt_pass pass_simplify_got =
182 RTL_PASS,
183 "simplify_got", /* name */
184 gate_handle_simplify_got, /* gate */
185 rest_of_handle_simplify_got, /* execute */
186 NULL, /* sub */
187 NULL, /* next */
188 0, /* static_pass_number */
189 TV_SIMPLIFY_GOT, /* tv_id */
190 0, /* properties_required */
191 0, /* properties_provided */
192 0, /* properties_destroyed */
193 0, /* todo_flags_start */
194 TODO_dump_func /* todo_flags_finish */