annotate gcc/config/nds32/nds32-relax-opt.c @ 131:84e7813d76e9

gcc-8.2
author mir3636
date Thu, 25 Oct 2018 07:37:49 +0900
parents
children 1830386684a0
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
131
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
1 /* relax-opt pass of Andes NDS32 cpu for GNU compiler
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
2 Copyright (C) 2012-2018 Free Software Foundation, Inc.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
3 Contributed by Andes Technology Corporation.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
4
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
5 This file is part of GCC.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
6
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
7 GCC is free software; you can redistribute it and/or modify it
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
8 under the terms of the GNU General Public License as published
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
9 by the Free Software Foundation; either version 3, or (at your
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
10 option) any later version.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
11
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
12 GCC is distributed in the hope that it will be useful, but WITHOUT
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
13 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
14 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
15 License for more details.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
16
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
17 You should have received a copy of the GNU General Public License
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
18 along with GCC; see the file COPYING3. If not see
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
19 <http://www.gnu.org/licenses/>. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
20
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
21 /* ------------------------------------------------------------------------ */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
22
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
23 #define IN_TARGET_CODE 1
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
24
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
25 #include "config.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
26 #include "system.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
27 #include "coretypes.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
28 #include "backend.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
29 #include "target.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
30 #include "rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
31 #include "tree.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
32 #include "stringpool.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
33 #include "attribs.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
34 #include "df.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
35 #include "memmodel.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
36 #include "tm_p.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
37 #include "optabs.h" /* For GEN_FCN. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
38 #include "regs.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
39 #include "emit-rtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
40 #include "recog.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
41 #include "diagnostic-core.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
42 #include "stor-layout.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
43 #include "varasm.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
44 #include "calls.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
45 #include "output.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
46 #include "explow.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
47 #include "expr.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
48 #include "tm-constrs.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
49 #include "builtins.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
50 #include "cpplib.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
51 #include "insn-attr.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
52 #include "cfgrtl.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
53 #include "tree-pass.h"
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
54
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
55 using namespace nds32;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
56
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
57 /* This is used to create unique relax hint id value.
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
58 The initial value is 0. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
59 static int relax_group_id = 0;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
60
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
61 /* Group the following pattern as relax candidates:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
62
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
63 1. sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
64 ori $ra, $ra, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
65 ==>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
66 addi.gp $ra, sym
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
67
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
68 2. sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
69 lwi $rb, [$ra + lo12(sym)]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
70 ==>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
71 lwi.gp $rb, [(sym)]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
72
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
73 3. sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
74 ori $ra, $ra, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
75 lwi $rb, [$ra]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
76 swi $rc, [$ra]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
77 ==>
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
78 lwi37 $rb, [(sym)]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
79 swi37 $rc, [(sym)] */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
80
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
81 /* Return true if is load/store with REG addressing mode
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
82 and memory mode is SImode. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
83 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
84 nds32_reg_base_load_store_p (rtx_insn *insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
85 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
86 rtx mem_src = NULL_RTX;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
87
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
88 switch (get_attr_type (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
89 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
90 case TYPE_LOAD:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
91 mem_src = SET_SRC (PATTERN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
92 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
93 case TYPE_STORE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
94 mem_src = SET_DEST (PATTERN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
95 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
96 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
97 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
98 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
99
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
100 /* Find load/store insn with addressing mode is REG. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
101 if (mem_src != NULL_RTX)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
102 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
103 if ((GET_CODE (mem_src) == ZERO_EXTEND)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
104 || (GET_CODE (mem_src) == SIGN_EXTEND))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
105 mem_src = XEXP (mem_src, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
106
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
107 if (GET_CODE (XEXP (mem_src, 0)) == REG)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
108 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
109 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
110
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
111 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
112 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
113
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
114 /* Return true if insn is a sp/fp base or sp/fp plus load-store instruction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
115
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
116 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
117 nds32_sp_base_or_plus_load_store_p (rtx_insn *insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
118 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
119 rtx mem_src = NULL_RTX;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
120
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
121 switch (get_attr_type (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
122 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
123 case TYPE_LOAD:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
124 mem_src = SET_SRC (PATTERN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
125 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
126 case TYPE_STORE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
127 mem_src = SET_DEST (PATTERN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
128 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
129 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
130 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
131 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
132 /* Find load/store insn with addressing mode is REG. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
133 if (mem_src != NULL_RTX)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
134 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
135 if ((GET_CODE (mem_src) == ZERO_EXTEND)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
136 || (GET_CODE (mem_src) == SIGN_EXTEND))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
137 mem_src = XEXP (mem_src, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
138
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
139 if ((GET_CODE (XEXP (mem_src, 0)) == PLUS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
140 mem_src = XEXP (mem_src, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
141
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
142 if (REG_P (XEXP (mem_src, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
143 && ((frame_pointer_needed
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
144 && REGNO (XEXP (mem_src, 0)) == FP_REGNUM)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
145 || REGNO (XEXP (mem_src, 0)) == SP_REGNUM))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
146 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
147 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
148
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
149 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
150 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
151
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
152 /* Return true if is load with [REG + REG/CONST_INT] addressing mode. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
153 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
154 nds32_plus_reg_load_store_p (rtx_insn *insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
155 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
156 rtx mem_src = NULL_RTX;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
157
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
158 switch (get_attr_type (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
159 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
160 case TYPE_LOAD:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
161 mem_src = SET_SRC (PATTERN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
162 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
163 case TYPE_STORE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
164 mem_src = SET_DEST (PATTERN (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
165 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
166 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
167 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
168 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
169
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
170 /* Find load/store insn with addressing mode is [REG + REG/CONST]. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
171 if (mem_src != NULL_RTX)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
172 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
173 if ((GET_CODE (mem_src) == ZERO_EXTEND)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
174 || (GET_CODE (mem_src) == SIGN_EXTEND))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
175 mem_src = XEXP (mem_src, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
176
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
177 if ((GET_CODE (XEXP (mem_src, 0)) == PLUS))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
178 mem_src = XEXP (mem_src, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
179 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
180 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
181
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
182 if (GET_CODE (XEXP (mem_src, 0)) == REG)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
183 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
184
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
185 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
186
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
187 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
188 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
189
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
190 /* Return true if x is const and the referance is ict symbol. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
191 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
192 nds32_ict_const_p (rtx x)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
193 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
194 if (GET_CODE (x) == CONST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
195 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
196 x = XEXP (x, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
197 return nds32_indirect_call_referenced_p (x);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
198 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
199 return FALSE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
200 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
201
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
202 /* Group the following pattern as relax candidates:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
203
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
204 GOT:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
205 sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
206 ori $ra, $ra, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
207 lw $rb, [$ra + $gp]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
208
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
209 GOTOFF, TLSLE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
210 sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
211 ori $ra, $ra, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
212 LS $rb, [$ra + $gp]
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
213
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
214 GOTOFF, TLSLE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
215 sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
216 ori $ra, $ra, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
217 add $rb, $ra, $gp($tp)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
218
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
219 Initial GOT table:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
220 sethi $gp,hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
221 ori $gp, $gp, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
222 add5.pc $gp */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
223
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
224 static auto_vec<rtx_insn *, 32> nds32_group_infos;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
225 /* Group the PIC and TLS relax candidate instructions for linker. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
226 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
227 nds32_pic_tls_group (rtx_insn *def_insn,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
228 enum nds32_relax_insn_type relax_type,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
229 int sym_type)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
230 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
231 df_ref def_record;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
232 df_link *link;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
233 rtx_insn *use_insn = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
234 rtx pat, new_pat;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
235 def_record = DF_INSN_DEFS (def_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
236 for (link = DF_REF_CHAIN (def_record); link; link = link->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
237 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
238 if (!DF_REF_INSN_INFO (link->ref))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
239 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
240
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
241 use_insn = DF_REF_INSN (link->ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
242
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
243 /* Skip if define insn and use insn not in the same basic block. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
244 if (!dominated_by_p (CDI_DOMINATORS,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
245 BLOCK_FOR_INSN (use_insn),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
246 BLOCK_FOR_INSN (def_insn)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
247 return FALSE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
248
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
249 /* Skip if use_insn not active insn. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
250 if (!active_insn_p (use_insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
251 return FALSE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
252
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
253 switch (relax_type)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
254 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
255 case RELAX_ORI:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
256
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
257 /* GOTOFF, TLSLE:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
258 sethi $ra, hi20(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
259 ori $ra, $ra, lo12(sym)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
260 add $rb, $ra, $gp($tp) */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
261 if ((sym_type == UNSPEC_TLSLE
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
262 || sym_type == UNSPEC_GOTOFF)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
263 && (recog_memoized (use_insn) == CODE_FOR_addsi3))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
264 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
265 pat = XEXP (PATTERN (use_insn), 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
266 new_pat =
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
267 gen_rtx_UNSPEC (SImode,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
268 gen_rtvec (2, XEXP (pat, 0), XEXP (pat, 1)),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
269 UNSPEC_ADD32);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
270 validate_replace_rtx (pat, new_pat, use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
271 nds32_group_infos.safe_push (use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
272 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
273 else if (nds32_plus_reg_load_store_p (use_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
274 && !nds32_sp_base_or_plus_load_store_p (use_insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
275 nds32_group_infos.safe_push (use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
276 else
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
277 return FALSE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
278 break;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
279
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
280 default:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
281 return FALSE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
282 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
283 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
284 return TRUE;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
285 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
286
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
287 static int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
288 nds32_pic_tls_symbol_type (rtx x)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
289 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
290 x = XEXP (SET_SRC (PATTERN (x)), 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
291
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
292 if (GET_CODE (x) == CONST)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
293 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
294 x = XEXP (x, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
295
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
296 if (GET_CODE (x) == PLUS)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
297 x = XEXP (x, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
298
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
299 return XINT (x, 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
300 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
301
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
302 return XINT (x, 1);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
303 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
304
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
305 /* Group the relax candidates with group id. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
306 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
307 nds32_group_insns (rtx_insn *sethi)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
308 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
309 df_ref def_record, use_record;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
310 df_link *link;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
311 rtx_insn *use_insn = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
312 rtx group_id;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
313 bool valid;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
314
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
315 def_record = DF_INSN_DEFS (sethi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
316
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
317 for (link = DF_REF_CHAIN (def_record); link; link = link->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
318 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
319 if (!DF_REF_INSN_INFO (link->ref))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
320 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
321
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
322 use_insn = DF_REF_INSN (link->ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
323
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
324 /* Skip if define insn and use insn not in the same basic block. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
325 if (!dominated_by_p (CDI_DOMINATORS,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
326 BLOCK_FOR_INSN (use_insn),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
327 BLOCK_FOR_INSN (sethi)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
328 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
329
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
330 /* Skip if the low-part used register is from different high-part
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
331 instructions. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
332 use_record = DF_INSN_USES (use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
333 if (DF_REF_CHAIN (use_record) && DF_REF_CHAIN (use_record)->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
334 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
335
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
336 /* Skip if use_insn not active insn. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
337 if (!active_insn_p (use_insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
338 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
339
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
340 /* Initial use_insn_type. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
341 if (!(recog_memoized (use_insn) == CODE_FOR_lo_sum
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
342 || nds32_symbol_load_store_p (use_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
343 || (nds32_reg_base_load_store_p (use_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
344 &&!nds32_sp_base_or_plus_load_store_p (use_insn))))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
345 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
346 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
347
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
348 group_id = GEN_INT (relax_group_id);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
349 /* Insert .relax_* directive for sethi. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
350 emit_insn_before (gen_relax_group (group_id), sethi);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
351
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
352 /* Scan the use insns and insert the directive. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
353 for (link = DF_REF_CHAIN (def_record); link; link = link->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
354 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
355 if (!DF_REF_INSN_INFO (link->ref))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
356 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
357
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
358 use_insn = DF_REF_INSN (link->ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
359
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
360 /* Insert .relax_* directive. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
361 if (active_insn_p (use_insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
362 emit_insn_before (gen_relax_group (group_id), use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
363
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
364 /* Find ori ra, ra, unspec(symbol) instruction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
365 if (use_insn != NULL
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
366 && recog_memoized (use_insn) == CODE_FOR_lo_sum
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
367 && !nds32_const_unspec_p (XEXP (SET_SRC (PATTERN (use_insn)), 1)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
368 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
369 int sym_type = nds32_pic_tls_symbol_type (use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
370 valid = nds32_pic_tls_group (use_insn, RELAX_ORI, sym_type);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
371
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
372 /* Insert .relax_* directive. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
373 while (!nds32_group_infos.is_empty ())
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
374 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
375 use_insn = nds32_group_infos.pop ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
376 if (valid)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
377 emit_insn_before (gen_relax_group (group_id), use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
378 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
379 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
380 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
381
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
382 relax_group_id++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
383 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
384
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
385 /* Convert relax group id in rtl. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
386
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
387 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
388 nds32_group_tls_insn (rtx insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
389 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
390 rtx pat = PATTERN (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
391 rtx unspec_relax_group = XEXP (XVECEXP (pat, 0, 1), 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
392
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
393 while (GET_CODE (pat) != SET && GET_CODE (pat) == PARALLEL)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
394 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
395 pat = XVECEXP (pat, 0, 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
396 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
397
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
398 if (GET_CODE (unspec_relax_group) == UNSPEC
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
399 && XINT (unspec_relax_group, 1) == UNSPEC_VOLATILE_RELAX_GROUP)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
400 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
401 XVECEXP (unspec_relax_group, 0, 0) = GEN_INT (relax_group_id);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
402 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
403
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
404 relax_group_id++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
405 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
406
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
407 static bool
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
408 nds32_float_reg_load_store_p (rtx_insn *insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
409 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
410 rtx pat = PATTERN (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
411
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
412 if (get_attr_type (insn) == TYPE_FLOAD
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
413 && GET_CODE (pat) == SET
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
414 && (GET_MODE (XEXP (pat, 0)) == SFmode
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
415 || GET_MODE (XEXP (pat, 0)) == DFmode)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
416 && MEM_P (XEXP (pat, 1)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
417 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
418 rtx addr = XEXP (XEXP (pat, 1), 0);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
419
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
420 /* [$ra] */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
421 if (REG_P (addr))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
422 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
423 /* [$ra + offset] */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
424 if (GET_CODE (addr) == PLUS
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
425 && REG_P (XEXP (addr, 0))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
426 && CONST_INT_P (XEXP (addr, 1)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
427 return true;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
428 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
429 return false;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
430 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
431
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
432
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
433 /* Group float load-store instructions:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
434 la $ra, symbol
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
435 flsi $rt, [$ra + offset] */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
436
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
437 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
438 nds32_group_float_insns (rtx_insn *insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
439 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
440 df_ref def_record, use_record;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
441 df_link *link;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
442 rtx_insn *use_insn = NULL;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
443 rtx group_id;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
444
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
445 def_record = DF_INSN_DEFS (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
446
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
447 for (link = DF_REF_CHAIN (def_record); link; link = link->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
448 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
449 if (!DF_REF_INSN_INFO (link->ref))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
450 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
451
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
452 use_insn = DF_REF_INSN (link->ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
453
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
454 /* Skip if define insn and use insn not in the same basic block. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
455 if (!dominated_by_p (CDI_DOMINATORS,
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
456 BLOCK_FOR_INSN (use_insn),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
457 BLOCK_FOR_INSN (insn)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
458 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
459
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
460 /* Skip if the low-part used register is from different high-part
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
461 instructions. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
462 use_record = DF_INSN_USES (use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
463 if (DF_REF_CHAIN (use_record) && DF_REF_CHAIN (use_record)->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
464 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
465
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
466 /* Skip if use_insn not active insn. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
467 if (!active_insn_p (use_insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
468 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
469
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
470 if (!nds32_float_reg_load_store_p (use_insn)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
471 || find_post_update_rtx (use_insn) != -1)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
472 return;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
473 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
474
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
475 group_id = GEN_INT (relax_group_id);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
476 /* Insert .relax_* directive for insn. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
477 emit_insn_before (gen_relax_group (group_id), insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
478
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
479 /* Scan the use insns and insert the directive. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
480 for (link = DF_REF_CHAIN (def_record); link; link = link->next)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
481 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
482 if (!DF_REF_INSN_INFO (link->ref))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
483 continue;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
484
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
485 use_insn = DF_REF_INSN (link->ref);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
486
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
487 /* Insert .relax_* directive. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
488 emit_insn_before (gen_relax_group (group_id), use_insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
489 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
490
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
491 relax_group_id++;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
492 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
493
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
494 /* Group the relax candidate instructions for linker. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
495 static void
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
496 nds32_relax_group (void)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
497 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
498 rtx_insn *insn;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
499
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
500 compute_bb_for_insn ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
501
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
502 df_chain_add_problem (DF_DU_CHAIN | DF_UD_CHAIN);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
503 df_insn_rescan_all ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
504 df_analyze ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
505 df_set_flags (DF_DEFER_INSN_RESCAN);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
506 calculate_dominance_info (CDI_DOMINATORS);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
507
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
508 insn = get_insns ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
509 gcc_assert (NOTE_P (insn));
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
510
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
511 for (insn = next_active_insn (insn); insn; insn = next_active_insn (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
512 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
513 if (NONJUMP_INSN_P (insn))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
514 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
515 /* Find sethi ra, symbol instruction. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
516 if (recog_memoized (insn) == CODE_FOR_sethi
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
517 && nds32_symbolic_operand (XEXP (SET_SRC (PATTERN (insn)), 0),
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
518 SImode)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
519 && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
520 nds32_group_insns (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
521 else if (recog_memoized (insn) == CODE_FOR_tls_ie)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
522 nds32_group_tls_insn (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
523 else if (TARGET_FPU_SINGLE
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
524 && recog_memoized (insn) == CODE_FOR_move_addr
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
525 && !nds32_ict_const_p (XEXP (SET_SRC (PATTERN (insn)), 0)))
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
526 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
527 nds32_group_float_insns (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
528 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
529 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
530 else if (CALL_P (insn) && recog_memoized (insn) == CODE_FOR_tls_desc)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
531 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
532 nds32_group_tls_insn (insn);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
533 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
534 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
535
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
536 /* We must call df_finish_pass manually because it should be invoked before
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
537 BB information is destroyed. Hence we cannot set the TODO_df_finish flag
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
538 to the pass manager. */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
539 df_insn_rescan_all ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
540 df_finish_pass (false);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
541 free_dominance_info (CDI_DOMINATORS);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
542 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
543
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
544 static unsigned int
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
545 nds32_relax_opt (void)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
546 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
547 if (TARGET_RELAX_HINT)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
548 nds32_relax_group ();
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
549 return 1;
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
550 }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
551
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
552 const pass_data pass_data_nds32_relax_opt =
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
553 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
554 RTL_PASS, /* type */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
555 "relax_opt", /* name */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
556 OPTGROUP_NONE, /* optinfo_flags */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
557 TV_MACH_DEP, /* tv_id */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
558 0, /* properties_required */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
559 0, /* properties_provided */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
560 0, /* properties_destroyed */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
561 0, /* todo_flags_start */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
562 TODO_df_finish, /* todo_flags_finish */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
563 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
564
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
565 class pass_nds32_relax_opt : public rtl_opt_pass
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
566 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
567 public:
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
568 pass_nds32_relax_opt (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
569 : rtl_opt_pass (pass_data_nds32_relax_opt, ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
570 {}
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
571
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
572 /* opt_pass methods: */
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
573 bool gate (function *) { return TARGET_RELAX_HINT; }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
574 unsigned int execute (function *) { return nds32_relax_opt (); }
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
575 };
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
576
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
577 rtl_opt_pass *
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
578 make_pass_nds32_relax_opt (gcc::context *ctxt)
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
579 {
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
580 return new pass_nds32_relax_opt (ctxt);
84e7813d76e9 gcc-8.2
mir3636
parents:
diff changeset
581 }