]>
git.ipfire.org Git - thirdparty/gcc.git/blob - gcc/config/nds32/nds32-fp-as-gp.c
e2cdcfcd232d9a2e09e70abe7616dc1dd415a47c
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.
5 This file is part of GCC.
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.
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.
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/>. */
21 /* ------------------------------------------------------------------------ */
25 #include "coretypes.h"
28 #include "stor-layout.h"
33 #include "hard-reg-set.h"
34 #include "insn-config.h" /* Required by recog.h. */
35 #include "conditions.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(). */
49 #include "diagnostic-core.h"
52 #include "tm-constrs.h"
53 #include "optabs.h" /* For GEN_FCN. */
55 #include "target-def.h"
56 #include "langhooks.h" /* For add_builtin_function(). */
60 /* ------------------------------------------------------------------------ */
62 /* A helper function to check if this function should contain prologue. */
64 nds32_have_prologue_p (void)
68 for (i
= 0; i
< 28; i
++)
69 if (NDS32_REQUIRED_CALLEE_SAVED_P (i
))
73 || NDS32_REQUIRED_CALLEE_SAVED_P (FP_REGNUM
)
74 || NDS32_REQUIRED_CALLEE_SAVED_P (LP_REGNUM
));
77 /* Return true if is load/store with SYMBOL_REF addressing mode
78 and memory mode is SImode. */
80 nds32_symbol_load_store_p (rtx_insn
*insn
)
82 rtx mem_src
= NULL_RTX
;
84 switch (get_attr_type (insn
))
87 mem_src
= SET_SRC (PATTERN (insn
));
90 mem_src
= SET_DEST (PATTERN (insn
));
96 /* Find load/store insn with addressing mode is SYMBOL_REF. */
97 if (mem_src
!= NULL_RTX
)
99 if ((GET_CODE (mem_src
) == ZERO_EXTEND
)
100 || (GET_CODE (mem_src
) == SIGN_EXTEND
))
101 mem_src
= XEXP (mem_src
, 0);
103 if ((GET_CODE (XEXP (mem_src
, 0)) == SYMBOL_REF
)
104 || (GET_CODE (XEXP (mem_src
, 0)) == LO_SUM
))
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. */
117 nds32_fp_as_gp_check_available (void)
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
))
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
))
146 /* Now we can check the possibility of using fp_as_gp optimization. */
147 if (TARGET_FORCE_FP_AS_GP
)
149 /* User explicitly issues -mforce-fp-as-gp option. */
150 df_set_regs_ever_live (FP_REGNUM
, 1);
155 /* In the following we are going to evaluate whether
156 it is worth to do fp_as_gp optimization. */
158 int symbol_count
= 0;
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. */
169 || nds32_have_prologue_p ())
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. */
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);
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
))
200 if (single_set (insn
) && nds32_symbol_load_store_p (insn
))
203 if (symbol_count
== threshold
)
209 pop_topmost_sequence ();
211 /* Enable fp_as_gp optimization when potential gain is good enough. */
214 df_set_regs_ever_live (FP_REGNUM
, 1);
219 /* By default we return 0. */
223 /* ------------------------------------------------------------------------ */