1;; define_peephole2 optimization patterns of Andes NDS32 cpu for GNU compiler 2;; Copyright (C) 2012-2020 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. 11;; 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. 16;; 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/>. 20 21 22;; Use define_peephole2 to handle possible target-specific optimization. 23 24;; ------------------------------------------------------------------------ 25;; Try to utilize 16-bit instruction by swap operand if possible. 26;; ------------------------------------------------------------------------ 27 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)))]) 39 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)]))]) 53 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")]) 70 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 }) 85 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 }) 99 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. 103 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)))]) 115 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)))]) 127 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)] 135{ 136 rtx highpart = nds32_di_high_part_subreg (operands[0]); 137 emit_insn (gen_smulsi3_highpart (highpart, operands[1], operands[2])); 138 DONE; 139}) 140 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))] 147{ 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); 160}) 161