PR target/84064
[official-gcc.git] / gcc / config / arm / arm-ldmstm.ml
blob712d40fd086bde12fce9985494d20f32764d328b
1 (* Auto-generate ARM ldm/stm patterns
2 Copyright (C) 2010-2018 Free Software Foundation, Inc.
3 Contributed by CodeSourcery.
5 This file is part of GCC.
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.
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.
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 This is an O'Caml program. The O'Caml compiler is available from:
23 http://caml.inria.fr/
25 Or from your favourite OS's friendly packaging system. Tested with version
26 3.09.2, though other versions will probably work too.
28 Run with:
29 ocaml arm-ldmstm.ml >/path/to/gcc/config/arm/ldmstm.md
32 type amode = IA | IB | DA | DB
34 type optype = IN | OUT | INOUT
36 let rec string_of_addrmode addrmode thumb update =
37 if thumb || update
38 then
39 match addrmode with
40 IA -> "ia"
41 | IB -> "ib"
42 | DA -> "da"
43 | DB -> "db"
44 else
45 match addrmode with
46 IA -> ""
47 | IB -> "ib"
48 | DA -> "da"
49 | DB -> "db"
51 let rec initial_offset addrmode nregs =
52 match addrmode with
53 IA -> 0
54 | IB -> 4
55 | DA -> -4 * nregs + 4
56 | DB -> -4 * nregs
58 let rec final_offset addrmode nregs =
59 match addrmode with
60 IA -> nregs * 4
61 | IB -> nregs * 4
62 | DA -> -4 * nregs
63 | DB -> -4 * nregs
65 let constr thumb =
66 if thumb then "l" else "rk"
68 let inout_constr op_type =
69 match op_type with
70 OUT -> "=&"
71 | INOUT -> "+&"
72 | IN -> ""
74 let destreg nregs first op_type thumb =
75 if not first then
76 Printf.sprintf "(match_dup %d)" (nregs + 1)
77 else
78 Printf.sprintf ("(match_operand:SI %d \"s_register_operand\" \"%s%s\")")
79 (nregs + 1) (inout_constr op_type) (constr thumb)
81 let reg_predicate thumb =
82 if thumb then "low_register_operand" else "arm_hard_general_register_operand"
84 let write_ldm_set thumb nregs offset opnr first =
85 let indent = " " in
86 Printf.printf "%s" (if first then " [" else indent);
87 Printf.printf "(set (match_operand:SI %d \"%s\" \"\")\n" opnr (reg_predicate thumb);
88 Printf.printf "%s (mem:SI " indent;
89 begin if offset != 0 then Printf.printf "(plus:SI " end;
90 Printf.printf "%s" (destreg nregs first IN thumb);
91 begin if offset != 0 then Printf.printf "\n%s (const_int %d))" indent offset end;
92 Printf.printf "))"
94 let write_stm_set thumb nregs offset opnr first =
95 let indent = " " in
96 Printf.printf "%s" (if first then " [" else indent);
97 Printf.printf "(set (mem:SI ";
98 begin if offset != 0 then Printf.printf "(plus:SI " end;
99 Printf.printf "%s" (destreg nregs first IN thumb);
100 begin if offset != 0 then Printf.printf " (const_int %d))" offset end;
101 Printf.printf ")\n%s (match_operand:SI %d \"%s\" \"\"))" indent opnr (reg_predicate thumb)
103 let write_ldm_peep_set extra_indent nregs opnr first =
104 let indent = " " ^ extra_indent in
105 Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
106 Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
107 Printf.printf "%s (match_operand:SI %d \"memory_operand\" \"\"))" indent (nregs + opnr)
109 let write_stm_peep_set extra_indent nregs opnr first =
110 let indent = " " ^ extra_indent in
111 Printf.printf "%s" (if first then extra_indent ^ " [" else indent);
112 Printf.printf "(set (match_operand:SI %d \"memory_operand\" \"\")\n" (nregs + opnr);
113 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\"))" indent opnr
115 let write_any_load optype nregs opnr first =
116 let indent = " " in
117 Printf.printf "%s" (if first then " [" else indent);
118 Printf.printf "(set (match_operand:SI %d \"s_register_operand\" \"\")\n" opnr;
119 Printf.printf "%s (match_operand:SI %d \"%s\" \"\"))" indent (nregs * 2 + opnr) optype
121 let write_const_store nregs opnr first =
122 let indent = " " in
123 Printf.printf "%s(set (match_operand:SI %d \"memory_operand\" \"\")\n" indent (nregs + opnr);
124 Printf.printf "%s (match_dup %d))" indent opnr
126 let write_const_stm_peep_set nregs opnr first =
127 write_any_load "const_int_operand" nregs opnr first;
128 Printf.printf "\n";
129 write_const_store nregs opnr false
132 let rec write_pat_sets func opnr offset first n_left =
133 func offset opnr first;
134 begin
135 if n_left > 1 then begin
136 Printf.printf "\n";
137 write_pat_sets func (opnr + 1) (offset + 4) false (n_left - 1);
138 end else
139 Printf.printf "]"
142 let rec write_peep_sets func opnr first n_left =
143 func opnr first;
144 begin
145 if n_left > 1 then begin
146 Printf.printf "\n";
147 write_peep_sets func (opnr + 1) false (n_left - 1);
151 let can_thumb addrmode update is_store =
152 match addrmode, update, is_store with
153 (* Thumb1 mode only supports IA with update. However, for LDMIA,
154 if the address register also appears in the list of loaded
155 registers, the loaded value is stored, hence the RTL pattern
156 to describe such an insn does not have an update. We check
157 in the match_parallel predicate that the condition described
158 above is met. *)
159 IA, _, false -> true
160 | IA, true, true -> true
161 | _ -> false
163 exception InvalidAddrMode of string;;
165 let target addrmode thumb =
166 match addrmode, thumb with
167 IA, true -> "TARGET_THUMB1"
168 | IA, false -> "TARGET_32BIT"
169 | DB, false -> "TARGET_32BIT"
170 | _, false -> "TARGET_ARM"
171 | _, _ -> raise (InvalidAddrMode "ERROR: Invalid Addressing mode for Thumb1.")
173 let write_pattern_1 name ls addrmode nregs write_set_fn update thumb =
174 let astr = string_of_addrmode addrmode thumb update in
175 Printf.printf "(define_insn \"*%s%s%d_%s%s\"\n"
176 (if thumb then "thumb_" else "") name nregs astr
177 (if update then "_update" else "");
178 Printf.printf " [(match_parallel 0 \"%s_multiple_operation\"\n" ls;
179 begin
180 if update then begin
181 Printf.printf " [(set %s\n (plus:SI %s"
182 (destreg nregs true INOUT thumb) (destreg nregs false IN thumb);
183 Printf.printf " (const_int %d)))\n"
184 (final_offset addrmode nregs)
186 end;
187 write_pat_sets
188 (write_set_fn thumb nregs) 1
189 (initial_offset addrmode nregs)
190 (not update) nregs;
191 Printf.printf ")]\n \"%s && XVECLEN (operands[0], 0) == %d\"\n"
192 (target addrmode thumb)
193 (if update then nregs + 1 else nregs);
194 if thumb then
195 Printf.printf " \"%s%s\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "")
196 else
197 Printf.printf " \"%s%s%%?\\t%%%d%s, {" name astr (nregs + 1) (if update then "!" else "");
198 for n = 1 to nregs; do
199 Printf.printf "%%%d%s" n (if n < nregs then ", " else "")
200 done;
201 Printf.printf "}\"\n";
202 Printf.printf " [(set_attr \"type\" \"%s%d\")" ls nregs;
203 if not thumb then begin
204 Printf.printf "\n (set_attr \"predicable\" \"yes\")";
205 if addrmode == IA || addrmode == DB then
206 Printf.printf "\n (set_attr \"predicable_short_it\" \"no\")";
207 end;
208 Printf.printf "])\n\n"
210 let write_ldm_pattern addrmode nregs update =
211 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update false;
212 begin if can_thumb addrmode update false then
213 write_pattern_1 "ldm" "load" addrmode nregs write_ldm_set update true;
216 let write_stm_pattern addrmode nregs update =
217 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update false;
218 begin if can_thumb addrmode update true then
219 write_pattern_1 "stm" "store" addrmode nregs write_stm_set update true;
222 let write_ldm_commutative_peephole thumb =
223 let nregs = 2 in
224 Printf.printf "(define_peephole2\n";
225 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
226 let indent = " " in
227 if thumb then begin
228 Printf.printf "\n%s(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
229 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
230 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
231 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))]\n" indent (nregs * 2 + 3)
232 end else begin
233 Printf.printf "\n%s(parallel\n" indent;
234 Printf.printf "%s [(set (match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2);
235 Printf.printf "%s (match_operator:SI %d \"commutative_binary_operator\"\n" indent (nregs * 2 + 1);
236 Printf.printf "%s [(match_operand:SI %d \"s_register_operand\" \"\")\n" indent (nregs * 2 + 2);
237 Printf.printf "%s (match_operand:SI %d \"s_register_operand\" \"\")]))\n" indent (nregs * 2 + 3);
238 Printf.printf "%s (clobber (reg:CC CC_REGNUM))])]\n" indent
239 end;
240 Printf.printf " \"((((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 2);
241 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1])))\n" (nregs * 2 + 3);
242 Printf.printf " || ((REGNO (operands[%d]) == REGNO (operands[0]))\n" (nregs * 2 + 3);
243 Printf.printf " && (REGNO (operands[%d]) == REGNO (operands[1]))))\n" (nregs * 2 + 2);
244 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[0]))\n" (nregs + 1);
245 Printf.printf " || (REGNO (operands[0]) == REGNO (operands[%d])))\n" (nregs * 2);
246 Printf.printf " && (peep2_regno_dead_p (%d, REGNO (operands[1]))\n" (nregs + 1);
247 Printf.printf " || (REGNO (operands[1]) == REGNO (operands[%d]))))\"\n" (nregs * 2);
248 begin
249 if thumb then
250 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))]\n"
251 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3)
252 else begin
253 Printf.printf " [(parallel\n";
254 Printf.printf " [(set (match_dup %d) (match_op_dup %d [(match_dup %d) (match_dup %d)]))\n"
255 (nregs * 2) (nregs * 2 + 1) (nregs * 2 + 2) (nregs * 2 + 3);
256 Printf.printf " (clobber (reg:CC CC_REGNUM))])]\n"
258 end;
259 Printf.printf "{\n if (!gen_ldm_seq (operands, %d, true))\n FAIL;\n" nregs;
260 Printf.printf "})\n\n"
262 let write_ldm_peephole nregs =
263 Printf.printf "(define_peephole2\n";
264 write_peep_sets (write_ldm_peep_set "" nregs) 0 true nregs;
265 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
266 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
268 let write_ldm_peephole_b nregs =
269 if nregs > 2 then begin
270 Printf.printf "(define_peephole2\n";
271 write_ldm_peep_set "" nregs 0 true;
272 Printf.printf "\n (parallel\n";
273 write_peep_sets (write_ldm_peep_set " " nregs) 1 true (nregs - 1);
274 Printf.printf "])]\n \"\"\n [(const_int 0)]\n{\n";
275 Printf.printf " if (gen_ldm_seq (operands, %d, false))\n DONE;\n else\n FAIL;\n})\n\n" nregs
278 let write_stm_peephole nregs =
279 Printf.printf "(define_peephole2\n";
280 write_peep_sets (write_stm_peep_set "" nregs) 0 true nregs;
281 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
282 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
284 let write_stm_peephole_b nregs =
285 if nregs > 2 then begin
286 Printf.printf "(define_peephole2\n";
287 write_stm_peep_set "" nregs 0 true;
288 Printf.printf "\n (parallel\n";
289 write_peep_sets (write_stm_peep_set "" nregs) 1 true (nregs - 1);
290 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
291 Printf.printf " if (gen_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
294 let write_const_stm_peephole_a nregs =
295 Printf.printf "(define_peephole2\n";
296 write_peep_sets (write_const_stm_peep_set nregs) 0 true nregs;
297 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
298 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
300 let write_const_stm_peephole_b nregs =
301 Printf.printf "(define_peephole2\n";
302 write_peep_sets (write_any_load "const_int_operand" nregs) 0 true nregs;
303 Printf.printf "\n";
304 write_peep_sets (write_const_store nregs) 0 false nregs;
305 Printf.printf "]\n \"\"\n [(const_int 0)]\n{\n";
306 Printf.printf " if (gen_const_stm_seq (operands, %d))\n DONE;\n else\n FAIL;\n})\n\n" nregs
308 let patterns () =
309 let addrmodes = [ IA; IB; DA; DB ] in
310 let sizes = [ 4; 3; 2] in
311 List.iter
312 (fun n ->
313 List.iter
314 (fun addrmode ->
315 write_ldm_pattern addrmode n false;
316 write_ldm_pattern addrmode n true;
317 write_stm_pattern addrmode n false;
318 write_stm_pattern addrmode n true)
319 addrmodes;
320 write_ldm_peephole n;
321 write_ldm_peephole_b n;
322 write_const_stm_peephole_a n;
323 write_const_stm_peephole_b n;
324 write_stm_peephole n;)
325 sizes;
326 write_ldm_commutative_peephole false;
327 write_ldm_commutative_peephole true
329 let print_lines = List.iter (fun s -> Format.printf "%s@\n" s)
331 (* Do it. *)
333 let _ =
334 print_lines [
335 "/* ARM ldm/stm instruction patterns. This file was automatically generated";
336 " using arm-ldmstm.ml. Please do not edit manually.";
338 " Copyright (C) 2010-2018 Free Software Foundation, Inc.";
339 " Contributed by CodeSourcery.";
341 " This file is part of GCC.";
343 " GCC is free software; you can redistribute it and/or modify it";
344 " under the terms of the GNU General Public License as published";
345 " by the Free Software Foundation; either version 3, or (at your";
346 " option) any later version.";
348 " GCC is distributed in the hope that it will be useful, but WITHOUT";
349 " ANY WARRANTY; without even the implied warranty of MERCHANTABILITY";
350 " or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public";
351 " License for more details.";
353 " You should have received a copy of the GNU General Public License and";
354 " a copy of the GCC Runtime Library Exception along with this program;";
355 " see the files COPYING3 and COPYING.RUNTIME respectively. If not, see";
356 " <http://www.gnu.org/licenses/>. */";
357 ""];
358 patterns ();