annotate gcc/config/arm/ldrdstrd.md @ 111:04ced10e8804

gcc 7
author kono
date Fri, 27 Oct 2017 22:46:09 +0900
parents
children 84e7813d76e9
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
111
kono
parents:
diff changeset
1 ;; ARM ldrd/strd peephole optimizations.
kono
parents:
diff changeset
2 ;;
kono
parents:
diff changeset
3 ;; Copyright (C) 2013-2017 Free Software Foundation, Inc.
kono
parents:
diff changeset
4 ;;
kono
parents:
diff changeset
5 ;; Written by Greta Yorsh <greta.yorsh@arm.com>
kono
parents:
diff changeset
6
kono
parents:
diff changeset
7 ;; This file is part of GCC.
kono
parents:
diff changeset
8 ;;
kono
parents:
diff changeset
9 ;; GCC is free software; you can redistribute it and/or modify it
kono
parents:
diff changeset
10 ;; under the terms of the GNU General Public License as published by
kono
parents:
diff changeset
11 ;; the Free Software Foundation; either version 3, or (at your option)
kono
parents:
diff changeset
12 ;; any later version.
kono
parents:
diff changeset
13 ;;
kono
parents:
diff changeset
14 ;; GCC is distributed in the hope that it will be useful, but
kono
parents:
diff changeset
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
kono
parents:
diff changeset
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
kono
parents:
diff changeset
17 ;; General Public License for more details.
kono
parents:
diff changeset
18 ;;
kono
parents:
diff changeset
19 ;; You should have received a copy of the GNU General Public License
kono
parents:
diff changeset
20 ;; along with GCC; see the file COPYING3. If not see
kono
parents:
diff changeset
21 ;; <http://www.gnu.org/licenses/>.
kono
parents:
diff changeset
22
kono
parents:
diff changeset
23 ;; The following peephole optimizations identify consecutive memory
kono
parents:
diff changeset
24 ;; accesses, and try to rearrange the operands to enable generation of
kono
parents:
diff changeset
25 ;; ldrd/strd.
kono
parents:
diff changeset
26
kono
parents:
diff changeset
27 (define_peephole2 ; ldrd
kono
parents:
diff changeset
28 [(set (match_operand:SI 0 "arm_general_register_operand" "")
kono
parents:
diff changeset
29 (match_operand:SI 2 "memory_operand" ""))
kono
parents:
diff changeset
30 (set (match_operand:SI 1 "arm_general_register_operand" "")
kono
parents:
diff changeset
31 (match_operand:SI 3 "memory_operand" ""))]
kono
parents:
diff changeset
32 "TARGET_LDRD"
kono
parents:
diff changeset
33 [(const_int 0)]
kono
parents:
diff changeset
34 {
kono
parents:
diff changeset
35 if (!gen_operands_ldrd_strd (operands, true, false, false))
kono
parents:
diff changeset
36 FAIL;
kono
parents:
diff changeset
37 else if (TARGET_ARM)
kono
parents:
diff changeset
38 {
kono
parents:
diff changeset
39 /* In ARM state, the destination registers of LDRD/STRD must be
kono
parents:
diff changeset
40 consecutive. We emit DImode access. */
kono
parents:
diff changeset
41 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
kono
parents:
diff changeset
42 operands[2] = adjust_address (operands[2], DImode, 0);
kono
parents:
diff changeset
43 /* Emit [(set (match_dup 0) (match_dup 2))] */
kono
parents:
diff changeset
44 emit_insn (gen_rtx_SET (operands[0], operands[2]));
kono
parents:
diff changeset
45 DONE;
kono
parents:
diff changeset
46 }
kono
parents:
diff changeset
47 else if (TARGET_THUMB2)
kono
parents:
diff changeset
48 {
kono
parents:
diff changeset
49 /* Emit the pattern:
kono
parents:
diff changeset
50 [(parallel [(set (match_dup 0) (match_dup 2))
kono
parents:
diff changeset
51 (set (match_dup 1) (match_dup 3))])] */
kono
parents:
diff changeset
52 rtx t1 = gen_rtx_SET (operands[0], operands[2]);
kono
parents:
diff changeset
53 rtx t2 = gen_rtx_SET (operands[1], operands[3]);
kono
parents:
diff changeset
54 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
kono
parents:
diff changeset
55 DONE;
kono
parents:
diff changeset
56 }
kono
parents:
diff changeset
57 })
kono
parents:
diff changeset
58
kono
parents:
diff changeset
59 (define_peephole2 ; strd
kono
parents:
diff changeset
60 [(set (match_operand:SI 2 "memory_operand" "")
kono
parents:
diff changeset
61 (match_operand:SI 0 "arm_general_register_operand" ""))
kono
parents:
diff changeset
62 (set (match_operand:SI 3 "memory_operand" "")
kono
parents:
diff changeset
63 (match_operand:SI 1 "arm_general_register_operand" ""))]
kono
parents:
diff changeset
64 "TARGET_LDRD"
kono
parents:
diff changeset
65 [(const_int 0)]
kono
parents:
diff changeset
66 {
kono
parents:
diff changeset
67 if (!gen_operands_ldrd_strd (operands, false, false, false))
kono
parents:
diff changeset
68 FAIL;
kono
parents:
diff changeset
69 else if (TARGET_ARM)
kono
parents:
diff changeset
70 {
kono
parents:
diff changeset
71 /* In ARM state, the destination registers of LDRD/STRD must be
kono
parents:
diff changeset
72 consecutive. We emit DImode access. */
kono
parents:
diff changeset
73 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
kono
parents:
diff changeset
74 operands[2] = adjust_address (operands[2], DImode, 0);
kono
parents:
diff changeset
75 /* Emit [(set (match_dup 2) (match_dup 0))] */
kono
parents:
diff changeset
76 emit_insn (gen_rtx_SET (operands[2], operands[0]));
kono
parents:
diff changeset
77 DONE;
kono
parents:
diff changeset
78 }
kono
parents:
diff changeset
79 else if (TARGET_THUMB2)
kono
parents:
diff changeset
80 {
kono
parents:
diff changeset
81 /* Emit the pattern:
kono
parents:
diff changeset
82 [(parallel [(set (match_dup 2) (match_dup 0))
kono
parents:
diff changeset
83 (set (match_dup 3) (match_dup 1))])] */
kono
parents:
diff changeset
84 rtx t1 = gen_rtx_SET (operands[2], operands[0]);
kono
parents:
diff changeset
85 rtx t2 = gen_rtx_SET (operands[3], operands[1]);
kono
parents:
diff changeset
86 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
kono
parents:
diff changeset
87 DONE;
kono
parents:
diff changeset
88 }
kono
parents:
diff changeset
89 })
kono
parents:
diff changeset
90
kono
parents:
diff changeset
91 ;; The following peepholes reorder registers to enable LDRD/STRD.
kono
parents:
diff changeset
92 (define_peephole2 ; strd of constants
kono
parents:
diff changeset
93 [(set (match_operand:SI 0 "arm_general_register_operand" "")
kono
parents:
diff changeset
94 (match_operand:SI 4 "const_int_operand" ""))
kono
parents:
diff changeset
95 (set (match_operand:SI 2 "memory_operand" "")
kono
parents:
diff changeset
96 (match_dup 0))
kono
parents:
diff changeset
97 (set (match_operand:SI 1 "arm_general_register_operand" "")
kono
parents:
diff changeset
98 (match_operand:SI 5 "const_int_operand" ""))
kono
parents:
diff changeset
99 (set (match_operand:SI 3 "memory_operand" "")
kono
parents:
diff changeset
100 (match_dup 1))]
kono
parents:
diff changeset
101 "TARGET_LDRD"
kono
parents:
diff changeset
102 [(const_int 0)]
kono
parents:
diff changeset
103 {
kono
parents:
diff changeset
104 if (!gen_operands_ldrd_strd (operands, false, true, false))
kono
parents:
diff changeset
105 FAIL;
kono
parents:
diff changeset
106 else if (TARGET_ARM)
kono
parents:
diff changeset
107 {
kono
parents:
diff changeset
108 rtx tmp = gen_rtx_REG (DImode, REGNO (operands[0]));
kono
parents:
diff changeset
109 operands[2] = adjust_address (operands[2], DImode, 0);
kono
parents:
diff changeset
110 /* Emit the pattern:
kono
parents:
diff changeset
111 [(set (match_dup 0) (match_dup 4))
kono
parents:
diff changeset
112 (set (match_dup 1) (match_dup 5))
kono
parents:
diff changeset
113 (set (match_dup 2) tmp)] */
kono
parents:
diff changeset
114 emit_insn (gen_rtx_SET (operands[0], operands[4]));
kono
parents:
diff changeset
115 emit_insn (gen_rtx_SET (operands[1], operands[5]));
kono
parents:
diff changeset
116 emit_insn (gen_rtx_SET (operands[2], tmp));
kono
parents:
diff changeset
117 DONE;
kono
parents:
diff changeset
118 }
kono
parents:
diff changeset
119 else if (TARGET_THUMB2)
kono
parents:
diff changeset
120 {
kono
parents:
diff changeset
121 /* Emit the pattern:
kono
parents:
diff changeset
122 [(set (match_dup 0) (match_dup 4))
kono
parents:
diff changeset
123 (set (match_dup 1) (match_dup 5))
kono
parents:
diff changeset
124 (parallel [(set (match_dup 2) (match_dup 0))
kono
parents:
diff changeset
125 (set (match_dup 3) (match_dup 1))])] */
kono
parents:
diff changeset
126 emit_insn (gen_rtx_SET (operands[0], operands[4]));
kono
parents:
diff changeset
127 emit_insn (gen_rtx_SET (operands[1], operands[5]));
kono
parents:
diff changeset
128 rtx t1 = gen_rtx_SET (operands[2], operands[0]);
kono
parents:
diff changeset
129 rtx t2 = gen_rtx_SET (operands[3], operands[1]);
kono
parents:
diff changeset
130 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
kono
parents:
diff changeset
131 DONE;
kono
parents:
diff changeset
132 }
kono
parents:
diff changeset
133 })
kono
parents:
diff changeset
134
kono
parents:
diff changeset
135 (define_peephole2 ; strd of constants
kono
parents:
diff changeset
136 [(set (match_operand:SI 0 "arm_general_register_operand" "")
kono
parents:
diff changeset
137 (match_operand:SI 4 "const_int_operand" ""))
kono
parents:
diff changeset
138 (set (match_operand:SI 1 "arm_general_register_operand" "")
kono
parents:
diff changeset
139 (match_operand:SI 5 "const_int_operand" ""))
kono
parents:
diff changeset
140 (set (match_operand:SI 2 "memory_operand" "")
kono
parents:
diff changeset
141 (match_dup 0))
kono
parents:
diff changeset
142 (set (match_operand:SI 3 "memory_operand" "")
kono
parents:
diff changeset
143 (match_dup 1))]
kono
parents:
diff changeset
144 "TARGET_LDRD"
kono
parents:
diff changeset
145 [(const_int 0)]
kono
parents:
diff changeset
146 {
kono
parents:
diff changeset
147 if (!gen_operands_ldrd_strd (operands, false, true, false))
kono
parents:
diff changeset
148 FAIL;
kono
parents:
diff changeset
149 else if (TARGET_ARM)
kono
parents:
diff changeset
150 {
kono
parents:
diff changeset
151 rtx tmp = gen_rtx_REG (DImode, REGNO (operands[0]));
kono
parents:
diff changeset
152 operands[2] = adjust_address (operands[2], DImode, 0);
kono
parents:
diff changeset
153 /* Emit the pattern
kono
parents:
diff changeset
154 [(set (match_dup 0) (match_dup 4))
kono
parents:
diff changeset
155 (set (match_dup 1) (match_dup 5))
kono
parents:
diff changeset
156 (set (match_dup 2) tmp)] */
kono
parents:
diff changeset
157 emit_insn (gen_rtx_SET (operands[0], operands[4]));
kono
parents:
diff changeset
158 emit_insn (gen_rtx_SET (operands[1], operands[5]));
kono
parents:
diff changeset
159 emit_insn (gen_rtx_SET (operands[2], tmp));
kono
parents:
diff changeset
160 DONE;
kono
parents:
diff changeset
161 }
kono
parents:
diff changeset
162 else if (TARGET_THUMB2)
kono
parents:
diff changeset
163 {
kono
parents:
diff changeset
164 /* Emit the pattern:
kono
parents:
diff changeset
165 [(set (match_dup 0) (match_dup 4))
kono
parents:
diff changeset
166 (set (match_dup 1) (match_dup 5))
kono
parents:
diff changeset
167 (parallel [(set (match_dup 2) (match_dup 0))
kono
parents:
diff changeset
168 (set (match_dup 3) (match_dup 1))])] */
kono
parents:
diff changeset
169 emit_insn (gen_rtx_SET (operands[0], operands[4]));
kono
parents:
diff changeset
170 emit_insn (gen_rtx_SET (operands[1], operands[5]));
kono
parents:
diff changeset
171 rtx t1 = gen_rtx_SET (operands[2], operands[0]);
kono
parents:
diff changeset
172 rtx t2 = gen_rtx_SET (operands[3], operands[1]);
kono
parents:
diff changeset
173 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
kono
parents:
diff changeset
174 DONE;
kono
parents:
diff changeset
175 }
kono
parents:
diff changeset
176 })
kono
parents:
diff changeset
177
kono
parents:
diff changeset
178 ;; The following two peephole optimizations are only relevant for ARM
kono
parents:
diff changeset
179 ;; mode where LDRD/STRD require consecutive registers.
kono
parents:
diff changeset
180
kono
parents:
diff changeset
181 (define_peephole2 ; swap the destination registers of two loads
kono
parents:
diff changeset
182 ; before a commutative operation.
kono
parents:
diff changeset
183 [(set (match_operand:SI 0 "arm_general_register_operand" "")
kono
parents:
diff changeset
184 (match_operand:SI 2 "memory_operand" ""))
kono
parents:
diff changeset
185 (set (match_operand:SI 1 "arm_general_register_operand" "")
kono
parents:
diff changeset
186 (match_operand:SI 3 "memory_operand" ""))
kono
parents:
diff changeset
187 (set (match_operand:SI 4 "arm_general_register_operand" "")
kono
parents:
diff changeset
188 (match_operator:SI 5 "commutative_binary_operator"
kono
parents:
diff changeset
189 [(match_operand 6 "arm_general_register_operand" "")
kono
parents:
diff changeset
190 (match_operand 7 "arm_general_register_operand" "") ]))]
kono
parents:
diff changeset
191 "TARGET_LDRD && TARGET_ARM
kono
parents:
diff changeset
192 && ( ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], operands[7])))
kono
parents:
diff changeset
193 ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], operands[6]))))
kono
parents:
diff changeset
194 && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], operands[4]))
kono
parents:
diff changeset
195 && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], operands[4]))"
kono
parents:
diff changeset
196 [(set (match_dup 0) (match_dup 2))
kono
parents:
diff changeset
197 (set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
kono
parents:
diff changeset
198 {
kono
parents:
diff changeset
199 if (!gen_operands_ldrd_strd (operands, true, false, true))
kono
parents:
diff changeset
200 {
kono
parents:
diff changeset
201 FAIL;
kono
parents:
diff changeset
202 }
kono
parents:
diff changeset
203 else
kono
parents:
diff changeset
204 {
kono
parents:
diff changeset
205 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
kono
parents:
diff changeset
206 operands[2] = adjust_address (operands[2], DImode, 0);
kono
parents:
diff changeset
207 }
kono
parents:
diff changeset
208 }
kono
parents:
diff changeset
209 )
kono
parents:
diff changeset
210
kono
parents:
diff changeset
211 (define_peephole2 ; swap the destination registers of two loads
kono
parents:
diff changeset
212 ; before a commutative operation that sets the flags.
kono
parents:
diff changeset
213 [(set (match_operand:SI 0 "arm_general_register_operand" "")
kono
parents:
diff changeset
214 (match_operand:SI 2 "memory_operand" ""))
kono
parents:
diff changeset
215 (set (match_operand:SI 1 "arm_general_register_operand" "")
kono
parents:
diff changeset
216 (match_operand:SI 3 "memory_operand" ""))
kono
parents:
diff changeset
217 (parallel
kono
parents:
diff changeset
218 [(set (match_operand:SI 4 "arm_general_register_operand" "")
kono
parents:
diff changeset
219 (match_operator:SI 5 "commutative_binary_operator"
kono
parents:
diff changeset
220 [(match_operand 6 "arm_general_register_operand" "")
kono
parents:
diff changeset
221 (match_operand 7 "arm_general_register_operand" "") ]))
kono
parents:
diff changeset
222 (clobber (reg:CC CC_REGNUM))])]
kono
parents:
diff changeset
223 "TARGET_LDRD && TARGET_ARM
kono
parents:
diff changeset
224 && ( ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], operands[7])))
kono
parents:
diff changeset
225 ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], operands[6]))))
kono
parents:
diff changeset
226 && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], operands[4]))
kono
parents:
diff changeset
227 && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], operands[4]))"
kono
parents:
diff changeset
228 [(set (match_dup 0) (match_dup 2))
kono
parents:
diff changeset
229 (parallel
kono
parents:
diff changeset
230 [(set (match_dup 4)
kono
parents:
diff changeset
231 (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
kono
parents:
diff changeset
232 (clobber (reg:CC CC_REGNUM))])]
kono
parents:
diff changeset
233 {
kono
parents:
diff changeset
234 if (!gen_operands_ldrd_strd (operands, true, false, true))
kono
parents:
diff changeset
235 {
kono
parents:
diff changeset
236 FAIL;
kono
parents:
diff changeset
237 }
kono
parents:
diff changeset
238 else
kono
parents:
diff changeset
239 {
kono
parents:
diff changeset
240 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
kono
parents:
diff changeset
241 operands[2] = adjust_address (operands[2], DImode, 0);
kono
parents:
diff changeset
242 }
kono
parents:
diff changeset
243 }
kono
parents:
diff changeset
244 )
kono
parents:
diff changeset
245
kono
parents:
diff changeset
246 ;; TODO: Handle LDRD/STRD with writeback:
kono
parents:
diff changeset
247 ;; (a) memory operands can be POST_INC, POST_DEC, PRE_MODIFY, POST_MODIFY
kono
parents:
diff changeset
248 ;; (b) Patterns may be followed by an update of the base address.