/* Functions and structures shared between arm and aarch64. Copyright (C) 1991-2022 Free Software Foundation, Inc. Contributed by ARM Ltd. This file is part of GCC. GCC is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. GCC is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GCC; see the file COPYING3. If not see . */ #ifndef GCC_AARCH_COMMON_PROTOS_H #define GCC_AARCH_COMMON_PROTOS_H #include "hard-reg-set.h" extern int aarch_accumulator_forwarding (rtx_insn *, rtx_insn *); extern bool aarch_rev16_p (rtx); extern bool aarch_rev16_shleft_mask_imm_p (rtx, machine_mode); extern bool aarch_rev16_shright_mask_imm_p (rtx, machine_mode); extern bool aarch_mm_needs_acquire (rtx); extern bool aarch_mm_needs_release (rtx); extern int arm_early_load_addr_dep (rtx, rtx); extern int arm_early_load_addr_dep_ptr (rtx, rtx); extern int arm_early_store_addr_dep (rtx, rtx); extern int arm_early_store_addr_dep_ptr (rtx, rtx); extern int arm_mac_accumulator_is_mul_result (rtx, rtx); extern int arm_mac_accumulator_is_result (rtx, rtx); extern int arm_no_early_alu_shift_dep (rtx, rtx); extern int arm_no_early_alu_shift_value_dep (rtx, rtx); extern int arm_no_early_mul_dep (rtx, rtx); extern int arm_no_early_store_addr_dep (rtx, rtx); extern bool arm_rtx_shift_left_p (rtx); /* RTX cost table definitions. These are used when tuning for speed rather than for size and should reflect the _additional_ cost over the cost of the fastest instruction in the machine, which is COSTS_N_INSNS (1). Therefore it's okay for some costs to be 0. Costs may not have a negative value. */ struct alu_cost_table { const int arith; /* ADD/SUB. */ const int logical; /* AND/ORR/EOR/BIC, etc. */ const int shift; /* Simple shift. */ const int shift_reg; /* Simple shift by reg. */ const int arith_shift; /* Additional when arith also shifts... */ const int arith_shift_reg; /* ... and when the shift is by a reg. */ const int log_shift; /* Additional when logic also shifts... */ const int log_shift_reg; /* ... and when the shift is by a reg. */ const int extend; /* Zero/sign extension. */ const int extend_arith; /* Extend and arith. */ const int bfi; /* Bit-field insert. */ const int bfx; /* Bit-field extraction. */ const int clz; /* Count Leading Zeros. */ const int rev; /* Reverse bits/bytes. */ const int non_exec; /* Extra cost when not executing insn. */ const bool non_exec_costs_exec; /* True if non-execution must add the exec cost. */ }; struct mult_cost_table { const int simple; const int flag_setting; /* Additional cost if multiply sets flags. */ const int extend; const int add; const int extend_add; const int idiv; }; /* Calculations of LDM costs are complex. We assume an initial cost (ldm_1st) which will load the number of registers mentioned in ldm_regs_per_insn_1st registers; then each additional ldm_regs_per_insn_subsequent registers cost one more insn. Similarly for STM operations. Therefore the ldm_regs_per_insn_1st/stm_regs_per_insn_1st and ldm_regs_per_insn_subsequent/stm_regs_per_insn_subsequent fields indicate the number of registers loaded/stored and are expressed by a simple integer and not by a COSTS_N_INSNS (N) expression. */ struct mem_cost_table { const int load; const int load_sign_extend; /* Additional to load cost. */ const int ldrd; /* Cost of LDRD. */ const int ldm_1st; const int ldm_regs_per_insn_1st; const int ldm_regs_per_insn_subsequent; const int loadf; /* SFmode. */ const int loadd; /* DFmode. */ const int load_unaligned; /* Extra for unaligned loads. */ const int store; const int strd; const int stm_1st; const int stm_regs_per_insn_1st; const int stm_regs_per_insn_subsequent; const int storef; /* SFmode. */ const int stored; /* DFmode. */ const int store_unaligned; /* Extra for unaligned stores. */ const int loadv; /* Vector load. */ const int storev; /* Vector store. */ }; struct fp_cost_table { const int div; const int mult; const int mult_addsub; /* Non-fused. */ const int fma; /* Fused. */ const int addsub; const int fpconst; /* Immediate. */ const int neg; /* NEG and ABS. */ const int compare; const int widen; /* Widen to this size. */ const int narrow; /* Narrow from this size. */ const int toint; const int fromint; const int roundint; /* V8 round to integral, remains FP format. */ }; struct vector_cost_table { const int alu; const int mult; const int movi; const int dup; const int extract; }; struct cpu_cost_table { const struct alu_cost_table alu; const struct mult_cost_table mult[2]; /* SImode and DImode. */ const struct mem_cost_table ldst; const struct fp_cost_table fp[2]; /* SFmode and DFmode. */ const struct vector_cost_table vect; }; rtx_insn *arm_md_asm_adjust (vec &outputs, vec & /*inputs*/, vec & /*input_modes*/, vec &constraints, vec &clobbers, HARD_REG_SET &clobbered_regs, location_t loc); #endif /* GCC_AARCH_COMMON_PROTOS_H */