]> git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32-fp-as-gp.c
e2cdcfcd232d9a2e09e70abe7616dc1dd415a47c
[thirdparty/gcc.git] / gcc / config / nds32 / nds32-fp-as-gp.c
1 /* The fp-as-gp pass of Andes NDS32 cpu for GNU compiler
2 Copyright (C) 2012-2014 Free Software Foundation, Inc.
3 Contributed by Andes Technology Corporation.
4
5 This file is part of GCC.
6
7 GCC is free software; you can redistribute it and/or modify it
8 under the terms of the GNU General Public License as published
9 by the Free Software Foundation; either version 3, or (at your
10 option) any later version.
11
12 GCC is distributed in the hope that it will be useful, but WITHOUT
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
15 License 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 /* ------------------------------------------------------------------------ */
22
23 #include "config.h"
24 #include "system.h"
25 #include "coretypes.h"
26 #include "tm.h"
27 #include "tree.h"
28 #include "stor-layout.h"
29 #include "varasm.h"
30 #include "calls.h"
31 #include "rtl.h"
32 #include "regs.h"
33 #include "hard-reg-set.h"
34 #include "insn-config.h" /* Required by recog.h. */
35 #include "conditions.h"
36 #include "output.h"
37 #include "insn-attr.h" /* For DFA state_t. */
38 #include "insn-codes.h" /* For CODE_FOR_xxx. */
39 #include "reload.h" /* For push_reload(). */
40 #include "flags.h"
41 #include "hashtab.h"
42 #include "hash-set.h"
43 #include "vec.h"
44 #include "machmode.h"
45 #include "input.h"
46 #include "function.h"
47 #include "expr.h"
48 #include "recog.h"
49 #include "diagnostic-core.h"
50 #include "df.h"
51 #include "tm_p.h"
52 #include "tm-constrs.h"
53 #include "optabs.h" /* For GEN_FCN. */
54 #include "target.h"
55 #include "target-def.h"
56 #include "langhooks.h" /* For add_builtin_function(). */
57 #include "ggc.h"
58 #include "builtins.h"
59
60 /* ------------------------------------------------------------------------ */
61
62 /* A helper function to check if this function should contain prologue. */
63 static int
64 nds32_have_prologue_p (void)
65 {
66 int i;
67
68 for (i = 0; i < 28; i++)
69 if (NDS32_REQUIRED_CALLEE_SAVED_P (i))
70 return 1;
71
72 return (flag_pic
73 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
74 || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM));
75 }
76
77 /* Return true if is load/store with SYMBOL_REF addressing mode
78 and memory mode is SImode. */
79 static bool
80 nds32_symbol_load_store_p (rtx_insn *insn)
81 {
82 rtx mem_src = NULL_RTX;
83
84 switch (get_attr_type (insn))
85 {
86 case TYPE_LOAD:
87 mem_src = SET_SRC (PATTERN (insn));
88 break;
89 case TYPE_STORE:
90 mem_src = SET_DEST (PATTERN (insn));
91 break;
92 default:
93 break;
94 }
95
96 /* Find load/store insn with addressing mode is SYMBOL_REF. */
97 if (mem_src != NULL_RTX)
98 {
99 if ((GET_CODE (mem_src) == ZERO_EXTEND)
100 || (GET_CODE (mem_src) == SIGN_EXTEND))
101 mem_src = XEXP (mem_src, 0);
102
103 if ((GET_CODE (XEXP (mem_src, 0)) == SYMBOL_REF)
104 || (GET_CODE (XEXP (mem_src, 0)) == LO_SUM))
105 return true;
106 }
107
108 return false;
109 }
110
111 /* Function to determine whether it is worth to do fp_as_gp optimization.
112 Return 0: It is NOT worth to do fp_as_gp optimization.
113 Return 1: It is APPROXIMATELY worth to do fp_as_gp optimization.
114 Note that if it is worth to do fp_as_gp optimization,
115 we MUST set FP_REGNUM ever live in this function. */
116 int
117 nds32_fp_as_gp_check_available (void)
118 {
119 /* If there exists ANY of following conditions,
120 we DO NOT perform fp_as_gp optimization:
121 1. TARGET_FORBID_FP_AS_GP is set
122 regardless of the TARGET_FORCE_FP_AS_GP.
123 2. User explicitly uses 'naked' attribute.
124 3. Not optimize for size.
125 4. Need frame pointer.
126 5. If $fp is already required to be saved,
127 it means $fp is already choosen by register allocator.
128 Thus we better not to use it for fp_as_gp optimization.
129 6. This function is a vararg function.
130 DO NOT apply fp_as_gp optimization on this function
131 because it may change and break stack frame.
132 7. The epilogue is empty.
133 This happens when the function uses exit()
134 or its attribute is no_return.
135 In that case, compiler will not expand epilogue
136 so that we have no chance to output .omit_fp_end directive. */
137 if (TARGET_FORBID_FP_AS_GP
138 || lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl))
139 || !optimize_size
140 || frame_pointer_needed
141 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM)
142 || (cfun->stdarg == 1)
143 || (find_fallthru_edge (EXIT_BLOCK_PTR_FOR_FN (cfun)->preds) == NULL))
144 return 0;
145
146 /* Now we can check the possibility of using fp_as_gp optimization. */
147 if (TARGET_FORCE_FP_AS_GP)
148 {
149 /* User explicitly issues -mforce-fp-as-gp option. */
150 df_set_regs_ever_live (FP_REGNUM, 1);
151 return 1;
152 }
153 else
154 {
155 /* In the following we are going to evaluate whether
156 it is worth to do fp_as_gp optimization. */
157 int good_gain = 0;
158 int symbol_count = 0;
159
160 int threshold;
161 rtx_insn *insn;
162
163 /* We check if there already requires prologue.
164 Note that $gp will be saved in prologue for PIC code generation.
165 After that, we can set threshold by the existence of prologue.
166 Each fp-implied instruction will gain 2-byte code size
167 from gp-aware instruction, so we have following heuristics. */
168 if (flag_pic
169 || nds32_have_prologue_p ())
170 {
171 /* Have-prologue:
172 Compiler already intends to generate prologue content,
173 so the fp_as_gp optimization will only insert
174 'la $fp,_FP_BASE_' instruction, which will be
175 converted into 4-byte instruction at link time.
176 The threshold is "3" symbol accesses, 2 + 2 + 2 > 4. */
177 threshold = 3;
178 }
179 else
180 {
181 /* None-prologue:
182 Compiler originally does not generate prologue content,
183 so the fp_as_gp optimization will NOT ONLY insert
184 'la $fp,_FP_BASE' instruction, but also causes
185 push/pop instructions.
186 If we are using v3push (push25/pop25),
187 the threshold is "5" symbol accesses, 5*2 > 4 + 2 + 2;
188 If we are using normal push (smw/lmw),
189 the threshold is "5+2" symbol accesses 7*2 > 4 + 4 + 4. */
190 threshold = 5 + (TARGET_V3PUSH ? 0 : 2);
191 }
192
193 /* We would like to traverse every instruction in this function.
194 So we need to have push_topmost_sequence()/pop_topmost_sequence()
195 surrounding our for-loop evaluation. */
196 push_topmost_sequence ();
197 /* Counting the insn number which the addressing mode is symbol. */
198 for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
199 {
200 if (single_set (insn) && nds32_symbol_load_store_p (insn))
201 symbol_count++;
202
203 if (symbol_count == threshold)
204 {
205 good_gain = 1;
206 break;
207 }
208 }
209 pop_topmost_sequence ();
210
211 /* Enable fp_as_gp optimization when potential gain is good enough. */
212 if (good_gain)
213 {
214 df_set_regs_ever_live (FP_REGNUM, 1);
215 return 1;
216 }
217 }
218
219 /* By default we return 0. */
220 return 0;
221 }
222
223 /* ------------------------------------------------------------------------ */