[NDS32] Implement peephole2 patterns for tuning code size.
[official-gcc.git] / gcc / config / nds32 / nds32-peephole2.md
blob033f62bae5ad85461deb74a2887182b00d0f828c
1 ;; define_peephole2 optimization patterns of Andes NDS32 cpu for GNU compiler
2 ;; Copyright (C) 2012-2018 Free Software Foundation, Inc.
3 ;; Contributed by Andes Technology Corporation.
4 ;;
5 ;; This file is part of GCC.
6 ;;
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; License 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/>.
22 ;; Use define_peephole2 to handle possible target-specific optimization.
24 ;; ------------------------------------------------------------------------
25 ;; Try to utilize 16-bit instruction by swap operand if possible.
26 ;; ------------------------------------------------------------------------
28 ;; Try to make add as add45.
29 (define_peephole2
30   [(set (match_operand:QIHISI 0 "register_operand"              "")
31         (plus:QIHISI (match_operand:QIHISI 1 "register_operand" "")
32                      (match_operand:QIHISI 2 "register_operand" "")))]
33   "reload_completed
34    && TARGET_16_BIT
35    && REGNO (operands[0]) == REGNO (operands[2])
36    && REGNO (operands[0]) != REGNO (operands[1])
37    && TEST_HARD_REG_BIT (reg_class_contents[MIDDLE_REGS], REGNO (operands[0]))"
38   [(set (match_dup 0) (plus:QIHISI (match_dup 2) (match_dup 1)))])
40 ;; Try to make xor/ior/and/mult as xor33/ior33/and33/mult33.
41 (define_peephole2
42   [(set (match_operand:SI 0 "register_operand"    "")
43         (match_operator:SI 1 "nds32_have_33_inst_operator"
44           [(match_operand:SI 2 "register_operand" "")
45            (match_operand:SI 3 "register_operand" "")]))]
46   "reload_completed
47    && TARGET_16_BIT
48    && REGNO (operands[0]) == REGNO (operands[3])
49    && REGNO (operands[0]) != REGNO (operands[2])
50    && TEST_HARD_REG_BIT (reg_class_contents[LOW_REGS], REGNO (operands[0]))
51    && TEST_HARD_REG_BIT (reg_class_contents[LOW_REGS], REGNO (operands[2]))"
52   [(set (match_dup 0) (match_op_dup 1 [(match_dup 3) (match_dup 2)]))])
54 (define_peephole
55   [(set (match_operand:SI 0 "register_operand" "")
56         (match_operand:SI 1 "register_operand" ""))
57    (set (match_operand:SI 2 "register_operand" "")
58         (match_operand:SI 3 "register_operand" ""))]
59   "TARGET_16_BIT
60    && !TARGET_ISA_V2
61    && NDS32_IS_GPR_REGNUM (REGNO (operands[0]))
62    && NDS32_IS_GPR_REGNUM (REGNO (operands[1]))
63    && ((REGNO (operands[0]) & 0x1) == 0)
64    && ((REGNO (operands[1]) & 0x1) == 0)
65    && (REGNO (operands[0]) + 1) == REGNO (operands[2])
66    && (REGNO (operands[1]) + 1) == REGNO (operands[3])"
67   "movd44\t%0, %1"
68   [(set_attr "type"   "alu")
69    (set_attr "length" "2")])
71 ;; Merge two fcpyss to fcpysd.
72 (define_peephole2
73   [(set (match_operand:SF 0 "float_even_register_operand" "")
74         (match_operand:SF 1 "float_even_register_operand" ""))
75    (set (match_operand:SF 2 "float_odd_register_operand"  "")
76         (match_operand:SF 3 "float_odd_register_operand"  ""))]
77   "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
78    && REGNO (operands[0]) == REGNO (operands[2]) - 1
79    && REGNO (operands[1]) == REGNO (operands[3]) - 1"
80   [(set (match_dup 4) (match_dup 5))]
81   {
82     operands[4] = gen_rtx_REG (DFmode, REGNO (operands[0]));
83     operands[5] = gen_rtx_REG (DFmode, REGNO (operands[1]));
84   })
86 (define_peephole2
87   [(set (match_operand:SF 0 "float_odd_register_operand"  "")
88         (match_operand:SF 1 "float_odd_register_operand"  ""))
89    (set (match_operand:SF 2 "float_even_register_operand" "")
90         (match_operand:SF 3 "float_even_register_operand" ""))]
91   "(TARGET_FPU_SINGLE || TARGET_FPU_DOUBLE)
92    && REGNO (operands[2]) == REGNO (operands[0]) - 1
93    && REGNO (operands[3]) == REGNO (operands[1]) - 1"
94   [(set (match_dup 4) (match_dup 5))]
95   {
96     operands[4] = gen_rtx_REG (DFmode, REGNO (operands[2]));
97     operands[5] = gen_rtx_REG (DFmode, REGNO (operands[3]));
98   })
100 ;; ------------------------------------------------------------------------
101 ;; GCC will prefer [u]divmodsi3 rather than [u]divsi3 even remainder is
102 ;; unused, so we use split to drop mod operation for lower register pressure.
104 (define_split
105   [(set (match_operand:SI 0 "register_operand")
106         (div:SI (match_operand:SI 1 "register_operand")
107                 (match_operand:SI 2 "register_operand")))
108    (set (match_operand:SI 3 "register_operand")
109         (mod:SI (match_dup 1) (match_dup 2)))]
110   "find_regno_note (insn, REG_UNUSED, REGNO (operands[3])) != NULL
111    && can_create_pseudo_p ()"
112   [(set (match_dup 0)
113         (div:SI (match_dup 1)
114                 (match_dup 2)))])
116 (define_split
117   [(set (match_operand:SI 0 "register_operand")
118         (udiv:SI (match_operand:SI 1 "register_operand")
119                  (match_operand:SI 2 "register_operand")))
120    (set (match_operand:SI 3 "register_operand")
121         (umod:SI (match_dup 1) (match_dup 2)))]
122   "find_regno_note (insn, REG_UNUSED, REGNO (operands[3])) != NULL
123    && can_create_pseudo_p ()"
124   [(set (match_dup 0)
125         (udiv:SI (match_dup 1)
126                  (match_dup 2)))])
128 (define_peephole2
129   [(set (match_operand:DI 0 "register_operand")
130         (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand"))
131                  (sign_extend:DI (match_operand:SI 2 "register_operand"))))]
132   "NDS32_EXT_DSP_P ()
133    && peep2_regno_dead_p (1, WORDS_BIG_ENDIAN ? REGNO (operands[0]) + 1 : REGNO (operands[0]))"
134   [(const_int 1)]
136   rtx highpart = nds32_di_high_part_subreg (operands[0]);
137   emit_insn (gen_smulsi3_highpart (highpart, operands[1], operands[2]));
138   DONE;
141 (define_split
142   [(set (match_operand:DI 0 "nds32_general_register_operand" "")
143         (match_operand:DI 1 "nds32_general_register_operand" ""))]
144   "find_regno_note (insn, REG_UNUSED, REGNO (operands[0])) != NULL
145    || find_regno_note (insn, REG_UNUSED, REGNO (operands[0]) + 1) != NULL"
146   [(set (match_dup 0) (match_dup 1))]
148   rtx dead_note = find_regno_note (curr_insn, REG_UNUSED, REGNO (operands[0]));
149   HOST_WIDE_INT offset;
150   if (dead_note == NULL_RTX)
151     offset = 0;
152   else
153     offset = 4;
154   operands[0] = simplify_gen_subreg (
155                   SImode, operands[0],
156                   DImode, offset);
157   operands[1] = simplify_gen_subreg (
158                   SImode, operands[1],
159                   DImode, offset);