1 ;; ARM ldrd/strd peephole optimizations.
3 ;; Copyright (C) 2013-2018 Free Software Foundation, Inc.
5 ;; Written by Greta Yorsh <greta.yorsh@arm.com>
7 ;; This file is part of GCC.
9 ;; GCC is free software; you can redistribute it and/or modify it
10 ;; under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 3, or (at your option)
14 ;; GCC is distributed in the hope that it will be useful, but
15 ;; WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 ;; General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GCC; see the file COPYING3. If not see
21 ;; <http://www.gnu.org/licenses/>.
23 ;; The following peephole optimizations identify consecutive memory
24 ;; accesses, and try to rearrange the operands to enable generation of
27 (define_peephole2 ; ldrd
28 [(set (match_operand:SI 0 "arm_general_register_operand" "")
29 (match_operand:SI 2 "memory_operand" ""))
30 (set (match_operand:SI 1 "arm_general_register_operand" "")
31 (match_operand:SI 3 "memory_operand" ""))]
35 if (!gen_operands_ldrd_strd (operands, true, false, false))
39 /* In ARM state, the destination registers of LDRD/STRD must be
40 consecutive. We emit DImode access. */
41 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
42 operands[2] = adjust_address (operands[2], DImode, 0);
43 /* Emit [(set (match_dup 0) (match_dup 2))] */
44 emit_insn (gen_rtx_SET (operands[0], operands[2]));
47 else if (TARGET_THUMB2)
50 [(parallel [(set (match_dup 0) (match_dup 2))
51 (set (match_dup 1) (match_dup 3))])] */
52 rtx t1 = gen_rtx_SET (operands[0], operands[2]);
53 rtx t2 = gen_rtx_SET (operands[1], operands[3]);
54 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
59 (define_peephole2 ; strd
60 [(set (match_operand:SI 2 "memory_operand" "")
61 (match_operand:SI 0 "arm_general_register_operand" ""))
62 (set (match_operand:SI 3 "memory_operand" "")
63 (match_operand:SI 1 "arm_general_register_operand" ""))]
67 if (!gen_operands_ldrd_strd (operands, false, false, false))
71 /* In ARM state, the destination registers of LDRD/STRD must be
72 consecutive. We emit DImode access. */
73 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
74 operands[2] = adjust_address (operands[2], DImode, 0);
75 /* Emit [(set (match_dup 2) (match_dup 0))] */
76 emit_insn (gen_rtx_SET (operands[2], operands[0]));
79 else if (TARGET_THUMB2)
82 [(parallel [(set (match_dup 2) (match_dup 0))
83 (set (match_dup 3) (match_dup 1))])] */
84 rtx t1 = gen_rtx_SET (operands[2], operands[0]);
85 rtx t2 = gen_rtx_SET (operands[3], operands[1]);
86 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
91 ;; The following peepholes reorder registers to enable LDRD/STRD.
92 (define_peephole2 ; strd of constants
93 [(set (match_operand:SI 0 "arm_general_register_operand" "")
94 (match_operand:SI 4 "const_int_operand" ""))
95 (set (match_operand:SI 2 "memory_operand" "")
97 (set (match_operand:SI 1 "arm_general_register_operand" "")
98 (match_operand:SI 5 "const_int_operand" ""))
99 (set (match_operand:SI 3 "memory_operand" "")
104 if (!gen_operands_ldrd_strd (operands, false, true, false))
108 rtx tmp = gen_rtx_REG (DImode, REGNO (operands[0]));
109 operands[2] = adjust_address (operands[2], DImode, 0);
111 [(set (match_dup 0) (match_dup 4))
112 (set (match_dup 1) (match_dup 5))
113 (set (match_dup 2) tmp)] */
114 emit_insn (gen_rtx_SET (operands[0], operands[4]));
115 emit_insn (gen_rtx_SET (operands[1], operands[5]));
116 emit_insn (gen_rtx_SET (operands[2], tmp));
119 else if (TARGET_THUMB2)
122 [(set (match_dup 0) (match_dup 4))
123 (set (match_dup 1) (match_dup 5))
124 (parallel [(set (match_dup 2) (match_dup 0))
125 (set (match_dup 3) (match_dup 1))])] */
126 emit_insn (gen_rtx_SET (operands[0], operands[4]));
127 emit_insn (gen_rtx_SET (operands[1], operands[5]));
128 rtx t1 = gen_rtx_SET (operands[2], operands[0]);
129 rtx t2 = gen_rtx_SET (operands[3], operands[1]);
130 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
135 (define_peephole2 ; strd of constants
136 [(set (match_operand:SI 0 "arm_general_register_operand" "")
137 (match_operand:SI 4 "const_int_operand" ""))
138 (set (match_operand:SI 1 "arm_general_register_operand" "")
139 (match_operand:SI 5 "const_int_operand" ""))
140 (set (match_operand:SI 2 "memory_operand" "")
142 (set (match_operand:SI 3 "memory_operand" "")
147 if (!gen_operands_ldrd_strd (operands, false, true, false))
151 rtx tmp = gen_rtx_REG (DImode, REGNO (operands[0]));
152 operands[2] = adjust_address (operands[2], DImode, 0);
154 [(set (match_dup 0) (match_dup 4))
155 (set (match_dup 1) (match_dup 5))
156 (set (match_dup 2) tmp)] */
157 emit_insn (gen_rtx_SET (operands[0], operands[4]));
158 emit_insn (gen_rtx_SET (operands[1], operands[5]));
159 emit_insn (gen_rtx_SET (operands[2], tmp));
162 else if (TARGET_THUMB2)
165 [(set (match_dup 0) (match_dup 4))
166 (set (match_dup 1) (match_dup 5))
167 (parallel [(set (match_dup 2) (match_dup 0))
168 (set (match_dup 3) (match_dup 1))])] */
169 emit_insn (gen_rtx_SET (operands[0], operands[4]));
170 emit_insn (gen_rtx_SET (operands[1], operands[5]));
171 rtx t1 = gen_rtx_SET (operands[2], operands[0]);
172 rtx t2 = gen_rtx_SET (operands[3], operands[1]);
173 emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, t1, t2)));
178 ;; The following two peephole optimizations are only relevant for ARM
179 ;; mode where LDRD/STRD require consecutive registers.
181 (define_peephole2 ; swap the destination registers of two loads
182 ; before a commutative operation.
183 [(set (match_operand:SI 0 "arm_general_register_operand" "")
184 (match_operand:SI 2 "memory_operand" ""))
185 (set (match_operand:SI 1 "arm_general_register_operand" "")
186 (match_operand:SI 3 "memory_operand" ""))
187 (set (match_operand:SI 4 "arm_general_register_operand" "")
188 (match_operator:SI 5 "commutative_binary_operator"
189 [(match_operand 6 "arm_general_register_operand" "")
190 (match_operand 7 "arm_general_register_operand" "") ]))]
191 "TARGET_LDRD && TARGET_ARM
192 && ( ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], operands[7])))
193 ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], operands[6]))))
194 && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], operands[4]))
195 && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], operands[4]))"
196 [(set (match_dup 0) (match_dup 2))
197 (set (match_dup 4) (match_op_dup 5 [(match_dup 6) (match_dup 7)]))]
199 if (!gen_operands_ldrd_strd (operands, true, false, true))
205 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
206 operands[2] = adjust_address (operands[2], DImode, 0);
211 (define_peephole2 ; swap the destination registers of two loads
212 ; before a commutative operation that sets the flags.
213 [(set (match_operand:SI 0 "arm_general_register_operand" "")
214 (match_operand:SI 2 "memory_operand" ""))
215 (set (match_operand:SI 1 "arm_general_register_operand" "")
216 (match_operand:SI 3 "memory_operand" ""))
218 [(set (match_operand:SI 4 "arm_general_register_operand" "")
219 (match_operator:SI 5 "commutative_binary_operator"
220 [(match_operand 6 "arm_general_register_operand" "")
221 (match_operand 7 "arm_general_register_operand" "") ]))
222 (clobber (reg:CC CC_REGNUM))])]
223 "TARGET_LDRD && TARGET_ARM
224 && ( ((rtx_equal_p(operands[0], operands[6])) && (rtx_equal_p(operands[1], operands[7])))
225 ||((rtx_equal_p(operands[0], operands[7])) && (rtx_equal_p(operands[1], operands[6]))))
226 && (peep2_reg_dead_p (3, operands[0]) || rtx_equal_p (operands[0], operands[4]))
227 && (peep2_reg_dead_p (3, operands[1]) || rtx_equal_p (operands[1], operands[4]))"
228 [(set (match_dup 0) (match_dup 2))
231 (match_op_dup 5 [(match_dup 6) (match_dup 7)]))
232 (clobber (reg:CC CC_REGNUM))])]
234 if (!gen_operands_ldrd_strd (operands, true, false, true))
240 operands[0] = gen_rtx_REG (DImode, REGNO (operands[0]));
241 operands[2] = adjust_address (operands[2], DImode, 0);
246 ;; TODO: Handle LDRD/STRD with writeback:
247 ;; (a) memory operands can be POST_INC, POST_DEC, PRE_MODIFY, POST_MODIFY
248 ;; (b) Patterns may be followed by an update of the base address.