aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorcollison <collison@138bc75d-0d04-0410-961f-82ee72b054a4>2015-03-19 04:56:56 +0000
committercollison <collison@138bc75d-0d04-0410-961f-82ee72b054a4>2015-03-19 04:56:56 +0000
commit62fd83c70da56dd9a270cb4f026c24281b8c7ef5 (patch)
tree798987e0c87e407463548162c425853b810aab8a
parent799dffcefea1e90ed5d4d97db1212ce490f93e62 (diff)
2015-03-18 Michael Collison <michael.collison@linaro.org>
Backport from trunk r218525. 2014-12-09 Andrew Pinski apinski@cavium.com Kyrylo Tkachov kyrylo.tkachov@arm.com * config/aarch64/aarch64.c (AARCH64_FUSE_CMP_BRANCH): New define. (thunderx_tunings): Add AARCH64_FUSE_CMP_BRANCH to fuseable_ops. (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_CMP_BRANCH. 2015-03-18 Michael Collison <michael.collison@linaro.org> Backport from trunk r218014. 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/aarch64/aarch64.c (AARCH64_FUSE_ADRP_LDR): Define. (cortexa53_tunings): Specify AARCH64_FUSE_ADRP_LDR in fuseable_ops. (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_ADRP_LDR. 2015-03-18 Michael Collison <michael.collison@linaro.org> Backport from trunk r218013. 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/aarch64/aarch64.c (AARCH64_FUSE_MOVK_MOVK): Define. (cortexa53_tunings): Specify AARCH64_FUSE_MOVK_MOVK in fuseable_ops. (cortexa57_tunings): Likewise. (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_MOVK_MOVK. 2015-03-18 Michael Collison <michael.collison@linaro.org> Backport from trunk r218012. 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * sched-deps.c (sched_macro_fuse_insns): Do not check modified_in_p in the not conditional jump case. * doc/tm.texi (TARGET_SCHED_MACRO_FUSION_PAIR_P): Update description. * target.def (TARGET_SCHED_MACRO_FUSION_PAIR_P): Update description. 2015-03-18 Michael Collison <michael.collison@linaro.org> Backport from trunk r218010. 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/aarch64/aarch64.c: Include tm-constrs.h (AARCH64_FUSE_ADRP_ADD): Define. (cortexa57_tunings): Add AARCH64_FUSE_ADRP_ADD to fuseable_ops. (cortexa53_tunings): Likewise. (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_ADRP_ADD. 2015-03-18 Michael Collison <michael.collison@linaro.org> Backport from trunk r218007. 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * config/aarch64/aarch64-protos.h (struct tune_params): Add fuseable_ops field. * config/aarch64/aarch64.c (generic_tunings): Specify fuseable_ops. (cortexa53_tunings): Likewise. (cortexa57_tunings): Likewise. (thunderx_tunings): Likewise. (aarch64_macro_fusion_p): New function. (aarch_macro_fusion_pair_p): Likewise. (TARGET_SCHED_MACRO_FUSION_P): Define. (TARGET_SCHED_MACRO_FUSION_PAIR_P): Likewise. (AARCH64_FUSE_MOV_MOVK): Likewise. (AARCH64_FUSE_NOTHING): Likewise. 2015-03-18 Michael Collison <michael.collison@linaro.org> Backport from trunk r218012. 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com> * gcc.target/aarch64/fuse_adrp_add_1.c: New test. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/branches/linaro/gcc-4_9-branch@221507 138bc75d-0d04-0410-961f-82ee72b054a4
-rw-r--r--gcc/ChangeLog.linaro68
-rw-r--r--gcc/config/aarch64/aarch64-protos.h1
-rw-r--r--gcc/config/aarch64/aarch64.c181
-rw-r--r--gcc/doc/tm.texi12
-rw-r--r--gcc/sched-deps.c3
-rw-r--r--gcc/target.def12
-rw-r--r--gcc/testsuite/ChangeLog.linaro7
-rw-r--r--gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c45
8 files changed, 313 insertions, 16 deletions
diff --git a/gcc/ChangeLog.linaro b/gcc/ChangeLog.linaro
index 5a739a14290..c41618dba05 100644
--- a/gcc/ChangeLog.linaro
+++ b/gcc/ChangeLog.linaro
@@ -1,3 +1,71 @@
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218525.
+ 2014-12-09 Andrew Pinski apinski@cavium.com
+ Kyrylo Tkachov kyrylo.tkachov@arm.com
+
+ * config/aarch64/aarch64.c (AARCH64_FUSE_CMP_BRANCH): New define.
+ (thunderx_tunings): Add AARCH64_FUSE_CMP_BRANCH to fuseable_ops.
+ (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_CMP_BRANCH.
+
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218014.
+ 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (AARCH64_FUSE_ADRP_LDR): Define.
+ (cortexa53_tunings): Specify AARCH64_FUSE_ADRP_LDR in fuseable_ops.
+ (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_ADRP_LDR.
+
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218013.
+ 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c (AARCH64_FUSE_MOVK_MOVK): Define.
+ (cortexa53_tunings): Specify AARCH64_FUSE_MOVK_MOVK in fuseable_ops.
+ (cortexa57_tunings): Likewise.
+ (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_MOVK_MOVK.
+
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218012.
+ 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * sched-deps.c (sched_macro_fuse_insns): Do not check modified_in_p
+ in the not conditional jump case.
+ * doc/tm.texi (TARGET_SCHED_MACRO_FUSION_PAIR_P): Update description.
+ * target.def (TARGET_SCHED_MACRO_FUSION_PAIR_P): Update description.
+
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218010.
+ 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64.c: Include tm-constrs.h
+ (AARCH64_FUSE_ADRP_ADD): Define.
+ (cortexa57_tunings): Add AARCH64_FUSE_ADRP_ADD to fuseable_ops.
+ (cortexa53_tunings): Likewise.
+ (aarch_macro_fusion_pair_p): Handle AARCH64_FUSE_ADRP_ADD.
+
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218007.
+ 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * config/aarch64/aarch64-protos.h (struct tune_params): Add
+ fuseable_ops field.
+ * config/aarch64/aarch64.c (generic_tunings): Specify fuseable_ops.
+ (cortexa53_tunings): Likewise.
+ (cortexa57_tunings): Likewise.
+ (thunderx_tunings): Likewise.
+ (aarch64_macro_fusion_p): New function.
+ (aarch_macro_fusion_pair_p): Likewise.
+ (TARGET_SCHED_MACRO_FUSION_P): Define.
+ (TARGET_SCHED_MACRO_FUSION_PAIR_P): Likewise.
+ (AARCH64_FUSE_MOV_MOVK): Likewise.
+ (AARCH64_FUSE_NOTHING): Likewise.
+
2015-03-12 Yvan Roux <yvan.roux@linaro.org>
* LINARO-VERSION: Bump version.
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index b0e5a31e3e7..d5c89d62119 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -170,6 +170,7 @@ struct tune_params
const struct cpu_vector_cost *const vec_costs;
const int memmov_cost;
const int issue_rate;
+ const unsigned int fuseable_ops;
};
HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 768c1154163..8e9d2d4274a 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -64,6 +64,7 @@
#include "tree-vectorizer.h"
#include "aarch64-cost-tables.h"
#include "dumpfile.h"
+#include "tm-constrs.h"
/* Defined for convenience. */
#define POINTER_BYTES (POINTER_SIZE / BITS_PER_UNIT)
@@ -291,6 +292,13 @@ static const struct cpu_vector_cost cortexa57_vector_cost =
NAMED_PARAM (cond_not_taken_branch_cost, 1)
};
+#define AARCH64_FUSE_NOTHING (0)
+#define AARCH64_FUSE_MOV_MOVK (1 << 0)
+#define AARCH64_FUSE_ADRP_ADD (1 << 1)
+#define AARCH64_FUSE_MOVK_MOVK (1 << 2)
+#define AARCH64_FUSE_ADRP_LDR (1 << 3)
+#define AARCH64_FUSE_CMP_BRANCH (1 << 4)
+
#if HAVE_DESIGNATED_INITIALIZERS && GCC_VERSION >= 2007
__extension__
#endif
@@ -301,7 +309,8 @@ static const struct tune_params generic_tunings =
&generic_regmove_cost,
&generic_vector_cost,
NAMED_PARAM (memmov_cost, 4),
- NAMED_PARAM (issue_rate, 2)
+ NAMED_PARAM (issue_rate, 2),
+ NAMED_PARAM (fuseable_ops, AARCH64_FUSE_NOTHING)
};
static const struct tune_params cortexa53_tunings =
@@ -311,7 +320,9 @@ static const struct tune_params cortexa53_tunings =
&cortexa53_regmove_cost,
&generic_vector_cost,
NAMED_PARAM (memmov_cost, 4),
- NAMED_PARAM (issue_rate, 2)
+ NAMED_PARAM (issue_rate, 2),
+ NAMED_PARAM (fuseable_ops, (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD
+ | AARCH64_FUSE_MOVK_MOVK | AARCH64_FUSE_ADRP_LDR))
};
static const struct tune_params cortexa57_tunings =
@@ -321,7 +332,8 @@ static const struct tune_params cortexa57_tunings =
&cortexa57_regmove_cost,
&cortexa57_vector_cost,
NAMED_PARAM (memmov_cost, 4),
- NAMED_PARAM (issue_rate, 3)
+ NAMED_PARAM (issue_rate, 3),
+ NAMED_PARAM (fuseable_ops, (AARCH64_FUSE_MOV_MOVK | AARCH64_FUSE_ADRP_ADD | AARCH64_FUSE_MOVK_MOVK))
};
static const struct tune_params thunderx_tunings =
@@ -331,7 +343,8 @@ static const struct tune_params thunderx_tunings =
&thunderx_regmove_cost,
&generic_vector_cost,
NAMED_PARAM (memmov_cost, 6),
- NAMED_PARAM (issue_rate, 2)
+ NAMED_PARAM (issue_rate, 2),
+ NAMED_PARAM (fuseable_ops, AARCH64_FUSE_CMP_BRANCH)
};
/* A processor implementing AArch64. */
@@ -10053,6 +10066,160 @@ aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
return default_use_by_pieces_infrastructure_p (size, align, op, speed_p);
}
+/* Implement TARGET_SCHED_MACRO_FUSION_P. Return true if target supports
+ instruction fusion of some sort. */
+
+static bool
+aarch64_macro_fusion_p (void)
+{
+ return aarch64_tune_params->fuseable_ops != AARCH64_FUSE_NOTHING;
+}
+
+
+/* Implement TARGET_SCHED_MACRO_FUSION_PAIR_P. Return true if PREV and CURR
+ should be kept together during scheduling. */
+
+static bool
+aarch_macro_fusion_pair_p (rtx prev, rtx curr)
+{
+ rtx set_dest;
+ rtx prev_set = single_set (prev);
+ rtx curr_set = single_set (curr);
+ /* prev and curr are simple SET insns i.e. no flag setting or branching. */
+ bool simple_sets_p = prev_set && curr_set && !any_condjump_p (curr);
+
+ if (!aarch64_macro_fusion_p ())
+ return false;
+
+ if (simple_sets_p
+ && (aarch64_tune_params->fuseable_ops & AARCH64_FUSE_MOV_MOVK))
+ {
+ /* We are trying to match:
+ prev (mov) == (set (reg r0) (const_int imm16))
+ curr (movk) == (set (zero_extract (reg r0)
+ (const_int 16)
+ (const_int 16))
+ (const_int imm16_1)) */
+
+ set_dest = SET_DEST (curr_set);
+
+ if (GET_CODE (set_dest) == ZERO_EXTRACT
+ && CONST_INT_P (SET_SRC (curr_set))
+ && CONST_INT_P (SET_SRC (prev_set))
+ && CONST_INT_P (XEXP (set_dest, 2))
+ && INTVAL (XEXP (set_dest, 2)) == 16
+ && REG_P (XEXP (set_dest, 0))
+ && REG_P (SET_DEST (prev_set))
+ && REGNO (XEXP (set_dest, 0)) == REGNO (SET_DEST (prev_set)))
+ {
+ return true;
+ }
+ }
+
+ if (simple_sets_p
+ && (aarch64_tune_params->fuseable_ops & AARCH64_FUSE_ADRP_ADD))
+ {
+
+ /* We're trying to match:
+ prev (adrp) == (set (reg r1)
+ (high (symbol_ref ("SYM"))))
+ curr (add) == (set (reg r0)
+ (lo_sum (reg r1)
+ (symbol_ref ("SYM"))))
+ Note that r0 need not necessarily be the same as r1, especially
+ during pre-regalloc scheduling. */
+
+ if (satisfies_constraint_Ush (SET_SRC (prev_set))
+ && REG_P (SET_DEST (prev_set)) && REG_P (SET_DEST (curr_set)))
+ {
+ if (GET_CODE (SET_SRC (curr_set)) == LO_SUM
+ && REG_P (XEXP (SET_SRC (curr_set), 0))
+ && REGNO (XEXP (SET_SRC (curr_set), 0))
+ == REGNO (SET_DEST (prev_set))
+ && rtx_equal_p (XEXP (SET_SRC (prev_set), 0),
+ XEXP (SET_SRC (curr_set), 1)))
+ return true;
+ }
+ }
+
+ if (simple_sets_p
+ && (aarch64_tune_params->fuseable_ops & AARCH64_FUSE_MOVK_MOVK))
+ {
+
+ /* We're trying to match:
+ prev (movk) == (set (zero_extract (reg r0)
+ (const_int 16)
+ (const_int 32))
+ (const_int imm16_1))
+ curr (movk) == (set (zero_extract (reg r0)
+ (const_int 16)
+ (const_int 48))
+ (const_int imm16_2)) */
+
+ if (GET_CODE (SET_DEST (prev_set)) == ZERO_EXTRACT
+ && GET_CODE (SET_DEST (curr_set)) == ZERO_EXTRACT
+ && REG_P (XEXP (SET_DEST (prev_set), 0))
+ && REG_P (XEXP (SET_DEST (curr_set), 0))
+ && REGNO (XEXP (SET_DEST (prev_set), 0))
+ == REGNO (XEXP (SET_DEST (curr_set), 0))
+ && CONST_INT_P (XEXP (SET_DEST (prev_set), 2))
+ && CONST_INT_P (XEXP (SET_DEST (curr_set), 2))
+ && INTVAL (XEXP (SET_DEST (prev_set), 2)) == 32
+ && INTVAL (XEXP (SET_DEST (curr_set), 2)) == 48
+ && CONST_INT_P (SET_SRC (prev_set))
+ && CONST_INT_P (SET_SRC (curr_set)))
+ return true;
+
+ }
+ if (simple_sets_p
+ && (aarch64_tune_params->fuseable_ops & AARCH64_FUSE_ADRP_LDR))
+ {
+ /* We're trying to match:
+ prev (adrp) == (set (reg r0)
+ (high (symbol_ref ("SYM"))))
+ curr (ldr) == (set (reg r1)
+ (mem (lo_sum (reg r0)
+ (symbol_ref ("SYM")))))
+ or
+ curr (ldr) == (set (reg r1)
+ (zero_extend (mem
+ (lo_sum (reg r0)
+ (symbol_ref ("SYM")))))) */
+ if (satisfies_constraint_Ush (SET_SRC (prev_set))
+ && REG_P (SET_DEST (prev_set)) && REG_P (SET_DEST (curr_set)))
+ {
+ rtx curr_src = SET_SRC (curr_set);
+
+ if (GET_CODE (curr_src) == ZERO_EXTEND)
+ curr_src = XEXP (curr_src, 0);
+
+ if (MEM_P (curr_src) && GET_CODE (XEXP (curr_src, 0)) == LO_SUM
+ && REG_P (XEXP (XEXP (curr_src, 0), 0))
+ && REGNO (XEXP (XEXP (curr_src, 0), 0))
+ == REGNO (SET_DEST (prev_set))
+ && rtx_equal_p (XEXP (XEXP (curr_src, 0), 1),
+ XEXP (SET_SRC (prev_set), 0)))
+ return true;
+ }
+ }
+
+ if ((aarch64_tune_params->fuseable_ops & AARCH64_FUSE_CMP_BRANCH)
+ && any_condjump_p (curr))
+ {
+ enum attr_type prev_type = get_attr_type (prev);
+
+ /* FIXME: this misses some which is considered simple arthematic
+ instructions for ThunderX. Simple shifts are missed here. */
+ if (prev_type == TYPE_ALUS_REG
+ || prev_type == TYPE_ALUS_IMM
+ || prev_type == TYPE_LOGICS_REG
+ || prev_type == TYPE_LOGICS_IMM)
+ return true;
+ }
+
+ return false;
+}
+
#undef TARGET_ADDRESS_COST
#define TARGET_ADDRESS_COST aarch64_address_cost
@@ -10306,6 +10473,12 @@ aarch64_use_by_pieces_infrastructure_p (unsigned HOST_WIDE_INT size,
#undef TARGET_CAN_USE_DOLOOP_P
#define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
+#undef TARGET_SCHED_MACRO_FUSION_P
+#define TARGET_SCHED_MACRO_FUSION_P aarch64_macro_fusion_p
+
+#undef TARGET_SCHED_MACRO_FUSION_PAIR_P
+#define TARGET_SCHED_MACRO_FUSION_PAIR_P aarch_macro_fusion_pair_p
+
struct gcc_target targetm = TARGET_INITIALIZER;
#include "gt-aarch64.h"
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index dfda07baea6..1720084c119 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -6569,11 +6569,13 @@ cycle. These other insns can then be taken into account properly.
This hook is used to check whether target platform supports macro fusion.
@end deftypefn
-@deftypefn {Target Hook} bool TARGET_SCHED_MACRO_FUSION_PAIR_P (rtx @var{condgen}, rtx @var{condjmp})
-This hook is used to check whether two insns could be macro fused for
-target microarchitecture. If this hook returns true for the given insn pair
-(@var{condgen} and @var{condjmp}), scheduler will put them into a sched
-group, and they will not be scheduled apart.
+@deftypefn {Target Hook} bool TARGET_SCHED_MACRO_FUSION_PAIR_P (rtx @var{prev}, rtx @var{curr})
+This hook is used to check whether two insns should be macro fused for
+a target microarchitecture. If this hook returns true for the given insn pair
+(@var{prev} and @var{curr}), the scheduler will put them into a sched
+group, and they will not be scheduled apart. The two insns will be either
+two SET insns or a compare and a conditional jump and this hook should
+validate any dependencies needed to fuse the two insns together.
@end deftypefn
@deftypefn {Target Hook} void TARGET_SCHED_DEPENDENCIES_EVALUATION_HOOK (rtx @var{head}, rtx @var{tail})
diff --git a/gcc/sched-deps.c b/gcc/sched-deps.c
index cd5d2ca8a02..2c501cf6968 100644
--- a/gcc/sched-deps.c
+++ b/gcc/sched-deps.c
@@ -2855,8 +2855,7 @@ sched_macro_fuse_insns (rtx insn)
prev = prev_nonnote_nondebug_insn (insn);
if (!prev
|| !insn_set
- || !single_set (prev)
- || !modified_in_p (SET_DEST (insn_set), prev))
+ || !single_set (prev))
return;
}
diff --git a/gcc/target.def b/gcc/target.def
index 01c837034fb..cf46a691138 100644
--- a/gcc/target.def
+++ b/gcc/target.def
@@ -1048,11 +1048,13 @@ DEFHOOK
DEFHOOK
(macro_fusion_pair_p,
- "This hook is used to check whether two insns could be macro fused for\n\
-target microarchitecture. If this hook returns true for the given insn pair\n\
-(@var{condgen} and @var{condjmp}), scheduler will put them into a sched\n\
-group, and they will not be scheduled apart.",
- bool, (rtx condgen, rtx condjmp), NULL)
+ "This hook is used to check whether two insns should be macro fused for\n\
+a target microarchitecture. If this hook returns true for the given insn pair\n\
+(@var{prev} and @var{curr}), the scheduler will put them into a sched\n\
+group, and they will not be scheduled apart. The two insns will be either\n\
+two SET insns or a compare and a conditional jump and this hook should\n\
+validate any dependencies needed to fuse the two insns together.",
+ bool, (rtx prev, rtx curr), NULL)
/* The following member value is a pointer to a function called
after evaluation forward dependencies of insns in chain given
diff --git a/gcc/testsuite/ChangeLog.linaro b/gcc/testsuite/ChangeLog.linaro
index 51d4c12f660..3f3d73be739 100644
--- a/gcc/testsuite/ChangeLog.linaro
+++ b/gcc/testsuite/ChangeLog.linaro
@@ -1,3 +1,10 @@
+2015-03-18 Michael Collison <michael.collison@linaro.org>
+
+ Backport from trunk r218012.
+ 2014-11-24 Kyrylo Tkachov <kyrylo.tkachov@arm.com>
+
+ * gcc.target/aarch64/fuse_adrp_add_1.c: New test.
+
2015-03-12 Yvan Roux <yvan.roux@linaro.org>
GCC Linaro 4.9-2015.03 released.
diff --git a/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c b/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c
new file mode 100644
index 00000000000..074c629469b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/fuse_adrp_add_1.c
@@ -0,0 +1,45 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -mcpu=cortex-a57" } */
+
+enum reg_class { NO_REGS, AP_REG, XRF_REGS, GENERAL_REGS, AGRF_REGS,
+ XGRF_REGS, ALL_REGS, LIM_REG_CLASSES };
+
+enum rtx_code { REG, LAST_AND_UNUSED_RTX_CODE };
+
+typedef union rtunion_def
+{
+ int rtint;
+} rtunion;
+
+typedef struct rtx_def
+{
+ unsigned int volatil : 1;
+ rtunion fld[1];
+} *rtx;
+
+extern char fixed_regs[64];
+extern char global_regs[64];
+
+int
+rtx_cost (rtx x, int outer_code)
+{
+ register enum rtx_code code;
+ switch (code)
+ {
+ case REG:
+ return ! ((((x)->volatil) && ((x)->fld[0].rtint) < 64)
+ || ((((x)->fld[0].rtint)) == 30 || (((x)->fld[0].rtint)) == 30
+ || (((x)->fld[0].rtint)) == 31 || (((x)->fld[0].rtint)) == 0
+ || ((((x)->fld[0].rtint)) >= (64)
+ && (((x)->fld[0].rtint)) <= (((64)) + 3))
+ || ((((x)->fld[0].rtint)) < 64 && ((((x)->fld[0].rtint)) == 30
+ || (((x)->fld[0].rtint)) == 30 || fixed_regs[((x)->fld[0].rtint)]
+ || global_regs[((x)->fld[0].rtint)])
+ && ((((x)->fld[0].rtint))
+ ? ((((x)->fld[0].rtint) < 32)
+ ? GENERAL_REGS : XRF_REGS)
+ : AP_REG) != NO_REGS)));
+ }
+}
+
+/* { dg-final { scan-assembler "adrp\tx.*, fixed_regs\n\tadd\tx.*, x.*fixed_regs" } } */