libcpp, c, middle-end: Optimize initializers using #embed in C
[official-gcc.git] / gcc / config / h8300 / shiftrotate.md
blobd3aa6bea064d54f6fa9b4c2a017fb2f325a0909e
1 ;; ----------------------------------------------------------------------
2 ;; SHIFTS
3 ;; ----------------------------------------------------------------------
4 ;;
5 ;; We make some attempt to provide real efficient shifting.  One example is
6 ;; doing an 8-bit shift of a 16-bit value by moving a byte reg into the other
7 ;; reg and moving 0 into the former reg.
8 ;;
9 ;; We also try to achieve this in a uniform way.  IE: We don't try to achieve
10 ;; this in both rtl and at insn emit time.  Ideally, we'd use rtl as that would
11 ;; give the optimizer more cracks at the code.  However, we wish to do things
12 ;; like optimizing shifting the sign bit to bit 0 by rotating the other way.
13 ;; There is rtl to handle this (rotate + and), but the H8/300 doesn't handle
14 ;; 16-bit rotates.  Also, if we emit complicated rtl, combine may not be able
15 ;; to detect cases it can optimize.
17 ;; For these and other fuzzy reasons, I've decided to go the less pretty but
18 ;; easier "do it at insn emit time" route.
21 (define_expand "ashl<mode>3"
22   [(set (match_operand:QHSI 0 "register_operand" "")
23         (ashift:QHSI (match_operand:QHSI 1 "register_operand" "")
24                      (match_operand:QI 2 "nonmemory_operand" "")))]
25   ""
26   {
27     if (expand_a_shift (<MODE>mode, ASHIFT, operands))
28     DONE;
29   })
31 (define_expand "ashr<mode>3"
32   [(set (match_operand:QHSI 0 "register_operand" "")
33         (ashiftrt:QHSI (match_operand:QHSI 1 "register_operand" "")
34                        (match_operand:QI 2 "nonmemory_operand" "")))]
35   ""
36   {
37     if (expand_a_shift (<MODE>mode, ASHIFTRT, operands))
38     DONE;
39   })
41 (define_expand "lshr<mode>3"
42   [(set (match_operand:QHSI 0 "register_operand" "")
43         (lshiftrt:QHSI (match_operand:QHSI 1 "register_operand" "")
44                        (match_operand:QI 2 "nonmemory_operand" "")))]
45   ""
46   {
47     if (expand_a_shift (<MODE>mode, LSHIFTRT, operands))
48     DONE;
49   })
51 ;; QI/HI/SI BIT SHIFTS
53 (define_insn_and_split ""
54   [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
55         (match_operator:QHSI 3 "h8sx_unary_shift_operator"
56          [(match_operand:QHSI 1 "h8300_dst_operand" "0")
57           (match_operand:QI 2 "const_int_operand" "")]))]
58   "h8300_operands_match_p (operands)"
59   "#"
60   "&& reload_completed"
61   [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
62               (clobber (reg:CC CC_REG))])])
64 (define_insn ""
65   [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
66         (match_operator:QHSI 3 "h8sx_unary_shift_operator"
67          [(match_operand:QHSI 1 "h8300_dst_operand" "0")
68           (match_operand:QI 2 "const_int_operand" "")]))
69    (clobber (reg:CC CC_REG))]
70   "h8300_operands_match_p (operands)"
72   if (<MODE>mode == E_QImode)
73     return output_h8sx_shift (operands, 'b', 'X');
74   if (<MODE>mode == E_HImode)
75     return output_h8sx_shift (operands, 'w', 'T');
76   if (<MODE>mode == E_SImode)
77     return output_h8sx_shift (operands, 'l', 'S');
78   gcc_unreachable ();
80   [(set_attr "length_table" "unary")])
82 (define_insn ""
83   [(set (reg:CCZN CC_REG)
84         (compare:CCZN
85           (match_operator:QHSI 3 "h8sx_unary_shift_operator"
86             [(match_operand:QHSI 1 "h8300_dst_operand" "0")
87              (match_operand:QI 2 "const_int_operand" "")])
88           (const_int 0)))
89    (set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ")
90         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
91   "h8300_operands_match_p (operands)"
93   if (<MODE>mode == E_QImode)
94     return output_h8sx_shift (operands, 'b', 'X');
95   if (<MODE>mode == E_HImode)
96     return output_h8sx_shift (operands, 'w', 'T');
97   if (<MODE>mode == E_SImode)
98     return output_h8sx_shift (operands, 'l', 'S');
99   gcc_unreachable ();
101   [(set_attr "length_table" "unary")])
103 (define_insn_and_split ""
104   [(set (match_operand:QHSI 0 "register_operand" "=r")
105         (match_operator:QHSI 3 "h8sx_binary_shift_operator"
106          [(match_operand:QHSI 1 "register_operand" "0")
107           (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))]
108   ""
109   "#"
110   "&& reload_completed"
111   [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
112               (clobber (reg:CC CC_REG))])])
114 (define_insn ""
115   [(set (match_operand:QHSI 0 "register_operand" "=r")
116         (match_operator:QHSI 3 "h8sx_binary_shift_operator"
117          [(match_operand:QHSI 1 "register_operand" "0")
118           (match_operand:QI 2 "nonmemory_operand" "r P5>X")]))
119    (clobber (reg:CC CC_REG))]
120   ""
122   if (<MODE>mode == QImode)
123     return output_h8sx_shift (operands, 'b', 'X');
124   if (<MODE>mode == HImode)
125     return output_h8sx_shift (operands, 'w', 'T');
126   if (<MODE>mode == SImode)
127     return output_h8sx_shift (operands, 'l', 'S');
128   gcc_unreachable ();
130   [(set_attr "length" "4")])
132 (define_insn ""
133   [(set (reg:CCZN CC_REG)
134         (compare:CCZN
135           (match_operator:QHSI 3 "h8sx_binary_shift_operator"
136            [(match_operand:QHSI 1 "register_operand" "0")
137             (match_operand:QI 2 "nonmemory_operand" "r P5>X")])
138           (const_int 0)))
139    (set (match_operand:QHSI 0 "register_operand" "=r")
140         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
141   ""
143   if (<MODE>mode == QImode)
144     return output_h8sx_shift (operands, 'b', 'X');
145   if (<MODE>mode == HImode)
146     return output_h8sx_shift (operands, 'w', 'T');
147   if (<MODE>mode == SImode)
148     return output_h8sx_shift (operands, 'l', 'S');
149   gcc_unreachable ();
151   [(set_attr "length" "4")])
153 (define_insn_and_split "*shiftqi_noscratch"
154   [(set (match_operand:QI 0 "register_operand" "=r,r")
155         (shifts:QI
156           (match_operand:QI 1 "register_operand" "0,0")
157           (match_operand:QI 2 "nonmemory_operand" "R,rn")))]
158   "(GET_CODE (operands[2]) == CONST_INT
159     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode,
160                                      <CODE>))"
161   "#"
162   "&& reload_completed"
163   [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
164               (clobber (reg:CC CC_REG))])])
166 (define_insn "*shiftqi_noscratch_clobber_flags"
167   [(set (match_operand:QI 0 "register_operand" "=r,r")
168         (shifts:QI
169           (match_operand:QI 1 "register_operand" "0,0")
170           (match_operand:QI 2 "nonmemory_operand" "R,rn")))
171    (clobber (reg:CC CC_REG))]
172   "(GET_CODE (operands[2]) == CONST_INT
173     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>))"
175   return output_a_shift (operands, <CODE>);
177   [(set (attr "length")
178         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
180 (define_insn "*shiftqi_noscratch_set_flags"
181   [(set (reg:CCZN CC_REG)
182         (compare:CCZN
183           (shifts:QI
184             (match_operand:QI 1 "register_operand" "0,0")
185             (match_operand:QI 2 "nonmemory_operand" "R,rn"))
186           (const_int 0)))
187    (set (match_operand:QI 0 "register_operand" "=r,r")
188         (shifts:QI (match_dup 1) (match_dup 2)))]
189   "(GET_CODE (operands[2]) == CONST_INT
190     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), QImode, <CODE>)
191     && compute_a_shift_cc (operands, <CODE>))"
193   return output_a_shift (operands, <CODE>);
195   [(set (attr "length")
196         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
199 (define_insn_and_split "*shiftqi"
200   [(set (match_operand:QI 0 "register_operand" "=r,r")
201         (shifts:QI
202           (match_operand:QI 1 "register_operand" "0,0")
203           (match_operand:QI 2 "nonmemory_operand" "R,rn")))
204    (clobber (match_scratch:QI 3 "=X,&r"))]
205   ""
206   "#"
207   "&& reload_completed"
208   [(parallel [(set (match_dup 0) (shifts:QI (match_dup 1) (match_dup 2)))
209               (clobber (match_dup 3))
210               (clobber (reg:CC CC_REG))])])
212 (define_insn "*shiftqi_clobber_flags"
213   [(set (match_operand:QI 0 "register_operand" "=r,r")
214         (shifts:QI
215           (match_operand:QI 1 "register_operand" "0,0")
216           (match_operand:QI 2 "nonmemory_operand" "R,rn")))
217    (clobber (match_scratch:QI 3 "=X,&r"))
218    (clobber (reg:CC CC_REG))]
219   ""
221   return output_a_shift (operands, <CODE>);
223   [(set (attr "length")
224         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
226 (define_insn_and_split "*shifthi_noscratch"
227   [(set (match_operand:HI 0 "register_operand" "=r,r")
228         (shifts:HI
229           (match_operand:HI 1 "register_operand" "0,0")
230           (match_operand:HI 2 "nonmemory_operand" "S,rn")))]
231   "(GET_CODE (operands[2]) == CONST_INT
232     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))"
233   "#"
234   "&& reload_completed"
235   [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
236               (clobber (reg:CC CC_REG))])])
238 (define_insn "*shifthi_noscratch_clobber_flags"
239   [(set (match_operand:HI 0 "register_operand" "=r,r")
240         (shifts:HI
241           (match_operand:HI 1 "register_operand" "0,0")
242           (match_operand:HI 2 "nonmemory_operand" "S,rn")))
243    (clobber (reg:CC CC_REG))]
244   "(GET_CODE (operands[2]) == CONST_INT
245     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>))"
247   return output_a_shift (operands, <CODE>);
249   [(set (attr "length")
250         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
252 (define_insn "*shifthi_noscratch_setzn"
253   [(set (reg:CCZN CC_REG)
254         (compare:CCZN
255           (shifts:HI (match_operand:HI 1 "register_operand" "0,0")
256                      (match_operand:HI 2 "nonmemory_operand" "S,rn"))
257           (const_int 0)))
258    (set (match_operand:HI 0 "register_operand" "=r,r")
259         (shifts:HI (match_dup 1) (match_dup 2)))]
260   "(GET_CODE (operands[2]) == CONST_INT
261     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), HImode, <CODE>)
262     && compute_a_shift_cc (operands, <CODE>))"
264   return output_a_shift (operands, <CODE>);
266   [(set (attr "length")
267         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
269 (define_insn_and_split "*shifthi"
270   [(set (match_operand:HI 0 "register_operand" "=r,r")
271         (shifts:HI
272           (match_operand:HI 1 "register_operand" "0,0")
273           (match_operand:QI 2 "nonmemory_operand" "S,rn")))
274    (clobber (match_scratch:QI 3 "=X,&r"))]
275   ""
276   "#"
277   "&& reload_completed"
278   [(parallel [(set (match_dup 0) (shifts:HI (match_dup 1) (match_dup 2)))
279               (clobber (match_dup 3))
280               (clobber (reg:CC CC_REG))])])
282 (define_insn "*shifthi_clobber_flags"
283   [(set (match_operand:HI 0 "register_operand" "=r,r")
284         (shifts:HI
285           (match_operand:HI 1 "register_operand" "0,0")
286           (match_operand:QI 2 "nonmemory_operand" "S,rn")))
287    (clobber (match_scratch:QI 3 "=X,&r"))
288    (clobber (reg:CC CC_REG))]
289   ""
291   return output_a_shift (operands, <CODE>);
293   [(set (attr "length")
294         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
296 (define_insn_and_split "*shiftsi_noscratch"
297   [(set (match_operand:SI 0 "register_operand" "=r,r")
298         (shifts:SI
299           (match_operand:SI 1 "register_operand" "0,0")
300           (match_operand:QI 2 "nonmemory_operand" "T,rn")))]
301   "(GET_CODE (operands[2]) == CONST_INT
302     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))"
303   "#"
304   "&& reload_completed"
305   [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
306               (clobber (reg:CC CC_REG))])])
308 (define_insn "*shiftsi_noscratch_clobber_flags"
309   [(set (match_operand:SI 0 "register_operand" "=r,r")
310         (shifts:SI
311           (match_operand:SI 1 "register_operand" "0,0")
312           (match_operand:SI 2 "nonmemory_operand" "T,rn")))
313    (clobber (reg:CC CC_REG))]
314   "(GET_CODE (operands[2]) == CONST_INT
315     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>))"
317   return output_a_shift (operands, <CODE>);
319   [(set (attr "length")
320         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
322 (define_insn "*shiftsi_noscratch_cczn"
323   [(set (reg:CCZN CC_REG)
324         (compare:CCZN
325           (shifts:SI
326             (match_operand:SI 1 "register_operand" "0,0")
327             (match_operand:SI 2 "nonmemory_operand" "T,rn"))
328           (const_int 0)))
329    (set (match_operand:SI 0 "register_operand" "=r,r")
330         (shifts:SI (match_dup 1) (match_dup 2)))]
331   "(GET_CODE (operands[2]) == CONST_INT
332     && !h8300_shift_needs_scratch_p (INTVAL (operands[2]), SImode, <CODE>)
333     && compute_a_shift_cc (operands, <CODE>))"
335   return output_a_shift (operands, <CODE>);
337   [(set (attr "length")
338         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
340 ;; Split a variable shift into a loop.  If the register containing
341 ;; the shift count dies, then we just use that register.
344 (define_insn_and_split "*shiftsi"
345   [(set (match_operand:SI 0 "register_operand" "=r,r")
346         (shifts:SI
347           (match_operand:SI 1 "register_operand" "0,0")
348           (match_operand:QI 2 "nonmemory_operand" "T,rn")))
349    (clobber (match_scratch:QI 3 "=X,&r"))]
350   ""
351   "#"
352   "&& reload_completed"
353   [(parallel [(set (match_dup 0) (shifts:SI (match_dup 1) (match_dup 2)))
354               (clobber (match_dup 3))
355               (clobber (reg:CC CC_REG))])])
357 (define_insn "*shiftsi_clobber_flags"
358   [(set (match_operand:SI 0 "register_operand" "=r,r")
359         (shifts:SI
360           (match_operand:SI 1 "register_operand" "0,0")
361           (match_operand:QI 2 "nonmemory_operand" "T,rn")))
362    (clobber (match_scratch:QI 3 "=X,&r"))
363    (clobber (reg:CC CC_REG))]
364   ""
366   return output_a_shift (operands, <CODE>);
368   [(set (attr "length")
369         (symbol_ref "compute_a_shift_length (operands, <CODE>)"))])
371 (define_split
372   [(set (match_operand 0 "register_operand" "")
373         (match_operator 2 "nshift_operator"
374          [(match_dup 0)
375           (match_operand:QI 1 "register_operand" "")]))
376    (clobber (match_operand:QI 3 "register_operand" ""))
377    (clobber (reg:CC CC_REG))]
378   "epilogue_completed
379    && find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
380   [(set (reg:CCZN CC_REG)
381         (compare:CCZN (match_dup 1) (const_int 0)))
382    (set (pc)
383         (if_then_else (le (reg:CCZN CC_REG)  (const_int 0))
384                       (label_ref (match_dup 5))
385                       (pc)))
386    (match_dup 4)
387    (parallel
388      [(set (match_dup 0)
389            (match_op_dup 2 [(match_dup 0) (const_int 1)]))
390       (clobber (reg:CC CC_REG))])
391    (parallel
392      [(set (reg:CCZN CC_REG)
393            (compare:CCZN
394              (plus:QI (match_dup 1) (const_int -1))
395              (const_int 0)))
396       (set (match_dup 1) (plus:QI (match_dup 1) (const_int -1)))])
397    (set (pc)
398         (if_then_else (ne (reg:CCZN CC_REG) (const_int 0))
399                       (label_ref (match_dup 4))
400                       (pc)))
401    (match_dup 5)]
402   {
403     operands[4] = gen_label_rtx ();
404     operands[5] = gen_label_rtx ();
405   })
407 (define_split
408   [(set (match_operand 0 "register_operand" "")
409         (match_operator 2 "nshift_operator"
410          [(match_dup 0)
411           (match_operand:QI 1 "register_operand" "")]))
412    (clobber (match_operand:QI 3 "register_operand" ""))
413    (clobber (reg:CC CC_REG))]
414   "epilogue_completed
415    && !find_regno_note (insn, REG_DEAD, REGNO (operands[1]))"
416   [(parallel
417      [(set (reg:CCZN CC_REG)
418            (compare:CCZN (match_dup 1) (const_int 0)))
419       (set (match_dup 3) (match_dup 1))])
420    (set (pc)
421         (if_then_else (le (reg:CCZN CC_REG) (const_int 0))
422                       (label_ref (match_dup 5))
423                       (pc)))
424    (match_dup 4)
425    (parallel
426      [(set (match_dup 0)
427            (match_op_dup 2 [(match_dup 0) (const_int 1)]))
428       (clobber (reg:CC CC_REG))])
429    (parallel
430      [(set (reg:CCZN CC_REG)
431            (compare:CCZN
432              (plus:QI (match_dup 3) (const_int -1))
433              (const_int 0)))
434       (set (match_dup 3) (plus:QI (match_dup 3) (const_int -1)))])
435    (set (pc)
436         (if_then_else (ne (reg:CCZN CC_REG) (const_int 0))
437                       (label_ref (match_dup 4))
438                       (pc)))
439    (match_dup 5)]
440   {
441     operands[4] = gen_label_rtx ();
442     operands[5] = gen_label_rtx ();
443   })
445 (define_split
446   [(set (match_operand:SI 0 "register_operand")
447         (match_operator:SI 3 "nshift_operator"
448          [(match_operand:SI 1 "register_operand")
449           (match_operand:QI 2 "nonmemory_operand")]))
450    (clobber (match_scratch:QI 4))]
451   "reload_completed"
452   [(parallel [(set (match_dup 0) (match_op_dup 3 [(match_dup 1) (match_dup 2)]))
453               (clobber (match_dup 4))
454               (clobber (reg:CC CC_REG))])])
457 ;; ----------------------------------------------------------------------
458 ;; ROTATIONS
459 ;; ----------------------------------------------------------------------
461 (define_expand "rotl<mode>3"
462   [(set (match_operand:QHSI 0 "register_operand" "")
463         (rotate:QHSI (match_operand:QHSI 1 "register_operand" "")
464                      (match_operand:QI 2 "nonmemory_operand" "")))]
465   ""
466   {
467     if (expand_a_rotate (operands))
468     DONE;
469   })
471 (define_insn_and_split "rotl<mode>3_1"
472   [(set (match_operand:QHSI 0 "register_operand" "=r")
473         (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0")
474                      (match_operand:QI 2 "immediate_operand" "")))]
475   ""
476   "#"
477   "&& reload_completed"
478   [(parallel [(set (match_dup 0) (rotate:QHSI (match_dup 1) (match_dup 2)))
479               (clobber (reg:CC CC_REG))])])
481 (define_insn "rotl<mode>3_1_clobber_flags"
482   [(set (match_operand:QHSI 0 "register_operand" "=r")
483         (rotate:QHSI (match_operand:QHSI 1 "register_operand" "0")
484                      (match_operand:QI 2 "immediate_operand" "")))
485    (clobber (reg:CC CC_REG))]
486   ""
488   return output_a_rotate (ROTATE, operands);
490   [(set (attr "length")
491         (symbol_ref "compute_a_rotate_length (operands)"))])