summaryrefslogtreecommitdiff
path: root/gcc/config/arm/aarch-common-protos.h
blob: f15cf336e9dfbd2fdd742a32e83dfa9c8751f2a0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
/* Functions and structures shared between arm and aarch64.

   Copyright (C) 1991-2019 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
   <http://www.gnu.org/licenses/>.  */


#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;
};

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<rtx> &outputs, vec<rtx> &/*inputs*/,
		    vec<const char *> &constraints,
		    vec<rtx> &clobbers, HARD_REG_SET &clobbered_regs);

#endif /* GCC_AARCH_COMMON_PROTOS_H */