Merge branch 'master' into devel/modula-2.
This commit is contained in:
commit
eae2c45ec9
20
ChangeLog
20
ChangeLog
|
@ -1,3 +1,23 @@
|
|||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
|
||||
* MAINTAINERS: (CPU Port Maintainers): Add myself and
|
||||
Lulu as LoongArch port maintainer.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* configure.ac: Add LoongArch tuples.
|
||||
* configure: Regenerate.
|
||||
|
||||
2022-03-28 Tom Tromey <tromey@adacore.com>
|
||||
|
||||
* configure.ac: Remove --with-mpfr-dir and --with-gmp-dir.
|
||||
* configure: Rebuild.
|
||||
|
||||
2022-03-24 Bill Schmidt <bill.schmidt@gmail.com>
|
||||
|
||||
* MAINTAINERS: Change my information.
|
||||
|
||||
2022-03-16 Chung-Ju Wu <jasonwucj@gmail.com>
|
||||
|
||||
* MAINTAINERS: Add myself to DCO section.
|
||||
|
|
|
@ -83,6 +83,8 @@ i386 vector ISA extns Kirill Yukhin <kirill.yukhin@gmail.com>
|
|||
i386 vector ISA extns Hongtao Liu <hongtao.liu@intel.com>
|
||||
iq2000 port Nick Clifton <nickc@redhat.com>
|
||||
lm32 port Sebastien Bourdeauducq <sebastien@milkymist.org>
|
||||
LoongArch port Chenghua Xu <xuchenghua@loongson.cn>
|
||||
LoongArch port Lulu Cheng <chenglulu@loongson.cn>
|
||||
m32r port Nick Clifton <nickc@redhat.com>
|
||||
m68k port (?) Jeff Law <jeffreyalaw@gmail.com>
|
||||
m68k port Andreas Schwab <schwab@linux-m68k.org>
|
||||
|
@ -252,7 +254,6 @@ testsuite Rainer Orth <ro@CeBiTec.Uni-Bielefeld.DE>
|
|||
testsuite Mike Stump <mikestump@comcast.net>
|
||||
register allocation Vladimir Makarov <vmakarov@redhat.com>
|
||||
gdbhooks.py David Malcolm <dmalcolm@redhat.com>
|
||||
SLSR Bill Schmidt <wschmidt@linux.ibm.com>
|
||||
jit David Malcolm <dmalcolm@redhat.com>
|
||||
gen* on machine desc Richard Sandiford <rdsandiford@googlemail.com>
|
||||
static analyzer David Malcolm <dmalcolm@redhat.com>
|
||||
|
@ -462,7 +463,7 @@ Daniel Jacobowitz <drow@false.org>
|
|||
Andreas Jaeger <aj@suse.de>
|
||||
Harsha Jagasia <harsha.jagasia@amd.com>
|
||||
Fariborz Jahanian <fjahanian@apple.com>
|
||||
Qian Jianhua <qianjh@cn.fujitsu.com>
|
||||
Qian Jianhua <qianjh@fujitsu.com>
|
||||
Janis Johnson <janis.marie.johnson@gmail.com>
|
||||
Teresa Johnson <tejohnson@google.com>
|
||||
Kean Johnston <jkj@sco.com>
|
||||
|
@ -720,6 +721,7 @@ Gaius Mulley <gaiusmod2@gmail.com>
|
|||
Siddhesh Poyarekar <siddhesh@gotplt.org>
|
||||
Navid Rahimi <navidrahimi@microsoft.com>
|
||||
Trevor Saunders <tbsaunde+gcc@tbsaunde.org>
|
||||
Bill Schmidt <bill.schmidt@fastmail.com>
|
||||
Nathan Sidwell <nathan@acm.org>
|
||||
Edward Smith-Rowland <esmithrowland@gmail.com>
|
||||
Petter Tomner <tomner@kth.se>
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* picflag.m4: Default add build option '-fpic' for LoongArch.
|
||||
|
||||
2021-12-21 Iain Buclaw <ibuclaw@gdcproject.org>
|
||||
|
||||
PR d/103528
|
||||
|
|
|
@ -44,6 +44,9 @@ case "${$2}" in
|
|||
# sets the default TLS model and affects inlining.
|
||||
$1=-fPIC
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
$1=-fpic
|
||||
;;
|
||||
mips-sgi-irix6*)
|
||||
# PIC is the default.
|
||||
;;
|
||||
|
|
|
@ -814,11 +814,9 @@ enable_pgo_build
|
|||
with_mpc
|
||||
with_mpc_include
|
||||
with_mpc_lib
|
||||
with_mpfr_dir
|
||||
with_mpfr
|
||||
with_mpfr_include
|
||||
with_mpfr_lib
|
||||
with_gmp_dir
|
||||
with_gmp
|
||||
with_gmp_include
|
||||
with_gmp_lib
|
||||
|
@ -1604,14 +1602,12 @@ Optional Packages:
|
|||
--with-mpc-lib=PATH/lib
|
||||
--with-mpc-include=PATH specify directory for installed MPC include files
|
||||
--with-mpc-lib=PATH specify directory for the installed MPC library
|
||||
--with-mpfr-dir=PATH this option has been REMOVED
|
||||
--with-mpfr=PATH specify prefix directory for installed MPFR package.
|
||||
Equivalent to --with-mpfr-include=PATH/include plus
|
||||
--with-mpfr-lib=PATH/lib
|
||||
--with-mpfr-include=PATH
|
||||
specify directory for installed MPFR include files
|
||||
--with-mpfr-lib=PATH specify directory for the installed MPFR library
|
||||
--with-gmp-dir=PATH this option has been REMOVED
|
||||
--with-gmp=PATH specify prefix directory for the installed GMP
|
||||
package. Equivalent to
|
||||
--with-gmp-include=PATH/include plus
|
||||
|
@ -3079,7 +3075,7 @@ case "${ENABLE_GOLD}" in
|
|||
# Check for target supported by gold.
|
||||
case "${target}" in
|
||||
i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \
|
||||
| aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*)
|
||||
| aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | loongarch*-*-*)
|
||||
configdirs="$configdirs gold"
|
||||
if test x${ENABLE_GOLD} = xdefault; then
|
||||
default_ld=gold
|
||||
|
@ -3676,6 +3672,9 @@ case "${target}" in
|
|||
i[3456789]86-*-*)
|
||||
libgloss_dir=i386
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
libgloss_dir=loongarch
|
||||
;;
|
||||
m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*)
|
||||
libgloss_dir=m68hc11
|
||||
;;
|
||||
|
@ -3798,7 +3797,7 @@ case "${target}" in
|
|||
*-*-dragonfly*)
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
if test "x$with_gmp" = x && test "x$with_gmp_dir" = x \
|
||||
if test "x$with_gmp" = x \
|
||||
&& ! test -d ${srcdir}/gmp \
|
||||
&& test -f /usr/local/include/gmp.h; then
|
||||
with_gmp=/usr/local
|
||||
|
@ -4060,6 +4059,11 @@ case "${target}" in
|
|||
wasm32-*-*)
|
||||
noconfigdirs="$noconfigdirs ld"
|
||||
;;
|
||||
loongarch*-*-linux*)
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
noconfigdirs="$noconfigdirs gprof"
|
||||
;;
|
||||
esac
|
||||
|
||||
# If we aren't building newlib, then don't build libgloss, since libgloss
|
||||
|
@ -8029,14 +8033,6 @@ fi
|
|||
# Specify a location for mpfr
|
||||
# check for this first so it ends up on the link line before gmp.
|
||||
|
||||
# Check whether --with-mpfr-dir was given.
|
||||
if test "${with_mpfr_dir+set}" = set; then :
|
||||
withval=$with_mpfr_dir; as_fn_error $? "The --with-mpfr-dir=PATH option has been removed.
|
||||
Use --with-mpfr=PATH or --with-mpfr-include=PATH plus --with-mpfr-lib=PATH" "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-mpfr was given.
|
||||
if test "${with_mpfr+set}" = set; then :
|
||||
withval=$with_mpfr;
|
||||
|
@ -8082,14 +8078,6 @@ fi
|
|||
|
||||
# Specify a location for gmp
|
||||
|
||||
# Check whether --with-gmp-dir was given.
|
||||
if test "${with_gmp_dir+set}" = set; then :
|
||||
withval=$with_gmp_dir; as_fn_error $? "The --with-gmp-dir=PATH option has been removed.
|
||||
Use --with-gmp=PATH or --with-gmp-include=PATH plus --with-gmp-lib=PATH" "$LINENO" 5
|
||||
fi
|
||||
|
||||
|
||||
|
||||
# Check whether --with-gmp was given.
|
||||
if test "${with_gmp+set}" = set; then :
|
||||
withval=$with_gmp;
|
||||
|
|
24
configure.ac
24
configure.ac
|
@ -1,6 +1,6 @@
|
|||
# Copyright (C) 1992, 1993, 1994, 1995, 1996, 1997, 1998, 1999, 2000,
|
||||
# 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
|
||||
# 2014, 2015, 2016, 2019 Free Software Foundation, Inc.
|
||||
# 2014, 2015, 2016, 2019, 2022 Free Software Foundation, Inc.
|
||||
#
|
||||
# This file is free software; you can redistribute it and/or modify it
|
||||
# under the terms of the GNU General Public License as published by
|
||||
|
@ -354,7 +354,7 @@ case "${ENABLE_GOLD}" in
|
|||
# Check for target supported by gold.
|
||||
case "${target}" in
|
||||
i?86-*-* | x86_64-*-* | sparc*-*-* | powerpc*-*-* | arm*-*-* \
|
||||
| aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-*)
|
||||
| aarch64*-*-* | tilegx*-*-* | mips*-*-* | s390*-*-* | loongarch*-*-*)
|
||||
configdirs="$configdirs gold"
|
||||
if test x${ENABLE_GOLD} = xdefault; then
|
||||
default_ld=gold
|
||||
|
@ -908,6 +908,9 @@ case "${target}" in
|
|||
i[[3456789]]86-*-*)
|
||||
libgloss_dir=i386
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
libgloss_dir=loongarch
|
||||
;;
|
||||
m68hc11-*-*|m6811-*-*|m68hc12-*-*|m6812-*-*)
|
||||
libgloss_dir=m68hc11
|
||||
;;
|
||||
|
@ -1030,7 +1033,7 @@ case "${target}" in
|
|||
*-*-dragonfly*)
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
if test "x$with_gmp" = x && test "x$with_gmp_dir" = x \
|
||||
if test "x$with_gmp" = x \
|
||||
&& ! test -d ${srcdir}/gmp \
|
||||
&& test -f /usr/local/include/gmp.h; then
|
||||
with_gmp=/usr/local
|
||||
|
@ -1292,6 +1295,11 @@ case "${target}" in
|
|||
wasm32-*-*)
|
||||
noconfigdirs="$noconfigdirs ld"
|
||||
;;
|
||||
loongarch*-*-linux*)
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
noconfigdirs="$noconfigdirs gprof"
|
||||
;;
|
||||
esac
|
||||
|
||||
# If we aren't building newlib, then don't build libgloss, since libgloss
|
||||
|
@ -1577,11 +1585,6 @@ fi
|
|||
|
||||
# Specify a location for mpfr
|
||||
# check for this first so it ends up on the link line before gmp.
|
||||
AC_ARG_WITH(mpfr-dir,
|
||||
[AS_HELP_STRING([--with-mpfr-dir=PATH], [this option has been REMOVED])],
|
||||
[AC_MSG_ERROR([The --with-mpfr-dir=PATH option has been removed.
|
||||
Use --with-mpfr=PATH or --with-mpfr-include=PATH plus --with-mpfr-lib=PATH])])
|
||||
|
||||
AC_ARG_WITH(mpfr,
|
||||
[AS_HELP_STRING([--with-mpfr=PATH],
|
||||
[specify prefix directory for installed MPFR package.
|
||||
|
@ -1621,11 +1624,6 @@ Building GCC with MPFR in the source tree is only handled for MPFR 3.1.0+.])
|
|||
fi
|
||||
|
||||
# Specify a location for gmp
|
||||
AC_ARG_WITH(gmp-dir,
|
||||
[AS_HELP_STRING([--with-gmp-dir=PATH], [this option has been REMOVED])],
|
||||
[AC_MSG_ERROR([The --with-gmp-dir=PATH option has been removed.
|
||||
Use --with-gmp=PATH or --with-gmp-include=PATH plus --with-gmp-lib=PATH])])
|
||||
|
||||
AC_ARG_WITH(gmp,
|
||||
[AS_HELP_STRING([--with-gmp=PATH],
|
||||
[specify prefix directory for the installed GMP package.
|
||||
|
|
|
@ -1,3 +1,34 @@
|
|||
2022-03-31 Jakub Jelinek <jakub@redhat.com>
|
||||
Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
PR other/105114
|
||||
* gcc_update: Fix up spelling of
|
||||
gcc/config/loongarch/genopts/loongarch-strings dependency.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* config-list.mk: Add LoongArch triplet.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* gcc_update (files_and_dependencies): Add
|
||||
config/loongarch/loongarch.opt and config/loongarch/loongarch-str.h.
|
||||
|
||||
2022-03-28 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* gcc-changelog/git_commit.py: Match trailing dot literally.
|
||||
|
||||
2022-03-28 Martin Liska <mliska@suse.cz>
|
||||
|
||||
* gcc-changelog/git_commit.py: Make the parsing stricter.
|
||||
|
||||
2022-03-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc-changelog/git_update_version.py: Add
|
||||
3ab5c8cd03d92bf4ec41e351820349d92fbc40c4 to ignored commits.
|
||||
|
||||
2022-03-10 Jonathan Wakely <jwakely@redhat.com>
|
||||
|
||||
PR other/102664
|
||||
|
|
|
@ -57,7 +57,9 @@ LIST = aarch64-elf aarch64-linux-gnu aarch64-rtems \
|
|||
i686-wrs-vxworksae \
|
||||
i686-cygwinOPT-enable-threads=yes i686-mingw32crt ia64-elf \
|
||||
ia64-freebsd6 ia64-linux ia64-hpux ia64-hp-vms iq2000-elf lm32-elf \
|
||||
lm32-rtems lm32-uclinux m32c-rtems m32c-elf m32r-elf m32rle-elf \
|
||||
lm32-rtems lm32-uclinux \
|
||||
loongarch64-linux-gnuf64 loongarch64-linux-gnuf32 loongarch64-linux-gnusf \
|
||||
m32c-rtems m32c-elf m32r-elf m32rle-elf \
|
||||
m68k-elf m68k-netbsdelf \
|
||||
m68k-uclinux m68k-linux m68k-rtems \
|
||||
mcore-elf microblaze-linux microblaze-elf \
|
||||
|
|
|
@ -165,7 +165,7 @@ star_prefix_regex = re.compile(r'\t\*(?P<spaces>\ *)(?P<content>.*)')
|
|||
end_of_location_regex = re.compile(r'[\[<(:]')
|
||||
item_empty_regex = re.compile(r'\t(\* \S+ )?\(\S+\):\s*$')
|
||||
item_parenthesis_regex = re.compile(r'\t(\*|\(\S+\):)')
|
||||
revert_regex = re.compile(r'This reverts commit (?P<hash>\w+).$')
|
||||
revert_regex = re.compile(r'This reverts commit (?P<hash>[0-9a-f]+)\.$')
|
||||
cherry_pick_regex = re.compile(r'cherry picked from commit (?P<hash>\w+)')
|
||||
|
||||
LINE_LIMIT = 100
|
||||
|
@ -317,7 +317,7 @@ class GitCommit:
|
|||
|
||||
# Identify first if the commit is a Revert commit
|
||||
for line in self.info.lines:
|
||||
m = revert_regex.match(line)
|
||||
m = revert_regex.fullmatch(line)
|
||||
if m:
|
||||
self.revert_commit = m.group('hash')
|
||||
break
|
||||
|
|
|
@ -30,7 +30,8 @@ current_timestamp = datetime.datetime.now().strftime('%Y%m%d\n')
|
|||
IGNORED_COMMITS = (
|
||||
'c2be82058fb40f3ae891c68d185ff53e07f14f45',
|
||||
'04a040d907a83af54e0a98bdba5bfabc0ef4f700',
|
||||
'2e96b5f14e4025691b57d2301d71aa6092ed44bc')
|
||||
'2e96b5f14e4025691b57d2301d71aa6092ed44bc',
|
||||
'3ab5c8cd03d92bf4ec41e351820349d92fbc40c4')
|
||||
|
||||
|
||||
def read_timestamp(path):
|
||||
|
|
|
@ -86,6 +86,8 @@ gcc/config/arm/arm-tables.opt: gcc/config/arm/arm-cpus.in gcc/config/arm/parsecp
|
|||
gcc/config/c6x/c6x-tables.opt: gcc/config/c6x/c6x-isas.def gcc/config/c6x/genopt.sh
|
||||
gcc/config/c6x/c6x-sched.md: gcc/config/c6x/c6x-sched.md.in gcc/config/c6x/gensched.sh
|
||||
gcc/config/c6x/c6x-mult.md: gcc/config/c6x/c6x-mult.md.in gcc/config/c6x/genmult.sh
|
||||
gcc/config/loongarch/loongarch-str.h: gcc/config/loongarch/genopts/genstr.sh gcc/config/loongarch/genopts/loongarch-strings
|
||||
gcc/config/loongarch/loongarch.opt: gcc/config/loongarch/genopts/genstr.sh gcc/config/loongarch/genopts/loongarch.opt.in
|
||||
gcc/config/m68k/m68k-tables.opt: gcc/config/m68k/m68k-devices.def gcc/config/m68k/m68k-isas.def gcc/config/m68k/m68k-microarchs.def gcc/config/m68k/genopt.sh
|
||||
gcc/config/mips/mips-tables.opt: gcc/config/mips/mips-cpus.def gcc/config/mips/genopt.sh
|
||||
gcc/config/rs6000/rs6000-tables.opt: gcc/config/rs6000/rs6000-cpus.def gcc/config/rs6000/genopt.sh
|
||||
|
|
496
gcc/ChangeLog
496
gcc/ChangeLog
|
@ -1,3 +1,499 @@
|
|||
2022-03-31 Bill Schmidt <wschmidt@linux.ibm.com>
|
||||
|
||||
PR target/104004
|
||||
* config/rs6000/rs6000-builtins.def (MFFSL): Mark nosoft.
|
||||
(MTFSB0): Likewise.
|
||||
(MTFSB1): Likewise.
|
||||
(SET_FPSCR_RN): Likewise.
|
||||
(SET_FPSCR_DRN): Mark nosoft and no32bit.
|
||||
|
||||
2022-03-31 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* doc/options.texi (Option file format): Clarifications around
|
||||
option definition records' help texts.
|
||||
|
||||
2022-03-31 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* optc-gen.awk <END>: Fix "Multiple different help strings" error
|
||||
diagnostic.
|
||||
|
||||
2022-03-31 Andre Vieira <andre.simoesdiasvieira@arm.com>
|
||||
|
||||
* config/aarch64/aarch64.cc (aarch64_vector_costs): Define
|
||||
determine_suggested_unroll_factor and m_has_avg.
|
||||
(determine_suggested_unroll_factor): New function.
|
||||
(aarch64_vector_costs::add_stmt_cost): Check for a qualifying pattern
|
||||
to set m_nosve_pattern.
|
||||
(aarch64_vector_costs::finish_costs): Use
|
||||
determine_suggested_unroll_factor.
|
||||
* config/aarch64/aarch64.opt (aarch64-vect-unroll-limit): New.
|
||||
* doc/invoke.texi: (aarch64-vect-unroll-limit): Document new option.
|
||||
|
||||
2022-03-31 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
PR ipa/103083
|
||||
* ipa-prop.h (ipa_ancestor_jf_data): New flag keep_null;
|
||||
(ipa_get_jf_ancestor_keep_null): New function.
|
||||
* ipa-prop.cc (ipa_set_ancestor_jf): Initialize keep_null field of the
|
||||
ancestor function.
|
||||
(compute_complex_assign_jump_func): Pass false to keep_null
|
||||
parameter of ipa_set_ancestor_jf.
|
||||
(compute_complex_ancestor_jump_func): Pass true to keep_null
|
||||
parameter of ipa_set_ancestor_jf.
|
||||
(update_jump_functions_after_inlining): Carry over keep_null from the
|
||||
original ancestor jump-function or merge them.
|
||||
(ipa_write_jump_function): Stream keep_null flag.
|
||||
(ipa_read_jump_function): Likewise.
|
||||
(ipa_print_node_jump_functions_for_edge): Print the new flag.
|
||||
* ipa-cp.cc (class ipcp_bits_lattice): Make various getters const. New
|
||||
member function known_nonzero_p.
|
||||
(ipcp_bits_lattice::known_nonzero_p): New.
|
||||
(ipcp_bits_lattice::meet_with_1): New parameter drop_all_ones,
|
||||
observe it.
|
||||
(ipcp_bits_lattice::meet_with): Likewise.
|
||||
(propagate_bits_across_jump_function): Simplify. Pass true in
|
||||
drop_all_ones when it is necessary.
|
||||
(propagate_aggs_across_jump_function): Take care of keep_null
|
||||
flag.
|
||||
(ipa_get_jf_ancestor_result): Propagate NULL accross keep_null
|
||||
jump functions.
|
||||
|
||||
2022-03-31 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
PR ipa/102513
|
||||
* ipa-cp.cc (decide_whether_version_node): Skip scalar values
|
||||
which do not fit the known value_range.
|
||||
|
||||
2022-03-31 Martin Jambor <mjambor@suse.cz>
|
||||
|
||||
PR ipa/103171
|
||||
* ipa-prop.cc (propagate_controlled_uses): Add a LOAD reference
|
||||
always when an ADDR_EXPR constant is known to reach a load because
|
||||
of inlining, not just when removing an ADDR reference.
|
||||
|
||||
2022-03-31 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/105109
|
||||
* tree-ssa.cc (execute_update_addresses_taken): Suppress
|
||||
diagnostics on the load of the other complex component.
|
||||
|
||||
2022-03-31 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* config/nvptx/nvptx.h (ASM_SPEC): Use "-m sm_35" for -misa=sm_30.
|
||||
|
||||
2022-03-31 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR rtl-optimization/105091
|
||||
* gimple-expr.cc (mark_addressable): Handle TARGET_MEM_REF
|
||||
bases.
|
||||
|
||||
2022-03-31 Richard Biener <rguenther@suse.de>
|
||||
|
||||
Revert:
|
||||
2021-09-13 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
PR target/102125
|
||||
* gimple-fold.c (gimple_fold_builtin_memory_op): Allow folding
|
||||
memcpy if the size is not more than MOVE_MAX * MOVE_RATIO.
|
||||
|
||||
2022-03-31 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* gcov-io.cc (gcov_read_string): Reword documentation comment.
|
||||
|
||||
2022-03-30 Bill Schmidt <wschmidt@linux.ibm.com>
|
||||
|
||||
* config/rs6000/rs6000-builtins.def (NEG_V16QI): Move to [altivec]
|
||||
stanza.
|
||||
(NEG_V4SF): Likewise.
|
||||
(NEG_V4SI): Likewise.
|
||||
(NEG_V8HI): Likewise.
|
||||
(NEG_V2DF): Move to [vsx] stanza.
|
||||
(NEG_V2DI): Likewise.
|
||||
|
||||
2022-03-30 Vladimir N. Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR middle-end/105032
|
||||
* lra-assigns.cc (find_reload_regno_insns): Modify loop condition.
|
||||
|
||||
2022-03-30 Tom de Vries <tdevries@suse.de>
|
||||
Tobias Burnus <tobias@codesourcery.com>
|
||||
|
||||
* doc/invoke.texi (march): Document __PTX_SM__.
|
||||
(mptx): Document __PTX_ISA_VERSION_MAJOR__ and
|
||||
__PTX_ISA_VERSION_MINOR__.
|
||||
|
||||
2022-03-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR sanitizer/105093
|
||||
* ubsan.cc (instrument_object_size): If t is equal to inner and
|
||||
is a decl other than global var, punt. When emitting call to
|
||||
UBSAN_OBJECT_SIZE ifn, make sure base is addressable.
|
||||
|
||||
2022-03-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/105094
|
||||
* gimple-ssa-store-merging.cc (mem_valid_for_store_merging): Punt if
|
||||
bitsize <= 0 rather than just == 0.
|
||||
|
||||
2022-03-30 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* doc/invoke.texi (misa, mptx): Update.
|
||||
(march, march-map): Add.
|
||||
|
||||
2022-03-30 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* opt-functions.awk (n_args): New function.
|
||||
(lang_enabled_by): Merge function into...
|
||||
* optc-gen.awk <END>: ... sole user here.
|
||||
Improve diagnostics.
|
||||
|
||||
2022-03-29 Marek Polacek <polacek@redhat.com>
|
||||
Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR middle-end/103597
|
||||
* gimplify.cc (collect_fallthrough_labels): Don't push UNUSED_LABEL_Ps
|
||||
into labels. Maybe set prev to the statement preceding UNUSED_LABEL_P.
|
||||
(gimplify_cond_expr): Set UNUSED_LABEL_P.
|
||||
* tree.h (UNUSED_LABEL_P): New.
|
||||
|
||||
2022-03-29 Michael Meissner <meissner@linux.ibm.com>
|
||||
|
||||
* config/rs6000/vsx.md (vsx_extract_<mode>): Allow destination to
|
||||
be any VSX register.
|
||||
|
||||
2022-03-29 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
PR target/102024
|
||||
* config/aarch64/aarch64.cc (aapcs_vfp_sub_candidate): Handle
|
||||
zero-sized bit-fields. Detect cases where a warning may be needed.
|
||||
(aarch64_vfp_is_call_or_return_candidate): Emit a note if a
|
||||
zero-sized bit-field has caused parameter passing to change.
|
||||
|
||||
2022-03-29 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
PR target/102024
|
||||
* config/arm/arm.cc (aapcs_vfp_sub_candidate): Handle zero-sized
|
||||
bit-fields. Detect cases where a warning may be needed.
|
||||
(aapcs_vfp_is_call_or_return_candidate): Emit a note if
|
||||
a zero-sized bit-field has caused parameter passing to change.
|
||||
|
||||
2022-03-29 Richard Earnshaw <rearnsha@arm.com>
|
||||
|
||||
PR target/96882
|
||||
* config/arm/arm.cc (arm_get_pcs_model): Disable selection of
|
||||
ARM_PCS_AAPCS_LOCAL.
|
||||
|
||||
2022-03-29 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
PR target/104857
|
||||
* config/nvptx/nvptx-c.cc (nvptx_cpu_cpp_builtins): Emit
|
||||
__PTX_ISA_VERSION_MAJOR__ and __PTX_ISA_VERSION_MINOR__.
|
||||
* config/nvptx/nvptx.cc (ptx_version_to_number): New function.
|
||||
* config/nvptx/nvptx-protos.h (ptx_version_to_number): Declare.
|
||||
|
||||
2022-03-29 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* config/nvptx/nvptx.opt (m64): Update help text to reflect that it
|
||||
is ignored.
|
||||
|
||||
2022-03-29 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
PR target/104714
|
||||
* config/nvptx/nvptx.opt (march-map=*): Add aliases.
|
||||
|
||||
2022-03-29 Jan Hubicka <hubicka@ucw.cz>
|
||||
|
||||
* config/i386/i386-builtins.cc (ix86_vectorize_builtin_gather): Test
|
||||
TARGET_USE_GATHER_2PARTS and TARGET_USE_GATHER_4PARTS.
|
||||
* config/i386/i386.h (TARGET_USE_GATHER_2PARTS): New macro.
|
||||
(TARGET_USE_GATHER_4PARTS): New macro.
|
||||
* config/i386/x86-tune.def (X86_TUNE_USE_GATHER_2PARTS): New tune
|
||||
(X86_TUNE_USE_GATHER_4PARTS): New tune
|
||||
|
||||
2022-03-29 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
* config/nvptx/nvptx.opt (march): Add alias of misa.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* doc/install.texi: Add LoongArch options section.
|
||||
* doc/invoke.texi: Add LoongArch options section.
|
||||
* doc/md.texi: Add LoongArch options section.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* config/loongarch/loongarch-c.cc
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* config/loongarch/larchintrin.h: New file.
|
||||
* config/loongarch/loongarch-builtins.cc: New file.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* config/host-linux.cc: Add LoongArch support.
|
||||
* config/loongarch/loongarch-protos.h: New file.
|
||||
* config/loongarch/loongarch-tune.h: Likewise.
|
||||
* config/loongarch/loongarch.cc: Likewise.
|
||||
* config/loongarch/loongarch.h: Likewise.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* config/loongarch/constraints.md: New file.
|
||||
* config/loongarch/generic.md: New file.
|
||||
* config/loongarch/la464.md: New file.
|
||||
* config/loongarch/loongarch-ftypes.def: New file.
|
||||
* config/loongarch/loongarch-modes.def: New file.
|
||||
* config/loongarch/loongarch.md: New file.
|
||||
* config/loongarch/predicates.md: New file.
|
||||
* config/loongarch/sync.md: New file.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* configure: Regenerate file.
|
||||
|
||||
2022-03-29 Chenghua Xu <xuchenghua@loongson.cn>
|
||||
Lulu Cheng <chenglulu@loongson.cn>
|
||||
|
||||
* common/config/loongarch/loongarch-common.cc: New file.
|
||||
* config/loongarch/genopts/genstr.sh: New file.
|
||||
* config/loongarch/genopts/loongarch-strings: New file.
|
||||
* config/loongarch/genopts/loongarch.opt.in: New file.
|
||||
* config/loongarch/loongarch-str.h: New file.
|
||||
* config/loongarch/gnu-user.h: New file.
|
||||
* config/loongarch/linux.h: New file.
|
||||
* config/loongarch/loongarch-cpu.cc: New file.
|
||||
* config/loongarch/loongarch-cpu.h: New file.
|
||||
* config/loongarch/loongarch-def.c: New file.
|
||||
* config/loongarch/loongarch-def.h: New file.
|
||||
* config/loongarch/loongarch-driver.cc: New file.
|
||||
* config/loongarch/loongarch-driver.h: New file.
|
||||
* config/loongarch/loongarch-opts.cc: New file.
|
||||
* config/loongarch/loongarch-opts.h: New file.
|
||||
* config/loongarch/loongarch.opt: New file.
|
||||
* config/loongarch/t-linux: New file.
|
||||
* config/loongarch/t-loongarch: New file.
|
||||
* config.gcc: Add LoongArch support.
|
||||
* configure.ac: Add LoongArch support.
|
||||
|
||||
2022-03-29 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* opt-functions.awk (lang_enabled_by): Fix 'enabledby_negargs'
|
||||
typo.
|
||||
|
||||
2022-03-29 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/105080
|
||||
* tree-ssa-strlen.cc (printf_strlen_execute): Always init
|
||||
loops and SCEV.
|
||||
|
||||
2022-03-28 Indu Bhagat <indu.bhagat@oracle.com>
|
||||
|
||||
* ctfout.cc (ctf_preprocess): Use ctfc_get_num_ctf_vars instead.
|
||||
(output_ctf_vars): Likewise.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/59426
|
||||
* doc/extend.texi: Refer to __is_trivial instead of __is_pod.
|
||||
|
||||
2022-03-28 H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
PR target/105068
|
||||
* config/i386/sse.md (*ssse3_pshufbv8qi3): Also replace "Yv" with
|
||||
"Yw" in clobber.
|
||||
|
||||
2022-03-28 Tom de Vries <tdevries@suse.de>
|
||||
|
||||
PR target/104818
|
||||
* config/nvptx/gen-opt.sh (ptx_isa): Improve help text.
|
||||
* config/nvptx/nvptx-gen.opt: Regenerate.
|
||||
* config/nvptx/nvptx.opt (misa, mptx, ptx_version): Improve help text.
|
||||
* config/nvptx/t-nvptx (s-nvptx-gen-opt): Add missing dependency on
|
||||
gen-opt.sh.
|
||||
|
||||
2022-03-28 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/104308
|
||||
* gimple-fold.cc (gimple_fold_builtin_memory_op): When optimizing
|
||||
to loads then stores, set the location of the new load stmt.
|
||||
|
||||
2022-03-28 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/105070
|
||||
* tree-switch-conversion.h
|
||||
(bit_test_cluster::hoist_edge_and_branch_if_true): Add location
|
||||
argument.
|
||||
* tree-switch-conversion.cc
|
||||
(bit_test_cluster::hoist_edge_and_branch_if_true): Annotate
|
||||
cond with location.
|
||||
(bit_test_cluster::emit): Annotate all generated expressions
|
||||
with location.
|
||||
|
||||
2022-03-28 Andre Vieira <andre.simoesdiasvieira@arm.com>
|
||||
|
||||
* config/aarch64/aarch64-cores.def: Update Neoverse N2 core entry.
|
||||
|
||||
2022-03-28 liuhongt <hongtao.liu@intel.com>
|
||||
|
||||
PR target/105066
|
||||
* config/i386/sse.md (vec_set<mode>_0): Change attr "isa" of
|
||||
alternative 4 from sse4_noavx to noavx.
|
||||
|
||||
2022-03-28 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR tree-optimization/105056
|
||||
* tree-predcom.cc (component::component): Initialize also comp_step.
|
||||
|
||||
2022-03-27 H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
PR target/105068
|
||||
* config/i386/sse.md (*ssse3_pshufbv8qi3): Replace "Yv" with
|
||||
"Yw".
|
||||
|
||||
2022-03-26 Roger Sayle <roger@nextmovesoftware.com>
|
||||
|
||||
PR middle-end/104885
|
||||
* calls.cc (mark_stack_region_used): Check that the region
|
||||
is within the allocated size of stack_usage_map.
|
||||
|
||||
2022-03-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR rtl-optimization/103775
|
||||
* recog.cc (check_invalid_inc_dec): New function.
|
||||
(insn_invalid_p): Return 1 if REG_INC operand overlaps
|
||||
any stored REGs.
|
||||
|
||||
2022-03-26 H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
PR target/105058
|
||||
* config/i386/sse.md (loadiwkey): Replace "v" with "x".
|
||||
(aes<aesklvariant>u8): Likewise.
|
||||
|
||||
2022-03-26 H.J. Lu <hjl.tools@gmail.com>
|
||||
|
||||
PR target/105052
|
||||
* config/i386/sse.md (ssse3_ph<plusminus_mnemonic>wv4hi3):
|
||||
Replace "Yv" with "x".
|
||||
(ssse3_ph<plusminus_mnemonic>dv2si3): Likewise.
|
||||
(ssse3_psign<mode>3): Likewise.
|
||||
|
||||
2022-03-26 Hans-Peter Nilsson <hp@axis.com>
|
||||
|
||||
* reload.cc (find_reloads): Align comment with code where
|
||||
considering the intersection of register classes then tweaking the
|
||||
regclass for the current alternative or rejecting it.
|
||||
|
||||
2022-03-25 Christophe Lyon <christohe.lyon@arm.com>
|
||||
|
||||
PR target/104882
|
||||
Revert
|
||||
2021-06-11 Christophe Lyon <christophe.lyon@linaro.org>
|
||||
|
||||
* config/arm/mve.md (mve_vec_unpack<US>_lo_<mode>): Delete.
|
||||
(mve_vec_unpack<US>_hi_<mode>): Delete.
|
||||
(@mve_vec_pack_trunc_lo_<mode>): Delete.
|
||||
(mve_vmovntq_<supf><mode>): Remove '@' prefix.
|
||||
* config/arm/neon.md (vec_unpack<US>_hi_<mode>): Move back
|
||||
from vec-common.md.
|
||||
(vec_unpack<US>_lo_<mode>): Likewise.
|
||||
(vec_pack_trunc_<mode>): Rename from
|
||||
neon_quad_vec_pack_trunc_<mode>.
|
||||
* config/arm/vec-common.md (vec_unpack<US>_hi_<mode>): Delete.
|
||||
(vec_unpack<US>_lo_<mode>): Delete.
|
||||
(vec_pack_trunc_<mode>): Delete.
|
||||
|
||||
2022-03-25 Vladimir N. Makarov <vmakarov@redhat.com>
|
||||
|
||||
PR middle-end/104971
|
||||
* lra-lives.cc (process_bb_lives): Check hard_regs_live for hard
|
||||
regs to clear remove_p flag.
|
||||
|
||||
2022-03-25 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR tree-optimization/105053
|
||||
* tree-vect-loop.cc (vect_create_epilog_for_reduction): Pick
|
||||
the correct live-out stmt for a reduction chain.
|
||||
|
||||
2022-03-25 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR middle-end/105049
|
||||
* tree.cc (uniform_vector_p): Recurse for VECTOR_CST or
|
||||
CONSTRUCTOR first elements.
|
||||
|
||||
2022-03-25 Tobias Burnus <tobias@codesourcery.com>
|
||||
|
||||
PR analyzer/103533
|
||||
* doc/invoke.texi (Static Analyzer Options): Move
|
||||
@ignore block after @gccoptlist's '}' for 'make pdf'.
|
||||
|
||||
2022-03-25 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/104954
|
||||
* doc/invoke.texi (Static Analyzer Options): Add
|
||||
-fdump-analyzer-untracked.
|
||||
|
||||
2022-03-25 Avinash Sonawane <rootkea@gmail.com>
|
||||
|
||||
PR analyzer/103533
|
||||
* doc/invoke.texi: Document that enabling taint analyzer
|
||||
checker disables some warnings from `-fanalyzer`.
|
||||
|
||||
2022-03-24 Alexandre Oliva <oliva@adacore.com>
|
||||
|
||||
PR debug/104564
|
||||
* gimple-harden-conditionals.cc (detach_value): Keep temps
|
||||
anonymous.
|
||||
|
||||
2022-03-24 Alexandre Oliva <oliva@adacore.com>
|
||||
|
||||
PR middle-end/104975
|
||||
* gimple-harden-conditionals.cc
|
||||
(pass_harden_compares::execute): Force split in case of
|
||||
multiple edges.
|
||||
|
||||
2022-03-24 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/105035
|
||||
* fold-const.cc (operand_equal_p) <case COMPONENT_REF>: If either
|
||||
field0 or field1 is not a FIELD_DECL, return false.
|
||||
|
||||
2022-03-24 Richard Biener <rguenther@suse.de>
|
||||
|
||||
* tree-predcom.cc (chain::chain): Add CTOR.
|
||||
(component::component): Likewise.
|
||||
(pcom_worker::release_chain): Use delete.
|
||||
(release_components): Likewise.
|
||||
(pcom_worker::filter_suitable_components): Likewise.
|
||||
(pcom_worker::split_data_refs_to_components): Use new.
|
||||
(make_invariant_chain): Likewise.
|
||||
(make_rooted_chain): Likewise.
|
||||
(pcom_worker::combine_chains): Likewise.
|
||||
* tree-vect-loop.cc (vect_create_epilog_for_reduction):
|
||||
Make sure to release previously constructed scalar_results.
|
||||
* tree-vect-stmts.cc (vectorizable_load): Use auto_vec
|
||||
for vec_offsets.
|
||||
* vr-values.cc (simplify_using_ranges::~simplify_using_ranges):
|
||||
Release m_flag_set_edges.
|
||||
|
||||
2022-03-24 Siddhesh Poyarekar <siddhesh@gotplt.org>
|
||||
|
||||
PR tree-optimization/104970
|
||||
* tree-object-size.cc (parm_object_size): Restrict size
|
||||
computation scenarios to explicit access attributes.
|
||||
|
||||
2022-03-24 Kewen Lin <linkw@linux.ibm.com>
|
||||
|
||||
PR target/104967
|
||||
* config/rs6000/rs6000-c.cc (find_instance): Skip instances with null
|
||||
function types.
|
||||
|
||||
2022-03-23 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR target/102125
|
||||
|
|
|
@ -1 +1 @@
|
|||
20220324
|
||||
20220401
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
2022-03-24 Pascal Obry <obry@adacore.com>
|
||||
|
||||
PR ada/104767
|
||||
* libgnat/g-sercom__mingw.adb (Close): Reset port handle to -1.
|
||||
* libgnat/g-sercom__linux.adb (Close): Likewise.
|
||||
|
||||
2022-03-10 Richard Biener <rguenther@suse.de>
|
||||
|
||||
PR ada/104861
|
||||
|
|
|
@ -1,3 +1,92 @@
|
|||
2022-03-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR testsuite/105085
|
||||
* region-model-manager.cc (dump_untracked_region): Skip decls in
|
||||
the constant pool.
|
||||
|
||||
2022-03-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/105087
|
||||
* analyzer.h (class conjured_purge): New forward decl.
|
||||
* region-model-asm.cc (region_model::on_asm_stmt): Add
|
||||
conjured_purge param to calls binding_cluster::on_asm and
|
||||
region_model_manager::get_or_create_conjured_svalue.
|
||||
* region-model-impl-calls.cc
|
||||
(call_details::get_or_create_conjured_svalue): Likewise for call
|
||||
to region_model_manager::get_or_create_conjured_svalue.
|
||||
(region_model::impl_call_fgets): Remove call to
|
||||
region_model::purge_state_involving, as this is now done
|
||||
implicitly by call_details::get_or_create_conjured_svalue.
|
||||
(region_model::impl_call_fread): Likewise.
|
||||
(region_model::impl_call_strchr): Pass conjured_purge param to
|
||||
call to region_model_manager::get_or_create_conjured_svalue.
|
||||
* region-model-manager.cc (conjured_purge::purge): New.
|
||||
(region_model_manager::get_or_create_conjured_svalue): Add
|
||||
param "p". Use it to purge state when reusing an existing
|
||||
conjured_svalue.
|
||||
* region-model.cc (region_model::on_call_pre): Replace call to
|
||||
region_model::purge_state_involving with passing conjured_purge
|
||||
to region_model_manager::get_or_create_conjured_svalue.
|
||||
(region_model::handle_unrecognized_call): Pass conjured_purge to
|
||||
store::on_unknown_fncall.
|
||||
* region-model.h
|
||||
(region_model_manager::get_or_create_conjured_svalue): Add param
|
||||
"p".
|
||||
* store.cc (binding_cluster::on_unknown_fncall): Likewise. Pass
|
||||
it on to region_model_manager::get_or_create_conjured_svalue.
|
||||
(binding_cluster::on_asm): Likewise.
|
||||
(store::on_unknown_fncall): Add param "p" and pass it on to
|
||||
binding_cluster::on_unknown_fncall.
|
||||
* store.h (binding_cluster::on_unknown_fncall): Add param p.
|
||||
(binding_cluster::on_asm): Likewise.
|
||||
(store::on_unknown_fncall): Likewise.
|
||||
* svalue.h (class conjured_purge): New.
|
||||
|
||||
2022-03-29 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/105074
|
||||
* region.cc (ipa_ref_requires_tracking): Drop "context_fndecl",
|
||||
instead using the ref->referring to get the cgraph node of the
|
||||
caller.
|
||||
(symnode_requires_tracking_p): Likewise.
|
||||
|
||||
2022-03-26 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/105057
|
||||
* store.cc (binding_cluster::make_unknown_relative_to): Reject
|
||||
attempts to create a cluster for untracked base regions.
|
||||
(store::set_value): Likewise.
|
||||
(store::fill_region): Likewise.
|
||||
(store::mark_region_as_unknown): Likewise.
|
||||
|
||||
2022-03-25 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/104954
|
||||
* analyzer.opt (-fdump-analyzer-untracked): New option.
|
||||
* engine.cc (impl_run_checkers): Handle it.
|
||||
* region-model-asm.cc (region_model::on_asm_stmt): Don't attempt
|
||||
to clobber regions with !tracked_p ().
|
||||
* region-model-manager.cc (dump_untracked_region): New.
|
||||
(region_model_manager::dump_untracked_regions): New.
|
||||
(frame_region::dump_untracked_regions): New.
|
||||
* region-model.h (region_model_manager::dump_untracked_regions):
|
||||
New decl.
|
||||
* region.cc (ipa_ref_requires_tracking): New.
|
||||
(symnode_requires_tracking_p): New.
|
||||
(decl_region::calc_tracked_p): New.
|
||||
* region.h (region::tracked_p): New vfunc.
|
||||
(frame_region::dump_untracked_regions): New decl.
|
||||
(class decl_region): Note that this is also used fo SSA names.
|
||||
(decl_region::decl_region): Initialize m_tracked.
|
||||
(decl_region::tracked_p): New.
|
||||
(decl_region::calc_tracked_p): New decl.
|
||||
(decl_region::m_tracked): New.
|
||||
* store.cc (store::get_or_create_cluster): Assert that we
|
||||
don't try to create clusters for base regions that aren't
|
||||
trackable.
|
||||
(store::mark_as_escaped): Don't mark base regions that we're not
|
||||
tracking.
|
||||
|
||||
2022-03-23 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/104979
|
||||
|
|
|
@ -70,6 +70,7 @@ class region;
|
|||
class string_region;
|
||||
class bit_range_region;
|
||||
class region_model_manager;
|
||||
class conjured_purge;
|
||||
struct model_merger;
|
||||
class store_manager;
|
||||
class store;
|
||||
|
|
|
@ -250,4 +250,8 @@ fdump-analyzer-supergraph
|
|||
Common RejectNegative Var(flag_dump_analyzer_supergraph)
|
||||
Dump the analyzer supergraph to a SRCFILE.supergraph.dot file.
|
||||
|
||||
fdump-analyzer-untracked
|
||||
Common RejectNegative Var(flag_dump_analyzer_untracked)
|
||||
Emit custom warnings with internal details intended for analyzer developers.
|
||||
|
||||
; This comment is to ensure we retain the blank line above.
|
||||
|
|
|
@ -5811,6 +5811,9 @@ impl_run_checkers (logger *logger)
|
|||
if (flag_dump_analyzer_json)
|
||||
dump_analyzer_json (sg, eg);
|
||||
|
||||
if (flag_dump_analyzer_untracked)
|
||||
eng.get_model_manager ()->dump_untracked_regions ();
|
||||
|
||||
delete purge_map;
|
||||
}
|
||||
|
||||
|
|
|
@ -267,11 +267,13 @@ region_model::on_asm_stmt (const gasm *stmt, region_model_context *ctxt)
|
|||
iter != reachable_regs.end_mutable_base_regs (); ++iter)
|
||||
{
|
||||
const region *base_reg = *iter;
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ())
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ()
|
||||
|| !base_reg->tracked_p ())
|
||||
continue;
|
||||
|
||||
binding_cluster *cluster = m_store.get_or_create_cluster (base_reg);
|
||||
cluster->on_asm (stmt, m_mgr->get_store_manager ());
|
||||
cluster->on_asm (stmt, m_mgr->get_store_manager (),
|
||||
conjured_purge (this, ctxt));
|
||||
}
|
||||
|
||||
/* Update the outputs. */
|
||||
|
@ -291,8 +293,9 @@ region_model::on_asm_stmt (const gasm *stmt, region_model_context *ctxt)
|
|||
{
|
||||
sval = m_mgr->get_or_create_conjured_svalue (TREE_TYPE (dst_expr),
|
||||
stmt,
|
||||
dst_reg);
|
||||
purge_state_involving (sval, ctxt);
|
||||
dst_reg,
|
||||
conjured_purge (this,
|
||||
ctxt));
|
||||
}
|
||||
set_value (dst_reg, sval, ctxt);
|
||||
}
|
||||
|
|
|
@ -212,13 +212,15 @@ call_details::dump (bool simple) const
|
|||
pp_flush (&pp);
|
||||
}
|
||||
|
||||
/* Get a conjured_svalue for this call for REG. */
|
||||
/* Get a conjured_svalue for this call for REG,
|
||||
and purge any state already relating to that conjured_svalue. */
|
||||
|
||||
const svalue *
|
||||
call_details::get_or_create_conjured_svalue (const region *reg) const
|
||||
{
|
||||
region_model_manager *mgr = m_model->get_manager ();
|
||||
return mgr->get_or_create_conjured_svalue (reg->get_type (), m_call, reg);
|
||||
return mgr->get_or_create_conjured_svalue (reg->get_type (), m_call, reg,
|
||||
conjured_purge (m_model, m_ctxt));
|
||||
}
|
||||
|
||||
/* Implementations of specific functions. */
|
||||
|
@ -434,7 +436,6 @@ region_model::impl_call_fgets (const call_details &cd)
|
|||
{
|
||||
const region *base_reg = reg->get_base_region ();
|
||||
const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg);
|
||||
purge_state_involving (new_sval, cd.get_ctxt ());
|
||||
set_value (base_reg, new_sval, cd.get_ctxt ());
|
||||
}
|
||||
}
|
||||
|
@ -449,7 +450,6 @@ region_model::impl_call_fread (const call_details &cd)
|
|||
{
|
||||
const region *base_reg = reg->get_base_region ();
|
||||
const svalue *new_sval = cd.get_or_create_conjured_svalue (base_reg);
|
||||
purge_state_involving (new_sval, cd.get_ctxt ());
|
||||
set_value (base_reg, new_sval, cd.get_ctxt ());
|
||||
}
|
||||
}
|
||||
|
@ -830,7 +830,9 @@ region_model::impl_call_strchr (const call_details &cd)
|
|||
const svalue *offset
|
||||
= mgr->get_or_create_conjured_svalue (size_type_node,
|
||||
cd.get_call_stmt (),
|
||||
str_reg);
|
||||
str_reg,
|
||||
conjured_purge (model,
|
||||
ctxt));
|
||||
result = mgr->get_or_create_binop (lhs_type, POINTER_PLUS_EXPR,
|
||||
str_sval, offset);
|
||||
}
|
||||
|
|
|
@ -1169,17 +1169,38 @@ region_model_manager::get_or_create_compound_svalue (tree type,
|
|||
return compound_sval;
|
||||
}
|
||||
|
||||
/* class conjured_purge. */
|
||||
|
||||
/* Purge state relating to SVAL. */
|
||||
|
||||
void
|
||||
conjured_purge::purge (const conjured_svalue *sval) const
|
||||
{
|
||||
m_model->purge_state_involving (sval, m_ctxt);
|
||||
}
|
||||
|
||||
/* Return the svalue * of type TYPE for the value conjured for ID_REG
|
||||
at STMT, creating it if necessary. */
|
||||
at STMT, creating it if necessary.
|
||||
Use P to purge existing state from the svalue, for the case where a
|
||||
conjured_svalue would be reused along an execution path. */
|
||||
|
||||
const svalue *
|
||||
region_model_manager::get_or_create_conjured_svalue (tree type,
|
||||
const gimple *stmt,
|
||||
const region *id_reg)
|
||||
const region *id_reg,
|
||||
const conjured_purge &p)
|
||||
{
|
||||
conjured_svalue::key_t key (type, stmt, id_reg);
|
||||
if (conjured_svalue **slot = m_conjured_values_map.get (key))
|
||||
return *slot;
|
||||
{
|
||||
const conjured_svalue *sval = *slot;
|
||||
/* We're reusing an existing conjured_svalue, perhaps from a different
|
||||
state within this analysis, or perhaps from an earlier state on this
|
||||
execution path. For the latter, purge any state involving the "new"
|
||||
svalue from the current program_state. */
|
||||
p.purge (sval);
|
||||
return sval;
|
||||
}
|
||||
conjured_svalue *conjured_sval
|
||||
= new conjured_svalue (type, stmt, id_reg);
|
||||
RETURN_UNKNOWN_IF_TOO_COMPLEX (conjured_sval);
|
||||
|
@ -1740,6 +1761,54 @@ store_manager::log_stats (logger *logger, bool show_objs) const
|
|||
m_symbolic_binding_key_mgr);
|
||||
}
|
||||
|
||||
/* Emit a warning showing DECL_REG->tracked_p () for use in DejaGnu tests
|
||||
(using -fdump-analyzer-untracked). */
|
||||
|
||||
static void
|
||||
dump_untracked_region (const decl_region *decl_reg)
|
||||
{
|
||||
tree decl = decl_reg->get_decl ();
|
||||
if (TREE_CODE (decl) != VAR_DECL)
|
||||
return;
|
||||
/* For now, don't emit the status of decls in the constant pool, to avoid
|
||||
differences in DejaGnu test results between targets that use these vs
|
||||
those that don't.
|
||||
(Eventually these decls should probably be untracked and we should test
|
||||
for that, but that's not stage 4 material). */
|
||||
if (DECL_IN_CONSTANT_POOL (decl))
|
||||
return;
|
||||
warning_at (DECL_SOURCE_LOCATION (decl), 0,
|
||||
"track %qD: %s",
|
||||
decl, (decl_reg->tracked_p () ? "yes" : "no"));
|
||||
}
|
||||
|
||||
/* Implementation of -fdump-analyzer-untracked. */
|
||||
|
||||
void
|
||||
region_model_manager::dump_untracked_regions () const
|
||||
{
|
||||
for (auto iter : m_globals_map)
|
||||
{
|
||||
const decl_region *decl_reg = iter.second;
|
||||
dump_untracked_region (decl_reg);
|
||||
}
|
||||
for (auto frame_iter : m_frame_regions)
|
||||
{
|
||||
const frame_region *frame_reg = frame_iter.second;
|
||||
frame_reg->dump_untracked_regions ();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
frame_region::dump_untracked_regions () const
|
||||
{
|
||||
for (auto iter : m_locals)
|
||||
{
|
||||
const decl_region *decl_reg = iter.second;
|
||||
dump_untracked_region (decl_reg);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace ana
|
||||
|
||||
#endif /* #if ENABLE_ANALYZER */
|
||||
|
|
|
@ -1324,8 +1324,9 @@ region_model::on_call_pre (const gcall *call, region_model_context *ctxt,
|
|||
use a conjured value, and purge any prior state involving that
|
||||
value (in case this is in a loop). */
|
||||
sval = m_mgr->get_or_create_conjured_svalue (TREE_TYPE (lhs), call,
|
||||
lhs_region);
|
||||
purge_state_involving (sval, ctxt);
|
||||
lhs_region,
|
||||
conjured_purge (this,
|
||||
ctxt));
|
||||
}
|
||||
set_value (lhs_region, sval, ctxt);
|
||||
}
|
||||
|
@ -1802,7 +1803,8 @@ region_model::handle_unrecognized_call (const gcall *call,
|
|||
|
||||
/* Update bindings for all clusters that have escaped, whether above,
|
||||
or previously. */
|
||||
m_store.on_unknown_fncall (call, m_mgr->get_store_manager ());
|
||||
m_store.on_unknown_fncall (call, m_mgr->get_store_manager (),
|
||||
conjured_purge (this, ctxt));
|
||||
|
||||
/* Purge dynamic extents from any regions that have escaped mutably:
|
||||
realloc could have been called on them. */
|
||||
|
|
|
@ -277,7 +277,8 @@ public:
|
|||
const svalue *get_or_create_compound_svalue (tree type,
|
||||
const binding_map &map);
|
||||
const svalue *get_or_create_conjured_svalue (tree type, const gimple *stmt,
|
||||
const region *id_reg);
|
||||
const region *id_reg,
|
||||
const conjured_purge &p);
|
||||
const svalue *
|
||||
get_or_create_asm_output_svalue (tree type,
|
||||
const gasm *asm_stmt,
|
||||
|
@ -349,6 +350,8 @@ public:
|
|||
|
||||
logger *get_logger () const { return m_logger; }
|
||||
|
||||
void dump_untracked_regions () const;
|
||||
|
||||
private:
|
||||
bool too_complex_p (const complexity &c) const;
|
||||
bool reject_if_too_complex (svalue *sval);
|
||||
|
|
|
@ -1167,6 +1167,95 @@ decl_region::get_svalue_for_initializer (region_model_manager *mgr) const
|
|||
return m.get_rvalue (path_var (init, 0), NULL);
|
||||
}
|
||||
|
||||
/* Subroutine of symnode_requires_tracking_p; return true if REF
|
||||
might imply that we should be tracking the value of its decl. */
|
||||
|
||||
static bool
|
||||
ipa_ref_requires_tracking (ipa_ref *ref)
|
||||
{
|
||||
/* If we have a load/store/alias of the symbol, then we'll track
|
||||
the decl's value. */
|
||||
if (ref->use != IPA_REF_ADDR)
|
||||
return true;
|
||||
|
||||
if (ref->stmt == NULL)
|
||||
return true;
|
||||
|
||||
switch (ref->stmt->code)
|
||||
{
|
||||
default:
|
||||
return true;
|
||||
case GIMPLE_CALL:
|
||||
{
|
||||
cgraph_node *caller_cnode = dyn_cast <cgraph_node *> (ref->referring);
|
||||
if (caller_cnode == NULL)
|
||||
return true;
|
||||
cgraph_edge *edge = caller_cnode->get_edge (ref->stmt);
|
||||
if (!edge)
|
||||
return true;
|
||||
if (edge->callee == NULL)
|
||||
return true; /* e.g. call through function ptr. */
|
||||
if (edge->callee->definition)
|
||||
return true;
|
||||
/* If we get here, then this ref is a pointer passed to
|
||||
a function we don't have the definition for. */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case GIMPLE_ASM:
|
||||
{
|
||||
const gasm *asm_stmt = as_a <const gasm *> (ref->stmt);
|
||||
if (gimple_asm_noutputs (asm_stmt) > 0)
|
||||
return true;
|
||||
if (gimple_asm_nclobbers (asm_stmt) > 0)
|
||||
return true;
|
||||
/* If we get here, then this ref is the decl being passed
|
||||
by pointer to asm with no outputs. */
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine if the decl for SYMNODE should have binding_clusters
|
||||
in our state objects; return false to optimize away tracking
|
||||
certain decls in our state objects, as an optimization. */
|
||||
|
||||
static bool
|
||||
symnode_requires_tracking_p (symtab_node *symnode)
|
||||
{
|
||||
gcc_assert (symnode);
|
||||
if (symnode->externally_visible)
|
||||
return true;
|
||||
tree context_fndecl = DECL_CONTEXT (symnode->decl);
|
||||
if (context_fndecl == NULL)
|
||||
return true;
|
||||
if (TREE_CODE (context_fndecl) != FUNCTION_DECL)
|
||||
return true;
|
||||
for (auto ref : symnode->ref_list.referring)
|
||||
if (ipa_ref_requires_tracking (ref))
|
||||
return true;
|
||||
|
||||
/* If we get here, then we don't have uses of this decl that require
|
||||
tracking; we never read from it or write to it explicitly. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Subroutine of decl_region ctor: determine whether this decl_region
|
||||
can have binding_clusters; return false to optimize away tracking
|
||||
of certain decls in our state objects, as an optimization. */
|
||||
|
||||
bool
|
||||
decl_region::calc_tracked_p (tree decl)
|
||||
{
|
||||
/* Precondition of symtab_node::get. */
|
||||
if (TREE_CODE (decl) == VAR_DECL
|
||||
&& (TREE_STATIC (decl) || DECL_EXTERNAL (decl) || in_lto_p))
|
||||
if (symtab_node *symnode = symtab_node::get (decl))
|
||||
return symnode_requires_tracking_p (symnode);
|
||||
return true;
|
||||
}
|
||||
|
||||
/* class field_region : public region. */
|
||||
|
||||
/* Implementation of region::dump_to_pp vfunc for field_region. */
|
||||
|
|
|
@ -197,6 +197,11 @@ public:
|
|||
|
||||
bool symbolic_for_unknown_ptr_p () const;
|
||||
|
||||
/* For most base regions it makes sense to track the bindings of the region
|
||||
within the store. As an optimization, some are not tracked (to avoid
|
||||
bloating the store object with redundant binding clusters). */
|
||||
virtual bool tracked_p () const { return true; }
|
||||
|
||||
const complexity &get_complexity () const { return m_complexity; }
|
||||
|
||||
bool is_named_decl_p (const char *decl_name) const;
|
||||
|
@ -319,6 +324,9 @@ public:
|
|||
|
||||
unsigned get_num_locals () const { return m_locals.elements (); }
|
||||
|
||||
/* Implemented in region-model-manager.cc. */
|
||||
void dump_untracked_regions () const;
|
||||
|
||||
private:
|
||||
const frame_region *m_calling_frame;
|
||||
function *m_fun;
|
||||
|
@ -633,13 +641,15 @@ template <> struct default_hash_traits<symbolic_region::key_t>
|
|||
namespace ana {
|
||||
|
||||
/* Concrete region subclass representing the memory occupied by a
|
||||
variable (whether for a global or a local). */
|
||||
variable (whether for a global or a local).
|
||||
Also used for representing SSA names, as if they were locals. */
|
||||
|
||||
class decl_region : public region
|
||||
{
|
||||
public:
|
||||
decl_region (unsigned id, const region *parent, tree decl)
|
||||
: region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl)
|
||||
: region (complexity (parent), id, parent, TREE_TYPE (decl)), m_decl (decl),
|
||||
m_tracked (calc_tracked_p (decl))
|
||||
{}
|
||||
|
||||
enum region_kind get_kind () const FINAL OVERRIDE { return RK_DECL; }
|
||||
|
@ -648,6 +658,8 @@ public:
|
|||
|
||||
void dump_to_pp (pretty_printer *pp, bool simple) const FINAL OVERRIDE;
|
||||
|
||||
bool tracked_p () const FINAL OVERRIDE { return m_tracked; }
|
||||
|
||||
tree get_decl () const { return m_decl; }
|
||||
int get_stack_depth () const;
|
||||
|
||||
|
@ -657,7 +669,15 @@ public:
|
|||
const svalue *get_svalue_for_initializer (region_model_manager *mgr) const;
|
||||
|
||||
private:
|
||||
static bool calc_tracked_p (tree decl);
|
||||
|
||||
tree m_decl;
|
||||
|
||||
/* Cached result of calc_tracked_p, so that we can quickly determine when
|
||||
we don't to track a binding_cluster for this decl (to avoid bloating
|
||||
store objects).
|
||||
This can be debugged using -fdump-analyzer-untracked. */
|
||||
bool m_tracked;
|
||||
};
|
||||
|
||||
} // namespace ana
|
||||
|
|
|
@ -1823,7 +1823,8 @@ binding_cluster::make_unknown_relative_to (const binding_cluster *other,
|
|||
{
|
||||
const region *base_reg
|
||||
= region_sval->get_pointee ()->get_base_region ();
|
||||
if (!base_reg->symbolic_for_unknown_ptr_p ())
|
||||
if (base_reg->tracked_p ()
|
||||
&& !base_reg->symbolic_for_unknown_ptr_p ())
|
||||
{
|
||||
binding_cluster *c = out_store->get_or_create_cluster (base_reg);
|
||||
c->mark_as_escaped ();
|
||||
|
@ -1842,12 +1843,14 @@ binding_cluster::mark_as_escaped ()
|
|||
|
||||
/* If this cluster has escaped (by this call, or by an earlier one, or
|
||||
by being an external param), then unbind all values and mark it
|
||||
as "touched", so that it has an unknown value, rather than an
|
||||
initial_svalue. */
|
||||
as "touched", so that it has a conjured value, rather than an
|
||||
initial_svalue.
|
||||
Use P to purge state involving conjured_svalues. */
|
||||
|
||||
void
|
||||
binding_cluster::on_unknown_fncall (const gcall *call,
|
||||
store_manager *mgr)
|
||||
store_manager *mgr,
|
||||
const conjured_purge &p)
|
||||
{
|
||||
if (m_escaped)
|
||||
{
|
||||
|
@ -1856,25 +1859,27 @@ binding_cluster::on_unknown_fncall (const gcall *call,
|
|||
/* Bind it to a new "conjured" value using CALL. */
|
||||
const svalue *sval
|
||||
= mgr->get_svalue_manager ()->get_or_create_conjured_svalue
|
||||
(m_base_region->get_type (), call, m_base_region);
|
||||
(m_base_region->get_type (), call, m_base_region, p);
|
||||
bind (mgr, m_base_region, sval);
|
||||
|
||||
m_touched = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark this cluster as having been clobbered by STMT. */
|
||||
/* Mark this cluster as having been clobbered by STMT.
|
||||
Use P to purge state involving conjured_svalues. */
|
||||
|
||||
void
|
||||
binding_cluster::on_asm (const gasm *stmt,
|
||||
store_manager *mgr)
|
||||
store_manager *mgr,
|
||||
const conjured_purge &p)
|
||||
{
|
||||
m_map.empty ();
|
||||
|
||||
/* Bind it to a new "conjured" value using CALL. */
|
||||
const svalue *sval
|
||||
= mgr->get_svalue_manager ()->get_or_create_conjured_svalue
|
||||
(m_base_region->get_type (), stmt, m_base_region);
|
||||
(m_base_region->get_type (), stmt, m_base_region, p);
|
||||
bind (mgr, m_base_region, sval);
|
||||
|
||||
m_touched = true;
|
||||
|
@ -2384,11 +2389,17 @@ store::set_value (store_manager *mgr, const region *lhs_reg,
|
|||
mark_as_escaped (ptr_base_reg);
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (lhs_base_reg->tracked_p ())
|
||||
{
|
||||
lhs_cluster = get_or_create_cluster (lhs_base_reg);
|
||||
lhs_cluster->bind (mgr, lhs_reg, rhs_sval);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Reject attempting to bind values into an untracked region;
|
||||
merely invalidate values below. */
|
||||
lhs_cluster = NULL;
|
||||
}
|
||||
|
||||
/* Bindings to a cluster can affect other clusters if a symbolic
|
||||
base region is involved.
|
||||
|
@ -2564,7 +2575,8 @@ void
|
|||
store::fill_region (store_manager *mgr, const region *reg, const svalue *sval)
|
||||
{
|
||||
const region *base_reg = reg->get_base_region ();
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ())
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ()
|
||||
|| !base_reg->tracked_p ())
|
||||
return;
|
||||
binding_cluster *cluster = get_or_create_cluster (base_reg);
|
||||
cluster->fill_region (mgr, reg, sval);
|
||||
|
@ -2587,7 +2599,8 @@ store::mark_region_as_unknown (store_manager *mgr, const region *reg,
|
|||
uncertainty_t *uncertainty)
|
||||
{
|
||||
const region *base_reg = reg->get_base_region ();
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ())
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ()
|
||||
|| !base_reg->tracked_p ())
|
||||
return;
|
||||
binding_cluster *cluster = get_or_create_cluster (base_reg);
|
||||
cluster->mark_region_as_unknown (mgr, reg, uncertainty);
|
||||
|
@ -2654,6 +2667,9 @@ store::get_or_create_cluster (const region *base_reg)
|
|||
/* We shouldn't create clusters for dereferencing an UNKNOWN ptr. */
|
||||
gcc_assert (!base_reg->symbolic_for_unknown_ptr_p ());
|
||||
|
||||
/* We shouldn't create clusters for base regions that aren't trackable. */
|
||||
gcc_assert (base_reg->tracked_p ());
|
||||
|
||||
if (binding_cluster **slot = m_cluster_map.get (base_reg))
|
||||
return *slot;
|
||||
|
||||
|
@ -2742,7 +2758,8 @@ store::mark_as_escaped (const region *base_reg)
|
|||
gcc_assert (base_reg);
|
||||
gcc_assert (base_reg->get_base_region () == base_reg);
|
||||
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ())
|
||||
if (base_reg->symbolic_for_unknown_ptr_p ()
|
||||
|| !base_reg->tracked_p ())
|
||||
return;
|
||||
|
||||
binding_cluster *cluster = get_or_create_cluster (base_reg);
|
||||
|
@ -2753,13 +2770,14 @@ store::mark_as_escaped (const region *base_reg)
|
|||
(either in this fncall, or in a prior one). */
|
||||
|
||||
void
|
||||
store::on_unknown_fncall (const gcall *call, store_manager *mgr)
|
||||
store::on_unknown_fncall (const gcall *call, store_manager *mgr,
|
||||
const conjured_purge &p)
|
||||
{
|
||||
m_called_unknown_fn = true;
|
||||
|
||||
for (cluster_map_t::iterator iter = m_cluster_map.begin ();
|
||||
iter != m_cluster_map.end (); ++iter)
|
||||
(*iter).second->on_unknown_fncall (call, mgr);
|
||||
(*iter).second->on_unknown_fncall (call, mgr, p);
|
||||
}
|
||||
|
||||
/* Return true if a non-const pointer to BASE_REG (or something within it)
|
||||
|
|
|
@ -609,8 +609,10 @@ public:
|
|||
store_manager *mgr);
|
||||
|
||||
void mark_as_escaped ();
|
||||
void on_unknown_fncall (const gcall *call, store_manager *mgr);
|
||||
void on_asm (const gasm *stmt, store_manager *mgr);
|
||||
void on_unknown_fncall (const gcall *call, store_manager *mgr,
|
||||
const conjured_purge &p);
|
||||
void on_asm (const gasm *stmt, store_manager *mgr,
|
||||
const conjured_purge &p);
|
||||
|
||||
bool escaped_p () const { return m_escaped; }
|
||||
bool touched_p () const { return m_touched; }
|
||||
|
@ -735,7 +737,8 @@ public:
|
|||
model_merger *merger);
|
||||
|
||||
void mark_as_escaped (const region *base_reg);
|
||||
void on_unknown_fncall (const gcall *call, store_manager *mgr);
|
||||
void on_unknown_fncall (const gcall *call, store_manager *mgr,
|
||||
const conjured_purge &p);
|
||||
bool escaped_p (const region *reg) const;
|
||||
|
||||
void get_representative_path_vars (const region_model *model,
|
||||
|
|
|
@ -1306,6 +1306,27 @@ template <> struct default_hash_traits<compound_svalue::key_t>
|
|||
|
||||
namespace ana {
|
||||
|
||||
/* A bundle of state for purging information from a program_state about
|
||||
a conjured_svalue. We pass this whenever calling
|
||||
get_or_create_conjured_svalue, so that if the program_state already
|
||||
has information about this conjured_svalue on an execution path, we
|
||||
can purge that information, to avoid the analyzer confusing the two
|
||||
values as being the same. */
|
||||
|
||||
class conjured_purge
|
||||
{
|
||||
public:
|
||||
conjured_purge (region_model *model, region_model_context *ctxt)
|
||||
: m_model (model), m_ctxt (ctxt)
|
||||
{
|
||||
}
|
||||
void purge (const conjured_svalue *sval) const;
|
||||
|
||||
private:
|
||||
region_model *m_model;
|
||||
region_model_context *m_ctxt;
|
||||
};
|
||||
|
||||
/* A defined value arising from a statement, where we want to identify a
|
||||
particular unknown value, rather than resorting to the unknown_value
|
||||
singleton, so that the value can have sm-state.
|
||||
|
|
|
@ -1,3 +1,36 @@
|
|||
2022-03-30 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/101030
|
||||
* c-warn.cc (conversion_warning) <case COND_EXPR>: Don't call
|
||||
conversion_warning when OP1 is null.
|
||||
|
||||
2022-03-30 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* c.opt (Wc++11-extensions, Wc++14-extensions, Wc++17-extensions)
|
||||
(Wc++20-extensions, Wc++23-extensions): Remove 'LangEnabledBy'
|
||||
option properties.
|
||||
|
||||
2022-03-30 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* c.opt (Wuse-after-free): Remove.
|
||||
|
||||
2022-03-30 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* c.opt (Warray-bounds): Remove.
|
||||
|
||||
2022-03-26 Thomas Schwinge <thomas@codesourcery.com>
|
||||
|
||||
* c.opt: Properly quote comment.
|
||||
|
||||
2022-03-25 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* c-ada-spec.cc (dump_ada_import): Deal with the "section" attribute
|
||||
(dump_ada_node) <POINTER_TYPE>: Do not modify and pass the name, but
|
||||
the referenced type instead. Deal with the anonymous original type
|
||||
of a typedef'ed type. In the actual access case, follow the chain
|
||||
of external subtypes.
|
||||
<TYPE_DECL>: Tidy up control flow.
|
||||
|
||||
2022-03-21 Qian Jianhua <qianjh@cn.fujitsu.com>
|
||||
|
||||
* c-ada-spec.cc: Change array length
|
||||
|
|
|
@ -1526,6 +1526,15 @@ dump_ada_import (pretty_printer *buffer, tree t, int spc)
|
|||
|
||||
newline_and_indent (buffer, spc + 5);
|
||||
|
||||
tree sec = lookup_attribute ("section", DECL_ATTRIBUTES (t));
|
||||
if (sec)
|
||||
{
|
||||
pp_string (buffer, "Linker_Section => \"");
|
||||
pp_string (buffer, TREE_STRING_POINTER (TREE_VALUE (TREE_VALUE (sec))));
|
||||
pp_string (buffer, "\", ");
|
||||
newline_and_indent (buffer, spc + 5);
|
||||
}
|
||||
|
||||
pp_string (buffer, "External_Name => \"");
|
||||
|
||||
if (is_stdcall)
|
||||
|
@ -2179,10 +2188,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
|
|||
}
|
||||
else
|
||||
{
|
||||
const unsigned int quals = TYPE_QUALS (TREE_TYPE (node));
|
||||
tree ref_type = TREE_TYPE (node);
|
||||
const unsigned int quals = TYPE_QUALS (ref_type);
|
||||
bool is_access = false;
|
||||
|
||||
if (VOID_TYPE_P (TREE_TYPE (node)))
|
||||
if (VOID_TYPE_P (ref_type))
|
||||
{
|
||||
if (!name_only)
|
||||
pp_string (buffer, "new ");
|
||||
|
@ -2197,9 +2207,8 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
|
|||
else
|
||||
{
|
||||
if (TREE_CODE (node) == POINTER_TYPE
|
||||
&& TREE_CODE (TREE_TYPE (node)) == INTEGER_TYPE
|
||||
&& id_equal (DECL_NAME (TYPE_NAME (TREE_TYPE (node))),
|
||||
"char"))
|
||||
&& TREE_CODE (ref_type) == INTEGER_TYPE
|
||||
&& id_equal (DECL_NAME (TYPE_NAME (ref_type)), "char"))
|
||||
{
|
||||
if (!name_only)
|
||||
pp_string (buffer, "new ");
|
||||
|
@ -2214,28 +2223,11 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
|
|||
}
|
||||
else
|
||||
{
|
||||
tree type_name = TYPE_NAME (TREE_TYPE (node));
|
||||
|
||||
/* Generate "access <type>" instead of "access <subtype>"
|
||||
if the subtype comes from another file, because subtype
|
||||
declarations do not contribute to the limited view of a
|
||||
package and thus subtypes cannot be referenced through
|
||||
a limited_with clause. */
|
||||
if (type_name
|
||||
&& TREE_CODE (type_name) == TYPE_DECL
|
||||
&& DECL_ORIGINAL_TYPE (type_name)
|
||||
&& TYPE_NAME (DECL_ORIGINAL_TYPE (type_name)))
|
||||
{
|
||||
const expanded_location xloc
|
||||
= expand_location (decl_sloc (type_name, false));
|
||||
if (xloc.line
|
||||
&& xloc.file
|
||||
&& xloc.file != current_source_file)
|
||||
type_name = DECL_ORIGINAL_TYPE (type_name);
|
||||
}
|
||||
tree stub = TYPE_STUB_DECL (ref_type);
|
||||
tree type_name = TYPE_NAME (ref_type);
|
||||
|
||||
/* For now, handle access-to-access as System.Address. */
|
||||
if (TREE_CODE (TREE_TYPE (node)) == POINTER_TYPE)
|
||||
if (TREE_CODE (ref_type) == POINTER_TYPE)
|
||||
{
|
||||
if (package_prefix)
|
||||
{
|
||||
|
@ -2251,7 +2243,7 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
|
|||
|
||||
if (!package_prefix)
|
||||
pp_string (buffer, "access");
|
||||
else if (AGGREGATE_TYPE_P (TREE_TYPE (node)))
|
||||
else if (AGGREGATE_TYPE_P (ref_type))
|
||||
{
|
||||
if (!type || TREE_CODE (type) != FUNCTION_DECL)
|
||||
{
|
||||
|
@ -2281,12 +2273,41 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
|
|||
pp_string (buffer, "all ");
|
||||
}
|
||||
|
||||
if (RECORD_OR_UNION_TYPE_P (TREE_TYPE (node)) && type_name)
|
||||
dump_ada_node (buffer, type_name, TREE_TYPE (node), spc,
|
||||
is_access, true);
|
||||
else
|
||||
dump_ada_node (buffer, TREE_TYPE (node), TREE_TYPE (node),
|
||||
spc, false, true);
|
||||
/* If this is the anonymous original type of a typedef'ed
|
||||
type, then use the name of the latter. */
|
||||
if (!type_name
|
||||
&& stub
|
||||
&& DECL_CHAIN (stub)
|
||||
&& TREE_CODE (DECL_CHAIN (stub)) == TYPE_DECL
|
||||
&& DECL_ORIGINAL_TYPE (DECL_CHAIN (stub)) == ref_type)
|
||||
ref_type = TREE_TYPE (DECL_CHAIN (stub));
|
||||
|
||||
/* Generate "access <type>" instead of "access <subtype>"
|
||||
if the subtype comes from another file, because subtype
|
||||
declarations do not contribute to the limited view of a
|
||||
package and thus subtypes cannot be referenced through
|
||||
a limited_with clause. */
|
||||
else if (is_access)
|
||||
while (type_name
|
||||
&& TREE_CODE (type_name) == TYPE_DECL
|
||||
&& DECL_ORIGINAL_TYPE (type_name)
|
||||
&& TYPE_NAME (DECL_ORIGINAL_TYPE (type_name)))
|
||||
{
|
||||
const expanded_location xloc
|
||||
= expand_location (decl_sloc (type_name, false));
|
||||
if (xloc.line
|
||||
&& xloc.file
|
||||
&& xloc.file != current_source_file)
|
||||
{
|
||||
ref_type = DECL_ORIGINAL_TYPE (type_name);
|
||||
type_name = TYPE_NAME (ref_type);
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
dump_ada_node (buffer, ref_type, ref_type, spc, is_access,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -2361,10 +2382,8 @@ dump_ada_node (pretty_printer *buffer, tree node, tree type, int spc,
|
|||
else
|
||||
pp_string (buffer, "address");
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (name_only)
|
||||
else if (name_only)
|
||||
dump_ada_decl_name (buffer, node, limited_access);
|
||||
else
|
||||
{
|
||||
|
|
|
@ -1300,7 +1300,7 @@ conversion_warning (location_t loc, tree type, tree expr, tree result)
|
|||
tree op1 = TREE_OPERAND (expr, 1);
|
||||
tree op2 = TREE_OPERAND (expr, 2);
|
||||
|
||||
return (conversion_warning (loc, type, op1, result)
|
||||
return ((op1 && conversion_warning (loc, type, op1, result))
|
||||
|| conversion_warning (loc, type, op2, result));
|
||||
}
|
||||
|
||||
|
|
|
@ -342,10 +342,6 @@ Wno-alloca-larger-than
|
|||
C ObjC C++ LTO ObjC++ Alias(Walloca-larger-than=,18446744073709551615EiB,none) Warning
|
||||
Disable Walloca-larger-than= warning. Equivalent to Walloca-larger-than=<SIZE_MAX> or larger.
|
||||
|
||||
Warray-bounds
|
||||
LangEnabledBy(C ObjC C++ LTO ObjC++)
|
||||
; in common.opt
|
||||
|
||||
Warray-bounds=
|
||||
LangEnabledBy(C ObjC C++ LTO ObjC++,Wall,1,0)
|
||||
; in common.opt
|
||||
|
@ -463,23 +459,23 @@ C++ ObjC++ Var(warn_cxx20_compat) Warning LangEnabledBy(C++ ObjC++,Wall)
|
|||
Warn about C++ constructs whose meaning differs between ISO C++ 2017 and ISO C++ 2020.
|
||||
|
||||
Wc++11-extensions
|
||||
C++ ObjC++ Var(warn_cxx11_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1)
|
||||
C++ ObjC++ Var(warn_cxx11_extensions) Warning Init(1)
|
||||
Warn about C++11 constructs in code compiled with an older standard.
|
||||
|
||||
Wc++14-extensions
|
||||
C++ ObjC++ Var(warn_cxx14_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1)
|
||||
C++ ObjC++ Var(warn_cxx14_extensions) Warning Init(1)
|
||||
Warn about C++14 constructs in code compiled with an older standard.
|
||||
|
||||
Wc++17-extensions
|
||||
C++ ObjC++ Var(warn_cxx17_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1)
|
||||
C++ ObjC++ Var(warn_cxx17_extensions) Warning Init(1)
|
||||
Warn about C++17 constructs in code compiled with an older standard.
|
||||
|
||||
Wc++20-extensions
|
||||
C++ ObjC++ Var(warn_cxx20_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1)
|
||||
C++ ObjC++ Var(warn_cxx20_extensions) Warning Init(1)
|
||||
Warn about C++20 constructs in code compiled with an older standard.
|
||||
|
||||
Wc++23-extensions
|
||||
C++ ObjC++ Var(warn_cxx23_extensions) Warning LangEnabledBy(C++ ObjC++) Init(1)
|
||||
C++ ObjC++ Var(warn_cxx23_extensions) Warning Init(1)
|
||||
Warn about C++23 constructs in code compiled with an older standard.
|
||||
|
||||
Wcast-function-type
|
||||
|
@ -1377,13 +1373,9 @@ Wunused-const-variable=
|
|||
C ObjC C++ ObjC++ Joined RejectNegative UInteger Var(warn_unused_const_variable) Warning LangEnabledBy(C ObjC,Wunused-variable, 1, 0) IntegerRange(0, 2)
|
||||
Warn when a const variable is unused.
|
||||
|
||||
# Defining these options here in addition to common.opt is necessary
|
||||
# in order for the default -Wall setting of -Wuse-after-free=2 to take
|
||||
# effect.
|
||||
|
||||
Wuse-after-free
|
||||
LangEnabledBy(C ObjC C++ LTO ObjC++)
|
||||
; in common.opt
|
||||
; Defining this option here in addition to common.opt is necessary
|
||||
; in order for the default -Wall setting of -Wuse-after-free=2 to take
|
||||
; effect.
|
||||
|
||||
Wuse-after-free=
|
||||
LangEnabledBy(C ObjC C++ LTO ObjC++, Wall,2,0)
|
||||
|
|
|
@ -201,7 +201,8 @@ mark_stack_region_used (poly_uint64 lower_bound, poly_uint64 upper_bound)
|
|||
{
|
||||
unsigned HOST_WIDE_INT const_lower, const_upper;
|
||||
const_lower = constant_lower_bound (lower_bound);
|
||||
if (upper_bound.is_constant (&const_upper))
|
||||
if (upper_bound.is_constant (&const_upper)
|
||||
&& const_upper <= highest_outgoing_arg_in_use)
|
||||
for (unsigned HOST_WIDE_INT i = const_lower; i < const_upper; ++i)
|
||||
stack_usage_map[i] = 1;
|
||||
else
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
/* Common hooks for LoongArch.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
|
||||
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/>. */
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "common/common-target.h"
|
||||
#include "common/common-target-def.h"
|
||||
#include "opts.h"
|
||||
#include "flags.h"
|
||||
#include "diagnostic-core.h"
|
||||
|
||||
#undef TARGET_OPTION_OPTIMIZATION_TABLE
|
||||
#define TARGET_OPTION_OPTIMIZATION_TABLE loongarch_option_optimization_table
|
||||
|
||||
/* Set default optimization options. */
|
||||
static const struct default_options loongarch_option_optimization_table[] =
|
||||
{
|
||||
{ OPT_LEVELS_ALL, OPT_fasynchronous_unwind_tables, NULL, 1 },
|
||||
{ OPT_LEVELS_NONE, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
#undef TARGET_DEFAULT_TARGET_FLAGS
|
||||
#define TARGET_DEFAULT_TARGET_FLAGS MASK_CHECK_ZERO_DIV
|
||||
|
||||
struct gcc_targetm_common targetm_common = TARGETM_COMMON_INITIALIZER;
|
435
gcc/config.gcc
435
gcc/config.gcc
|
@ -454,6 +454,13 @@ mips*-*-*)
|
|||
extra_objs="frame-header-opt.o"
|
||||
extra_options="${extra_options} g.opt fused-madd.opt mips/mips-tables.opt"
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
cpu_type=loongarch
|
||||
extra_headers="larchintrin.h"
|
||||
extra_objs="loongarch-c.o loongarch-builtins.o loongarch-cpu.o loongarch-opts.o loongarch-def.o"
|
||||
extra_gcc_objs="loongarch-driver.o loongarch-cpu.o loongarch-opts.o loongarch-def.o"
|
||||
extra_options="${extra_options} g.opt fused-madd.opt"
|
||||
;;
|
||||
nds32*)
|
||||
cpu_type=nds32
|
||||
extra_headers="nds32_intrinsic.h nds32_isr.h nds32_init.inc"
|
||||
|
@ -2495,6 +2502,20 @@ riscv*-*-freebsd*)
|
|||
# automatically detect that GAS supports it, yet we require it.
|
||||
gcc_cv_initfini_array=yes
|
||||
;;
|
||||
|
||||
loongarch*-*-linux*)
|
||||
tm_file="dbxelf.h elfos.h gnu-user.h linux.h linux-android.h glibc-stdint.h ${tm_file}"
|
||||
tm_file="${tm_file} loongarch/gnu-user.h loongarch/linux.h"
|
||||
extra_options="${extra_options} linux-android.opt"
|
||||
tmake_file="${tmake_file} loongarch/t-linux"
|
||||
gnu_ld=yes
|
||||
gas=yes
|
||||
|
||||
# Force .init_array support. The configure script cannot always
|
||||
# automatically detect that GAS supports it, yet we require it.
|
||||
gcc_cv_initfini_array=yes
|
||||
;;
|
||||
|
||||
mips*-*-netbsd*) # NetBSD/mips, either endian.
|
||||
target_cpu_default="MASK_ABICALLS"
|
||||
tm_file="elfos.h ${tm_file} mips/elf.h ${nbsd_tm_file} mips/netbsd.h"
|
||||
|
@ -3601,7 +3622,7 @@ case ${target} in
|
|||
;;
|
||||
*-*-linux* | *-*-gnu*)
|
||||
case ${target} in
|
||||
aarch64*-* | arm*-* | i[34567]86-* | powerpc*-* | s390*-* | sparc*-* | x86_64-*)
|
||||
aarch64*-* | arm*-* | i[34567]86-* | powerpc*-* | s390*-* | sparc*-* | x86_64-* | loongarch*-*)
|
||||
default_gnu_indirect_function=yes
|
||||
;;
|
||||
esac
|
||||
|
@ -4933,6 +4954,373 @@ case "${target}" in
|
|||
esac
|
||||
;;
|
||||
|
||||
loongarch*-*-*)
|
||||
supported_defaults="abi arch tune fpu"
|
||||
|
||||
# Local variables
|
||||
unset \
|
||||
abi_pattern abi_default \
|
||||
abiext_pattern abiext_default \
|
||||
arch_pattern arch_default \
|
||||
fpu_pattern fpu_default \
|
||||
tune_pattern tune_default \
|
||||
triplet_os triplet_abi
|
||||
|
||||
# Infer ABI from the triplet.
|
||||
case ${target} in
|
||||
loongarch64-*-*-*f64)
|
||||
abi_pattern="lp64d"
|
||||
triplet_abi="f64"
|
||||
;;
|
||||
loongarch64-*-*-*f32)
|
||||
abi_pattern="lp64f"
|
||||
triplet_abi="f32"
|
||||
;;
|
||||
loongarch64-*-*-*sf)
|
||||
abi_pattern="lp64s"
|
||||
triplet_abi="sf"
|
||||
;;
|
||||
loongarch64-*-*-*)
|
||||
abi_pattern="lp64[dfs]"
|
||||
abi_default="lp64d"
|
||||
triplet_abi=""
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported target ${target}." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
abiext_pattern="*"
|
||||
abiext_default="base"
|
||||
|
||||
# Get the canonical triplet (multiarch specifier).
|
||||
case ${target} in
|
||||
*-linux-gnu*) triplet_os="linux-gnu";;
|
||||
*-linux-musl*) triplet_os="linux-musl";;
|
||||
*)
|
||||
echo "Unsupported target ${target}." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
la_canonical_triplet="loongarch64-${triplet_os}${triplet_abi}"
|
||||
|
||||
|
||||
# Perform initial sanity checks on --with-* options.
|
||||
case ${with_arch} in
|
||||
"" | loongarch64 | la464) ;; # OK, append here.
|
||||
native)
|
||||
if test x${host} != x${target}; then
|
||||
echo "--with-arch=native is illegal for cross-compiler." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
"")
|
||||
echo "Please set a default value for \${with_arch}" \
|
||||
"according to your target triplet \"${target}\"." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Unknown arch in --with-arch=$with_arch" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case ${with_abi} in
|
||||
"" | lp64d | lp64f | lp64s) ;; # OK, append here.
|
||||
*)
|
||||
echo "Unsupported ABI given in --with-abi=$with_abi" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case ${with_abiext} in
|
||||
"" | base) ;; # OK, append here.
|
||||
*)
|
||||
echo "Unsupported ABI extention type $with_abiext" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
case ${with_fpu} in
|
||||
"" | none | 32 | 64) ;; # OK, append here.
|
||||
0)
|
||||
# Convert "0" to "none" for upcoming checks.
|
||||
with_fpu="none"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown fpu type in --with-fpu=$with_fpu" 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Set default value for with_abi.
|
||||
case ${with_abi} in
|
||||
"")
|
||||
if test x${abi_default} != x; then
|
||||
with_abi=${abi_default}
|
||||
else
|
||||
with_abi=${abi_pattern}
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if echo "${with_abi}" | grep -E "^${abi_pattern}$" > /dev/null; then
|
||||
: # OK
|
||||
else
|
||||
echo "Incompatible options:" \
|
||||
"--with-abi=${with_abi} and --target=${target}." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Set default value for with_abiext (internal)
|
||||
case ${with_abiext} in
|
||||
"")
|
||||
if test x${abiext_default} != x; then
|
||||
with_abiext=${abiext_default}
|
||||
else
|
||||
with_abiext=${abiext_pattern}
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if echo "${with_abiext}" | grep -E "^${abiext_pattern}$" > /dev/null; then
|
||||
: # OK
|
||||
else
|
||||
echo "The ABI extension type \"${with_abiext}\"" \
|
||||
"is incompatible with --target=${target}." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
;;
|
||||
esac
|
||||
|
||||
# Infer ISA-related default options from the ABI: pass 1
|
||||
case ${with_abi}/${with_abiext} in
|
||||
lp64*/base)
|
||||
# architectures that support lp64* ABI
|
||||
arch_pattern="native|loongarch64|la464"
|
||||
# default architecture for lp64* ABI
|
||||
arch_default="loongarch64"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
# Infer ISA-related default options from the ABI: pass 2
|
||||
case ${with_abi}/${with_abiext} in
|
||||
lp64d/base)
|
||||
fpu_pattern="64"
|
||||
;;
|
||||
lp64f/base)
|
||||
fpu_pattern="32|64"
|
||||
fpu_default="32"
|
||||
;;
|
||||
lp64s/base)
|
||||
fpu_pattern="none|32|64"
|
||||
fpu_default="none"
|
||||
;;
|
||||
*)
|
||||
echo "Unsupported ABI type ${with_abi}/${with_abiext}." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
## Set default value for with_arch.
|
||||
case ${with_arch} in
|
||||
"")
|
||||
if test x${arch_default} != x; then
|
||||
with_arch=${arch_default}
|
||||
else
|
||||
with_arch=${arch_pattern}
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if echo "${with_arch}" | grep -E "^${arch_pattern}$" > /dev/null; then
|
||||
: # OK
|
||||
else
|
||||
echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \
|
||||
"--with-arch=${with_arch}." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
## Set default value for with_fpu.
|
||||
case ${with_fpu} in
|
||||
"")
|
||||
if test x${fpu_default} != x; then
|
||||
with_fpu=${fpu_default}
|
||||
else
|
||||
with_fpu=${fpu_pattern}
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if echo "${with_fpu}" | grep -E "^${fpu_pattern}$" > /dev/null; then
|
||||
: # OK
|
||||
else
|
||||
echo "${with_abi}/${with_abiext} ABI cannot be implemented with" \
|
||||
"--with-fpu=${with_fpu}." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
|
||||
# Infer default with_tune from with_arch: pass 1
|
||||
case ${with_arch} in
|
||||
native)
|
||||
tune_pattern="*"
|
||||
tune_default="native"
|
||||
;;
|
||||
loongarch64)
|
||||
tune_pattern="loongarch64|la464"
|
||||
tune_default="la464"
|
||||
;;
|
||||
*)
|
||||
# By default, $with_tune == $with_arch
|
||||
tune_pattern="$with_arch"
|
||||
;;
|
||||
esac
|
||||
|
||||
## Set default value for with_tune.
|
||||
case ${with_tune} in
|
||||
"")
|
||||
if test x${tune_default} != x; then
|
||||
with_tune=${tune_default}
|
||||
else
|
||||
with_tune=${tune_pattern}
|
||||
fi
|
||||
;;
|
||||
|
||||
*)
|
||||
if echo "${with_tune}" | grep -E "^${tune_pattern}$" > /dev/null; then
|
||||
: # OK
|
||||
else
|
||||
echo "Incompatible options: --with-tune=${with_tune}" \
|
||||
"and --with-arch=${with_arch}." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
esac
|
||||
|
||||
# Handle --with-multilib-list.
|
||||
if test x"${with_multilib_list}" = x \
|
||||
|| test x"${with_multilib_list}" = xno \
|
||||
|| test x"${with_multilib_list}" = xdefault \
|
||||
|| test x"${enable_multilib}" != xyes; then
|
||||
|
||||
with_multilib_list="${with_abi}/${with_abiext}"
|
||||
fi
|
||||
|
||||
# Check if the configured default ABI combination is included in
|
||||
# ${with_multilib_list}.
|
||||
loongarch_multilib_list_sane=no
|
||||
|
||||
# This one goes to TM_MULTILIB_CONFIG, for use in t-linux.
|
||||
loongarch_multilib_list_make=""
|
||||
|
||||
# This one goes to tm_defines, for use in loongarch-driver.c.
|
||||
loongarch_multilib_list_c=""
|
||||
|
||||
# ${with_multilib_list} should not contain whitespaces,
|
||||
# consecutive commas or slashes.
|
||||
if echo "${with_multilib_list}" \
|
||||
| grep -E -e "[[:space:]]" -e '[,/][,/]' -e '[,/]$' -e '^[,/]' > /dev/null; then
|
||||
echo "Invalid argument to --with-multilib-list." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
unset component idx elem_abi_base elem_abi_ext elem_tmp
|
||||
for elem in $(echo "${with_multilib_list}" | tr ',' ' '); do
|
||||
idx=0
|
||||
while true; do
|
||||
idx=$((idx + 1))
|
||||
component=$(echo "${elem}" | awk -F'/' '{print $'"${idx}"'}')
|
||||
|
||||
case ${idx} in
|
||||
1)
|
||||
# Component 1: Base ABI type
|
||||
case ${component} in
|
||||
lp64d) elem_tmp="ABI_BASE_LP64D,";;
|
||||
lp64f) elem_tmp="ABI_BASE_LP64F,";;
|
||||
lp64s) elem_tmp="ABI_BASE_LP64S,";;
|
||||
*)
|
||||
echo "Unknown base ABI \"${component}\" in --with-multilib-list." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}"
|
||||
loongarch_multilib_list_make="${loongarch_multilib_list_make}mabi=${component}"
|
||||
elem_abi_base="${component}"
|
||||
;;
|
||||
|
||||
2)
|
||||
# Component 2: ABI extension type
|
||||
case ${component} in
|
||||
"" | base)
|
||||
component="base"
|
||||
elem_tmp="ABI_EXT_BASE,"
|
||||
;;
|
||||
*)
|
||||
echo "Unknown ABI extension \"${component}\" in --with-multilib-list." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
loongarch_multilib_list_c="${loongarch_multilib_list_c}${elem_tmp}"
|
||||
loongarch_multilib_list_make="${loongarch_multilib_list_make}" # Add nothing for now.
|
||||
elem_abi_ext="${component}"
|
||||
;;
|
||||
|
||||
*)
|
||||
# Component 3 and on: optional stuff
|
||||
case ${component} in
|
||||
"")
|
||||
# End of component list.
|
||||
break
|
||||
;;
|
||||
*)
|
||||
echo "Unknown ABI \"${elem}\" in --with-multilib-list." 1>&2
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
if test x${elem_abi_base} = x${with_abi} \
|
||||
&& test x${elem_abi_ext} = x${with_abiext}; then
|
||||
loongarch_multilib_list_sane=yes
|
||||
fi
|
||||
loongarch_multilib_list_make="${loongarch_multilib_list_make},"
|
||||
done
|
||||
|
||||
# Check if the default ABI combination is in the default list.
|
||||
if test x${loongarch_multilib_list_sane} = xno; then
|
||||
if test x${with_abiext} = xbase; then
|
||||
with_abiext=""
|
||||
else
|
||||
with_abiext="/${with_abiext}"
|
||||
fi
|
||||
|
||||
echo "Default ABI combination (${with_abi}${with_abiext})" \
|
||||
"not found in --with-multilib-list." 1>&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Remove the excessive appending comma.
|
||||
loongarch_multilib_list_c=${loongarch_multilib_list_c%,}
|
||||
loongarch_multilib_list_make=${loongarch_multilib_list_make%,}
|
||||
;;
|
||||
|
||||
nds32*-*-*)
|
||||
supported_defaults="arch cpu nds32_lib float fpu_config"
|
||||
|
||||
|
@ -5370,6 +5758,51 @@ case ${target} in
|
|||
tmake_file="mips/t-mips $tmake_file"
|
||||
;;
|
||||
|
||||
loongarch*-*-*)
|
||||
# Export canonical triplet.
|
||||
tm_defines="${tm_defines} LA_MULTIARCH_TRIPLET=${la_canonical_triplet}"
|
||||
|
||||
# Define macro LA_DISABLE_MULTILIB if --disable-multilib
|
||||
tm_defines="${tm_defines} TM_MULTILIB_LIST=${loongarch_multilib_list_c}"
|
||||
if test x$enable_multilib = xyes; then
|
||||
TM_MULTILIB_CONFIG="${loongarch_multilib_list_make}"
|
||||
else
|
||||
tm_defines="${tm_defines} LA_DISABLE_MULTILIB"
|
||||
fi
|
||||
|
||||
# Let --with- flags initialize the enum variables from loongarch.opt.
|
||||
# See macro definitions from loongarch-opts.h and loongarch-cpu.h.
|
||||
case ${with_arch} in
|
||||
native) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_NATIVE" ;;
|
||||
la464) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LA464" ;;
|
||||
loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_ARCH=CPU_LOONGARCH64" ;;
|
||||
esac
|
||||
|
||||
case ${with_tune} in
|
||||
native) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_NATIVE" ;;
|
||||
la464) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LA464" ;;
|
||||
loongarch64) tm_defines="${tm_defines} DEFAULT_CPU_TUNE=CPU_LOONGARCH64" ;;
|
||||
esac
|
||||
|
||||
case ${with_abi} in
|
||||
lp64d) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64D" ;;
|
||||
lp64f) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64F" ;;
|
||||
lp64s) tm_defines="${tm_defines} DEFAULT_ABI_BASE=ABI_BASE_LP64S" ;;
|
||||
esac
|
||||
|
||||
case ${with_abiext} in
|
||||
base) tm_defines="${tm_defines} DEFAULT_ABI_EXT=ABI_EXT_BASE" ;;
|
||||
esac
|
||||
|
||||
case ${with_fpu} in
|
||||
none) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_NOFPU" ;;
|
||||
32) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU32" ;;
|
||||
64) tm_defines="$tm_defines DEFAULT_ISA_EXT_FPU=ISA_EXT_FPU64" ;;
|
||||
esac
|
||||
|
||||
tmake_file="loongarch/t-loongarch $tmake_file"
|
||||
;;
|
||||
|
||||
powerpc*-*-* | rs6000-*-*)
|
||||
# FIXME: The PowerPC port uses the value set at compile time,
|
||||
# although it's only cosmetic.
|
||||
|
|
|
@ -145,9 +145,6 @@ AARCH64_CORE("neoverse-512tvb", neoverse512tvb, cortexa57, 8_4A, AARCH64_FL_FOR
|
|||
/* Qualcomm ('Q') cores. */
|
||||
AARCH64_CORE("saphira", saphira, saphira, 8_4A, AARCH64_FL_FOR_ARCH8_4 | AARCH64_FL_CRYPTO | AARCH64_FL_RCPC, saphira, 0x51, 0xC01, -1)
|
||||
|
||||
/* Armv8.5-A Architecture Processors. */
|
||||
AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 8_5A, AARCH64_FL_FOR_ARCH8_5 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_F16 | AARCH64_FL_SVE | AARCH64_FL_SVE2 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG, neoversen2, 0x41, 0xd49, -1)
|
||||
|
||||
/* ARMv8-A big.LITTLE implementations. */
|
||||
|
||||
AARCH64_CORE("cortex-a57.cortex-a53", cortexa57cortexa53, cortexa53, 8A, AARCH64_FL_FOR_ARCH8 | AARCH64_FL_CRC, cortexa57, 0x41, AARCH64_BIG_LITTLE (0xd07, 0xd03), -1)
|
||||
|
@ -172,6 +169,8 @@ AARCH64_CORE("cortex-a710", cortexa710, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 |
|
|||
|
||||
AARCH64_CORE("cortex-x2", cortexx2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_MEMTAG | AARCH64_FL_I8MM | AARCH64_FL_BF16, neoversen2, 0x41, 0xd48, -1)
|
||||
|
||||
AARCH64_CORE("neoverse-n2", neoversen2, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, neoversen2, 0x41, 0xd49, -1)
|
||||
|
||||
AARCH64_CORE("demeter", demeter, cortexa57, 9A, AARCH64_FL_FOR_ARCH9 | AARCH64_FL_I8MM | AARCH64_FL_BF16 | AARCH64_FL_SVE2_BITPERM | AARCH64_FL_RNG | AARCH64_FL_MEMTAG | AARCH64_FL_PROFILE, demeter, 0x41, 0xd4f, -1)
|
||||
|
||||
#undef AARCH64_CORE
|
||||
|
|
|
@ -15637,11 +15637,16 @@ private:
|
|||
unsigned int adjust_body_cost (loop_vec_info, const aarch64_vector_costs *,
|
||||
unsigned int);
|
||||
bool prefer_unrolled_loop () const;
|
||||
unsigned int determine_suggested_unroll_factor ();
|
||||
|
||||
/* True if we have performed one-time initialization based on the
|
||||
vec_info. */
|
||||
bool m_analyzed_vinfo = false;
|
||||
|
||||
/* This loop uses an average operation that is not supported by SVE, but is
|
||||
supported by Advanced SIMD and SVE2. */
|
||||
bool m_has_avg = false;
|
||||
|
||||
/* - If M_VEC_FLAGS is zero then we're costing the original scalar code.
|
||||
- If M_VEC_FLAGS & VEC_ADVSIMD is nonzero then we're costing Advanced
|
||||
SIMD code.
|
||||
|
@ -16642,6 +16647,21 @@ aarch64_vector_costs::add_stmt_cost (int count, vect_cost_for_stmt kind,
|
|||
as one iteration of the SVE loop. */
|
||||
if (where == vect_body && m_unrolled_advsimd_niters)
|
||||
m_unrolled_advsimd_stmts += count * m_unrolled_advsimd_niters;
|
||||
|
||||
/* Detect the use of an averaging operation. */
|
||||
gimple *stmt = stmt_info->stmt;
|
||||
if (is_gimple_call (stmt)
|
||||
&& gimple_call_internal_p (stmt))
|
||||
{
|
||||
switch (gimple_call_internal_fn (stmt))
|
||||
{
|
||||
case IFN_AVG_FLOOR:
|
||||
case IFN_AVG_CEIL:
|
||||
m_has_avg = true;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return record_stmt_cost (stmt_info, where, (count * stmt_cost).ceil ());
|
||||
}
|
||||
|
@ -16725,6 +16745,68 @@ adjust_body_cost_sve (const aarch64_vec_op_count *ops,
|
|||
return sve_cycles_per_iter;
|
||||
}
|
||||
|
||||
unsigned int
|
||||
aarch64_vector_costs::determine_suggested_unroll_factor ()
|
||||
{
|
||||
bool sve = m_vec_flags & VEC_ANY_SVE;
|
||||
/* If we are trying to unroll an Advanced SIMD main loop that contains
|
||||
an averaging operation that we do not support with SVE and we might use a
|
||||
predicated epilogue, we need to be conservative and block unrolling as
|
||||
this might lead to a less optimal loop for the first and only epilogue
|
||||
using the original loop's vectorization factor.
|
||||
TODO: Remove this constraint when we add support for multiple epilogue
|
||||
vectorization. */
|
||||
if (!sve && !TARGET_SVE2 && m_has_avg)
|
||||
return 1;
|
||||
|
||||
unsigned int max_unroll_factor = 1;
|
||||
for (auto vec_ops : m_ops)
|
||||
{
|
||||
aarch64_simd_vec_issue_info const *vec_issue
|
||||
= vec_ops.simd_issue_info ();
|
||||
if (!vec_issue)
|
||||
return 1;
|
||||
/* Limit unroll factor to a value adjustable by the user, the default
|
||||
value is 4. */
|
||||
unsigned int unroll_factor = aarch64_vect_unroll_limit;
|
||||
unsigned int factor
|
||||
= vec_ops.reduction_latency > 1 ? vec_ops.reduction_latency : 1;
|
||||
unsigned int temp;
|
||||
|
||||
/* Sanity check, this should never happen. */
|
||||
if ((vec_ops.stores + vec_ops.loads + vec_ops.general_ops) == 0)
|
||||
return 1;
|
||||
|
||||
/* Check stores. */
|
||||
if (vec_ops.stores > 0)
|
||||
{
|
||||
temp = CEIL (factor * vec_issue->stores_per_cycle,
|
||||
vec_ops.stores);
|
||||
unroll_factor = MIN (unroll_factor, temp);
|
||||
}
|
||||
|
||||
/* Check loads + stores. */
|
||||
if (vec_ops.loads > 0)
|
||||
{
|
||||
temp = CEIL (factor * vec_issue->loads_stores_per_cycle,
|
||||
vec_ops.loads + vec_ops.stores);
|
||||
unroll_factor = MIN (unroll_factor, temp);
|
||||
}
|
||||
|
||||
/* Check general ops. */
|
||||
if (vec_ops.general_ops > 0)
|
||||
{
|
||||
temp = CEIL (factor * vec_issue->general_ops_per_cycle,
|
||||
vec_ops.general_ops);
|
||||
unroll_factor = MIN (unroll_factor, temp);
|
||||
}
|
||||
max_unroll_factor = MAX (max_unroll_factor, unroll_factor);
|
||||
}
|
||||
|
||||
/* Make sure unroll factor is power of 2. */
|
||||
return 1 << ceil_log2 (max_unroll_factor);
|
||||
}
|
||||
|
||||
/* BODY_COST is the cost of a vector loop body. Adjust the cost as necessary
|
||||
and return the new cost. */
|
||||
unsigned int
|
||||
|
@ -16861,8 +16943,11 @@ aarch64_vector_costs::finish_cost (const vector_costs *uncast_scalar_costs)
|
|||
if (loop_vinfo
|
||||
&& m_vec_flags
|
||||
&& aarch64_use_new_vector_costs_p ())
|
||||
m_costs[vect_body] = adjust_body_cost (loop_vinfo, scalar_costs,
|
||||
m_costs[vect_body]);
|
||||
{
|
||||
m_costs[vect_body] = adjust_body_cost (loop_vinfo, scalar_costs,
|
||||
m_costs[vect_body]);
|
||||
m_suggested_unroll_factor = determine_suggested_unroll_factor ();
|
||||
}
|
||||
|
||||
/* Apply the heuristic described above m_stp_sequence_cost. Prefer
|
||||
the scalar code in the event of a tie, since there is more chance
|
||||
|
@ -19917,6 +20002,7 @@ aarch64_member_type_forces_blk (const_tree field_or_array, machine_mode mode)
|
|||
a HFA or HVA. */
|
||||
const unsigned int WARN_PSABI_EMPTY_CXX17_BASE = 1U << 0;
|
||||
const unsigned int WARN_PSABI_NO_UNIQUE_ADDRESS = 1U << 1;
|
||||
const unsigned int WARN_PSABI_ZERO_WIDTH_BITFIELD = 1U << 2;
|
||||
|
||||
/* Walk down the type tree of TYPE counting consecutive base elements.
|
||||
If *MODEP is VOIDmode, then set it to the first valid floating point
|
||||
|
@ -20073,6 +20159,28 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
/* A zero-width bitfield may affect layout in some
|
||||
circumstances, but adds no members. The determination
|
||||
of whether or not a type is an HFA is performed after
|
||||
layout is complete, so if the type still looks like an
|
||||
HFA afterwards, it is still classed as one. This is
|
||||
potentially an ABI break for the hard-float ABI. */
|
||||
else if (DECL_BIT_FIELD (field)
|
||||
&& integer_zerop (DECL_SIZE (field)))
|
||||
{
|
||||
/* Prior to GCC-12 these fields were striped early,
|
||||
hiding them from the back-end entirely and
|
||||
resulting in the correct behaviour for argument
|
||||
passing. Simulate that old behaviour without
|
||||
generating a warning. */
|
||||
if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field))
|
||||
continue;
|
||||
if (warn_psabi_flags)
|
||||
{
|
||||
*warn_psabi_flags |= WARN_PSABI_ZERO_WIDTH_BITFIELD;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep,
|
||||
warn_psabi_flags);
|
||||
|
@ -20273,8 +20381,10 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
|
|||
&& ((alt = aapcs_vfp_sub_candidate (type, &new_mode, NULL))
|
||||
!= ag_count))
|
||||
{
|
||||
const char *url
|
||||
const char *url10
|
||||
= CHANGES_ROOT_URL "gcc-10/changes.html#empty_base";
|
||||
const char *url12
|
||||
= CHANGES_ROOT_URL "gcc-12/changes.html#zero_width_bitfields";
|
||||
gcc_assert (alt == -1);
|
||||
last_reported_type_uid = uid;
|
||||
/* Use TYPE_MAIN_VARIANT to strip any redundant const
|
||||
|
@ -20283,12 +20393,16 @@ aarch64_vfp_is_call_or_return_candidate (machine_mode mode,
|
|||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT with %<[[no_unique_address]]%> members "
|
||||
"changed %{in GCC 10.1%}",
|
||||
TYPE_MAIN_VARIANT (type), url);
|
||||
TYPE_MAIN_VARIANT (type), url10);
|
||||
else if (warn_psabi_flags & WARN_PSABI_EMPTY_CXX17_BASE)
|
||||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT when C++17 is enabled changed to match "
|
||||
"C++14 %{in GCC 10.1%}",
|
||||
TYPE_MAIN_VARIANT (type), url);
|
||||
TYPE_MAIN_VARIANT (type), url10);
|
||||
else if (warn_psabi_flags & WARN_PSABI_ZERO_WIDTH_BITFIELD)
|
||||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT changed %{in GCC 12.1%}",
|
||||
TYPE_MAIN_VARIANT (type), url12);
|
||||
}
|
||||
|
||||
if (is_ha != NULL) *is_ha = true;
|
||||
|
|
|
@ -292,3 +292,7 @@ Constant memmove size in bytes above which to start using MOPS sequence.
|
|||
-param=aarch64-mops-memset-size-threshold=
|
||||
Target Joined UInteger Var(aarch64_mops_memset_size_threshold) Init(256) Param
|
||||
Constant memset size in bytes from which to start using MOPS sequence.
|
||||
|
||||
-param=aarch64-vect-unroll-limit=
|
||||
Target Joined UInteger Var(aarch64_vect_unroll_limit) Init(4) Param
|
||||
Limit how much the autovectorizer may unroll a loop.
|
||||
|
|
|
@ -6194,7 +6194,7 @@ arm_pcs_from_attribute (tree attr)
|
|||
specification, DECL is the specific declartion. DECL may be null if
|
||||
the call could be indirect or if this is a library call. */
|
||||
static enum arm_pcs
|
||||
arm_get_pcs_model (const_tree type, const_tree decl)
|
||||
arm_get_pcs_model (const_tree type, const_tree decl ATTRIBUTE_UNUSED)
|
||||
{
|
||||
bool user_convention = false;
|
||||
enum arm_pcs user_pcs = arm_pcs_default;
|
||||
|
@ -6228,6 +6228,14 @@ arm_get_pcs_model (const_tree type, const_tree decl)
|
|||
return ARM_PCS_AAPCS;
|
||||
else if (user_convention)
|
||||
return user_pcs;
|
||||
#if 0
|
||||
/* Unfortunately, this is not safe and can lead to wrong code
|
||||
being generated (PR96882). Not all calls into the back-end
|
||||
pass the DECL, so it is unsafe to make any PCS-changing
|
||||
decisions based on it. In particular the RETURN_IN_MEMORY
|
||||
hook is only ever passed a TYPE. This needs revisiting to
|
||||
see if there are any partial improvements that can be
|
||||
re-enabled. */
|
||||
else if (decl && flag_unit_at_a_time)
|
||||
{
|
||||
/* Local functions never leak outside this compilation unit,
|
||||
|
@ -6239,6 +6247,7 @@ arm_get_pcs_model (const_tree type, const_tree decl)
|
|||
if (local_info_node && local_info_node->local)
|
||||
return ARM_PCS_AAPCS_LOCAL;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
else if (user_convention && user_pcs != arm_pcs_default)
|
||||
sorry ("PCS variant");
|
||||
|
@ -6274,6 +6283,7 @@ aapcs_vfp_cum_init (CUMULATIVE_ARGS *pcum ATTRIBUTE_UNUSED,
|
|||
a HFA or HVA. */
|
||||
const unsigned int WARN_PSABI_EMPTY_CXX17_BASE = 1U << 0;
|
||||
const unsigned int WARN_PSABI_NO_UNIQUE_ADDRESS = 1U << 1;
|
||||
const unsigned int WARN_PSABI_ZERO_WIDTH_BITFIELD = 1U << 2;
|
||||
|
||||
/* Walk down the type tree of TYPE counting consecutive base elements.
|
||||
If *MODEP is VOIDmode, then set it to the first valid floating point
|
||||
|
@ -6426,6 +6436,28 @@ aapcs_vfp_sub_candidate (const_tree type, machine_mode *modep,
|
|||
continue;
|
||||
}
|
||||
}
|
||||
/* A zero-width bitfield may affect layout in some
|
||||
circumstances, but adds no members. The determination
|
||||
of whether or not a type is an HFA is performed after
|
||||
layout is complete, so if the type still looks like an
|
||||
HFA afterwards, it is still classed as one. This is
|
||||
potentially an ABI break for the hard-float ABI. */
|
||||
else if (DECL_BIT_FIELD (field)
|
||||
&& integer_zerop (DECL_SIZE (field)))
|
||||
{
|
||||
/* Prior to GCC-12 these fields were striped early,
|
||||
hiding them from the back-end entirely and
|
||||
resulting in the correct behaviour for argument
|
||||
passing. Simulate that old behaviour without
|
||||
generating a warning. */
|
||||
if (DECL_FIELD_CXX_ZERO_WIDTH_BIT_FIELD (field))
|
||||
continue;
|
||||
if (warn_psabi_flags)
|
||||
{
|
||||
*warn_psabi_flags |= WARN_PSABI_ZERO_WIDTH_BITFIELD;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
sub_count = aapcs_vfp_sub_candidate (TREE_TYPE (field), modep,
|
||||
warn_psabi_flags);
|
||||
|
@ -6538,8 +6570,10 @@ aapcs_vfp_is_call_or_return_candidate (enum arm_pcs pcs_variant,
|
|||
&& ((alt = aapcs_vfp_sub_candidate (type, &new_mode, NULL))
|
||||
!= ag_count))
|
||||
{
|
||||
const char *url
|
||||
const char *url10
|
||||
= CHANGES_ROOT_URL "gcc-10/changes.html#empty_base";
|
||||
const char *url12
|
||||
= CHANGES_ROOT_URL "gcc-12/changes.html#zero_width_bitfields";
|
||||
gcc_assert (alt == -1);
|
||||
last_reported_type_uid = uid;
|
||||
/* Use TYPE_MAIN_VARIANT to strip any redundant const
|
||||
|
@ -6548,12 +6582,16 @@ aapcs_vfp_is_call_or_return_candidate (enum arm_pcs pcs_variant,
|
|||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT with %<[[no_unique_address]]%> members "
|
||||
"changed %{in GCC 10.1%}",
|
||||
TYPE_MAIN_VARIANT (type), url);
|
||||
TYPE_MAIN_VARIANT (type), url10);
|
||||
else if (warn_psabi_flags & WARN_PSABI_EMPTY_CXX17_BASE)
|
||||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT when C++17 is enabled changed to match "
|
||||
"C++14 %{in GCC 10.1%}",
|
||||
TYPE_MAIN_VARIANT (type), url);
|
||||
TYPE_MAIN_VARIANT (type), url10);
|
||||
else if (warn_psabi_flags & WARN_PSABI_ZERO_WIDTH_BITFIELD)
|
||||
inform (input_location, "parameter passing for argument of "
|
||||
"type %qT changed %{in GCC 12.1%}",
|
||||
TYPE_MAIN_VARIANT (type), url12);
|
||||
}
|
||||
*count = ag_count;
|
||||
}
|
||||
|
|
|
@ -535,26 +535,6 @@
|
|||
[(set_attr "type" "mve_move")
|
||||
])
|
||||
|
||||
(define_insn "mve_vec_unpack<US>_lo_<mode>"
|
||||
[(set (match_operand:<V_unpack> 0 "register_operand" "=w")
|
||||
(SE:<V_unpack> (vec_select:<V_HALF>
|
||||
(match_operand:MVE_3 1 "register_operand" "w")
|
||||
(match_operand:MVE_3 2 "vect_par_constant_low" ""))))]
|
||||
"TARGET_HAVE_MVE"
|
||||
"vmovlb.<US>%#<V_sz_elem> %q0, %q1"
|
||||
[(set_attr "type" "mve_move")]
|
||||
)
|
||||
|
||||
(define_insn "mve_vec_unpack<US>_hi_<mode>"
|
||||
[(set (match_operand:<V_unpack> 0 "register_operand" "=w")
|
||||
(SE:<V_unpack> (vec_select:<V_HALF>
|
||||
(match_operand:MVE_3 1 "register_operand" "w")
|
||||
(match_operand:MVE_3 2 "vect_par_constant_high" ""))))]
|
||||
"TARGET_HAVE_MVE"
|
||||
"vmovlt.<US>%#<V_sz_elem> %q0, %q1"
|
||||
[(set_attr "type" "mve_move")]
|
||||
)
|
||||
|
||||
;;
|
||||
;; [vcvtpq_s, vcvtpq_u])
|
||||
;;
|
||||
|
@ -2219,23 +2199,10 @@
|
|||
[(set_attr "type" "mve_move")
|
||||
])
|
||||
|
||||
;; vmovnb pattern used by the vec_pack_trunc expander to avoid the
|
||||
;; need for an uninitialized input operand.
|
||||
(define_insn "@mve_vec_pack_trunc_lo_<mode>"
|
||||
[
|
||||
(set (match_operand:<V_narrow_pack> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_narrow_pack> [(match_operand:MVE_5 1 "s_register_operand" "w")]
|
||||
VMOVNBQ_S))
|
||||
]
|
||||
"TARGET_HAVE_MVE"
|
||||
"vmovnb.i%#<V_sz_elem> %q0, %q1"
|
||||
[(set_attr "type" "mve_move")
|
||||
])
|
||||
|
||||
;;
|
||||
;; [vmovntq_s, vmovntq_u])
|
||||
;;
|
||||
(define_insn "@mve_vmovntq_<supf><mode>"
|
||||
(define_insn "mve_vmovntq_<supf><mode>"
|
||||
[
|
||||
(set (match_operand:<V_narrow_pack> 0 "s_register_operand" "=w")
|
||||
(unspec:<V_narrow_pack> [(match_operand:<V_narrow_pack> 1 "s_register_operand" "0")
|
||||
|
|
|
@ -6005,6 +6005,43 @@ if (BYTES_BIG_ENDIAN)
|
|||
[(set_attr "type" "neon_shift_imm_long")]
|
||||
)
|
||||
|
||||
(define_expand "vec_unpack<US>_hi_<mode>"
|
||||
[(match_operand:<V_unpack> 0 "register_operand")
|
||||
(SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
|
||||
"TARGET_NEON && !BYTES_BIG_ENDIAN"
|
||||
{
|
||||
rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
|
||||
rtx t1;
|
||||
int i;
|
||||
for (i = 0; i < (<V_mode_nunits>/2); i++)
|
||||
RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
|
||||
|
||||
t1 = gen_rtx_PARALLEL (<MODE>mode, v);
|
||||
emit_insn (gen_neon_vec_unpack<US>_hi_<mode> (operands[0],
|
||||
operands[1],
|
||||
t1));
|
||||
DONE;
|
||||
}
|
||||
)
|
||||
|
||||
(define_expand "vec_unpack<US>_lo_<mode>"
|
||||
[(match_operand:<V_unpack> 0 "register_operand")
|
||||
(SE:<V_unpack> (match_operand:VU 1 "register_operand"))]
|
||||
"TARGET_NEON && !BYTES_BIG_ENDIAN"
|
||||
{
|
||||
rtvec v = rtvec_alloc (<V_mode_nunits>/2) ;
|
||||
rtx t1;
|
||||
int i;
|
||||
for (i = 0; i < (<V_mode_nunits>/2) ; i++)
|
||||
RTVEC_ELT (v, i) = GEN_INT (i);
|
||||
t1 = gen_rtx_PARALLEL (<MODE>mode, v);
|
||||
emit_insn (gen_neon_vec_unpack<US>_lo_<mode> (operands[0],
|
||||
operands[1],
|
||||
t1));
|
||||
DONE;
|
||||
}
|
||||
)
|
||||
|
||||
(define_insn "neon_vec_<US>mult_lo_<mode>"
|
||||
[(set (match_operand:<V_unpack> 0 "register_operand" "=w")
|
||||
(mult:<V_unpack> (SE:<V_unpack> (vec_select:<V_HALF>
|
||||
|
@ -6220,7 +6257,7 @@ if (BYTES_BIG_ENDIAN)
|
|||
; because the ordering of vector elements in Q registers is different from what
|
||||
; the semantics of the instructions require.
|
||||
|
||||
(define_insn "neon_quad_vec_pack_trunc_<mode>"
|
||||
(define_insn "vec_pack_trunc_<mode>"
|
||||
[(set (match_operand:<V_narrow_pack> 0 "register_operand" "=&w")
|
||||
(vec_concat:<V_narrow_pack>
|
||||
(truncate:<V_narrow>
|
||||
|
|
|
@ -580,77 +580,6 @@
|
|||
"ARM_HAVE_<MODE>_ARITH
|
||||
&& !TARGET_REALLY_IWMMXT"
|
||||
)
|
||||
|
||||
;; vmovl[tb] are not available for V4SI on MVE
|
||||
(define_expand "vec_unpack<US>_hi_<mode>"
|
||||
[(set (match_operand:<V_unpack> 0 "register_operand")
|
||||
(SE:<V_unpack> (vec_select:<V_HALF>
|
||||
(match_operand:VU 1 "register_operand")
|
||||
(match_dup 2))))]
|
||||
"ARM_HAVE_<MODE>_ARITH
|
||||
&& !TARGET_REALLY_IWMMXT
|
||||
&& ! (<MODE>mode == V4SImode && TARGET_HAVE_MVE)
|
||||
&& !BYTES_BIG_ENDIAN"
|
||||
{
|
||||
rtvec v = rtvec_alloc (<V_mode_nunits>/2);
|
||||
int i;
|
||||
for (i = 0; i < (<V_mode_nunits>/2); i++)
|
||||
RTVEC_ELT (v, i) = GEN_INT ((<V_mode_nunits>/2) + i);
|
||||
|
||||
operands[2] = gen_rtx_PARALLEL (<MODE>mode, v);
|
||||
}
|
||||
)
|
||||
|
||||
;; vmovl[tb] are not available for V4SI on MVE
|
||||
(define_expand "vec_unpack<US>_lo_<mode>"
|
||||
[(set (match_operand:<V_unpack> 0 "register_operand")
|
||||
(SE:<V_unpack> (vec_select:<V_HALF>
|
||||
(match_operand:VU 1 "register_operand")
|
||||
(match_dup 2))))]
|
||||
"ARM_HAVE_<MODE>_ARITH
|
||||
&& !TARGET_REALLY_IWMMXT
|
||||
&& ! (<MODE>mode == V4SImode && TARGET_HAVE_MVE)
|
||||
&& !BYTES_BIG_ENDIAN"
|
||||
{
|
||||
rtvec v = rtvec_alloc (<V_mode_nunits>/2);
|
||||
int i;
|
||||
for (i = 0; i < (<V_mode_nunits>/2) ; i++)
|
||||
RTVEC_ELT (v, i) = GEN_INT (i);
|
||||
|
||||
operands[2] = gen_rtx_PARALLEL (<MODE>mode, v);
|
||||
|
||||
}
|
||||
)
|
||||
|
||||
;; vmovn[tb] are not available for V2DI on MVE
|
||||
(define_expand "vec_pack_trunc_<mode>"
|
||||
[(set (match_operand:<V_narrow_pack> 0 "register_operand")
|
||||
(vec_concat:<V_narrow_pack>
|
||||
(truncate:<V_narrow>
|
||||
(match_operand:VN 1 "register_operand"))
|
||||
(truncate:<V_narrow>
|
||||
(match_operand:VN 2 "register_operand"))))]
|
||||
"ARM_HAVE_<MODE>_ARITH
|
||||
&& !TARGET_REALLY_IWMMXT
|
||||
&& ! (<MODE>mode == V2DImode && TARGET_HAVE_MVE)
|
||||
&& !BYTES_BIG_ENDIAN"
|
||||
{
|
||||
if (TARGET_NEON)
|
||||
{
|
||||
emit_insn (gen_neon_quad_vec_pack_trunc_<mode> (operands[0], operands[1],
|
||||
operands[2]));
|
||||
}
|
||||
else
|
||||
{
|
||||
rtx tmpreg = gen_reg_rtx (<V_narrow_pack>mode);
|
||||
emit_insn (gen_mve_vec_pack_trunc_lo (<MODE>mode, tmpreg, operands[1]));
|
||||
emit_insn (gen_mve_vmovntq (VMOVNTQ_S, <MODE>mode,
|
||||
operands[0], tmpreg, operands[2]));
|
||||
}
|
||||
DONE;
|
||||
}
|
||||
)
|
||||
|
||||
(define_expand "vec_init<mode><V_elem_l>"
|
||||
[(match_operand:VDQX 0 "s_register_operand")
|
||||
(match_operand 1 "" "")]
|
||||
|
|
|
@ -98,6 +98,8 @@
|
|||
# define TRY_EMPTY_VM_SPACE 0x60000000
|
||||
#elif defined(__riscv) && defined (__LP64__)
|
||||
# define TRY_EMPTY_VM_SPACE 0x1000000000
|
||||
#elif defined(__loongarch__) && defined(__LP64__)
|
||||
# define TRY_EMPTY_VM_SPACE 0x8000000000
|
||||
#else
|
||||
# define TRY_EMPTY_VM_SPACE 0
|
||||
#endif
|
||||
|
|
|
@ -1785,7 +1785,12 @@ ix86_vectorize_builtin_gather (const_tree mem_vectype,
|
|||
bool si;
|
||||
enum ix86_builtins code;
|
||||
|
||||
if (! TARGET_AVX2 || !TARGET_USE_GATHER)
|
||||
if (! TARGET_AVX2
|
||||
|| (known_eq (TYPE_VECTOR_SUBPARTS (mem_vectype), 2u)
|
||||
? !TARGET_USE_GATHER_2PARTS
|
||||
: (known_eq (TYPE_VECTOR_SUBPARTS (mem_vectype), 4u)
|
||||
? !TARGET_USE_GATHER_4PARTS
|
||||
: !TARGET_USE_GATHER)))
|
||||
return NULL_TREE;
|
||||
|
||||
if ((TREE_CODE (index_type) != INTEGER_TYPE
|
||||
|
|
|
@ -390,6 +390,10 @@ extern unsigned char ix86_tune_features[X86_TUNE_LAST];
|
|||
ix86_tune_features[X86_TUNE_SLOW_PSHUFB]
|
||||
#define TARGET_AVOID_4BYTE_PREFIXES \
|
||||
ix86_tune_features[X86_TUNE_AVOID_4BYTE_PREFIXES]
|
||||
#define TARGET_USE_GATHER_2PARTS \
|
||||
ix86_tune_features[X86_TUNE_USE_GATHER_2PARTS]
|
||||
#define TARGET_USE_GATHER_4PARTS \
|
||||
ix86_tune_features[X86_TUNE_USE_GATHER_4PARTS]
|
||||
#define TARGET_USE_GATHER \
|
||||
ix86_tune_features[X86_TUNE_USE_GATHER]
|
||||
#define TARGET_FUSE_CMP_AND_BRANCH_32 \
|
||||
|
|
|
@ -10617,9 +10617,9 @@
|
|||
[(set (attr "isa")
|
||||
(cond [(eq_attr "alternative" "0,1,2")
|
||||
(const_string "avx512fp16")
|
||||
(eq_attr "alternative" "3")
|
||||
(eq_attr "alternative" "3,4")
|
||||
(const_string "noavx")
|
||||
(eq_attr "alternative" "4,5,6")
|
||||
(eq_attr "alternative" "5,6")
|
||||
(const_string "sse4_noavx")
|
||||
(eq_attr "alternative" "7,8,9")
|
||||
(const_string "avx")
|
||||
|
@ -20221,12 +20221,12 @@
|
|||
(set_attr "mode" "TI")])
|
||||
|
||||
(define_insn_and_split "ssse3_ph<plusminus_mnemonic>wv4hi3"
|
||||
[(set (match_operand:V4HI 0 "register_operand" "=y,x,Yv")
|
||||
[(set (match_operand:V4HI 0 "register_operand" "=y,x,x")
|
||||
(ssse3_plusminus:V4HI
|
||||
(vec_select:V4HI
|
||||
(vec_concat:V8HI
|
||||
(match_operand:V4HI 1 "register_operand" "0,0,Yv")
|
||||
(match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,Yv"))
|
||||
(match_operand:V4HI 1 "register_operand" "0,0,x")
|
||||
(match_operand:V4HI 2 "register_mmxmem_operand" "ym,x,x"))
|
||||
(parallel
|
||||
[(const_int 0) (const_int 2) (const_int 4) (const_int 6)]))
|
||||
(vec_select:V4HI
|
||||
|
@ -20308,12 +20308,12 @@
|
|||
(set_attr "mode" "TI")])
|
||||
|
||||
(define_insn_and_split "ssse3_ph<plusminus_mnemonic>dv2si3"
|
||||
[(set (match_operand:V2SI 0 "register_operand" "=y,x,Yv")
|
||||
[(set (match_operand:V2SI 0 "register_operand" "=y,x,x")
|
||||
(plusminus:V2SI
|
||||
(vec_select:V2SI
|
||||
(vec_concat:V4SI
|
||||
(match_operand:V2SI 1 "register_operand" "0,0,Yv")
|
||||
(match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,Yv"))
|
||||
(match_operand:V2SI 1 "register_operand" "0,0,x")
|
||||
(match_operand:V2SI 2 "register_mmxmem_operand" "ym,x,x"))
|
||||
(parallel [(const_int 0) (const_int 2)]))
|
||||
(vec_select:V2SI
|
||||
(vec_concat:V4SI (match_dup 1) (match_dup 2))
|
||||
|
@ -20758,13 +20758,13 @@
|
|||
})
|
||||
|
||||
(define_insn_and_split "*ssse3_pshufbv8qi3"
|
||||
[(set (match_operand:V8QI 0 "register_operand" "=y,x,Yv")
|
||||
(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0,0,Yv")
|
||||
(match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yv")
|
||||
[(set (match_operand:V8QI 0 "register_operand" "=y,x,Yw")
|
||||
(unspec:V8QI [(match_operand:V8QI 1 "register_operand" "0,0,Yw")
|
||||
(match_operand:V8QI 2 "register_mmxmem_operand" "ym,x,Yw")
|
||||
(match_operand:V4SI 4 "reg_or_const_vector_operand"
|
||||
"i,3,3")]
|
||||
UNSPEC_PSHUFB))
|
||||
(clobber (match_scratch:V4SI 3 "=X,&x,&Yv"))]
|
||||
(clobber (match_scratch:V4SI 3 "=X,&x,&Yw"))]
|
||||
"(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
|
||||
"@
|
||||
pshufb\t{%2, %0|%0, %2}
|
||||
|
@ -20811,10 +20811,10 @@
|
|||
(set_attr "mode" "<sseinsnmode>")])
|
||||
|
||||
(define_insn "ssse3_psign<mode>3"
|
||||
[(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,Yv")
|
||||
[(set (match_operand:MMXMODEI 0 "register_operand" "=y,x,x")
|
||||
(unspec:MMXMODEI
|
||||
[(match_operand:MMXMODEI 1 "register_operand" "0,0,Yv")
|
||||
(match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,Yv")]
|
||||
[(match_operand:MMXMODEI 1 "register_operand" "0,0,x")
|
||||
(match_operand:MMXMODEI 2 "register_mmxmem_operand" "ym,x,x")]
|
||||
UNSPEC_PSIGN))]
|
||||
"(TARGET_MMX || TARGET_MMX_WITH_SSE) && TARGET_SSSE3"
|
||||
"@
|
||||
|
@ -28364,8 +28364,8 @@
|
|||
|
||||
;; KEYLOCKER
|
||||
(define_insn "loadiwkey"
|
||||
[(unspec_volatile:V2DI [(match_operand:V2DI 0 "register_operand" "v")
|
||||
(match_operand:V2DI 1 "register_operand" "v")
|
||||
[(unspec_volatile:V2DI [(match_operand:V2DI 0 "register_operand" "x")
|
||||
(match_operand:V2DI 1 "register_operand" "x")
|
||||
(match_operand:V2DI 2 "register_operand" "Yz")
|
||||
(match_operand:SI 3 "register_operand" "a")]
|
||||
UNSPECV_LOADIWKEY)
|
||||
|
@ -28498,7 +28498,7 @@
|
|||
(UNSPECV_AESENC256KLU8 "enc256kl")])
|
||||
|
||||
(define_insn "aes<aesklvariant>u8"
|
||||
[(set (match_operand:V2DI 0 "register_operand" "=v")
|
||||
[(set (match_operand:V2DI 0 "register_operand" "=x")
|
||||
(unspec_volatile:V2DI [(match_operand:V2DI 1 "register_operand" "0")
|
||||
(match_operand:BLK 2 "memory_operand" "m")]
|
||||
AESDECENCKL))
|
||||
|
|
|
@ -464,7 +464,18 @@ DEF_TUNE (X86_TUNE_AVOID_4BYTE_PREFIXES, "avoid_4byte_prefixes",
|
|||
m_SILVERMONT | m_GOLDMONT | m_GOLDMONT_PLUS | m_TREMONT | m_ALDERLAKE
|
||||
| m_INTEL)
|
||||
|
||||
/* X86_TUNE_USE_GATHER: Use gather instructions. */
|
||||
/* X86_TUNE_USE_GATHER_2PARTS: Use gather instructions for vectors with 2
|
||||
elements. */
|
||||
DEF_TUNE (X86_TUNE_USE_GATHER_2PARTS, "use_gather_2parts",
|
||||
~(m_ZNVER1 | m_ZNVER2 | m_ZNVER3 | m_ALDERLAKE | m_GENERIC))
|
||||
|
||||
/* X86_TUNE_USE_GATHER_4PARTS: Use gather instructions for vectors with 4
|
||||
elements. */
|
||||
DEF_TUNE (X86_TUNE_USE_GATHER_4PARTS, "use_gather_4parts",
|
||||
~(m_ZNVER1 | m_ZNVER2 | m_ZNVER3 | m_ALDERLAKE | m_GENERIC))
|
||||
|
||||
/* X86_TUNE_USE_GATHER: Use gather instructions for vectors with 8 or more
|
||||
elements. */
|
||||
DEF_TUNE (X86_TUNE_USE_GATHER, "use_gather",
|
||||
~(m_ZNVER1 | m_ZNVER2 | m_ALDERLAKE | m_GENERIC))
|
||||
|
||||
|
|
|
@ -0,0 +1,202 @@
|
|||
;; Constraint definitions for LoongArch.
|
||||
;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;; Contributed by Loongson 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/>.
|
||||
|
||||
;; Register constraints
|
||||
|
||||
;; "a" "A constant call global and noplt address."
|
||||
;; "b" <-----unused
|
||||
;; "c" "A constant call local address."
|
||||
;; "d" <-----unused
|
||||
;; "e" JIRL_REGS
|
||||
;; "f" FP_REGS
|
||||
;; "g" <-----unused
|
||||
;; "h" "A constant call plt address."
|
||||
;; "i" "Matches a general integer constant." (Global non-architectural)
|
||||
;; "j" SIBCALL_REGS
|
||||
;; "k" "A memory operand whose address is formed by a base register and
|
||||
;; (optionally scaled) index register."
|
||||
;; "l" "A signed 16-bit constant."
|
||||
;; "m" "A memory operand whose address is formed by a base register and offset
|
||||
;; that is suitable for use in instructions with the same addressing mode
|
||||
;; as @code{st.w} and @code{ld.w}."
|
||||
;; "n" "Matches a non-symbolic integer constant." (Global non-architectural)
|
||||
;; "o" "Matches an offsettable memory reference." (Global non-architectural)
|
||||
;; "p" "Matches a general address." (Global non-architectural)
|
||||
;; "q" CSR_REGS
|
||||
;; "r" GENERAL_REGS (Global non-architectural)
|
||||
;; "s" "Matches a symbolic integer constant." (Global non-architectural)
|
||||
;; "t" "A constant call weak address"
|
||||
;; "u" "A signed 52bit constant and low 32-bit is zero (for logic instructions)"
|
||||
;; "v" "A signed 64-bit constant and low 44-bit is zero (for logic instructions)."
|
||||
;; "w" "Matches any valid memory."
|
||||
;; "x" <-----unused
|
||||
;; "y" <-----unused
|
||||
;; "z" FCC_REGS
|
||||
;; "A" <-----unused
|
||||
;; "B" <-----unused
|
||||
;; "C" <-----unused
|
||||
;; "D" <-----unused
|
||||
;; "E" "Matches a floating-point constant." (Global non-architectural)
|
||||
;; "F" "Matches a floating-point constant." (Global non-architectural)
|
||||
;; "G" "Floating-point zero."
|
||||
;; "H" <-----unused
|
||||
;; "I" "A signed 12-bit constant (for arithmetic instructions)."
|
||||
;; "J" "Integer zero."
|
||||
;; "K" "An unsigned 12-bit constant (for logic instructions)."
|
||||
;; "L" <-----unused
|
||||
;; "M" <-----unused
|
||||
;; "N" <-----unused
|
||||
;; "O" <-----unused
|
||||
;; "P" <-----unused
|
||||
;; "Q" <-----unused
|
||||
;; "R" <-----unused
|
||||
;; "S" <-----unused
|
||||
;; "T" <-----unused
|
||||
;; "U" <-----unused
|
||||
;; "V" "Matches a non-offsettable memory reference." (Global non-architectural)
|
||||
;; "W" <-----unused
|
||||
;; "X" "Matches anything." (Global non-architectural)
|
||||
;; "Y" -
|
||||
;; "Yd"
|
||||
;; "A constant @code{move_operand} that can be safely loaded using
|
||||
;; @code{la}."
|
||||
;; "Yx"
|
||||
;; "Z" -
|
||||
;; "ZC"
|
||||
;; "A memory operand whose address is formed by a base register and offset
|
||||
;; that is suitable for use in instructions with the same addressing mode
|
||||
;; as @code{ll.w} and @code{sc.w}."
|
||||
;; "ZB"
|
||||
;; "An address that is held in a general-purpose register.
|
||||
;; The offset is zero"
|
||||
;; "<" "Matches a pre-dec or post-dec operand." (Global non-architectural)
|
||||
;; ">" "Matches a pre-inc or post-inc operand." (Global non-architectural)
|
||||
|
||||
(define_constraint "a"
|
||||
"@internal
|
||||
A constant call global and noplt address."
|
||||
(match_operand 0 "is_const_call_global_noplt_symbol"))
|
||||
|
||||
(define_constraint "c"
|
||||
"@internal
|
||||
A constant call local address."
|
||||
(match_operand 0 "is_const_call_local_symbol"))
|
||||
|
||||
(define_register_constraint "e" "JIRL_REGS"
|
||||
"@internal")
|
||||
|
||||
(define_register_constraint "f" "TARGET_HARD_FLOAT ? FP_REGS : NO_REGS"
|
||||
"A floating-point register (if available).")
|
||||
|
||||
(define_constraint "h"
|
||||
"@internal
|
||||
A constant call plt address."
|
||||
(match_operand 0 "is_const_call_plt_symbol"))
|
||||
|
||||
(define_register_constraint "j" "SIBCALL_REGS"
|
||||
"@internal")
|
||||
|
||||
(define_memory_constraint "k"
|
||||
"A memory operand whose address is formed by a base register and (optionally scaled)
|
||||
index register."
|
||||
(and (match_code "mem")
|
||||
(match_test "loongarch_base_index_address_p (XEXP (op, 0), mode)")))
|
||||
|
||||
(define_constraint "l"
|
||||
"A signed 16-bit constant."
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM16_OPERAND (ival)")))
|
||||
|
||||
(define_memory_constraint "m"
|
||||
"A memory operand whose address is formed by a base register and offset
|
||||
that is suitable for use in instructions with the same addressing mode
|
||||
as @code{st.w} and @code{ld.w}."
|
||||
(and (match_code "mem")
|
||||
(match_test "loongarch_12bit_offset_address_p (XEXP (op, 0), mode)")))
|
||||
|
||||
(define_register_constraint "q" "CSR_REGS"
|
||||
"A general-purpose register except for $r0 and $r1 for lcsr.")
|
||||
|
||||
(define_constraint "t"
|
||||
"@internal
|
||||
A constant call weak address."
|
||||
(match_operand 0 "is_const_call_weak_symbol"))
|
||||
|
||||
(define_constraint "u"
|
||||
"A signed 52bit constant and low 32-bit is zero (for logic instructions)."
|
||||
(and (match_code "const_int")
|
||||
(match_test "LU32I_OPERAND (ival)")))
|
||||
|
||||
(define_constraint "v"
|
||||
"A signed 64-bit constant and low 44-bit is zero (for logic instructions)."
|
||||
(and (match_code "const_int")
|
||||
(match_test "LU52I_OPERAND (ival)")))
|
||||
|
||||
(define_register_constraint "z" "FCC_REGS"
|
||||
"A floating-point condition code register.")
|
||||
|
||||
;; Floating-point constraints
|
||||
|
||||
(define_constraint "G"
|
||||
"Floating-point zero."
|
||||
(and (match_code "const_double")
|
||||
(match_test "op == CONST0_RTX (mode)")))
|
||||
|
||||
;; Integer constraints
|
||||
|
||||
(define_constraint "I"
|
||||
"A signed 12-bit constant (for arithmetic instructions)."
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM12_OPERAND (ival)")))
|
||||
|
||||
(define_constraint "J"
|
||||
"Integer zero."
|
||||
(and (match_code "const_int")
|
||||
(match_test "ival == 0")))
|
||||
|
||||
(define_constraint "K"
|
||||
"An unsigned 12-bit constant (for logic instructions)."
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM12_OPERAND_UNSIGNED (ival)")))
|
||||
|
||||
(define_constraint "Yd"
|
||||
"@internal
|
||||
A constant @code{move_operand} that can be safely loaded using
|
||||
@code{la}."
|
||||
(and (match_operand 0 "move_operand")
|
||||
(match_test "CONSTANT_P (op)")))
|
||||
|
||||
(define_constraint "Yx"
|
||||
"@internal"
|
||||
(match_operand 0 "low_bitmask_operand"))
|
||||
|
||||
(define_memory_constraint "ZC"
|
||||
"A memory operand whose address is formed by a base register and offset
|
||||
that is suitable for use in instructions with the same addressing mode
|
||||
as @code{ll.w} and @code{sc.w}."
|
||||
(and (match_code "mem")
|
||||
(match_test "loongarch_14bit_shifted_offset_address_p (XEXP (op, 0), mode)")))
|
||||
|
||||
(define_memory_constraint "ZB"
|
||||
"@internal
|
||||
An address that is held in a general-purpose register.
|
||||
The offset is zero"
|
||||
(and (match_code "mem")
|
||||
(match_test "REG_P (XEXP (op, 0))")))
|
|
@ -0,0 +1,118 @@
|
|||
;; Generic DFA-based pipeline description for LoongArch targets
|
||||
;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;; Contributed by Loongson Ltd.
|
||||
;; Based on MIPS target for GNU compiler.
|
||||
|
||||
;; 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/>.
|
||||
|
||||
(define_automaton "alu,imuldiv")
|
||||
|
||||
(define_cpu_unit "alu" "alu")
|
||||
(define_cpu_unit "imuldiv" "imuldiv")
|
||||
|
||||
;; Ghost instructions produce no real code.
|
||||
;; They exist purely to express an effect on dataflow.
|
||||
(define_insn_reservation "ghost" 0
|
||||
(eq_attr "type" "ghost")
|
||||
"nothing")
|
||||
|
||||
(define_insn_reservation "generic_alu" 1
|
||||
(eq_attr "type" "unknown,prefetch,prefetchx,condmove,const,arith,
|
||||
shift,slt,clz,trap,multi,nop,logical,signext,move")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_load" 3
|
||||
(eq_attr "type" "load,fpload,fpidxload")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_store" 1
|
||||
(eq_attr "type" "store,fpstore,fpidxstore")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_xfer" 2
|
||||
(eq_attr "type" "mftg,mgtf")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_branch" 1
|
||||
(eq_attr "type" "branch,jump,call")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_imul" 17
|
||||
(eq_attr "type" "imul")
|
||||
"imuldiv*17")
|
||||
|
||||
(define_insn_reservation "generic_fcvt" 1
|
||||
(eq_attr "type" "fcvt")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fmove" 2
|
||||
(eq_attr "type" "fabs,fneg,fmove")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fcmp" 3
|
||||
(eq_attr "type" "fcmp")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fadd" 4
|
||||
(eq_attr "type" "fadd")
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fmul_single" 7
|
||||
(and (eq_attr "type" "fmul,fmadd")
|
||||
(eq_attr "mode" "SF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fmul_double" 8
|
||||
(and (eq_attr "type" "fmul,fmadd")
|
||||
(eq_attr "mode" "DF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fdiv_single" 23
|
||||
(and (eq_attr "type" "fdiv,frdiv")
|
||||
(eq_attr "mode" "SF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fdiv_double" 36
|
||||
(and (eq_attr "type" "fdiv,frdiv")
|
||||
(eq_attr "mode" "DF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fsqrt_single" 54
|
||||
(and (eq_attr "type" "fsqrt,frsqrt")
|
||||
(eq_attr "mode" "SF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_fsqrt_double" 112
|
||||
(and (eq_attr "type" "fsqrt,frsqrt")
|
||||
(eq_attr "mode" "DF"))
|
||||
"alu")
|
||||
|
||||
(define_insn_reservation "generic_atomic" 10
|
||||
(eq_attr "type" "atomic")
|
||||
"alu")
|
||||
|
||||
;; Sync loop consists of (in order)
|
||||
;; (1) optional sync,
|
||||
;; (2) LL instruction,
|
||||
;; (3) branch and 1-2 ALU instructions,
|
||||
;; (4) SC instruction,
|
||||
;; (5) branch and ALU instruction.
|
||||
;; The net result of this reservation is a big delay with a flush of
|
||||
;; ALU pipeline.
|
||||
(define_insn_reservation "generic_sync_loop" 40
|
||||
(eq_attr "type" "syncloop")
|
||||
"alu*39")
|
|
@ -0,0 +1,104 @@
|
|||
#!/bin/sh
|
||||
# A simple script that generates loongarch-str.h and loongarch.opt
|
||||
# from genopt/loongarch-optstr.
|
||||
#
|
||||
# Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
cd "$(dirname "$0")"
|
||||
|
||||
# Generate a header containing definitions from the string table.
|
||||
gen_defines() {
|
||||
cat <<EOF
|
||||
/* Generated automatically by "genstr" from "loongarch-strings".
|
||||
Please do not edit this file directly.
|
||||
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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 LOONGARCH_STR_H
|
||||
#define LOONGARCH_STR_H
|
||||
EOF
|
||||
|
||||
sed -e '/^$/n' -e 's@#.*$@@' -e '/^$/d' \
|
||||
-e 's@^\([^ \t]\+\)[ \t]*\([^ \t]*\)@#define \1 "\2"@' \
|
||||
loongarch-strings
|
||||
|
||||
echo
|
||||
echo "#endif /* LOONGARCH_STR_H */"
|
||||
}
|
||||
|
||||
|
||||
# Substitute all "@@<KEY>@@" to "<VALUE>" in loongarch.opt.in
|
||||
# according to the key-value pairs defined in loongarch-strings.
|
||||
|
||||
gen_options() {
|
||||
|
||||
sed -e '/^$/n' -e 's@#.*$@@' -e '/^$/d' \
|
||||
-e 's@^\([^ \t]\+\)[ \t]*\([^ \t]*\)@\1="\2"@' \
|
||||
loongarch-strings | { \
|
||||
|
||||
# read the definitions
|
||||
while read -r line; do
|
||||
eval "$line"
|
||||
done
|
||||
|
||||
# print a header
|
||||
cat << EOF
|
||||
; Generated by "genstr" from the template "loongarch.opt.in"
|
||||
; and definitions from "loongarch-strings".
|
||||
;
|
||||
; Please do not edit this file directly.
|
||||
; It will be automatically updated during a gcc build
|
||||
; if you change "loongarch.opt.in" or "loongarch-strings".
|
||||
;
|
||||
EOF
|
||||
|
||||
# make the substitutions
|
||||
sed -e 's@"@\\"@g' -e 's/@@\([^@]\+\)@@/${\1}/g' loongarch.opt.in | \
|
||||
while read -r line; do
|
||||
eval "echo \"$line\""
|
||||
done
|
||||
}
|
||||
}
|
||||
|
||||
main() {
|
||||
case "$1" in
|
||||
header) gen_defines;;
|
||||
opt) gen_options;;
|
||||
*) echo "Unknown Command: \"$1\". Available: header, opt"; exit 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
main "$@"
|
|
@ -0,0 +1,58 @@
|
|||
# Defines the key strings for LoongArch compiler options.
|
||||
#
|
||||
# Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# -march= / -mtune=
|
||||
OPTSTR_ARCH arch
|
||||
OPTSTR_TUNE tune
|
||||
|
||||
STR_CPU_NATIVE native
|
||||
STR_CPU_LOONGARCH64 loongarch64
|
||||
STR_CPU_LA464 la464
|
||||
|
||||
# Base architecture
|
||||
STR_ISA_BASE_LA64V100 la64
|
||||
|
||||
# -mfpu
|
||||
OPTSTR_ISA_EXT_FPU fpu
|
||||
STR_ISA_EXT_NOFPU none
|
||||
STR_ISA_EXT_FPU0 0
|
||||
STR_ISA_EXT_FPU32 32
|
||||
STR_ISA_EXT_FPU64 64
|
||||
|
||||
OPTSTR_SOFT_FLOAT soft-float
|
||||
OPTSTR_SINGLE_FLOAT single-float
|
||||
OPTSTR_DOUBLE_FLOAT double-float
|
||||
|
||||
# -mabi=
|
||||
OPTSTR_ABI_BASE abi
|
||||
STR_ABI_BASE_LP64D lp64d
|
||||
STR_ABI_BASE_LP64F lp64f
|
||||
STR_ABI_BASE_LP64S lp64s
|
||||
|
||||
# ABI extension types
|
||||
STR_ABI_EXT_BASE base
|
||||
|
||||
# -mcmodel=
|
||||
OPTSTR_CMODEL cmodel
|
||||
STR_CMODEL_NORMAL normal
|
||||
STR_CMODEL_TINY tiny
|
||||
STR_CMODEL_TS tiny-static
|
||||
STR_CMODEL_LARGE large
|
||||
STR_CMODEL_EXTREME extreme
|
|
@ -0,0 +1,179 @@
|
|||
; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;
|
||||
; 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/>.
|
||||
;
|
||||
|
||||
; Variables (macros) that should be exported by loongarch.opt:
|
||||
; la_opt_switches,
|
||||
; la_opt_abi_base, la_opt_abi_ext,
|
||||
; la_opt_cpu_arch, la_opt_cpu_tune,
|
||||
; la_opt_fpu,
|
||||
; la_cmodel.
|
||||
|
||||
HeaderInclude
|
||||
config/loongarch/loongarch-opts.h
|
||||
|
||||
HeaderInclude
|
||||
config/loongarch/loongarch-str.h
|
||||
|
||||
Variable
|
||||
HOST_WIDE_INT la_opt_switches = 0
|
||||
|
||||
; ISA related options
|
||||
;; Base ISA
|
||||
Enum
|
||||
Name(isa_base) Type(int)
|
||||
Basic ISAs of LoongArch:
|
||||
|
||||
EnumValue
|
||||
Enum(isa_base) String(@@STR_ISA_BASE_LA64V100@@) Value(ISA_BASE_LA64V100)
|
||||
|
||||
|
||||
;; ISA extensions / adjustments
|
||||
Enum
|
||||
Name(isa_ext_fpu) Type(int)
|
||||
FPU types of LoongArch:
|
||||
|
||||
EnumValue
|
||||
Enum(isa_ext_fpu) String(@@STR_ISA_EXT_NOFPU@@) Value(ISA_EXT_NOFPU)
|
||||
|
||||
EnumValue
|
||||
Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU32@@) Value(ISA_EXT_FPU32)
|
||||
|
||||
EnumValue
|
||||
Enum(isa_ext_fpu) String(@@STR_ISA_EXT_FPU64@@) Value(ISA_EXT_FPU64)
|
||||
|
||||
m@@OPTSTR_ISA_EXT_FPU@@=
|
||||
Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN)
|
||||
-m@@OPTSTR_ISA_EXT_FPU@@=FPU Generate code for the given FPU.
|
||||
|
||||
m@@OPTSTR_ISA_EXT_FPU@@=@@STR_ISA_EXT_FPU0@@
|
||||
Target RejectNegative Alias(m@@OPTSTR_ISA_EXT_FPU@@=,@@STR_ISA_EXT_NOFPU@@)
|
||||
|
||||
m@@OPTSTR_SOFT_FLOAT@@
|
||||
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(m@@OPTSTR_SINGLE_FLOAT@@)
|
||||
Prevent the use of all hardware floating-point instructions.
|
||||
|
||||
m@@OPTSTR_SINGLE_FLOAT@@
|
||||
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(m@@OPTSTR_DOUBLE_FLOAT@@)
|
||||
Restrict the use of hardware floating-point instructions to 32-bit operations.
|
||||
|
||||
m@@OPTSTR_DOUBLE_FLOAT@@
|
||||
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(m@@OPTSTR_SOFT_FLOAT@@)
|
||||
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
|
||||
|
||||
|
||||
;; Base target models (implies ISA & tune parameters)
|
||||
Enum
|
||||
Name(cpu_type) Type(int)
|
||||
LoongArch CPU types:
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(@@STR_CPU_NATIVE@@) Value(CPU_NATIVE)
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(@@STR_CPU_LOONGARCH64@@) Value(CPU_LOONGARCH64)
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(@@STR_CPU_LA464@@) Value(CPU_LA464)
|
||||
|
||||
m@@OPTSTR_ARCH@@=
|
||||
Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN)
|
||||
-m@@OPTSTR_ARCH@@=PROCESSOR Generate code for the given PROCESSOR ISA.
|
||||
|
||||
m@@OPTSTR_TUNE@@=
|
||||
Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN)
|
||||
-m@@OPTSTR_TUNE@@=PROCESSOR Generate optimized code for PROCESSOR.
|
||||
|
||||
|
||||
; ABI related options
|
||||
; (ISA constraints on ABI are handled dynamically)
|
||||
|
||||
;; Base ABI
|
||||
Enum
|
||||
Name(abi_base) Type(int)
|
||||
Base ABI types for LoongArch:
|
||||
|
||||
EnumValue
|
||||
Enum(abi_base) String(@@STR_ABI_BASE_LP64D@@) Value(ABI_BASE_LP64D)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_base) String(@@STR_ABI_BASE_LP64F@@) Value(ABI_BASE_LP64F)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_base) String(@@STR_ABI_BASE_LP64S@@) Value(ABI_BASE_LP64S)
|
||||
|
||||
m@@OPTSTR_ABI_BASE@@=
|
||||
Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN)
|
||||
-m@@OPTSTR_ABI_BASE@@=BASEABI Generate code that conforms to the given BASEABI.
|
||||
|
||||
;; ABI Extension
|
||||
Variable
|
||||
int la_opt_abi_ext = M_OPTION_NOT_SEEN
|
||||
|
||||
|
||||
mbranch-cost=
|
||||
Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
|
||||
-mbranch-cost=COST Set the cost of branches to roughly COST instructions.
|
||||
|
||||
mcheck-zero-division
|
||||
Target Mask(CHECK_ZERO_DIV)
|
||||
Trap on integer divide by zero.
|
||||
|
||||
mcond-move-int
|
||||
Target Var(TARGET_COND_MOVE_INT) Init(1)
|
||||
Conditional moves for integral are enabled.
|
||||
|
||||
mcond-move-float
|
||||
Target Var(TARGET_COND_MOVE_FLOAT) Init(1)
|
||||
Conditional moves for float are enabled.
|
||||
|
||||
mmemcpy
|
||||
Target Mask(MEMCPY)
|
||||
Prevent optimizing block moves, which is also the default behavior of -Os.
|
||||
|
||||
mstrict-align
|
||||
Target Var(TARGET_STRICT_ALIGN) Init(0)
|
||||
Do not generate unaligned memory accesses.
|
||||
|
||||
mmax-inline-memcpy-size=
|
||||
Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
|
||||
-mmax-inline-memcpy-size=SIZE Set the max size of memcpy to inline, default is 1024.
|
||||
|
||||
; The code model option names for -mcmodel.
|
||||
Enum
|
||||
Name(cmodel) Type(int)
|
||||
The code model option names for -mcmodel:
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(@@STR_CMODEL_NORMAL@@) Value(CMODEL_NORMAL)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(@@STR_CMODEL_TINY@@) Value(CMODEL_TINY)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(@@STR_CMODEL_TS@@) Value(CMODEL_TINY_STATIC)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(@@STR_CMODEL_LARGE@@) Value(CMODEL_LARGE)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(@@STR_CMODEL_EXTREME@@) Value(CMODEL_EXTREME)
|
||||
|
||||
mcmodel=
|
||||
Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL)
|
||||
Specify the code model.
|
|
@ -0,0 +1,80 @@
|
|||
/* Definitions for LoongArch systems using GNU (glibc-based) userspace,
|
||||
or other userspace with libc derived from glibc.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
|
||||
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/>. */
|
||||
|
||||
/* Define the size of the wide character type. */
|
||||
#undef WCHAR_TYPE
|
||||
#define WCHAR_TYPE "int"
|
||||
|
||||
#undef WCHAR_TYPE_SIZE
|
||||
#define WCHAR_TYPE_SIZE 32
|
||||
|
||||
|
||||
/* GNU-specific SPEC definitions. */
|
||||
#define GNU_USER_LINK_EMULATION "elf" ABI_GRLEN_SPEC "loongarch"
|
||||
|
||||
#undef GLIBC_DYNAMIC_LINKER
|
||||
#define GLIBC_DYNAMIC_LINKER \
|
||||
"/lib" ABI_GRLEN_SPEC "/ld-linux-loongarch-" ABI_SPEC ".so.1"
|
||||
|
||||
#undef MUSL_DYNAMIC_LINKER
|
||||
#define MUSL_DYNAMIC_LINKER \
|
||||
"/lib" ABI_GRLEN_SPEC "/ld-musl-loongarch-" ABI_SPEC ".so.1"
|
||||
|
||||
#undef GNU_USER_TARGET_LINK_SPEC
|
||||
#define GNU_USER_TARGET_LINK_SPEC \
|
||||
"%{G*} %{shared} -m " GNU_USER_LINK_EMULATION \
|
||||
"%{!shared: %{static} %{!static: %{rdynamic:-export-dynamic} " \
|
||||
"-dynamic-linker " GNU_USER_DYNAMIC_LINKER "}}"
|
||||
|
||||
|
||||
/* Similar to standard Linux, but adding -ffast-math support. */
|
||||
#undef GNU_USER_TARGET_MATHFILE_SPEC
|
||||
#define GNU_USER_TARGET_MATHFILE_SPEC \
|
||||
"%{Ofast|ffast-math|funsafe-math-optimizations:crtfastmath.o%s}"
|
||||
|
||||
#undef LIB_SPEC
|
||||
#define LIB_SPEC GNU_USER_TARGET_LIB_SPEC
|
||||
|
||||
#undef LINK_SPEC
|
||||
#define LINK_SPEC GNU_USER_TARGET_LINK_SPEC
|
||||
|
||||
#undef ENDFILE_SPEC
|
||||
#define ENDFILE_SPEC \
|
||||
GNU_USER_TARGET_MATHFILE_SPEC " " \
|
||||
GNU_USER_TARGET_ENDFILE_SPEC
|
||||
|
||||
#undef SUBTARGET_CPP_SPEC
|
||||
#define SUBTARGET_CPP_SPEC "%{posix:-D_POSIX_SOURCE} %{pthread:-D_REENTRANT}"
|
||||
|
||||
/* A standard GNU/Linux mapping. On most targets, it is included in
|
||||
CC1_SPEC itself by config/linux.h, but loongarch.h overrides CC1_SPEC
|
||||
and provides this hook instead. */
|
||||
#undef SUBTARGET_CC1_SPEC
|
||||
#define SUBTARGET_CC1_SPEC GNU_USER_TARGET_CC1_SPEC
|
||||
|
||||
#define TARGET_OS_CPP_BUILTINS() \
|
||||
do \
|
||||
{ \
|
||||
GNU_USER_TARGET_OS_CPP_BUILTINS (); \
|
||||
/* The GNU C++ standard library requires this. */ \
|
||||
if (c_dialect_cxx ()) \
|
||||
builtin_define ("_GNU_SOURCE"); \
|
||||
} \
|
||||
while (0)
|
|
@ -0,0 +1,132 @@
|
|||
;; Pipeline model for LoongArch LA464 cores.
|
||||
|
||||
;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;; Contributed by Loongson 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/>.
|
||||
|
||||
;; Uncomment the following line to output automata for debugging.
|
||||
;; (automata_option "v")
|
||||
|
||||
;; Automaton for integer instructions.
|
||||
(define_automaton "la464_a_alu")
|
||||
|
||||
;; Automaton for floating-point instructions.
|
||||
(define_automaton "la464_a_falu")
|
||||
|
||||
;; Automaton for memory operations.
|
||||
(define_automaton "la464_a_mem")
|
||||
|
||||
;; Describe the resources.
|
||||
|
||||
(define_cpu_unit "la464_alu1" "la464_a_alu")
|
||||
(define_cpu_unit "la464_alu2" "la464_a_alu")
|
||||
(define_cpu_unit "la464_mem1" "la464_a_mem")
|
||||
(define_cpu_unit "la464_mem2" "la464_a_mem")
|
||||
(define_cpu_unit "la464_falu1" "la464_a_falu")
|
||||
(define_cpu_unit "la464_falu2" "la464_a_falu")
|
||||
|
||||
;; Describe instruction reservations.
|
||||
|
||||
(define_insn_reservation "la464_arith" 1
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "arith,clz,const,logical,
|
||||
move,nop,shift,signext,slt"))
|
||||
"la464_alu1 | la464_alu2")
|
||||
|
||||
(define_insn_reservation "la464_branch" 1
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "branch,jump,call,condmove,trap"))
|
||||
"la464_alu1 | la464_alu2")
|
||||
|
||||
(define_insn_reservation "la464_imul" 7
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "imul"))
|
||||
"la464_alu1 | la464_alu2")
|
||||
|
||||
(define_insn_reservation "la464_idiv_si" 12
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(and (eq_attr "type" "idiv")
|
||||
(eq_attr "mode" "SI")))
|
||||
"la464_alu1 | la464_alu2")
|
||||
|
||||
(define_insn_reservation "la464_idiv_di" 25
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(and (eq_attr "type" "idiv")
|
||||
(eq_attr "mode" "DI")))
|
||||
"la464_alu1 | la464_alu2")
|
||||
|
||||
(define_insn_reservation "la464_load" 4
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "load"))
|
||||
"la464_mem1 | la464_mem2")
|
||||
|
||||
(define_insn_reservation "la464_gpr_fp" 16
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "mftg,mgtf"))
|
||||
"la464_mem1")
|
||||
|
||||
(define_insn_reservation "la464_fpload" 4
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "fpload"))
|
||||
"la464_mem1 | la464_mem2")
|
||||
|
||||
(define_insn_reservation "la464_prefetch" 0
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "prefetch,prefetchx"))
|
||||
"la464_mem1 | la464_mem2")
|
||||
|
||||
(define_insn_reservation "la464_store" 0
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "store,fpstore,fpidxstore"))
|
||||
"la464_mem1 | la464_mem2")
|
||||
|
||||
(define_insn_reservation "la464_fadd" 4
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "fadd,fmul,fmadd"))
|
||||
"la464_falu1 | la464_falu2")
|
||||
|
||||
(define_insn_reservation "la464_fcmp" 2
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "fabs,fcmp,fmove,fneg"))
|
||||
"la464_falu1 | la464_falu2")
|
||||
|
||||
(define_insn_reservation "la464_fcvt" 4
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "fcvt"))
|
||||
"la464_falu1 | la464_falu2")
|
||||
|
||||
(define_insn_reservation "la464_fdiv_sf" 12
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
|
||||
(eq_attr "mode" "SF")))
|
||||
"la464_falu1 | la464_falu2")
|
||||
|
||||
(define_insn_reservation "la464_fdiv_df" 19
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(and (eq_attr "type" "fdiv,frdiv,fsqrt,frsqrt")
|
||||
(eq_attr "mode" "DF")))
|
||||
"la464_falu1 | la464_falu2")
|
||||
|
||||
;; Force single-dispatch for unknown or multi.
|
||||
(define_insn_reservation "la464_unknown" 1
|
||||
(and (match_test "TARGET_TUNE_LA464")
|
||||
(eq_attr "type" "unknown,multi,atomic,syncloop"))
|
||||
"la464_alu1 + la464_alu2 + la464_falu1
|
||||
+ la464_falu2 + la464_mem1 + la464_mem2")
|
||||
|
||||
;; End of DFA-based pipeline description for la464
|
|
@ -0,0 +1,355 @@
|
|||
/* Intrinsics for LoongArch BASE operations.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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.
|
||||
|
||||
Under Section 7 of GPL version 3, you are granted additional
|
||||
permissions described in the GCC Runtime Library Exception, version
|
||||
3.1, as published by the Free Software Foundation.
|
||||
|
||||
You should have received a copy of the GNU General Public License and
|
||||
a copy of the GCC Runtime Library Exception along with this program;
|
||||
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
|
||||
<http://www.gnu.org/licenses/>. */
|
||||
|
||||
#ifndef _GCC_LOONGARCH_BASE_INTRIN_H
|
||||
#define _GCC_LOONGARCH_BASE_INTRIN_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct drdtime
|
||||
{
|
||||
unsigned long dvalue;
|
||||
unsigned long dtimeid;
|
||||
} __drdtime_t;
|
||||
|
||||
typedef struct rdtime
|
||||
{
|
||||
unsigned int value;
|
||||
unsigned int timeid;
|
||||
} __rdtime_t;
|
||||
|
||||
#ifdef __loongarch64
|
||||
extern __inline __drdtime_t
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__rdtime_d (void)
|
||||
{
|
||||
__drdtime_t __drdtime;
|
||||
__asm__ volatile (
|
||||
"rdtime.d\t%[val],%[tid]\n\t"
|
||||
: [val]"=&r"(__drdtime.dvalue),[tid]"=&r"(__drdtime.dtimeid)
|
||||
:);
|
||||
return __drdtime;
|
||||
}
|
||||
#endif
|
||||
|
||||
extern __inline __rdtime_t
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__rdtimeh_w (void)
|
||||
{
|
||||
__rdtime_t __rdtime;
|
||||
__asm__ volatile (
|
||||
"rdtimeh.w\t%[val],%[tid]\n\t"
|
||||
: [val]"=&r"(__rdtime.value),[tid]"=&r"(__rdtime.timeid)
|
||||
:);
|
||||
return __rdtime;
|
||||
}
|
||||
|
||||
extern __inline __rdtime_t
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__rdtimel_w (void)
|
||||
{
|
||||
__rdtime_t __rdtime;
|
||||
__asm__ volatile (
|
||||
"rdtimel.w\t%[val],%[tid]\n\t"
|
||||
: [val]"=&r"(__rdtime.value),[tid]"=&r"(__rdtime.timeid)
|
||||
:);
|
||||
return __rdtime;
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rj, fcsr. */
|
||||
/* Data types in instruction templates: USI, UQI. */
|
||||
#define __movfcsr2gr(/*ui5*/ _1) __builtin_loongarch_movfcsr2gr ((_1));
|
||||
|
||||
/* Assembly instruction format: fcsr, rj. */
|
||||
/* Data types in instruction templates: VOID, UQI, USI. */
|
||||
#define __movgr2fcsr(/*ui5*/ _1, _2) \
|
||||
__builtin_loongarch_movgr2fcsr ((_1), (unsigned int) _2);
|
||||
|
||||
#if defined __loongarch64
|
||||
/* Assembly instruction format: ui5, rj, si12. */
|
||||
/* Data types in instruction templates: VOID, USI, UDI, SI. */
|
||||
#define __cacop_d(/*ui5*/ _1, /*unsigned long int*/ _2, /*si12*/ _3) \
|
||||
((void) __builtin_loongarch_cacop_d ((_1), (unsigned long int) (_2), (_3)))
|
||||
#else
|
||||
#error "Unsupported ABI."
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: USI, USI. */
|
||||
extern __inline unsigned int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__cpucfg (unsigned int _1)
|
||||
{
|
||||
return (unsigned int) __builtin_loongarch_cpucfg ((unsigned int) _1);
|
||||
}
|
||||
|
||||
#ifdef __loongarch64
|
||||
/* Assembly instruction format: rj, rk. */
|
||||
/* Data types in instruction templates: DI, DI. */
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__asrtle_d (long int _1, long int _2)
|
||||
{
|
||||
__builtin_loongarch_asrtle_d ((long int) _1, (long int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rj, rk. */
|
||||
/* Data types in instruction templates: DI, DI. */
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__asrtgt_d (long int _1, long int _2)
|
||||
{
|
||||
__builtin_loongarch_asrtgt_d ((long int) _1, (long int) _2);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined __loongarch64
|
||||
/* Assembly instruction format: rd, rj, ui5. */
|
||||
/* Data types in instruction templates: DI, DI, UQI. */
|
||||
#define __lddir_d(/*long int*/ _1, /*ui5*/ _2) \
|
||||
((long int) __builtin_loongarch_lddir_d ((long int) (_1), (_2)))
|
||||
#else
|
||||
#error "Unsupported ABI."
|
||||
#endif
|
||||
|
||||
#if defined __loongarch64
|
||||
/* Assembly instruction format: rj, ui5. */
|
||||
/* Data types in instruction templates: VOID, DI, UQI. */
|
||||
#define __ldpte_d(/*long int*/ _1, /*ui5*/ _2) \
|
||||
((void) __builtin_loongarch_ldpte_d ((long int) (_1), (_2)))
|
||||
#else
|
||||
#error "Unsupported ABI."
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, QI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crc_w_b_w (char _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crc_w_b_w ((char) _1, (int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, HI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crc_w_h_w (short _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crc_w_h_w ((short) _1, (int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, SI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crc_w_w_w (int _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crc_w_w_w ((int) _1, (int) _2);
|
||||
}
|
||||
|
||||
#ifdef __loongarch64
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, DI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crc_w_d_w (long int _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crc_w_d_w ((long int) _1, (int) _2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, QI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crcc_w_b_w (char _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crcc_w_b_w ((char) _1, (int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, HI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crcc_w_h_w (short _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crcc_w_h_w ((short) _1, (int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, SI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crcc_w_w_w (int _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crcc_w_w_w ((int) _1, (int) _2);
|
||||
}
|
||||
|
||||
#ifdef __loongarch64
|
||||
/* Assembly instruction format: rd, rj, rk. */
|
||||
/* Data types in instruction templates: SI, DI, SI. */
|
||||
extern __inline int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__crcc_w_d_w (long int _1, int _2)
|
||||
{
|
||||
return (int) __builtin_loongarch_crcc_w_d_w ((long int) _1, (int) _2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: rd, ui14. */
|
||||
/* Data types in instruction templates: USI, USI. */
|
||||
#define __csrrd_w(/*ui14*/ _1) \
|
||||
((unsigned int) __builtin_loongarch_csrrd_w ((_1)))
|
||||
|
||||
/* Assembly instruction format: rd, ui14. */
|
||||
/* Data types in instruction templates: USI, USI, USI. */
|
||||
#define __csrwr_w(/*unsigned int*/ _1, /*ui14*/ _2) \
|
||||
((unsigned int) __builtin_loongarch_csrwr_w ((unsigned int) (_1), (_2)))
|
||||
|
||||
/* Assembly instruction format: rd, rj, ui14. */
|
||||
/* Data types in instruction templates: USI, USI, USI, USI. */
|
||||
#define __csrxchg_w(/*unsigned int*/ _1, /*unsigned int*/ _2, /*ui14*/ _3) \
|
||||
((unsigned int) __builtin_loongarch_csrxchg_w ((unsigned int) (_1), \
|
||||
(unsigned int) (_2), (_3)))
|
||||
|
||||
#ifdef __loongarch64
|
||||
/* Assembly instruction format: rd, ui14. */
|
||||
/* Data types in instruction templates: UDI, USI. */
|
||||
#define __csrrd_d(/*ui14*/ _1) \
|
||||
((unsigned long int) __builtin_loongarch_csrrd_d ((_1)))
|
||||
|
||||
/* Assembly instruction format: rd, ui14. */
|
||||
/* Data types in instruction templates: UDI, UDI, USI. */
|
||||
#define __csrwr_d(/*unsigned long int*/ _1, /*ui14*/ _2) \
|
||||
((unsigned long int) __builtin_loongarch_csrwr_d ((unsigned long int) (_1), \
|
||||
(_2)))
|
||||
|
||||
/* Assembly instruction format: rd, rj, ui14. */
|
||||
/* Data types in instruction templates: UDI, UDI, UDI, USI. */
|
||||
#define __csrxchg_d(/*unsigned long int*/ _1, /*unsigned long int*/ _2, \
|
||||
/*ui14*/ _3) \
|
||||
((unsigned long int) __builtin_loongarch_csrxchg_d ( \
|
||||
(unsigned long int) (_1), (unsigned long int) (_2), (_3)))
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: UQI, USI. */
|
||||
extern __inline unsigned char
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrrd_b (unsigned int _1)
|
||||
{
|
||||
return (unsigned char) __builtin_loongarch_iocsrrd_b ((unsigned int) _1);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: UHI, USI. */
|
||||
extern __inline unsigned char
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrrd_h (unsigned int _1)
|
||||
{
|
||||
return (unsigned short) __builtin_loongarch_iocsrrd_h ((unsigned int) _1);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: USI, USI. */
|
||||
extern __inline unsigned int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrrd_w (unsigned int _1)
|
||||
{
|
||||
return (unsigned int) __builtin_loongarch_iocsrrd_w ((unsigned int) _1);
|
||||
}
|
||||
|
||||
#ifdef __loongarch64
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: UDI, USI. */
|
||||
extern __inline unsigned long int
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrrd_d (unsigned int _1)
|
||||
{
|
||||
return (unsigned long int) __builtin_loongarch_iocsrrd_d ((unsigned int) _1);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: VOID, UQI, USI. */
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrwr_b (unsigned char _1, unsigned int _2)
|
||||
{
|
||||
__builtin_loongarch_iocsrwr_b ((unsigned char) _1, (unsigned int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: VOID, UHI, USI. */
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrwr_h (unsigned short _1, unsigned int _2)
|
||||
{
|
||||
__builtin_loongarch_iocsrwr_h ((unsigned short) _1, (unsigned int) _2);
|
||||
}
|
||||
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: VOID, USI, USI. */
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrwr_w (unsigned int _1, unsigned int _2)
|
||||
{
|
||||
__builtin_loongarch_iocsrwr_w ((unsigned int) _1, (unsigned int) _2);
|
||||
}
|
||||
|
||||
#ifdef __loongarch64
|
||||
/* Assembly instruction format: rd, rj. */
|
||||
/* Data types in instruction templates: VOID, UDI, USI. */
|
||||
extern __inline void
|
||||
__attribute__ ((__gnu_inline__, __always_inline__, __artificial__))
|
||||
__iocsrwr_d (unsigned long int _1, unsigned int _2)
|
||||
{
|
||||
__builtin_loongarch_iocsrwr_d ((unsigned long int) _1, (unsigned int) _2);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Assembly instruction format: ui15. */
|
||||
/* Data types in instruction templates: USI. */
|
||||
#define __dbar(/*ui15*/ _1) __builtin_loongarch_dbar ((_1))
|
||||
|
||||
/* Assembly instruction format: ui15. */
|
||||
/* Data types in instruction templates: USI. */
|
||||
#define __ibar(/*ui15*/ _1) __builtin_loongarch_ibar ((_1))
|
||||
|
||||
/* Assembly instruction format: ui15. */
|
||||
/* Data types in instruction templates: USI. */
|
||||
#define __syscall(/*ui15*/ _1) __builtin_loongarch_syscall ((_1))
|
||||
|
||||
/* Assembly instruction format: ui15. */
|
||||
/* Data types in instruction templates: USI. */
|
||||
#define __break(/*ui15*/ _1) __builtin_loongarch_break ((_1))
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* _GCC_LOONGARCH_BASE_INTRIN_H */
|
|
@ -0,0 +1,50 @@
|
|||
/* Definitions for Linux-based systems with libraries in ELF format.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
|
||||
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/>. */
|
||||
|
||||
/* Default system library search paths.
|
||||
* This ensures that a compiler configured with --disable-multilib
|
||||
* can work in a multilib environment. */
|
||||
|
||||
#if defined(LA_DISABLE_MULTILIB) && defined(LA_DISABLE_MULTIARCH)
|
||||
|
||||
#if DEFAULT_ABI_BASE == ABI_BASE_LP64D
|
||||
#define ABI_LIBDIR "lib64"
|
||||
#elif DEFAULT_ABI_BASE == ABI_BASE_LP64F
|
||||
#define ABI_LIBDIR "lib64/f32"
|
||||
#elif DEFAULT_ABI_BASE == ABI_BASE_LP64S
|
||||
#define ABI_LIBDIR "lib64/sf"
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef ABI_LIBDIR
|
||||
#define ABI_LIBDIR "lib"
|
||||
#endif
|
||||
|
||||
#define STANDARD_STARTFILE_PREFIX_1 "/" ABI_LIBDIR "/"
|
||||
#define STANDARD_STARTFILE_PREFIX_2 "/usr/" ABI_LIBDIR "/"
|
||||
|
||||
|
||||
/* Define this to be nonzero if static stack checking is supported. */
|
||||
#define STACK_CHECK_STATIC_BUILTIN 1
|
||||
|
||||
/* The default value isn't sufficient in 64-bit mode. */
|
||||
#define STACK_CHECK_PROTECT (TARGET_64BIT ? 16 * 1024 : 12 * 1024)
|
||||
|
||||
#define TARGET_ASM_FILE_END file_end_indicate_exec_stack
|
|
@ -0,0 +1,424 @@
|
|||
/* Subroutines used for expanding LoongArch builtins.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
#define IN_TARGET_CODE 1
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "backend.h"
|
||||
#include "target.h"
|
||||
#include "rtl.h"
|
||||
#include "tree.h"
|
||||
#include "memmodel.h"
|
||||
#include "gimple.h"
|
||||
#include "tm_p.h"
|
||||
#include "optabs.h"
|
||||
#include "recog.h"
|
||||
#include "diagnostic.h"
|
||||
#include "fold-const.h"
|
||||
#include "expr.h"
|
||||
#include "langhooks.h"
|
||||
|
||||
/* Macros to create an enumeration identifier for a function prototype. */
|
||||
#define LARCH_FTYPE_NAME1(A, B) LARCH_##A##_FTYPE_##B
|
||||
#define LARCH_FTYPE_NAME2(A, B, C) LARCH_##A##_FTYPE_##B##_##C
|
||||
#define LARCH_FTYPE_NAME3(A, B, C, D) LARCH_##A##_FTYPE_##B##_##C##_##D
|
||||
|
||||
/* Classifies the prototype of a built-in function. */
|
||||
enum loongarch_function_type
|
||||
{
|
||||
#define DEF_LARCH_FTYPE(NARGS, LIST) LARCH_FTYPE_NAME##NARGS LIST,
|
||||
#include "config/loongarch/loongarch-ftypes.def"
|
||||
#undef DEF_LARCH_FTYPE
|
||||
LARCH_MAX_FTYPE_MAX
|
||||
};
|
||||
|
||||
/* Specifies how a built-in function should be converted into rtl. */
|
||||
enum loongarch_builtin_type
|
||||
{
|
||||
/* The function corresponds directly to an .md pattern. The return
|
||||
value is mapped to operand 0 and the arguments are mapped to
|
||||
operands 1 and above. */
|
||||
LARCH_BUILTIN_DIRECT,
|
||||
|
||||
/* The function corresponds directly to an .md pattern. There is no return
|
||||
value and the arguments are mapped to operands 0 and above. */
|
||||
LARCH_BUILTIN_DIRECT_NO_TARGET,
|
||||
|
||||
};
|
||||
|
||||
/* Declare an availability predicate for built-in functions that require
|
||||
* COND to be true. NAME is the main part of the predicate's name. */
|
||||
#define AVAIL_ALL(NAME, COND) \
|
||||
static unsigned int \
|
||||
loongarch_builtin_avail_##NAME (void) \
|
||||
{ \
|
||||
return (COND) ? 1 : 0; \
|
||||
}
|
||||
|
||||
static unsigned int
|
||||
loongarch_builtin_avail_default (void)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
/* This structure describes a single built-in function. */
|
||||
struct loongarch_builtin_description
|
||||
{
|
||||
/* The code of the main .md file instruction. See loongarch_builtin_type
|
||||
for more information. */
|
||||
enum insn_code icode;
|
||||
|
||||
/* The name of the built-in function. */
|
||||
const char *name;
|
||||
|
||||
/* Specifies how the function should be expanded. */
|
||||
enum loongarch_builtin_type builtin_type;
|
||||
|
||||
/* The function's prototype. */
|
||||
enum loongarch_function_type function_type;
|
||||
|
||||
/* Whether the function is available. */
|
||||
unsigned int (*avail) (void);
|
||||
};
|
||||
|
||||
AVAIL_ALL (hard_float, TARGET_HARD_FLOAT_ABI)
|
||||
|
||||
/* Construct a loongarch_builtin_description from the given arguments.
|
||||
|
||||
INSN is the name of the associated instruction pattern, without the
|
||||
leading CODE_FOR_loongarch_.
|
||||
|
||||
CODE is the floating-point condition code associated with the
|
||||
function. It can be 'f' if the field is not applicable.
|
||||
|
||||
NAME is the name of the function itself, without the leading
|
||||
"__builtin_loongarch_".
|
||||
|
||||
BUILTIN_TYPE and FUNCTION_TYPE are loongarch_builtin_description fields.
|
||||
|
||||
AVAIL is the name of the availability predicate, without the leading
|
||||
loongarch_builtin_avail_. */
|
||||
#define LARCH_BUILTIN(INSN, NAME, BUILTIN_TYPE, FUNCTION_TYPE, AVAIL) \
|
||||
{ \
|
||||
CODE_FOR_loongarch_##INSN, "__builtin_loongarch_" NAME, \
|
||||
BUILTIN_TYPE, FUNCTION_TYPE, \
|
||||
loongarch_builtin_avail_##AVAIL \
|
||||
}
|
||||
|
||||
/* Define __builtin_loongarch_<INSN>, which is a LARCH_BUILTIN_DIRECT function
|
||||
mapped to instruction CODE_FOR_loongarch_<INSN>, FUNCTION_TYPE and AVAIL
|
||||
are as for LARCH_BUILTIN. */
|
||||
#define DIRECT_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \
|
||||
LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT, FUNCTION_TYPE, AVAIL)
|
||||
|
||||
/* Define __builtin_loongarch_<INSN>, which is a LARCH_BUILTIN_DIRECT_NO_TARGET
|
||||
function mapped to instruction CODE_FOR_loongarch_<INSN>, FUNCTION_TYPE
|
||||
and AVAIL are as for LARCH_BUILTIN. */
|
||||
#define DIRECT_NO_TARGET_BUILTIN(INSN, FUNCTION_TYPE, AVAIL) \
|
||||
LARCH_BUILTIN (INSN, #INSN, LARCH_BUILTIN_DIRECT_NO_TARGET, \
|
||||
FUNCTION_TYPE, AVAIL)
|
||||
|
||||
static const struct loongarch_builtin_description loongarch_builtins[] = {
|
||||
#define LARCH_MOVFCSR2GR 0
|
||||
DIRECT_BUILTIN (movfcsr2gr, LARCH_USI_FTYPE_UQI, hard_float),
|
||||
#define LARCH_MOVGR2FCSR 1
|
||||
DIRECT_NO_TARGET_BUILTIN (movgr2fcsr, LARCH_VOID_FTYPE_UQI_USI, hard_float),
|
||||
|
||||
DIRECT_NO_TARGET_BUILTIN (cacop_w, LARCH_VOID_FTYPE_USI_USI_SI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (cacop_d, LARCH_VOID_FTYPE_USI_UDI_SI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (dbar, LARCH_VOID_FTYPE_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (ibar, LARCH_VOID_FTYPE_USI, default),
|
||||
|
||||
DIRECT_BUILTIN (lddir_d, LARCH_DI_FTYPE_DI_UQI, default),
|
||||
DIRECT_BUILTIN (lddir_w, LARCH_SI_FTYPE_SI_UQI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (ldpte_d, LARCH_VOID_FTYPE_DI_UQI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (ldpte_w, LARCH_VOID_FTYPE_SI_UQI, default),
|
||||
|
||||
/* CRC Instrinsic */
|
||||
|
||||
DIRECT_BUILTIN (crc_w_b_w, LARCH_SI_FTYPE_QI_SI, default),
|
||||
DIRECT_BUILTIN (crc_w_h_w, LARCH_SI_FTYPE_HI_SI, default),
|
||||
DIRECT_BUILTIN (crc_w_w_w, LARCH_SI_FTYPE_SI_SI, default),
|
||||
DIRECT_BUILTIN (crc_w_d_w, LARCH_SI_FTYPE_DI_SI, default),
|
||||
DIRECT_BUILTIN (crcc_w_b_w, LARCH_SI_FTYPE_QI_SI, default),
|
||||
DIRECT_BUILTIN (crcc_w_h_w, LARCH_SI_FTYPE_HI_SI, default),
|
||||
DIRECT_BUILTIN (crcc_w_w_w, LARCH_SI_FTYPE_SI_SI, default),
|
||||
DIRECT_BUILTIN (crcc_w_d_w, LARCH_SI_FTYPE_DI_SI, default),
|
||||
|
||||
DIRECT_BUILTIN (csrrd_w, LARCH_USI_FTYPE_USI, default),
|
||||
DIRECT_BUILTIN (csrrd_d, LARCH_UDI_FTYPE_USI, default),
|
||||
DIRECT_BUILTIN (csrwr_w, LARCH_USI_FTYPE_USI_USI, default),
|
||||
DIRECT_BUILTIN (csrwr_d, LARCH_UDI_FTYPE_UDI_USI, default),
|
||||
DIRECT_BUILTIN (csrxchg_w, LARCH_USI_FTYPE_USI_USI_USI, default),
|
||||
DIRECT_BUILTIN (csrxchg_d, LARCH_UDI_FTYPE_UDI_UDI_USI, default),
|
||||
DIRECT_BUILTIN (iocsrrd_b, LARCH_UQI_FTYPE_USI, default),
|
||||
DIRECT_BUILTIN (iocsrrd_h, LARCH_UHI_FTYPE_USI, default),
|
||||
DIRECT_BUILTIN (iocsrrd_w, LARCH_USI_FTYPE_USI, default),
|
||||
DIRECT_BUILTIN (iocsrrd_d, LARCH_UDI_FTYPE_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (iocsrwr_b, LARCH_VOID_FTYPE_UQI_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (iocsrwr_h, LARCH_VOID_FTYPE_UHI_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (iocsrwr_w, LARCH_VOID_FTYPE_USI_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (iocsrwr_d, LARCH_VOID_FTYPE_UDI_USI, default),
|
||||
|
||||
DIRECT_BUILTIN (cpucfg, LARCH_USI_FTYPE_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (asrtle_d, LARCH_VOID_FTYPE_DI_DI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (asrtgt_d, LARCH_VOID_FTYPE_DI_DI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (syscall, LARCH_VOID_FTYPE_USI, default),
|
||||
DIRECT_NO_TARGET_BUILTIN (break, LARCH_VOID_FTYPE_USI, default),
|
||||
};
|
||||
|
||||
/* Index I is the function declaration for loongarch_builtins[I], or null if
|
||||
the function isn't defined on this target. */
|
||||
static GTY (()) tree loongarch_builtin_decls[ARRAY_SIZE (loongarch_builtins)];
|
||||
/* Get the index I of the function declaration for loongarch_builtin_decls[I]
|
||||
using the instruction code or return null if not defined for the target. */
|
||||
static GTY (()) int loongarch_get_builtin_decl_index[NUM_INSN_CODES];
|
||||
|
||||
/* Source-level argument types. */
|
||||
#define LARCH_ATYPE_VOID void_type_node
|
||||
#define LARCH_ATYPE_INT integer_type_node
|
||||
#define LARCH_ATYPE_POINTER ptr_type_node
|
||||
|
||||
/* Standard mode-based argument types. */
|
||||
#define LARCH_ATYPE_QI intQI_type_node
|
||||
#define LARCH_ATYPE_UQI unsigned_intQI_type_node
|
||||
#define LARCH_ATYPE_HI intHI_type_node
|
||||
#define LARCH_ATYPE_UHI unsigned_intHI_type_node
|
||||
#define LARCH_ATYPE_SI intSI_type_node
|
||||
#define LARCH_ATYPE_USI unsigned_intSI_type_node
|
||||
#define LARCH_ATYPE_DI intDI_type_node
|
||||
#define LARCH_ATYPE_UDI unsigned_intDI_type_node
|
||||
#define LARCH_ATYPE_SF float_type_node
|
||||
#define LARCH_ATYPE_DF double_type_node
|
||||
|
||||
/* LARCH_FTYPE_ATYPESN takes N LARCH_FTYPES-like type codes and lists
|
||||
their associated LARCH_ATYPEs. */
|
||||
#define LARCH_FTYPE_ATYPES1(A, B) LARCH_ATYPE_##A, LARCH_ATYPE_##B
|
||||
|
||||
#define LARCH_FTYPE_ATYPES2(A, B, C) \
|
||||
LARCH_ATYPE_##A, LARCH_ATYPE_##B, LARCH_ATYPE_##C
|
||||
|
||||
#define LARCH_FTYPE_ATYPES3(A, B, C, D) \
|
||||
LARCH_ATYPE_##A, LARCH_ATYPE_##B, LARCH_ATYPE_##C, LARCH_ATYPE_##D
|
||||
|
||||
#define LARCH_FTYPE_ATYPES4(A, B, C, D, E) \
|
||||
LARCH_ATYPE_##A, LARCH_ATYPE_##B, LARCH_ATYPE_##C, LARCH_ATYPE_##D, \
|
||||
LARCH_ATYPE_##E
|
||||
|
||||
/* Return the function type associated with function prototype TYPE. */
|
||||
|
||||
static tree
|
||||
loongarch_build_function_type (enum loongarch_function_type type)
|
||||
{
|
||||
static tree types[(int) LARCH_MAX_FTYPE_MAX];
|
||||
|
||||
if (types[(int) type] == NULL_TREE)
|
||||
switch (type)
|
||||
{
|
||||
#define DEF_LARCH_FTYPE(NUM, ARGS) \
|
||||
case LARCH_FTYPE_NAME##NUM ARGS: \
|
||||
types[(int) type] \
|
||||
= build_function_type_list (LARCH_FTYPE_ATYPES##NUM ARGS, NULL_TREE); \
|
||||
break;
|
||||
#include "config/loongarch/loongarch-ftypes.def"
|
||||
#undef DEF_LARCH_FTYPE
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
return types[(int) type];
|
||||
}
|
||||
|
||||
/* Implement TARGET_INIT_BUILTINS. */
|
||||
|
||||
void
|
||||
loongarch_init_builtins (void)
|
||||
{
|
||||
const struct loongarch_builtin_description *d;
|
||||
unsigned int i;
|
||||
tree type;
|
||||
|
||||
/* Iterate through all of the bdesc arrays, initializing all of the
|
||||
builtin functions. */
|
||||
for (i = 0; i < ARRAY_SIZE (loongarch_builtins); i++)
|
||||
{
|
||||
d = &loongarch_builtins[i];
|
||||
if (d->avail ())
|
||||
{
|
||||
type = loongarch_build_function_type (d->function_type);
|
||||
loongarch_builtin_decls[i]
|
||||
= add_builtin_function (d->name, type, i, BUILT_IN_MD, NULL,
|
||||
NULL);
|
||||
loongarch_get_builtin_decl_index[d->icode] = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Implement TARGET_BUILTIN_DECL. */
|
||||
|
||||
tree
|
||||
loongarch_builtin_decl (unsigned int code, bool initialize_p ATTRIBUTE_UNUSED)
|
||||
{
|
||||
if (code >= ARRAY_SIZE (loongarch_builtins))
|
||||
return error_mark_node;
|
||||
return loongarch_builtin_decls[code];
|
||||
}
|
||||
|
||||
/* Take argument ARGNO from EXP's argument list and convert it into
|
||||
an expand operand. Store the operand in *OP. */
|
||||
|
||||
static void
|
||||
loongarch_prepare_builtin_arg (struct expand_operand *op, tree exp,
|
||||
unsigned int argno)
|
||||
{
|
||||
tree arg;
|
||||
rtx value;
|
||||
|
||||
arg = CALL_EXPR_ARG (exp, argno);
|
||||
value = expand_normal (arg);
|
||||
create_input_operand (op, value, TYPE_MODE (TREE_TYPE (arg)));
|
||||
}
|
||||
|
||||
/* Expand instruction ICODE as part of a built-in function sequence.
|
||||
Use the first NOPS elements of OPS as the instruction's operands.
|
||||
HAS_TARGET_P is true if operand 0 is a target; it is false if the
|
||||
instruction has no target.
|
||||
|
||||
Return the target rtx if HAS_TARGET_P, otherwise return const0_rtx. */
|
||||
|
||||
static rtx
|
||||
loongarch_expand_builtin_insn (enum insn_code icode, unsigned int nops,
|
||||
struct expand_operand *ops, bool has_target_p)
|
||||
{
|
||||
if (!maybe_expand_insn (icode, nops, ops))
|
||||
{
|
||||
error ("invalid argument to built-in function");
|
||||
return has_target_p ? gen_reg_rtx (ops[0].mode) : const0_rtx;
|
||||
}
|
||||
return has_target_p ? ops[0].value : const0_rtx;
|
||||
}
|
||||
|
||||
/* Expand a LARCH_BUILTIN_DIRECT or LARCH_BUILTIN_DIRECT_NO_TARGET function;
|
||||
HAS_TARGET_P says which. EXP is the CALL_EXPR that calls the function
|
||||
and ICODE is the code of the associated .md pattern. TARGET, if nonnull,
|
||||
suggests a good place to put the result. */
|
||||
|
||||
static rtx
|
||||
loongarch_expand_builtin_direct (enum insn_code icode, rtx target, tree exp,
|
||||
bool has_target_p)
|
||||
{
|
||||
struct expand_operand ops[MAX_RECOG_OPERANDS];
|
||||
int opno, argno;
|
||||
|
||||
/* Map any target to operand 0. */
|
||||
opno = 0;
|
||||
if (has_target_p)
|
||||
create_output_operand (&ops[opno++], target, TYPE_MODE (TREE_TYPE (exp)));
|
||||
|
||||
/* Map the arguments to the other operands. */
|
||||
gcc_assert (opno + call_expr_nargs (exp)
|
||||
== insn_data[icode].n_generator_args);
|
||||
for (argno = 0; argno < call_expr_nargs (exp); argno++)
|
||||
loongarch_prepare_builtin_arg (&ops[opno++], exp, argno);
|
||||
|
||||
return loongarch_expand_builtin_insn (icode, opno, ops, has_target_p);
|
||||
}
|
||||
|
||||
/* Implement TARGET_EXPAND_BUILTIN. */
|
||||
|
||||
rtx
|
||||
loongarch_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
|
||||
machine_mode mode ATTRIBUTE_UNUSED,
|
||||
int ignore ATTRIBUTE_UNUSED)
|
||||
{
|
||||
tree fndecl;
|
||||
unsigned int fcode, avail;
|
||||
const struct loongarch_builtin_description *d;
|
||||
|
||||
fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
|
||||
fcode = DECL_MD_FUNCTION_CODE (fndecl);
|
||||
gcc_assert (fcode < ARRAY_SIZE (loongarch_builtins));
|
||||
d = &loongarch_builtins[fcode];
|
||||
avail = d->avail ();
|
||||
gcc_assert (avail != 0);
|
||||
switch (d->builtin_type)
|
||||
{
|
||||
case LARCH_BUILTIN_DIRECT:
|
||||
return loongarch_expand_builtin_direct (d->icode, target, exp, true);
|
||||
|
||||
case LARCH_BUILTIN_DIRECT_NO_TARGET:
|
||||
return loongarch_expand_builtin_direct (d->icode, target, exp, false);
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
/* Implement TARGET_ATOMIC_ASSIGN_EXPAND_FENV. */
|
||||
|
||||
void
|
||||
loongarch_atomic_assign_expand_fenv (tree *hold, tree *clear, tree *update)
|
||||
{
|
||||
if (!TARGET_HARD_FLOAT_ABI)
|
||||
return;
|
||||
tree exceptions_var = create_tmp_var_raw (LARCH_ATYPE_USI);
|
||||
tree fcsr_orig_var = create_tmp_var_raw (LARCH_ATYPE_USI);
|
||||
tree fcsr_mod_var = create_tmp_var_raw (LARCH_ATYPE_USI);
|
||||
tree const0 = build_int_cst (LARCH_ATYPE_UQI, 0);
|
||||
tree get_fcsr = loongarch_builtin_decls[LARCH_MOVFCSR2GR];
|
||||
tree set_fcsr = loongarch_builtin_decls[LARCH_MOVGR2FCSR];
|
||||
tree get_fcsr_hold_call = build_call_expr (get_fcsr, 1, const0);
|
||||
tree hold_assign_orig = build4 (TARGET_EXPR, LARCH_ATYPE_USI,
|
||||
fcsr_orig_var, get_fcsr_hold_call,
|
||||
NULL, NULL);
|
||||
tree hold_mod_val = build2 (BIT_AND_EXPR, LARCH_ATYPE_USI, fcsr_orig_var,
|
||||
build_int_cst (LARCH_ATYPE_USI, 0xffe0ffe0));
|
||||
tree hold_assign_mod = build4 (TARGET_EXPR, LARCH_ATYPE_USI,
|
||||
fcsr_mod_var, hold_mod_val, NULL, NULL);
|
||||
tree set_fcsr_hold_call = build_call_expr (set_fcsr, 2, const0,
|
||||
fcsr_mod_var);
|
||||
tree hold_all = build2 (COMPOUND_EXPR, LARCH_ATYPE_USI, hold_assign_orig,
|
||||
hold_assign_mod);
|
||||
*hold = build2 (COMPOUND_EXPR, void_type_node, hold_all, set_fcsr_hold_call);
|
||||
|
||||
*clear = build_call_expr (set_fcsr, 2, const0, fcsr_mod_var);
|
||||
|
||||
tree get_fcsr_update_call = build_call_expr (get_fcsr, 1, const0);
|
||||
*update = build4 (TARGET_EXPR, LARCH_ATYPE_USI, exceptions_var,
|
||||
get_fcsr_update_call, NULL, NULL);
|
||||
tree set_fcsr_update_call = build_call_expr (set_fcsr, 2, const0,
|
||||
fcsr_orig_var);
|
||||
*update = build2 (COMPOUND_EXPR, void_type_node, *update,
|
||||
set_fcsr_update_call);
|
||||
tree atomic_feraiseexcept
|
||||
= builtin_decl_implicit (BUILT_IN_ATOMIC_FERAISEEXCEPT);
|
||||
tree int_exceptions_var = fold_convert (integer_type_node, exceptions_var);
|
||||
tree atomic_feraiseexcept_call = build_call_expr (atomic_feraiseexcept, 1,
|
||||
int_exceptions_var);
|
||||
*update = build2 (COMPOUND_EXPR, void_type_node, *update,
|
||||
atomic_feraiseexcept_call);
|
||||
}
|
||||
|
||||
/* Implement TARGET_BUILTIN_VA_LIST. */
|
||||
|
||||
tree
|
||||
loongarch_build_builtin_va_list (void)
|
||||
{
|
||||
return ptr_type_node;
|
||||
}
|
|
@ -0,0 +1,109 @@
|
|||
/* LoongArch-specific code for C family languages.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
#define IN_TARGET_CODE 1
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "c-family/c-common.h"
|
||||
#include "cpplib.h"
|
||||
|
||||
#define preprocessing_asm_p() (cpp_get_options (pfile)->lang == CLK_ASM)
|
||||
#define builtin_define(TXT) cpp_define (pfile, TXT)
|
||||
#define builtin_assert(TXT) cpp_assert (pfile, TXT)
|
||||
|
||||
/* Define preprocessor macros for the -march and -mtune options.
|
||||
PREFIX is either _LOONGARCH_ARCH or _LOONGARCH_TUNE, INFO is
|
||||
the selected processor. If INFO's canonical name is "foo",
|
||||
define PREFIX to be "foo", and define an additional macro
|
||||
PREFIX_FOO. */
|
||||
#define LARCH_CPP_SET_PROCESSOR(PREFIX, CPU_TYPE) \
|
||||
do \
|
||||
{ \
|
||||
char *macro, *p; \
|
||||
int cpu_type = (CPU_TYPE); \
|
||||
\
|
||||
macro = concat ((PREFIX), "_", \
|
||||
loongarch_cpu_strings[cpu_type], NULL); \
|
||||
for (p = macro; *p != 0; p++) \
|
||||
*p = TOUPPER (*p); \
|
||||
\
|
||||
builtin_define (macro); \
|
||||
builtin_define_with_value ((PREFIX), \
|
||||
loongarch_cpu_strings[cpu_type], 1); \
|
||||
free (macro); \
|
||||
} \
|
||||
while (0)
|
||||
|
||||
void
|
||||
loongarch_cpu_cpp_builtins (cpp_reader *pfile)
|
||||
{
|
||||
builtin_assert ("machine=loongarch");
|
||||
builtin_assert ("cpu=loongarch");
|
||||
builtin_define ("__loongarch__");
|
||||
|
||||
LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_ARCH", LARCH_ACTUAL_ARCH);
|
||||
LARCH_CPP_SET_PROCESSOR ("_LOONGARCH_TUNE", LARCH_ACTUAL_TUNE);
|
||||
|
||||
/* Base architecture / ABI. */
|
||||
if (TARGET_64BIT)
|
||||
{
|
||||
builtin_define ("__loongarch_grlen=64");
|
||||
builtin_define ("__loongarch64");
|
||||
}
|
||||
|
||||
if (TARGET_ABI_LP64)
|
||||
{
|
||||
builtin_define ("_ABILP64=3");
|
||||
builtin_define ("_LOONGARCH_SIM=_ABILP64");
|
||||
builtin_define ("__loongarch_lp64");
|
||||
}
|
||||
|
||||
/* These defines reflect the ABI in use, not whether the
|
||||
FPU is directly accessible. */
|
||||
if (TARGET_DOUBLE_FLOAT_ABI)
|
||||
builtin_define ("__loongarch_double_float=1");
|
||||
else if (TARGET_SINGLE_FLOAT_ABI)
|
||||
builtin_define ("__loongarch_single_float=1");
|
||||
|
||||
if (TARGET_DOUBLE_FLOAT_ABI || TARGET_SINGLE_FLOAT_ABI)
|
||||
builtin_define ("__loongarch_hard_float=1");
|
||||
else
|
||||
builtin_define ("__loongarch_soft_float=1");
|
||||
|
||||
|
||||
/* ISA Extensions. */
|
||||
if (TARGET_DOUBLE_FLOAT)
|
||||
builtin_define ("__loongarch_frlen=64");
|
||||
else if (TARGET_SINGLE_FLOAT)
|
||||
builtin_define ("__loongarch_frlen=32");
|
||||
else
|
||||
builtin_define ("__loongarch_frlen=0");
|
||||
|
||||
/* Native Data Sizes. */
|
||||
builtin_define_with_int_value ("_LOONGARCH_SZINT", INT_TYPE_SIZE);
|
||||
builtin_define_with_int_value ("_LOONGARCH_SZLONG", LONG_TYPE_SIZE);
|
||||
builtin_define_with_int_value ("_LOONGARCH_SZPTR", POINTER_SIZE);
|
||||
builtin_define_with_int_value ("_LOONGARCH_FPSET", 32);
|
||||
builtin_define_with_int_value ("_LOONGARCH_SPFPSET", 32);
|
||||
|
||||
}
|
|
@ -0,0 +1,206 @@
|
|||
/* Definitions for LoongArch CPU properties.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
#define IN_TARGET_CODE 1
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "diagnostic-core.h"
|
||||
|
||||
#include "loongarch-opts.h"
|
||||
#include "loongarch-cpu.h"
|
||||
#include "loongarch-str.h"
|
||||
|
||||
/* Native CPU detection with "cpucfg" */
|
||||
#define N_CPUCFG_WORDS 0x15
|
||||
static uint32_t cpucfg_cache[N_CPUCFG_WORDS] = { 0 };
|
||||
static const int cpucfg_useful_idx[] = {0, 1, 2, 16, 17, 18, 19};
|
||||
|
||||
static uint32_t
|
||||
read_cpucfg_word (int wordno)
|
||||
{
|
||||
/* To make cross-compiler shut up. */
|
||||
(void) wordno;
|
||||
uint32_t ret = 0;
|
||||
|
||||
#ifdef __loongarch__
|
||||
__asm__ __volatile__ ("cpucfg %0,%1\n\t"
|
||||
:"=r"(ret)
|
||||
:"r"(wordno)
|
||||
:);
|
||||
#endif
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void
|
||||
cache_cpucfg (void)
|
||||
{
|
||||
for (unsigned int i = 0; i < sizeof (cpucfg_useful_idx) / sizeof (int); i++)
|
||||
{
|
||||
cpucfg_cache[cpucfg_useful_idx[i]]
|
||||
= read_cpucfg_word (cpucfg_useful_idx[i]);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
get_native_prid (void)
|
||||
{
|
||||
/* Fill loongarch_cpu_default_config[CPU_NATIVE] with cpucfg data,
|
||||
see "Loongson Architecture Reference Manual"
|
||||
(Volume 1, Section 2.2.10.5) */
|
||||
return cpucfg_cache[0];
|
||||
}
|
||||
|
||||
const char*
|
||||
get_native_prid_str (void)
|
||||
{
|
||||
static char prid_str[9];
|
||||
sprintf (prid_str, "%08x", cpucfg_cache[0]);
|
||||
return (const char*) prid_str;
|
||||
}
|
||||
|
||||
/* Fill property tables for CPU_NATIVE. */
|
||||
unsigned int
|
||||
fill_native_cpu_config (int p_arch_native, int p_tune_native)
|
||||
{
|
||||
int ret_cpu_type;
|
||||
|
||||
/* Nothing needs to be done unless "-march/tune=native"
|
||||
is given or implied. */
|
||||
if (!(p_arch_native || p_tune_native))
|
||||
return CPU_NATIVE;
|
||||
|
||||
/* Fill cpucfg_cache with the "cpucfg" instruction. */
|
||||
cache_cpucfg ();
|
||||
|
||||
|
||||
/* Fill: loongarch_cpu_default_isa[CPU_NATIVE].base
|
||||
With: base architecture (ARCH)
|
||||
At: cpucfg_words[1][1:0] */
|
||||
|
||||
#define NATIVE_BASE_ISA (loongarch_cpu_default_isa[CPU_NATIVE].base)
|
||||
switch (cpucfg_cache[1] & 0x3)
|
||||
{
|
||||
case 0x02:
|
||||
NATIVE_BASE_ISA = ISA_BASE_LA64V100;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (p_arch_native)
|
||||
fatal_error (UNKNOWN_LOCATION,
|
||||
"unknown base architecture %<0x%x%>, %qs failed",
|
||||
(unsigned int) (cpucfg_cache[1] & 0x3),
|
||||
"-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
|
||||
}
|
||||
|
||||
/* Fill: loongarch_cpu_default_isa[CPU_NATIVE].fpu
|
||||
With: FPU type (FP, FP_SP, FP_DP)
|
||||
At: cpucfg_words[2][2:0] */
|
||||
|
||||
#define NATIVE_FPU (loongarch_cpu_default_isa[CPU_NATIVE].fpu)
|
||||
switch (cpucfg_cache[2] & 0x7)
|
||||
{
|
||||
case 0x07:
|
||||
NATIVE_FPU = ISA_EXT_FPU64;
|
||||
break;
|
||||
|
||||
case 0x03:
|
||||
NATIVE_FPU = ISA_EXT_FPU32;
|
||||
break;
|
||||
|
||||
case 0x00:
|
||||
NATIVE_FPU = ISA_EXT_NOFPU;
|
||||
break;
|
||||
|
||||
default:
|
||||
if (p_arch_native)
|
||||
fatal_error (UNKNOWN_LOCATION,
|
||||
"unknown FPU type %<0x%x%>, %qs failed",
|
||||
(unsigned int) (cpucfg_cache[2] & 0x7),
|
||||
"-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
|
||||
}
|
||||
|
||||
/* Fill: loongarch_cpu_cache[CPU_NATIVE]
|
||||
With: cache size info
|
||||
At: cpucfg_words[16:20][31:0] */
|
||||
|
||||
int l1d_present = 0, l1u_present = 0;
|
||||
int l2d_present = 0;
|
||||
uint32_t l1_szword, l2_szword;
|
||||
|
||||
l1u_present |= cpucfg_cache[16] & 3; /* bit[1:0]: unified l1 cache */
|
||||
l1d_present |= cpucfg_cache[16] & 4; /* bit[2:2]: l1 dcache */
|
||||
l1_szword = l1d_present ? 18 : (l1u_present ? 17 : 0);
|
||||
l1_szword = l1_szword ? cpucfg_cache[l1_szword]: 0;
|
||||
|
||||
l2d_present |= cpucfg_cache[16] & 24; /* bit[4:3]: unified l2 cache */
|
||||
l2d_present |= cpucfg_cache[16] & 128; /* bit[7:7]: l2 dcache */
|
||||
l2_szword = l2d_present ? cpucfg_cache[19]: 0;
|
||||
|
||||
loongarch_cpu_cache[CPU_NATIVE].l1d_line_size
|
||||
= 1 << ((l1_szword & 0x7f000000) >> 24); /* bit[30:24]: log2(linesize) */
|
||||
|
||||
loongarch_cpu_cache[CPU_NATIVE].l1d_size
|
||||
= (1 << ((l1_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
|
||||
* ((l1_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */
|
||||
* (1 << ((l1_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
|
||||
>> 10; /* in kilobytes */
|
||||
|
||||
loongarch_cpu_cache[CPU_NATIVE].l2d_size
|
||||
= (1 << ((l2_szword & 0x00ff0000) >> 16)) /* bit[23:16]: log2(idx) */
|
||||
* ((l2_szword & 0x0000ffff) + 1) /* bit[15:0]: sets - 1 */
|
||||
* (1 << ((l2_szword & 0x7f000000) >> 24)) /* bit[30:24]: log2(linesize) */
|
||||
>> 10; /* in kilobytes */
|
||||
|
||||
/* Fill: ret_cpu_type
|
||||
With: processor ID (PRID)
|
||||
At: cpucfg_words[0][31:0] */
|
||||
|
||||
switch (cpucfg_cache[0] & 0x00ffff00)
|
||||
{
|
||||
case 0x0014c000: /* LA464 */
|
||||
ret_cpu_type = CPU_LA464;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown PRID. This is generally harmless as long as
|
||||
the properties above can be obtained via "cpucfg". */
|
||||
if (p_tune_native)
|
||||
inform (UNKNOWN_LOCATION, "unknown processor ID %<0x%x%>, "
|
||||
"some tuning parameters will fall back to default",
|
||||
cpucfg_cache[0]);
|
||||
break;
|
||||
}
|
||||
|
||||
/* Properties that cannot be looked up directly using cpucfg. */
|
||||
loongarch_cpu_issue_rate[CPU_NATIVE]
|
||||
= loongarch_cpu_issue_rate[ret_cpu_type];
|
||||
|
||||
loongarch_cpu_multipass_dfa_lookahead[CPU_NATIVE]
|
||||
= loongarch_cpu_multipass_dfa_lookahead[ret_cpu_type];
|
||||
|
||||
loongarch_cpu_rtx_cost_data[CPU_NATIVE]
|
||||
= loongarch_cpu_rtx_cost_data[ret_cpu_type];
|
||||
|
||||
return ret_cpu_type;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/* Definitions for loongarch native cpu property detection routines.
|
||||
Copyright (C) 2020-2021 Free Software Foundation, Inc.
|
||||
|
||||
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 LOONGARCH_CPU_H
|
||||
#define LOONGARCH_CPU_H
|
||||
|
||||
#include "system.h"
|
||||
|
||||
void cache_cpucfg (void);
|
||||
unsigned int fill_native_cpu_config (int p_arch_native, int p_tune_native);
|
||||
uint32_t get_native_prid (void);
|
||||
const char* get_native_prid_str (void);
|
||||
|
||||
#endif /* LOONGARCH_CPU_H */
|
|
@ -0,0 +1,179 @@
|
|||
/* LoongArch static properties.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
#include "loongarch-def.h"
|
||||
#include "loongarch-str.h"
|
||||
|
||||
/* Default RTX cost initializer. */
|
||||
#define COSTS_N_INSNS(N) ((N) * 4)
|
||||
#define DEFAULT_COSTS \
|
||||
.fp_add = COSTS_N_INSNS (1), \
|
||||
.fp_mult_sf = COSTS_N_INSNS (2), \
|
||||
.fp_mult_df = COSTS_N_INSNS (4), \
|
||||
.fp_div_sf = COSTS_N_INSNS (6), \
|
||||
.fp_div_df = COSTS_N_INSNS (8), \
|
||||
.int_mult_si = COSTS_N_INSNS (1), \
|
||||
.int_mult_di = COSTS_N_INSNS (1), \
|
||||
.int_div_si = COSTS_N_INSNS (4), \
|
||||
.int_div_di = COSTS_N_INSNS (6), \
|
||||
.branch_cost = 2, \
|
||||
.memory_latency = 4
|
||||
|
||||
/* CPU property tables. */
|
||||
const char*
|
||||
loongarch_cpu_strings[N_TUNE_TYPES] = {
|
||||
[CPU_NATIVE] = STR_CPU_NATIVE,
|
||||
[CPU_LOONGARCH64] = STR_CPU_LOONGARCH64,
|
||||
[CPU_LA464] = STR_CPU_LA464,
|
||||
};
|
||||
|
||||
struct loongarch_isa
|
||||
loongarch_cpu_default_isa[N_ARCH_TYPES] = {
|
||||
[CPU_LOONGARCH64] = {
|
||||
.base = ISA_BASE_LA64V100,
|
||||
.fpu = ISA_EXT_FPU64,
|
||||
},
|
||||
[CPU_LA464] = {
|
||||
.base = ISA_BASE_LA64V100,
|
||||
.fpu = ISA_EXT_FPU64,
|
||||
},
|
||||
};
|
||||
|
||||
struct loongarch_cache
|
||||
loongarch_cpu_cache[N_TUNE_TYPES] = {
|
||||
[CPU_LOONGARCH64] = {
|
||||
.l1d_line_size = 64,
|
||||
.l1d_size = 64,
|
||||
.l2d_size = 256,
|
||||
},
|
||||
[CPU_LA464] = {
|
||||
.l1d_line_size = 64,
|
||||
.l1d_size = 64,
|
||||
.l2d_size = 256,
|
||||
},
|
||||
};
|
||||
|
||||
/* The following properties cannot be looked up directly using "cpucfg".
|
||||
So it is necessary to provide a default value for "unknown native"
|
||||
tune targets (i.e. -mtune=native while PRID does not correspond to
|
||||
any known "-mtune" type). */
|
||||
|
||||
struct loongarch_rtx_cost_data
|
||||
loongarch_cpu_rtx_cost_data[N_TUNE_TYPES] = {
|
||||
[CPU_NATIVE] = {
|
||||
DEFAULT_COSTS
|
||||
},
|
||||
[CPU_LOONGARCH64] = {
|
||||
DEFAULT_COSTS
|
||||
},
|
||||
[CPU_LA464] = {
|
||||
DEFAULT_COSTS
|
||||
},
|
||||
};
|
||||
|
||||
/* RTX costs to use when optimizing for size. */
|
||||
extern const struct loongarch_rtx_cost_data
|
||||
loongarch_rtx_cost_optimize_size = {
|
||||
.fp_add = 4,
|
||||
.fp_mult_sf = 4,
|
||||
.fp_mult_df = 4,
|
||||
.fp_div_sf = 4,
|
||||
.fp_div_df = 4,
|
||||
.int_mult_si = 4,
|
||||
.int_mult_di = 4,
|
||||
.int_div_si = 4,
|
||||
.int_div_di = 4,
|
||||
.branch_cost = 2,
|
||||
.memory_latency = 4,
|
||||
};
|
||||
|
||||
int
|
||||
loongarch_cpu_issue_rate[N_TUNE_TYPES] = {
|
||||
[CPU_NATIVE] = 4,
|
||||
[CPU_LOONGARCH64] = 4,
|
||||
[CPU_LA464] = 4,
|
||||
};
|
||||
|
||||
int
|
||||
loongarch_cpu_multipass_dfa_lookahead[N_TUNE_TYPES] = {
|
||||
[CPU_NATIVE] = 4,
|
||||
[CPU_LOONGARCH64] = 4,
|
||||
[CPU_LA464] = 4,
|
||||
};
|
||||
|
||||
/* Wiring string definitions from loongarch-str.h to global arrays
|
||||
with standard index values from loongarch-opts.h, so we can
|
||||
print config-related messages and do ABI self-spec filtering
|
||||
from the driver in a self-consistent manner. */
|
||||
|
||||
const char*
|
||||
loongarch_isa_base_strings[N_ISA_BASE_TYPES] = {
|
||||
[ISA_BASE_LA64V100] = STR_ISA_BASE_LA64V100,
|
||||
};
|
||||
|
||||
const char*
|
||||
loongarch_isa_ext_strings[N_ISA_EXT_TYPES] = {
|
||||
[ISA_EXT_FPU64] = STR_ISA_EXT_FPU64,
|
||||
[ISA_EXT_FPU32] = STR_ISA_EXT_FPU32,
|
||||
[ISA_EXT_NOFPU] = STR_ISA_EXT_NOFPU,
|
||||
};
|
||||
|
||||
const char*
|
||||
loongarch_abi_base_strings[N_ABI_BASE_TYPES] = {
|
||||
[ABI_BASE_LP64D] = STR_ABI_BASE_LP64D,
|
||||
[ABI_BASE_LP64F] = STR_ABI_BASE_LP64F,
|
||||
[ABI_BASE_LP64S] = STR_ABI_BASE_LP64S,
|
||||
};
|
||||
|
||||
const char*
|
||||
loongarch_abi_ext_strings[N_ABI_EXT_TYPES] = {
|
||||
[ABI_EXT_BASE] = STR_ABI_EXT_BASE,
|
||||
};
|
||||
|
||||
const char*
|
||||
loongarch_cmodel_strings[] = {
|
||||
[CMODEL_NORMAL] = STR_CMODEL_NORMAL,
|
||||
[CMODEL_TINY] = STR_CMODEL_TINY,
|
||||
[CMODEL_TINY_STATIC] = STR_CMODEL_TS,
|
||||
[CMODEL_LARGE] = STR_CMODEL_LARGE,
|
||||
[CMODEL_EXTREME] = STR_CMODEL_EXTREME,
|
||||
};
|
||||
|
||||
const char*
|
||||
loongarch_switch_strings[] = {
|
||||
[SW_SOFT_FLOAT] = OPTSTR_SOFT_FLOAT,
|
||||
[SW_SINGLE_FLOAT] = OPTSTR_SINGLE_FLOAT,
|
||||
[SW_DOUBLE_FLOAT] = OPTSTR_DOUBLE_FLOAT,
|
||||
};
|
||||
|
||||
|
||||
/* ABI-related definitions. */
|
||||
const struct loongarch_isa
|
||||
abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = {
|
||||
[ABI_BASE_LP64D] = {
|
||||
[ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU64},
|
||||
},
|
||||
[ABI_BASE_LP64F] = {
|
||||
[ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_FPU32},
|
||||
},
|
||||
[ABI_BASE_LP64S] = {
|
||||
[ABI_EXT_BASE] = {.base = ISA_BASE_LA64V100, .fpu = ISA_EXT_NOFPU},
|
||||
},
|
||||
};
|
|
@ -0,0 +1,151 @@
|
|||
/* LoongArch definitions.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
/* Definition of standard codes for:
|
||||
- base architecture types (isa_base),
|
||||
- ISA extensions (isa_ext),
|
||||
- base ABI types (abi_base),
|
||||
- ABI extension types (abi_ext).
|
||||
|
||||
- code models (cmodel)
|
||||
- other command-line switches (switch)
|
||||
|
||||
These values are primarily used for implementing option handling
|
||||
logic in "loongarch.opt", "loongarch-driver.c" and "loongarch-opt.c".
|
||||
|
||||
As for the result of this option handling process, the following
|
||||
scheme is adopted to represent the final configuration:
|
||||
|
||||
- The target ABI is encoded with a tuple (abi_base, abi_ext)
|
||||
using the code defined below.
|
||||
|
||||
- The target ISA is encoded with a "struct loongarch_isa" defined
|
||||
in loongarch-cpu.h.
|
||||
|
||||
- The target microarchitecture is represented with a cpu model
|
||||
index defined in loongarch-cpu.h.
|
||||
*/
|
||||
|
||||
#ifndef LOONGARCH_DEF_H
|
||||
#define LOONGARCH_DEF_H
|
||||
|
||||
#include "loongarch-tune.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* enum isa_base */
|
||||
extern const char* loongarch_isa_base_strings[];
|
||||
#define ISA_BASE_LA64V100 0
|
||||
#define N_ISA_BASE_TYPES 1
|
||||
|
||||
/* enum isa_ext_* */
|
||||
extern const char* loongarch_isa_ext_strings[];
|
||||
#define ISA_EXT_NOFPU 0
|
||||
#define ISA_EXT_FPU32 1
|
||||
#define ISA_EXT_FPU64 2
|
||||
#define N_ISA_EXT_FPU_TYPES 3
|
||||
#define N_ISA_EXT_TYPES 3
|
||||
|
||||
/* enum abi_base */
|
||||
extern const char* loongarch_abi_base_strings[];
|
||||
#define ABI_BASE_LP64D 0
|
||||
#define ABI_BASE_LP64F 1
|
||||
#define ABI_BASE_LP64S 2
|
||||
#define N_ABI_BASE_TYPES 3
|
||||
|
||||
/* enum abi_ext */
|
||||
extern const char* loongarch_abi_ext_strings[];
|
||||
#define ABI_EXT_BASE 0
|
||||
#define N_ABI_EXT_TYPES 1
|
||||
|
||||
/* enum cmodel */
|
||||
extern const char* loongarch_cmodel_strings[];
|
||||
#define CMODEL_NORMAL 0
|
||||
#define CMODEL_TINY 1
|
||||
#define CMODEL_TINY_STATIC 2
|
||||
#define CMODEL_LARGE 3
|
||||
#define CMODEL_EXTREME 4
|
||||
#define N_CMODEL_TYPES 5
|
||||
|
||||
/* enum switches */
|
||||
/* The "SW_" codes represent command-line switches (options that
|
||||
accept no parameters). Definition for other switches that affects
|
||||
the target ISA / ABI configuration will also be appended here
|
||||
in the future. */
|
||||
|
||||
extern const char* loongarch_switch_strings[];
|
||||
#define SW_SOFT_FLOAT 0
|
||||
#define SW_SINGLE_FLOAT 1
|
||||
#define SW_DOUBLE_FLOAT 2
|
||||
#define N_SWITCH_TYPES 3
|
||||
|
||||
/* The common default value for variables whose assignments
|
||||
are triggered by command-line options. */
|
||||
|
||||
#define M_OPTION_NOT_SEEN -1
|
||||
#define M_OPT_ABSENT(opt_enum) ((opt_enum) == M_OPTION_NOT_SEEN)
|
||||
|
||||
|
||||
/* Internal representation of the target. */
|
||||
struct loongarch_isa
|
||||
{
|
||||
unsigned char base; /* ISA_BASE_ */
|
||||
unsigned char fpu; /* ISA_EXT_FPU_ */
|
||||
};
|
||||
|
||||
struct loongarch_abi
|
||||
{
|
||||
unsigned char base; /* ABI_BASE_ */
|
||||
unsigned char ext; /* ABI_EXT_ */
|
||||
};
|
||||
|
||||
struct loongarch_target
|
||||
{
|
||||
struct loongarch_isa isa;
|
||||
struct loongarch_abi abi;
|
||||
unsigned char cpu_arch; /* CPU_ */
|
||||
unsigned char cpu_tune; /* same */
|
||||
unsigned char cpu_native; /* same */
|
||||
unsigned char cmodel; /* CMODEL_ */
|
||||
};
|
||||
|
||||
/* CPU properties. */
|
||||
/* index */
|
||||
#define CPU_NATIVE 0
|
||||
#define CPU_LOONGARCH64 1
|
||||
#define CPU_LA464 2
|
||||
#define N_ARCH_TYPES 3
|
||||
#define N_TUNE_TYPES 3
|
||||
|
||||
/* parallel tables. */
|
||||
extern const char* loongarch_cpu_strings[];
|
||||
extern struct loongarch_isa loongarch_cpu_default_isa[];
|
||||
extern int loongarch_cpu_issue_rate[];
|
||||
extern int loongarch_cpu_multipass_dfa_lookahead[];
|
||||
|
||||
extern struct loongarch_cache loongarch_cpu_cache[];
|
||||
extern struct loongarch_rtx_cost_data loongarch_cpu_rtx_cost_data[];
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* LOONGARCH_DEF_H */
|
|
@ -0,0 +1,187 @@
|
|||
/* Subroutines for the gcc driver.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
#define IN_TARGET_CODE 1
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "obstack.h"
|
||||
#include "diagnostic-core.h"
|
||||
|
||||
#include "loongarch-opts.h"
|
||||
#include "loongarch-driver.h"
|
||||
|
||||
static int
|
||||
opt_arch_driver = M_OPTION_NOT_SEEN,
|
||||
opt_tune_driver = M_OPTION_NOT_SEEN,
|
||||
opt_fpu_driver = M_OPTION_NOT_SEEN,
|
||||
opt_abi_base_driver = M_OPTION_NOT_SEEN,
|
||||
opt_abi_ext_driver = M_OPTION_NOT_SEEN,
|
||||
opt_cmodel_driver = M_OPTION_NOT_SEEN;
|
||||
|
||||
int opt_switches = 0;
|
||||
|
||||
/* This flag is set to 1 if we believe that the user might be avoiding
|
||||
linking (implicitly) against something from the startfile search paths. */
|
||||
static int no_link = 0;
|
||||
|
||||
#define LARCH_DRIVER_SET_M_FLAG(OPTS_ARRAY, N_OPTS, FLAG, STR) \
|
||||
for (int i = 0; i < (N_OPTS); i++) \
|
||||
{ \
|
||||
if ((OPTS_ARRAY)[i] != 0) \
|
||||
if (strcmp ((STR), (OPTS_ARRAY)[i]) == 0) \
|
||||
(FLAG) = i; \
|
||||
}
|
||||
|
||||
/* Use the public obstack from the gcc driver (defined in gcc.c).
|
||||
This is for allocating space for the returned string. */
|
||||
extern struct obstack opts_obstack;
|
||||
|
||||
#define APPEND_LTR(S) \
|
||||
obstack_grow (&opts_obstack, (const void*) (S), \
|
||||
sizeof ((S)) / sizeof (char) -1)
|
||||
|
||||
#define APPEND_VAL(S) \
|
||||
obstack_grow (&opts_obstack, (const void*) (S), strlen ((S)))
|
||||
|
||||
|
||||
const char*
|
||||
driver_set_m_flag (int argc, const char **argv)
|
||||
{
|
||||
int parm_off = 0;
|
||||
|
||||
if (argc != 1)
|
||||
return "%eset_m_flag requires exactly 1 argument.";
|
||||
|
||||
#undef PARM
|
||||
#define PARM (argv[0] + parm_off)
|
||||
|
||||
/* Note: sizeof (OPTSTR_##NAME) equals the length of "<option>=". */
|
||||
#undef MATCH_OPT
|
||||
#define MATCH_OPT(NAME) \
|
||||
(strncmp (argv[0], OPTSTR_##NAME "=", \
|
||||
(parm_off = sizeof (OPTSTR_##NAME))) == 0)
|
||||
|
||||
if (strcmp (argv[0], "no_link") == 0)
|
||||
{
|
||||
no_link = 1;
|
||||
}
|
||||
else if (MATCH_OPT (ABI_BASE))
|
||||
{
|
||||
LARCH_DRIVER_SET_M_FLAG (
|
||||
loongarch_abi_base_strings, N_ABI_BASE_TYPES,
|
||||
opt_abi_base_driver, PARM)
|
||||
}
|
||||
else if (MATCH_OPT (ISA_EXT_FPU))
|
||||
{
|
||||
LARCH_DRIVER_SET_M_FLAG (loongarch_isa_ext_strings, N_ISA_EXT_FPU_TYPES,
|
||||
opt_fpu_driver, PARM)
|
||||
}
|
||||
else if (MATCH_OPT (ARCH))
|
||||
{
|
||||
LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_ARCH_TYPES,
|
||||
opt_arch_driver, PARM)
|
||||
}
|
||||
else if (MATCH_OPT (TUNE))
|
||||
{
|
||||
LARCH_DRIVER_SET_M_FLAG (loongarch_cpu_strings, N_TUNE_TYPES,
|
||||
opt_tune_driver, PARM)
|
||||
}
|
||||
else if (MATCH_OPT (CMODEL))
|
||||
{
|
||||
LARCH_DRIVER_SET_M_FLAG (loongarch_cmodel_strings, N_CMODEL_TYPES,
|
||||
opt_cmodel_driver, PARM)
|
||||
}
|
||||
else /* switches */
|
||||
{
|
||||
int switch_idx = M_OPTION_NOT_SEEN;
|
||||
|
||||
LARCH_DRIVER_SET_M_FLAG (loongarch_switch_strings, N_SWITCH_TYPES,
|
||||
switch_idx, argv[0])
|
||||
|
||||
if (switch_idx != M_OPTION_NOT_SEEN)
|
||||
opt_switches |= loongarch_switch_mask[switch_idx];
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
const char*
|
||||
driver_get_normalized_m_opts (int argc, const char **argv)
|
||||
{
|
||||
if (argc != 0)
|
||||
{
|
||||
(void) argv; /* To make compiler shut up about unused argument. */
|
||||
return " %eget_normalized_m_opts requires no argument.\n";
|
||||
}
|
||||
|
||||
loongarch_config_target (& la_target,
|
||||
opt_switches,
|
||||
opt_arch_driver,
|
||||
opt_tune_driver,
|
||||
opt_fpu_driver,
|
||||
opt_abi_base_driver,
|
||||
opt_abi_ext_driver,
|
||||
opt_cmodel_driver,
|
||||
!no_link /* follow_multilib_list */);
|
||||
|
||||
/* Output normalized option strings. */
|
||||
obstack_blank (&opts_obstack, 0);
|
||||
|
||||
#undef APPEND_LTR
|
||||
#define APPEND_LTR(S) \
|
||||
obstack_grow (&opts_obstack, (const void*) (S), \
|
||||
sizeof ((S)) / sizeof (char) -1)
|
||||
|
||||
#undef APPEND_VAL
|
||||
#define APPEND_VAL(S) \
|
||||
obstack_grow (&opts_obstack, (const void*) (S), strlen ((S)))
|
||||
|
||||
#undef APPEND_OPT
|
||||
#define APPEND_OPT(NAME) \
|
||||
APPEND_LTR (" %<m" OPTSTR_##NAME "=* " \
|
||||
" -m" OPTSTR_##NAME "=")
|
||||
|
||||
for (int i = 0; i < N_SWITCH_TYPES; i++)
|
||||
{
|
||||
APPEND_LTR (" %<m");
|
||||
APPEND_VAL (loongarch_switch_strings[i]);
|
||||
}
|
||||
|
||||
APPEND_OPT (ABI_BASE);
|
||||
APPEND_VAL (loongarch_abi_base_strings[la_target.abi.base]);
|
||||
|
||||
APPEND_OPT (ARCH);
|
||||
APPEND_VAL (loongarch_cpu_strings[la_target.cpu_arch]);
|
||||
|
||||
APPEND_OPT (ISA_EXT_FPU);
|
||||
APPEND_VAL (loongarch_isa_ext_strings[la_target.isa.fpu]);
|
||||
|
||||
APPEND_OPT (CMODEL);
|
||||
APPEND_VAL (loongarch_cmodel_strings[la_target.cmodel]);
|
||||
|
||||
APPEND_OPT (TUNE);
|
||||
APPEND_VAL (loongarch_cpu_strings[la_target.cpu_tune]);
|
||||
|
||||
obstack_1grow (&opts_obstack, '\0');
|
||||
|
||||
return XOBFINISH (&opts_obstack, const char *);
|
||||
}
|
|
@ -0,0 +1,68 @@
|
|||
/* Subroutine headers for the gcc driver.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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 LOONGARCH_DRIVER_H
|
||||
#define LOONGARCH_DRIVER_H
|
||||
|
||||
#include "loongarch-str.h"
|
||||
|
||||
extern const char*
|
||||
driver_set_m_flag (int argc, const char **argv);
|
||||
|
||||
extern const char*
|
||||
driver_get_normalized_m_opts (int argc, const char **argv);
|
||||
|
||||
#define EXTRA_SPEC_FUNCTIONS \
|
||||
{ "set_m_flag", driver_set_m_flag }, \
|
||||
{ "get_normalized_m_opts", driver_get_normalized_m_opts },
|
||||
|
||||
/* Pre-process ABI-related options. */
|
||||
#define LA_SET_PARM_SPEC(NAME) \
|
||||
" %{m" OPTSTR_##NAME "=*: %:set_m_flag(" OPTSTR_##NAME "=%*)}" \
|
||||
|
||||
#define LA_SET_FLAG_SPEC(NAME) \
|
||||
" %{m" OPTSTR_##NAME ": %:set_m_flag(" OPTSTR_##NAME ")}" \
|
||||
|
||||
#define DRIVER_HANDLE_MACHINE_OPTIONS \
|
||||
" %{c|S|E|nostdlib: %:set_m_flag(no_link)}" \
|
||||
" %{nostartfiles: %{nodefaultlibs: %:set_m_flag(no_link)}}" \
|
||||
LA_SET_PARM_SPEC (ABI_BASE) \
|
||||
LA_SET_PARM_SPEC (ARCH) \
|
||||
LA_SET_PARM_SPEC (TUNE) \
|
||||
LA_SET_PARM_SPEC (ISA_EXT_FPU) \
|
||||
LA_SET_PARM_SPEC (CMODEL) \
|
||||
LA_SET_FLAG_SPEC (SOFT_FLOAT) \
|
||||
LA_SET_FLAG_SPEC (SINGLE_FLOAT) \
|
||||
LA_SET_FLAG_SPEC (DOUBLE_FLOAT) \
|
||||
" %:get_normalized_m_opts()"
|
||||
|
||||
#define DRIVER_SELF_SPECS \
|
||||
DRIVER_HANDLE_MACHINE_OPTIONS
|
||||
|
||||
/* ABI spec strings. */
|
||||
#define ABI_GRLEN_SPEC \
|
||||
"%{mabi=lp64*:64}" \
|
||||
|
||||
#define ABI_SPEC \
|
||||
"%{mabi=lp64d:lp64d}" \
|
||||
"%{mabi=lp64f:lp64f}" \
|
||||
"%{mabi=lp64s:lp64s}" \
|
||||
|
||||
#endif /* LOONGARCH_DRIVER_H */
|
|
@ -0,0 +1,65 @@
|
|||
/* Definitions of prototypes for LoongArch built-in functions.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson Ltd.
|
||||
Based on MIPS target for GNU ckompiler.
|
||||
|
||||
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/>. */
|
||||
|
||||
/* Invoke DEF_LARCH_FTYPE (NARGS, LIST) for each prototype used by
|
||||
LoongArch built-in functions, where:
|
||||
|
||||
NARGS is the number of arguments.
|
||||
LIST contains the return-type code followed by the codes for each
|
||||
argument type.
|
||||
|
||||
Argument- and return-type codes are either modes or one of the following:
|
||||
|
||||
VOID for void_type_node
|
||||
INT for integer_type_node
|
||||
POINTER for ptr_type_node
|
||||
|
||||
(we don't use PTR because that's a ANSI-compatibillity macro).
|
||||
|
||||
Please keep this list lexicographically sorted by the LIST argument. */
|
||||
|
||||
DEF_LARCH_FTYPE (1, (UQI, USI))
|
||||
DEF_LARCH_FTYPE (1, (UHI, USI))
|
||||
DEF_LARCH_FTYPE (1, (USI, USI))
|
||||
DEF_LARCH_FTYPE (1, (UDI, USI))
|
||||
DEF_LARCH_FTYPE (1, (USI, UQI))
|
||||
DEF_LARCH_FTYPE (1, (VOID, USI))
|
||||
|
||||
DEF_LARCH_FTYPE (2, (VOID, UQI, USI))
|
||||
DEF_LARCH_FTYPE (2, (VOID, UHI, USI))
|
||||
DEF_LARCH_FTYPE (2, (VOID, USI, USI))
|
||||
DEF_LARCH_FTYPE (2, (VOID, UDI, USI))
|
||||
DEF_LARCH_FTYPE (2, (VOID, DI, UQI))
|
||||
DEF_LARCH_FTYPE (2, (VOID, SI, UQI))
|
||||
DEF_LARCH_FTYPE (2, (VOID, DI, DI))
|
||||
DEF_LARCH_FTYPE (2, (SI, SI, UQI))
|
||||
DEF_LARCH_FTYPE (2, (DI, DI, UQI))
|
||||
DEF_LARCH_FTYPE (2, (SI, QI, SI))
|
||||
DEF_LARCH_FTYPE (2, (SI, HI, SI))
|
||||
DEF_LARCH_FTYPE (2, (SI, SI, SI))
|
||||
DEF_LARCH_FTYPE (2, (SI, DI, SI))
|
||||
DEF_LARCH_FTYPE (2, (USI, USI, USI))
|
||||
DEF_LARCH_FTYPE (2, (UDI, UDI, USI))
|
||||
|
||||
DEF_LARCH_FTYPE (3, (VOID, USI, USI, SI))
|
||||
DEF_LARCH_FTYPE (3, (VOID, USI, UDI, SI))
|
||||
DEF_LARCH_FTYPE (3, (USI, USI, USI, USI))
|
||||
DEF_LARCH_FTYPE (3, (UDI, UDI, UDI, USI))
|
|
@ -0,0 +1,25 @@
|
|||
/* LoongArch extra machine modes.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson Ltd.
|
||||
Based on MIPS target for GNU compiler.
|
||||
|
||||
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/>. */
|
||||
|
||||
FLOAT_MODE (TF, 16, ieee_quad_format);
|
||||
|
||||
/* For floating point conditions in FCC registers. */
|
||||
CC_MODE (FCC);
|
|
@ -0,0 +1,577 @@
|
|||
/* Subroutines for loongarch-specific option handling.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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/>. */
|
||||
|
||||
#define IN_TARGET_CODE 1
|
||||
|
||||
#include "config.h"
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tm.h"
|
||||
#include "obstack.h"
|
||||
#include "diagnostic-core.h"
|
||||
#include "loongarch-cpu.h"
|
||||
#include "loongarch-opts.h"
|
||||
#include "loongarch-str.h"
|
||||
|
||||
struct loongarch_target la_target;
|
||||
|
||||
/* ABI-related configuration. */
|
||||
#define ABI_COUNT (sizeof(abi_priority_list)/sizeof(struct loongarch_abi))
|
||||
static const struct loongarch_abi
|
||||
abi_priority_list[] = {
|
||||
{ABI_BASE_LP64D, ABI_EXT_BASE},
|
||||
{ABI_BASE_LP64F, ABI_EXT_BASE},
|
||||
{ABI_BASE_LP64S, ABI_EXT_BASE},
|
||||
};
|
||||
|
||||
/* Initialize enabled_abi_types from TM_MULTILIB_LIST. */
|
||||
#ifdef LA_DISABLE_MULTILIB
|
||||
#define MULTILIB_LIST_LEN 1
|
||||
#else
|
||||
#define MULTILIB_LIST_LEN (sizeof (tm_multilib_list) / sizeof (int) / 2)
|
||||
static const int tm_multilib_list[] = { TM_MULTILIB_LIST };
|
||||
#endif
|
||||
static int enabled_abi_types[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES] = { 0 };
|
||||
|
||||
#define isa_required(ABI) (abi_minimal_isa[(ABI).base][(ABI).ext])
|
||||
extern "C" const struct loongarch_isa
|
||||
abi_minimal_isa[N_ABI_BASE_TYPES][N_ABI_EXT_TYPES];
|
||||
|
||||
static inline int
|
||||
is_multilib_enabled (struct loongarch_abi abi)
|
||||
{
|
||||
return enabled_abi_types[abi.base][abi.ext];
|
||||
}
|
||||
|
||||
static void
|
||||
init_enabled_abi_types ()
|
||||
{
|
||||
#ifdef LA_DISABLE_MULTILIB
|
||||
enabled_abi_types[DEFAULT_ABI_BASE][DEFAULT_ABI_EXT] = 1;
|
||||
#else
|
||||
int abi_base, abi_ext;
|
||||
for (unsigned int i = 0; i < MULTILIB_LIST_LEN; i++)
|
||||
{
|
||||
abi_base = tm_multilib_list[i << 1];
|
||||
abi_ext = tm_multilib_list[(i << 1) + 1];
|
||||
enabled_abi_types[abi_base][abi_ext] = 1;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Switch masks. */
|
||||
#undef M
|
||||
#define M(NAME) OPTION_MASK_##NAME
|
||||
const int loongarch_switch_mask[N_SWITCH_TYPES] = {
|
||||
/* SW_SOFT_FLOAT */ M(FORCE_SOFTF),
|
||||
/* SW_SINGLE_FLOAT */ M(FORCE_F32),
|
||||
/* SW_DOUBLE_FLOAT */ M(FORCE_F64),
|
||||
};
|
||||
#undef M
|
||||
|
||||
/* String processing. */
|
||||
static struct obstack msg_obstack;
|
||||
#define APPEND_STRING(STR) obstack_grow (&msg_obstack, STR, strlen(STR));
|
||||
#define APPEND1(CH) obstack_1grow(&msg_obstack, CH);
|
||||
|
||||
static const char* abi_str (struct loongarch_abi abi);
|
||||
static const char* isa_str (const struct loongarch_isa *isa, char separator);
|
||||
static const char* arch_str (const struct loongarch_target *target);
|
||||
static const char* multilib_enabled_abi_list ();
|
||||
|
||||
/* Misc */
|
||||
static struct loongarch_abi isa_default_abi (const struct loongarch_isa *isa);
|
||||
static int isa_base_compat_p (const struct loongarch_isa *set1,
|
||||
const struct loongarch_isa *set2);
|
||||
static int isa_fpu_compat_p (const struct loongarch_isa *set1,
|
||||
const struct loongarch_isa *set2);
|
||||
static int abi_compat_p (const struct loongarch_isa *isa,
|
||||
struct loongarch_abi abi);
|
||||
static int abi_default_cpu_arch (struct loongarch_abi abi);
|
||||
|
||||
/* Checking configure-time defaults. */
|
||||
#ifndef DEFAULT_ABI_BASE
|
||||
#error missing definition of DEFAULT_ABI_BASE in ${tm_defines}.
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_ABI_EXT
|
||||
#error missing definition of DEFAULT_ABI_EXT in ${tm_defines}.
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_CPU_ARCH
|
||||
#error missing definition of DEFAULT_CPU_ARCH in ${tm_defines}.
|
||||
#endif
|
||||
|
||||
#ifndef DEFAULT_ISA_EXT_FPU
|
||||
#error missing definition of DEFAULT_ISA_EXT_FPU in ${tm_defines}.
|
||||
#endif
|
||||
|
||||
/* Handle combinations of -m machine option values
|
||||
(see loongarch.opt and loongarch-opts.h). */
|
||||
void
|
||||
loongarch_config_target (struct loongarch_target *target,
|
||||
HOST_WIDE_INT opt_switches,
|
||||
int opt_arch, int opt_tune, int opt_fpu,
|
||||
int opt_abi_base, int opt_abi_ext,
|
||||
int opt_cmodel, int follow_multilib_list)
|
||||
{
|
||||
struct loongarch_target t;
|
||||
|
||||
if (!target)
|
||||
return;
|
||||
|
||||
/* Initialization */
|
||||
init_enabled_abi_types ();
|
||||
obstack_init (&msg_obstack);
|
||||
|
||||
struct {
|
||||
int arch, tune, fpu, abi_base, abi_ext, cmodel;
|
||||
} constrained = {
|
||||
M_OPT_ABSENT(opt_arch) ? 0 : 1,
|
||||
M_OPT_ABSENT(opt_tune) ? 0 : 1,
|
||||
M_OPT_ABSENT(opt_fpu) ? 0 : 1,
|
||||
M_OPT_ABSENT(opt_abi_base) ? 0 : 1,
|
||||
M_OPT_ABSENT(opt_abi_ext) ? 0 : 1,
|
||||
M_OPT_ABSENT(opt_cmodel) ? 0 : 1,
|
||||
};
|
||||
|
||||
#define on(NAME) ((loongarch_switch_mask[(SW_##NAME)] & opt_switches) \
|
||||
&& (on_switch = (SW_##NAME), 1))
|
||||
int on_switch;
|
||||
|
||||
/* 1. Target ABI */
|
||||
t.abi.base = constrained.abi_base ? opt_abi_base : DEFAULT_ABI_BASE;
|
||||
|
||||
t.abi.ext = constrained.abi_ext ? opt_abi_ext : DEFAULT_ABI_EXT;
|
||||
|
||||
/* Extra switch handling. */
|
||||
if (on (SOFT_FLOAT) || on (SINGLE_FLOAT) || on (DOUBLE_FLOAT))
|
||||
{
|
||||
switch (on_switch)
|
||||
{
|
||||
case SW_SOFT_FLOAT:
|
||||
opt_fpu = ISA_EXT_NOFPU;
|
||||
break;
|
||||
|
||||
case SW_SINGLE_FLOAT:
|
||||
opt_fpu = ISA_EXT_FPU32;
|
||||
break;
|
||||
|
||||
case SW_DOUBLE_FLOAT:
|
||||
opt_fpu = ISA_EXT_FPU64;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable();
|
||||
}
|
||||
constrained.fpu = 1;
|
||||
|
||||
/* The target ISA is not ready yet, but (isa_required (t.abi)
|
||||
+ forced fpu) is enough for computing the forced base ABI. */
|
||||
struct loongarch_isa default_isa = isa_required (t.abi);
|
||||
struct loongarch_isa force_isa = default_isa;
|
||||
struct loongarch_abi force_abi = t.abi;
|
||||
force_isa.fpu = opt_fpu;
|
||||
force_abi.base = isa_default_abi (&force_isa).base;
|
||||
|
||||
if (constrained.abi_base && (t.abi.base != force_abi.base))
|
||||
inform (UNKNOWN_LOCATION,
|
||||
"%<-m%s%> overrides %<-m%s=%s%>, adjusting ABI to %qs",
|
||||
loongarch_switch_strings[on_switch],
|
||||
OPTSTR_ABI_BASE, loongarch_abi_base_strings[t.abi.base],
|
||||
abi_str (force_abi));
|
||||
|
||||
t.abi.base = force_abi.base;
|
||||
}
|
||||
|
||||
#ifdef LA_DISABLE_MULTILIB
|
||||
if (follow_multilib_list)
|
||||
if (t.abi.base != DEFAULT_ABI_BASE || t.abi.ext != DEFAULT_ABI_EXT)
|
||||
{
|
||||
static const struct loongarch_abi default_abi
|
||||
= {DEFAULT_ABI_BASE, DEFAULT_ABI_EXT};
|
||||
|
||||
warning (0, "ABI changed (%qs to %qs) while multilib is disabled",
|
||||
abi_str (default_abi), abi_str (t.abi));
|
||||
}
|
||||
#endif
|
||||
|
||||
/* 2. Target CPU */
|
||||
t.cpu_arch = constrained.arch ? opt_arch : DEFAULT_CPU_ARCH;
|
||||
|
||||
t.cpu_tune = constrained.tune ? opt_tune
|
||||
: (constrained.arch ? DEFAULT_CPU_ARCH : DEFAULT_CPU_TUNE);
|
||||
|
||||
#ifdef __loongarch__
|
||||
/* For native compilers, gather local CPU information
|
||||
and fill the "CPU_NATIVE" index of arrays defined in
|
||||
loongarch-cpu.c. */
|
||||
|
||||
t.cpu_native = fill_native_cpu_config (t.cpu_arch == CPU_NATIVE,
|
||||
t.cpu_tune == CPU_NATIVE);
|
||||
|
||||
#else
|
||||
if (t.cpu_arch == CPU_NATIVE)
|
||||
fatal_error (UNKNOWN_LOCATION,
|
||||
"%qs does not work on a cross compiler",
|
||||
"-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
|
||||
|
||||
else if (t.cpu_tune == CPU_NATIVE)
|
||||
fatal_error (UNKNOWN_LOCATION,
|
||||
"%qs does not work on a cross compiler",
|
||||
"-m" OPTSTR_TUNE "=" STR_CPU_NATIVE);
|
||||
#endif
|
||||
|
||||
/* 3. Target ISA */
|
||||
config_target_isa:
|
||||
|
||||
/* Get default ISA from "-march" or its default value. */
|
||||
t.isa = loongarch_cpu_default_isa[LARCH_ACTUAL_ARCH];
|
||||
|
||||
/* Apply incremental changes. */
|
||||
/* "-march=native" overrides the default FPU type. */
|
||||
t.isa.fpu = constrained.fpu ? opt_fpu :
|
||||
((t.cpu_arch == CPU_NATIVE && constrained.arch) ?
|
||||
t.isa.fpu : DEFAULT_ISA_EXT_FPU);
|
||||
|
||||
|
||||
/* 4. ABI-ISA compatibility */
|
||||
/* Note:
|
||||
- There IS a unique default -march value for each ABI type
|
||||
(config.gcc: triplet -> abi -> default arch).
|
||||
|
||||
- If the base ABI is incompatible with the default arch,
|
||||
try using the default -march it implies (and mark it
|
||||
as "constrained" this time), then re-apply step 3. */
|
||||
|
||||
struct loongarch_abi abi_tmp;
|
||||
const struct loongarch_isa* isa_min;
|
||||
|
||||
abi_tmp = t.abi;
|
||||
isa_min = &isa_required (abi_tmp);
|
||||
|
||||
if (isa_base_compat_p (&t.isa, isa_min)); /* OK. */
|
||||
else if (!constrained.arch)
|
||||
{
|
||||
/* Base architecture can only be implied by -march,
|
||||
so we adjust that first if it is not constrained. */
|
||||
int fallback_arch = abi_default_cpu_arch (t.abi);
|
||||
|
||||
if (t.cpu_arch == CPU_NATIVE)
|
||||
warning (0, "your native CPU architecture (%qs) "
|
||||
"does not support %qs ABI, falling back to %<-m%s=%s%>",
|
||||
arch_str (&t), abi_str (t.abi), OPTSTR_ARCH,
|
||||
loongarch_cpu_strings[fallback_arch]);
|
||||
else
|
||||
warning (0, "default CPU architecture (%qs) "
|
||||
"does not support %qs ABI, falling back to %<-m%s=%s%>",
|
||||
arch_str (&t), abi_str (t.abi), OPTSTR_ARCH,
|
||||
loongarch_cpu_strings[fallback_arch]);
|
||||
|
||||
t.cpu_arch = fallback_arch;
|
||||
constrained.arch = 1;
|
||||
goto config_target_isa;
|
||||
}
|
||||
else if (!constrained.abi_base)
|
||||
{
|
||||
/* If -march is given while -mabi is not,
|
||||
try selecting another base ABI type. */
|
||||
abi_tmp.base = isa_default_abi (&t.isa).base;
|
||||
}
|
||||
else
|
||||
goto fatal;
|
||||
|
||||
if (isa_fpu_compat_p (&t.isa, isa_min)); /* OK. */
|
||||
else if (!constrained.fpu)
|
||||
t.isa.fpu = isa_min->fpu;
|
||||
else if (!constrained.abi_base)
|
||||
/* If -march is compatible with the default ABI
|
||||
while -mfpu is not. */
|
||||
abi_tmp.base = isa_default_abi (&t.isa).base;
|
||||
else
|
||||
goto fatal;
|
||||
|
||||
if (0)
|
||||
fatal:
|
||||
fatal_error (UNKNOWN_LOCATION,
|
||||
"unable to implement ABI %qs with instruction set %qs",
|
||||
abi_str (t.abi), isa_str (&t.isa, '/'));
|
||||
|
||||
|
||||
/* Using the fallback ABI. */
|
||||
if (abi_tmp.base != t.abi.base || abi_tmp.ext != t.abi.ext)
|
||||
{
|
||||
/* This flag is only set in the GCC driver. */
|
||||
if (follow_multilib_list)
|
||||
{
|
||||
|
||||
/* Continue falling back until we find a feasible ABI type
|
||||
enabled by TM_MULTILIB_LIST. */
|
||||
if (!is_multilib_enabled (abi_tmp))
|
||||
{
|
||||
for (unsigned int i = 0; i < ABI_COUNT; i++)
|
||||
{
|
||||
if (is_multilib_enabled (abi_priority_list[i])
|
||||
&& abi_compat_p (&t.isa, abi_priority_list[i]))
|
||||
{
|
||||
abi_tmp = abi_priority_list[i];
|
||||
|
||||
warning (0, "ABI %qs cannot be implemented due to "
|
||||
"limited instruction set %qs, "
|
||||
"falling back to %qs", abi_str (t.abi),
|
||||
isa_str (&t.isa, '/'), abi_str (abi_tmp));
|
||||
|
||||
goto fallback;
|
||||
}
|
||||
}
|
||||
|
||||
/* Otherwise, keep using abi_tmp with a warning. */
|
||||
#ifdef LA_DISABLE_MULTILIB
|
||||
warning (0, "instruction set %qs cannot implement "
|
||||
"default ABI %qs, falling back to %qs",
|
||||
isa_str (&t.isa, '/'), abi_str (t.abi),
|
||||
abi_str (abi_tmp));
|
||||
#else
|
||||
warning (0, "no multilib-enabled ABI (%qs) can be implemented "
|
||||
"with instruction set %qs, falling back to %qs",
|
||||
multilib_enabled_abi_list (),
|
||||
isa_str (&t.isa, '/'), abi_str (abi_tmp));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
fallback:
|
||||
t.abi = abi_tmp;
|
||||
}
|
||||
else if (follow_multilib_list)
|
||||
{
|
||||
if (!is_multilib_enabled (t.abi))
|
||||
{
|
||||
inform (UNKNOWN_LOCATION,
|
||||
"ABI %qs is not enabled at configure-time, "
|
||||
"the linker might report an error", abi_str (t.abi));
|
||||
|
||||
inform (UNKNOWN_LOCATION, "ABI with startfiles: %s",
|
||||
multilib_enabled_abi_list ());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* 5. Target code model */
|
||||
t.cmodel = constrained.cmodel ? opt_cmodel : CMODEL_NORMAL;
|
||||
|
||||
/* Cleanup and return. */
|
||||
obstack_free (&msg_obstack, NULL);
|
||||
*target = t;
|
||||
}
|
||||
|
||||
/* Returns the default ABI for the given instruction set. */
|
||||
static inline struct loongarch_abi
|
||||
isa_default_abi (const struct loongarch_isa *isa)
|
||||
{
|
||||
struct loongarch_abi abi;
|
||||
|
||||
switch (isa->fpu)
|
||||
{
|
||||
case ISA_EXT_FPU64:
|
||||
if (isa->base == ISA_BASE_LA64V100)
|
||||
abi.base = ABI_BASE_LP64D;
|
||||
break;
|
||||
|
||||
case ISA_EXT_FPU32:
|
||||
if (isa->base == ISA_BASE_LA64V100)
|
||||
abi.base = ABI_BASE_LP64F;
|
||||
break;
|
||||
|
||||
case ISA_EXT_NOFPU:
|
||||
if (isa->base == ISA_BASE_LA64V100)
|
||||
abi.base = ABI_BASE_LP64S;
|
||||
break;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
abi.ext = ABI_EXT_BASE;
|
||||
return abi;
|
||||
}
|
||||
|
||||
/* Check if set2 is a subset of set1. */
|
||||
static inline int
|
||||
isa_base_compat_p (const struct loongarch_isa *set1,
|
||||
const struct loongarch_isa *set2)
|
||||
{
|
||||
switch (set2->base)
|
||||
{
|
||||
case ISA_BASE_LA64V100:
|
||||
return (set1->base == ISA_BASE_LA64V100);
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
isa_fpu_compat_p (const struct loongarch_isa *set1,
|
||||
const struct loongarch_isa *set2)
|
||||
{
|
||||
switch (set2->fpu)
|
||||
{
|
||||
case ISA_EXT_FPU64:
|
||||
return set1->fpu == ISA_EXT_FPU64;
|
||||
|
||||
case ISA_EXT_FPU32:
|
||||
return set1->fpu == ISA_EXT_FPU32 || set1->fpu == ISA_EXT_FPU64;
|
||||
|
||||
case ISA_EXT_NOFPU:
|
||||
return 1;
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static inline int
|
||||
abi_compat_p (const struct loongarch_isa *isa, struct loongarch_abi abi)
|
||||
{
|
||||
int compatible = 1;
|
||||
const struct loongarch_isa *isa2 = &isa_required (abi);
|
||||
|
||||
/* Append conditionals for new ISA components below. */
|
||||
compatible = compatible && isa_base_compat_p (isa, isa2);
|
||||
compatible = compatible && isa_fpu_compat_p (isa, isa2);
|
||||
return compatible;
|
||||
}
|
||||
|
||||
/* The behavior of this function should be consistent
|
||||
with config.gcc. */
|
||||
static inline int
|
||||
abi_default_cpu_arch (struct loongarch_abi abi)
|
||||
{
|
||||
switch (abi.base)
|
||||
{
|
||||
case ABI_BASE_LP64D:
|
||||
case ABI_BASE_LP64F:
|
||||
case ABI_BASE_LP64S:
|
||||
if (abi.ext == ABI_EXT_BASE)
|
||||
return CPU_LOONGARCH64;
|
||||
}
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
static const char*
|
||||
abi_str (struct loongarch_abi abi)
|
||||
{
|
||||
/* "/base" can be omitted. */
|
||||
if (abi.ext == ABI_EXT_BASE)
|
||||
return (const char*)
|
||||
obstack_copy0 (&msg_obstack, loongarch_abi_base_strings[abi.base],
|
||||
strlen (loongarch_abi_base_strings[abi.base]));
|
||||
else
|
||||
{
|
||||
APPEND_STRING (loongarch_abi_base_strings[abi.base])
|
||||
APPEND1 ('/')
|
||||
APPEND_STRING (loongarch_abi_ext_strings[abi.ext])
|
||||
APPEND1 ('\0')
|
||||
|
||||
return XOBFINISH (&msg_obstack, const char *);
|
||||
}
|
||||
}
|
||||
|
||||
static const char*
|
||||
isa_str (const struct loongarch_isa *isa, char separator)
|
||||
{
|
||||
APPEND_STRING (loongarch_isa_base_strings[isa->base])
|
||||
APPEND1 (separator)
|
||||
|
||||
if (isa->fpu == ISA_EXT_NOFPU)
|
||||
{
|
||||
APPEND_STRING ("no" OPTSTR_ISA_EXT_FPU)
|
||||
}
|
||||
else
|
||||
{
|
||||
APPEND_STRING (OPTSTR_ISA_EXT_FPU)
|
||||
APPEND_STRING (loongarch_isa_ext_strings[isa->fpu])
|
||||
}
|
||||
APPEND1 ('\0')
|
||||
|
||||
/* Add more here. */
|
||||
|
||||
return XOBFINISH (&msg_obstack, const char *);
|
||||
}
|
||||
|
||||
static const char*
|
||||
arch_str (const struct loongarch_target *target)
|
||||
{
|
||||
if (target->cpu_arch == CPU_NATIVE)
|
||||
{
|
||||
if (target->cpu_native == CPU_NATIVE)
|
||||
{
|
||||
/* Describe a native CPU with unknown PRID. */
|
||||
const char* isa_string = isa_str (&target->isa, ',');
|
||||
APPEND_STRING ("PRID: 0x")
|
||||
APPEND_STRING (get_native_prid_str ())
|
||||
APPEND_STRING (", ISA features: ")
|
||||
APPEND_STRING (isa_string)
|
||||
APPEND1 ('\0')
|
||||
}
|
||||
else
|
||||
APPEND_STRING (loongarch_cpu_strings[target->cpu_native]);
|
||||
}
|
||||
else
|
||||
APPEND_STRING (loongarch_cpu_strings[target->cpu_arch]);
|
||||
|
||||
APPEND1 ('\0')
|
||||
return XOBFINISH (&msg_obstack, const char *);
|
||||
}
|
||||
|
||||
static const char*
|
||||
multilib_enabled_abi_list ()
|
||||
{
|
||||
int enabled_abi_idx[MULTILIB_LIST_LEN] = { 0 };
|
||||
const char* enabled_abi_str[MULTILIB_LIST_LEN] = { NULL };
|
||||
unsigned int j = 0;
|
||||
|
||||
for (unsigned int i = 0; i < ABI_COUNT && j < MULTILIB_LIST_LEN; i++)
|
||||
{
|
||||
if (enabled_abi_types[abi_priority_list[i].base]
|
||||
[abi_priority_list[i].ext])
|
||||
{
|
||||
enabled_abi_idx[j++] = i;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int k = 0; k < j; k++)
|
||||
{
|
||||
enabled_abi_str[k] = abi_str (abi_priority_list[enabled_abi_idx[k]]);
|
||||
}
|
||||
|
||||
for (unsigned int k = 0; k < j - 1; k++)
|
||||
{
|
||||
APPEND_STRING (enabled_abi_str[k])
|
||||
APPEND1 (',')
|
||||
APPEND1 (' ')
|
||||
}
|
||||
APPEND_STRING (enabled_abi_str[j - 1])
|
||||
APPEND1 ('\0')
|
||||
|
||||
return XOBFINISH (&msg_obstack, const char *);
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/* Definitions for loongarch-specific option handling.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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 LOONGARCH_OPTS_H
|
||||
#define LOONGARCH_OPTS_H
|
||||
|
||||
|
||||
/* Target configuration */
|
||||
extern struct loongarch_target la_target;
|
||||
|
||||
/* Switch masks */
|
||||
extern const int loongarch_switch_mask[];
|
||||
|
||||
#include "loongarch-def.h"
|
||||
|
||||
#if !defined(IN_LIBGCC2) && !defined(IN_TARGET_LIBS) && !defined(IN_RTS)
|
||||
/* Handler for "-m" option combinations,
|
||||
shared by the driver and the compiler proper. */
|
||||
void
|
||||
loongarch_config_target (struct loongarch_target *target,
|
||||
HOST_WIDE_INT opt_switches,
|
||||
int opt_arch, int opt_tune, int opt_fpu,
|
||||
int opt_abi_base, int opt_abi_ext,
|
||||
int opt_cmodel, int follow_multilib_list);
|
||||
#endif
|
||||
|
||||
|
||||
/* Macros for common conditional expressions used in loongarch.{c,h,md} */
|
||||
#define TARGET_CMODEL_NORMAL (la_target.cmodel == CMODEL_NORMAL)
|
||||
#define TARGET_CMODEL_TINY (la_target.cmodel == CMODEL_TINY)
|
||||
#define TARGET_CMODEL_TINY_STATIC (la_target.cmodel == CMODEL_TINY_STATIC)
|
||||
#define TARGET_CMODEL_LARGE (la_target.cmodel == CMODEL_LARGE)
|
||||
#define TARGET_CMODEL_EXTREME (la_target.cmodel == CMODEL_EXTREME)
|
||||
|
||||
#define TARGET_HARD_FLOAT (la_target.isa.fpu != ISA_EXT_NOFPU)
|
||||
#define TARGET_HARD_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D \
|
||||
|| la_target.abi.base == ABI_BASE_LP64F)
|
||||
|
||||
#define TARGET_SOFT_FLOAT (la_target.isa.fpu == ISA_EXT_NOFPU)
|
||||
#define TARGET_SOFT_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64S)
|
||||
#define TARGET_SINGLE_FLOAT (la_target.isa.fpu == ISA_EXT_FPU32)
|
||||
#define TARGET_SINGLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64F)
|
||||
#define TARGET_DOUBLE_FLOAT (la_target.isa.fpu == ISA_EXT_FPU64)
|
||||
#define TARGET_DOUBLE_FLOAT_ABI (la_target.abi.base == ABI_BASE_LP64D)
|
||||
|
||||
#define TARGET_64BIT (la_target.isa.base == ISA_BASE_LA64V100)
|
||||
#define TARGET_ABI_LP64 (la_target.abi.base == ABI_BASE_LP64D \
|
||||
|| la_target.abi.base == ABI_BASE_LP64F \
|
||||
|| la_target.abi.base == ABI_BASE_LP64S)
|
||||
|
||||
#define TARGET_ARCH_NATIVE (la_target.cpu_arch == CPU_NATIVE)
|
||||
#define LARCH_ACTUAL_ARCH (TARGET_ARCH_NATIVE \
|
||||
? (la_target.cpu_native < N_ARCH_TYPES \
|
||||
? (la_target.cpu_native) : (CPU_NATIVE)) \
|
||||
: (la_target.cpu_arch))
|
||||
|
||||
#define TARGET_TUNE_NATIVE (la_target.cpu_tune == CPU_NATIVE)
|
||||
#define LARCH_ACTUAL_TUNE (TARGET_TUNE_NATIVE \
|
||||
? (la_target.cpu_native < N_TUNE_TYPES \
|
||||
? (la_target.cpu_native) : (CPU_NATIVE)) \
|
||||
: (la_target.cpu_tune))
|
||||
|
||||
#define TARGET_ARCH_LOONGARCH64 (LARCH_ACTUAL_ARCH == CPU_LOONGARCH64)
|
||||
#define TARGET_ARCH_LA464 (LARCH_ACTUAL_ARCH == CPU_LA464)
|
||||
|
||||
#define TARGET_TUNE_LOONGARCH64 (LARCH_ACTUAL_TUNE == CPU_LOONGARCH64)
|
||||
#define TARGET_TUNE_LA464 (LARCH_ACTUAL_TUNE == CPU_LA464)
|
||||
|
||||
/* Note: optimize_size may vary across functions,
|
||||
while -m[no]-memcpy imposes a global constraint. */
|
||||
#define TARGET_DO_OPTIMIZE_BLOCK_MOVE_P loongarch_do_optimize_block_move_p()
|
||||
|
||||
#endif /* LOONGARCH_OPTS_H */
|
|
@ -0,0 +1,172 @@
|
|||
/* Prototypes of target machine for GNU compiler. LoongArch version.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson Ltd.
|
||||
Based on MIPS target for GNU compiler.
|
||||
|
||||
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_LOONGARCH_PROTOS_H
|
||||
#define GCC_LOONGARCH_PROTOS_H
|
||||
|
||||
/* Classifies a SYMBOL_REF, LABEL_REF or UNSPEC address.
|
||||
|
||||
SYMBOL_GOT_DISP
|
||||
The symbol's value will be loaded directly from the GOT.
|
||||
|
||||
SYMBOL_TLS
|
||||
A thread-local symbol.
|
||||
|
||||
SYMBOL_TLSGD
|
||||
SYMBOL_TLSLDM
|
||||
UNSPEC wrappers around SYMBOL_TLS, corresponding to the
|
||||
thread-local storage relocation operators.
|
||||
*/
|
||||
enum loongarch_symbol_type {
|
||||
SYMBOL_GOT_DISP,
|
||||
SYMBOL_TLS,
|
||||
SYMBOL_TLSGD,
|
||||
SYMBOL_TLSLDM,
|
||||
};
|
||||
#define NUM_SYMBOL_TYPES (SYMBOL_TLSLDM + 1)
|
||||
|
||||
/* Routines implemented in loongarch.c. */
|
||||
extern rtx loongarch_emit_move (rtx, rtx);
|
||||
extern HOST_WIDE_INT loongarch_initial_elimination_offset (int, int);
|
||||
extern void loongarch_expand_prologue (void);
|
||||
extern void loongarch_expand_epilogue (bool);
|
||||
extern bool loongarch_can_use_return_insn (void);
|
||||
|
||||
extern bool loongarch_symbolic_constant_p (rtx, enum loongarch_symbol_type *);
|
||||
extern int loongarch_regno_mode_ok_for_base_p (int, machine_mode, bool);
|
||||
extern int loongarch_address_insns (rtx, machine_mode, bool);
|
||||
extern int loongarch_const_insns (rtx);
|
||||
extern int loongarch_split_const_insns (rtx);
|
||||
extern int loongarch_split_128bit_const_insns (rtx);
|
||||
extern int loongarch_load_store_insns (rtx, rtx_insn *);
|
||||
extern int loongarch_idiv_insns (machine_mode);
|
||||
#ifdef RTX_CODE
|
||||
extern void loongarch_emit_binary (enum rtx_code, rtx, rtx, rtx);
|
||||
#endif
|
||||
extern bool loongarch_split_symbol (rtx, rtx, machine_mode, rtx *);
|
||||
extern rtx loongarch_unspec_address (rtx, enum loongarch_symbol_type);
|
||||
extern rtx loongarch_strip_unspec_address (rtx);
|
||||
extern void loongarch_move_integer (rtx, rtx, unsigned HOST_WIDE_INT);
|
||||
extern bool loongarch_legitimize_move (machine_mode, rtx, rtx);
|
||||
extern rtx loongarch_legitimize_call_address (rtx);
|
||||
|
||||
extern rtx loongarch_subword (rtx, bool);
|
||||
extern bool loongarch_split_move_p (rtx, rtx);
|
||||
extern void loongarch_split_move (rtx, rtx, rtx);
|
||||
extern bool loongarch_split_move_insn_p (rtx, rtx);
|
||||
extern void loongarch_split_move_insn (rtx, rtx, rtx);
|
||||
extern const char *loongarch_output_move (rtx, rtx);
|
||||
extern bool loongarch_cfun_has_cprestore_slot_p (void);
|
||||
#ifdef RTX_CODE
|
||||
extern void loongarch_expand_scc (rtx *);
|
||||
extern void loongarch_expand_conditional_branch (rtx *);
|
||||
extern void loongarch_expand_conditional_move (rtx *);
|
||||
extern void loongarch_expand_conditional_trap (rtx);
|
||||
#endif
|
||||
extern void loongarch_set_return_address (rtx, rtx);
|
||||
extern bool loongarch_move_by_pieces_p (unsigned HOST_WIDE_INT, unsigned int);
|
||||
extern bool loongarch_expand_block_move (rtx, rtx, rtx);
|
||||
extern bool loongarch_do_optimize_block_move_p (void);
|
||||
|
||||
extern bool loongarch_expand_ext_as_unaligned_load (rtx, rtx, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT, bool);
|
||||
extern bool loongarch_expand_ins_as_unaligned_store (rtx, rtx, HOST_WIDE_INT,
|
||||
HOST_WIDE_INT);
|
||||
extern HOST_WIDE_INT loongarch_debugger_offset (rtx, HOST_WIDE_INT);
|
||||
|
||||
extern void loongarch_output_external (FILE *, tree, const char *);
|
||||
extern void loongarch_output_ascii (FILE *, const char *, size_t);
|
||||
extern bool loongarch_small_data_pattern_p (rtx);
|
||||
extern rtx loongarch_rewrite_small_data (rtx);
|
||||
extern rtx loongarch_return_addr (int, rtx);
|
||||
|
||||
extern enum reg_class loongarch_secondary_reload_class (enum reg_class,
|
||||
machine_mode,
|
||||
rtx, bool);
|
||||
extern int loongarch_class_max_nregs (enum reg_class, machine_mode);
|
||||
|
||||
extern machine_mode loongarch_hard_regno_caller_save_mode (unsigned int,
|
||||
unsigned int,
|
||||
machine_mode);
|
||||
extern int loongarch_adjust_insn_length (rtx_insn *, int);
|
||||
extern const char *loongarch_output_conditional_branch (rtx_insn *, rtx *,
|
||||
const char *,
|
||||
const char *);
|
||||
extern const char *loongarch_output_order_conditional_branch (rtx_insn *,
|
||||
rtx *,
|
||||
bool);
|
||||
extern const char *loongarch_output_equal_conditional_branch (rtx_insn *,
|
||||
rtx *,
|
||||
bool);
|
||||
extern const char *loongarch_output_division (const char *, rtx *);
|
||||
extern const char *loongarch_output_probe_stack_range (rtx, rtx, rtx);
|
||||
extern bool loongarch_hard_regno_rename_ok (unsigned int, unsigned int);
|
||||
extern int loongarch_dspalu_bypass_p (rtx, rtx);
|
||||
extern rtx loongarch_prefetch_cookie (rtx, rtx);
|
||||
|
||||
extern bool loongarch_global_symbol_p (const_rtx);
|
||||
extern bool loongarch_global_symbol_noweak_p (const_rtx);
|
||||
extern bool loongarch_weak_symbol_p (const_rtx);
|
||||
extern bool loongarch_symbol_binds_local_p (const_rtx);
|
||||
|
||||
extern const char *current_section_name (void);
|
||||
extern unsigned int current_section_flags (void);
|
||||
extern bool loongarch_use_ins_ext_p (rtx, HOST_WIDE_INT, HOST_WIDE_INT);
|
||||
|
||||
union loongarch_gen_fn_ptrs
|
||||
{
|
||||
rtx (*fn_8) (rtx, rtx, rtx, rtx, rtx, rtx, rtx, rtx);
|
||||
rtx (*fn_7) (rtx, rtx, rtx, rtx, rtx, rtx, rtx);
|
||||
rtx (*fn_6) (rtx, rtx, rtx, rtx, rtx, rtx);
|
||||
rtx (*fn_5) (rtx, rtx, rtx, rtx, rtx);
|
||||
rtx (*fn_4) (rtx, rtx, rtx, rtx);
|
||||
};
|
||||
|
||||
extern void loongarch_expand_atomic_qihi (union loongarch_gen_fn_ptrs,
|
||||
rtx, rtx, rtx, rtx, rtx);
|
||||
|
||||
extern bool loongarch_signed_immediate_p (unsigned HOST_WIDE_INT, int, int);
|
||||
extern bool loongarch_unsigned_immediate_p (unsigned HOST_WIDE_INT, int, int);
|
||||
extern bool loongarch_12bit_offset_address_p (rtx, machine_mode);
|
||||
extern bool loongarch_14bit_shifted_offset_address_p (rtx, machine_mode);
|
||||
extern bool loongarch_base_index_address_p (rtx, machine_mode);
|
||||
extern rtx loongarch_expand_thread_pointer (rtx);
|
||||
|
||||
extern bool loongarch_eh_uses (unsigned int);
|
||||
extern bool loongarch_epilogue_uses (unsigned int);
|
||||
extern bool loongarch_load_store_bonding_p (rtx *, machine_mode, bool);
|
||||
extern bool loongarch_split_symbol_type (enum loongarch_symbol_type);
|
||||
|
||||
typedef rtx (*mulsidi3_gen_fn) (rtx, rtx, rtx);
|
||||
|
||||
extern void loongarch_register_frame_header_opt (void);
|
||||
|
||||
/* Routines implemented in loongarch-c.c. */
|
||||
void loongarch_cpu_cpp_builtins (cpp_reader *);
|
||||
|
||||
extern void loongarch_init_builtins (void);
|
||||
extern void loongarch_atomic_assign_expand_fenv (tree *, tree *, tree *);
|
||||
extern tree loongarch_builtin_decl (unsigned int, bool);
|
||||
extern rtx loongarch_expand_builtin (tree, rtx, rtx subtarget ATTRIBUTE_UNUSED,
|
||||
machine_mode, int);
|
||||
extern tree loongarch_build_builtin_va_list (void);
|
||||
|
||||
#endif /* ! GCC_LOONGARCH_PROTOS_H */
|
|
@ -0,0 +1,59 @@
|
|||
/* Generated automatically by "genstr" from "loongarch-strings".
|
||||
Please do not edit this file directly.
|
||||
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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 LOONGARCH_STR_H
|
||||
#define LOONGARCH_STR_H
|
||||
|
||||
#define OPTSTR_ARCH "arch"
|
||||
#define OPTSTR_TUNE "tune"
|
||||
|
||||
#define STR_CPU_NATIVE "native"
|
||||
#define STR_CPU_LOONGARCH64 "loongarch64"
|
||||
#define STR_CPU_LA464 "la464"
|
||||
|
||||
#define STR_ISA_BASE_LA64V100 "la64"
|
||||
|
||||
#define OPTSTR_ISA_EXT_FPU "fpu"
|
||||
#define STR_ISA_EXT_NOFPU "none"
|
||||
#define STR_ISA_EXT_FPU0 "0"
|
||||
#define STR_ISA_EXT_FPU32 "32"
|
||||
#define STR_ISA_EXT_FPU64 "64"
|
||||
|
||||
#define OPTSTR_SOFT_FLOAT "soft-float"
|
||||
#define OPTSTR_SINGLE_FLOAT "single-float"
|
||||
#define OPTSTR_DOUBLE_FLOAT "double-float"
|
||||
|
||||
#define OPTSTR_ABI_BASE "abi"
|
||||
#define STR_ABI_BASE_LP64D "lp64d"
|
||||
#define STR_ABI_BASE_LP64F "lp64f"
|
||||
#define STR_ABI_BASE_LP64S "lp64s"
|
||||
|
||||
#define STR_ABI_EXT_BASE "base"
|
||||
|
||||
#define OPTSTR_CMODEL "cmodel"
|
||||
#define STR_CMODEL_NORMAL "normal"
|
||||
#define STR_CMODEL_TINY "tiny"
|
||||
#define STR_CMODEL_TS "tiny-static"
|
||||
#define STR_CMODEL_LARGE "large"
|
||||
#define STR_CMODEL_EXTREME "extreme"
|
||||
|
||||
#endif /* LOONGARCH_STR_H */
|
|
@ -0,0 +1,50 @@
|
|||
/* Definitions for microarchitecture-related data structures.
|
||||
Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
Contributed by Loongson 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 LOONGARCH_TUNE_H
|
||||
#define LOONGARCH_TUNE_H
|
||||
|
||||
/* RTX costs of various operations on the different architectures. */
|
||||
struct loongarch_rtx_cost_data
|
||||
{
|
||||
unsigned short fp_add;
|
||||
unsigned short fp_mult_sf;
|
||||
unsigned short fp_mult_df;
|
||||
unsigned short fp_div_sf;
|
||||
unsigned short fp_div_df;
|
||||
unsigned short int_mult_si;
|
||||
unsigned short int_mult_di;
|
||||
unsigned short int_div_si;
|
||||
unsigned short int_div_di;
|
||||
unsigned short branch_cost;
|
||||
unsigned short memory_latency;
|
||||
};
|
||||
|
||||
/* Costs to use when optimizing for size. */
|
||||
extern const struct loongarch_rtx_cost_data loongarch_rtx_cost_optimize_size;
|
||||
|
||||
/* Cache size record of known processor models. */
|
||||
struct loongarch_cache {
|
||||
int l1d_line_size; /* bytes */
|
||||
int l1d_size; /* KiB */
|
||||
int l2d_size; /* kiB */
|
||||
};
|
||||
|
||||
#endif /* LOONGARCH_TUNE_H */
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,186 @@
|
|||
; Generated by "genstr" from the template "loongarch.opt.in"
|
||||
; and definitions from "loongarch-strings".
|
||||
;
|
||||
; Please do not edit this file directly.
|
||||
; It will be automatically updated during a gcc build
|
||||
; if you change "loongarch.opt.in" or "loongarch-strings".
|
||||
;
|
||||
; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;
|
||||
; 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/>.
|
||||
;
|
||||
|
||||
; Variables (macros) that should be exported by loongarch.opt:
|
||||
; la_opt_switches,
|
||||
; la_opt_abi_base, la_opt_abi_ext,
|
||||
; la_opt_cpu_arch, la_opt_cpu_tune,
|
||||
; la_opt_fpu,
|
||||
; la_cmodel.
|
||||
|
||||
HeaderInclude
|
||||
config/loongarch/loongarch-opts.h
|
||||
|
||||
HeaderInclude
|
||||
config/loongarch/loongarch-str.h
|
||||
|
||||
Variable
|
||||
HOST_WIDE_INT la_opt_switches = 0
|
||||
|
||||
; ISA related options
|
||||
;; Base ISA
|
||||
Enum
|
||||
Name(isa_base) Type(int)
|
||||
Basic ISAs of LoongArch:
|
||||
|
||||
EnumValue
|
||||
Enum(isa_base) String(la64) Value(ISA_BASE_LA64V100)
|
||||
|
||||
|
||||
;; ISA extensions / adjustments
|
||||
Enum
|
||||
Name(isa_ext_fpu) Type(int)
|
||||
FPU types of LoongArch:
|
||||
|
||||
EnumValue
|
||||
Enum(isa_ext_fpu) String(none) Value(ISA_EXT_NOFPU)
|
||||
|
||||
EnumValue
|
||||
Enum(isa_ext_fpu) String(32) Value(ISA_EXT_FPU32)
|
||||
|
||||
EnumValue
|
||||
Enum(isa_ext_fpu) String(64) Value(ISA_EXT_FPU64)
|
||||
|
||||
mfpu=
|
||||
Target RejectNegative Joined ToLower Enum(isa_ext_fpu) Var(la_opt_fpu) Init(M_OPTION_NOT_SEEN)
|
||||
-mfpu=FPU Generate code for the given FPU.
|
||||
|
||||
mfpu=0
|
||||
Target RejectNegative Alias(mfpu=,none)
|
||||
|
||||
msoft-float
|
||||
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_SOFTF) Negative(msingle-float)
|
||||
Prevent the use of all hardware floating-point instructions.
|
||||
|
||||
msingle-float
|
||||
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F32) Negative(mdouble-float)
|
||||
Restrict the use of hardware floating-point instructions to 32-bit operations.
|
||||
|
||||
mdouble-float
|
||||
Target Driver RejectNegative Var(la_opt_switches) Mask(FORCE_F64) Negative(msoft-float)
|
||||
Allow hardware floating-point instructions to cover both 32-bit and 64-bit operations.
|
||||
|
||||
|
||||
;; Base target models (implies ISA & tune parameters)
|
||||
Enum
|
||||
Name(cpu_type) Type(int)
|
||||
LoongArch CPU types:
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(native) Value(CPU_NATIVE)
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(loongarch64) Value(CPU_LOONGARCH64)
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(la464) Value(CPU_LA464)
|
||||
|
||||
march=
|
||||
Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPTION_NOT_SEEN)
|
||||
-march=PROCESSOR Generate code for the given PROCESSOR ISA.
|
||||
|
||||
mtune=
|
||||
Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_tune) Init(M_OPTION_NOT_SEEN)
|
||||
-mtune=PROCESSOR Generate optimized code for PROCESSOR.
|
||||
|
||||
|
||||
; ABI related options
|
||||
; (ISA constraints on ABI are handled dynamically)
|
||||
|
||||
;; Base ABI
|
||||
Enum
|
||||
Name(abi_base) Type(int)
|
||||
Base ABI types for LoongArch:
|
||||
|
||||
EnumValue
|
||||
Enum(abi_base) String(lp64d) Value(ABI_BASE_LP64D)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_base) String(lp64f) Value(ABI_BASE_LP64F)
|
||||
|
||||
EnumValue
|
||||
Enum(abi_base) String(lp64s) Value(ABI_BASE_LP64S)
|
||||
|
||||
mabi=
|
||||
Target RejectNegative Joined ToLower Enum(abi_base) Var(la_opt_abi_base) Init(M_OPTION_NOT_SEEN)
|
||||
-mabi=BASEABI Generate code that conforms to the given BASEABI.
|
||||
|
||||
;; ABI Extension
|
||||
Variable
|
||||
int la_opt_abi_ext = M_OPTION_NOT_SEEN
|
||||
|
||||
|
||||
mbranch-cost=
|
||||
Target RejectNegative Joined UInteger Var(loongarch_branch_cost)
|
||||
-mbranch-cost=COST Set the cost of branches to roughly COST instructions.
|
||||
|
||||
mcheck-zero-division
|
||||
Target Mask(CHECK_ZERO_DIV)
|
||||
Trap on integer divide by zero.
|
||||
|
||||
mcond-move-int
|
||||
Target Var(TARGET_COND_MOVE_INT) Init(1)
|
||||
Conditional moves for integral are enabled.
|
||||
|
||||
mcond-move-float
|
||||
Target Var(TARGET_COND_MOVE_FLOAT) Init(1)
|
||||
Conditional moves for float are enabled.
|
||||
|
||||
mmemcpy
|
||||
Target Mask(MEMCPY)
|
||||
Prevent optimizing block moves, which is also the default behavior of -Os.
|
||||
|
||||
mstrict-align
|
||||
Target Var(TARGET_STRICT_ALIGN) Init(0)
|
||||
Do not generate unaligned memory accesses.
|
||||
|
||||
mmax-inline-memcpy-size=
|
||||
Target Joined RejectNegative UInteger Var(loongarch_max_inline_memcpy_size) Init(1024)
|
||||
-mmax-inline-memcpy-size=SIZE Set the max size of memcpy to inline, default is 1024.
|
||||
|
||||
; The code model option names for -mcmodel.
|
||||
Enum
|
||||
Name(cmodel) Type(int)
|
||||
The code model option names for -mcmodel:
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(normal) Value(CMODEL_NORMAL)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(tiny) Value(CMODEL_TINY)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(tiny-static) Value(CMODEL_TINY_STATIC)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(large) Value(CMODEL_LARGE)
|
||||
|
||||
EnumValue
|
||||
Enum(cmodel) String(extreme) Value(CMODEL_EXTREME)
|
||||
|
||||
mcmodel=
|
||||
Target RejectNegative Joined Enum(cmodel) Var(la_opt_cmodel) Init(CMODEL_NORMAL)
|
||||
Specify the code model.
|
|
@ -0,0 +1,253 @@
|
|||
;; Predicate definitions for LoongArch target.
|
||||
;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;; Contributed by Loongson Ltd.
|
||||
;; Based on MIPS target for GNU compiler.
|
||||
;;
|
||||
;; 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/>.
|
||||
|
||||
(define_predicate "const_uns_arith_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM12_OPERAND_UNSIGNED (INTVAL (op))")))
|
||||
|
||||
(define_predicate "uns_arith_operand"
|
||||
(ior (match_operand 0 "const_uns_arith_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_lu32i_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "LU32I_OPERAND (INTVAL (op))")))
|
||||
|
||||
(define_predicate "const_lu52i_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "LU52I_OPERAND (INTVAL (op))")))
|
||||
|
||||
(define_predicate "const_arith_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM12_OPERAND (INTVAL (op))")))
|
||||
|
||||
(define_predicate "const_imm16_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM16_OPERAND (INTVAL (op))")))
|
||||
|
||||
(define_predicate "arith_operand"
|
||||
(ior (match_operand 0 "const_arith_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_immalsl_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 1, 4)")))
|
||||
|
||||
(define_predicate "const_uimm5_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 31)")))
|
||||
|
||||
(define_predicate "const_uimm14_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 16383)")))
|
||||
|
||||
(define_predicate "const_uimm15_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 32767)")))
|
||||
|
||||
(define_predicate "const_imm12_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM12_OPERAND (INTVAL (op))")))
|
||||
|
||||
(define_predicate "sle_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IMM12_OPERAND (INTVAL (op) + 1)")))
|
||||
|
||||
(define_predicate "sleu_operand"
|
||||
(and (match_operand 0 "sle_operand")
|
||||
(match_test "INTVAL (op) + 1 != 0")))
|
||||
|
||||
(define_predicate "const_0_operand"
|
||||
(and (match_code "const_int,const_double,const_vector")
|
||||
(match_test "op == CONST0_RTX (GET_MODE (op))")))
|
||||
|
||||
(define_predicate "reg_or_0_operand"
|
||||
(ior (match_operand 0 "const_0_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_1_operand"
|
||||
(and (match_code "const_int,const_double,const_vector")
|
||||
(match_test "op == CONST1_RTX (GET_MODE (op))")))
|
||||
|
||||
(define_predicate "reg_or_1_operand"
|
||||
(ior (match_operand 0 "const_1_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "const_0_to_3_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 3)")))
|
||||
|
||||
(define_predicate "const_0_to_7_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "IN_RANGE (INTVAL (op), 0, 7)")))
|
||||
|
||||
(define_predicate "lu52i_mask_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "UINTVAL (op) == 0xfffffffffffff")))
|
||||
|
||||
(define_predicate "low_bitmask_operand"
|
||||
(and (match_code "const_int")
|
||||
(match_test "low_bitmask_len (mode, INTVAL (op)) > 12")))
|
||||
|
||||
(define_predicate "const_call_insn_operand"
|
||||
(match_code "const,symbol_ref,label_ref")
|
||||
{
|
||||
enum loongarch_symbol_type symbol_type;
|
||||
|
||||
if (!loongarch_symbolic_constant_p (op, &symbol_type))
|
||||
return false;
|
||||
|
||||
switch (symbol_type)
|
||||
{
|
||||
case SYMBOL_GOT_DISP:
|
||||
/* Without explicit relocs, there is no special syntax for
|
||||
loading the address of a call destination into a register.
|
||||
Using "la.global JIRL_REGS,foo; jirl JIRL_REGS" would prevent the lazy
|
||||
binding of "foo", so keep the address of global symbols with the jirl
|
||||
macro. */
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
})
|
||||
|
||||
(define_predicate "call_insn_operand"
|
||||
(ior (match_operand 0 "const_call_insn_operand")
|
||||
(match_operand 0 "register_operand")))
|
||||
|
||||
(define_predicate "is_const_call_local_symbol"
|
||||
(and (match_operand 0 "const_call_insn_operand")
|
||||
(ior (match_test "loongarch_global_symbol_p (op) == 0")
|
||||
(match_test "loongarch_symbol_binds_local_p (op) != 0"))
|
||||
(match_test "CONSTANT_P (op)")))
|
||||
|
||||
(define_predicate "is_const_call_weak_symbol"
|
||||
(and (match_operand 0 "const_call_insn_operand")
|
||||
(not (match_operand 0 "is_const_call_local_symbol"))
|
||||
(match_test "loongarch_weak_symbol_p (op) != 0")
|
||||
(match_test "CONSTANT_P (op)")))
|
||||
|
||||
(define_predicate "is_const_call_plt_symbol"
|
||||
(and (match_operand 0 "const_call_insn_operand")
|
||||
(match_test "flag_plt != 0")
|
||||
(match_test "loongarch_global_symbol_noweak_p (op) != 0")
|
||||
(match_test "CONSTANT_P (op)")))
|
||||
|
||||
(define_predicate "is_const_call_global_noplt_symbol"
|
||||
(and (match_operand 0 "const_call_insn_operand")
|
||||
(match_test "flag_plt == 0")
|
||||
(match_test "loongarch_global_symbol_noweak_p (op) != 0")
|
||||
(match_test "CONSTANT_P (op)")))
|
||||
|
||||
;; A legitimate CONST_INT operand that takes more than one instruction
|
||||
;; to load.
|
||||
(define_predicate "splittable_const_int_operand"
|
||||
(match_code "const_int")
|
||||
{
|
||||
/* Don't handle multi-word moves this way; we don't want to introduce
|
||||
the individual word-mode moves until after reload. */
|
||||
if (GET_MODE_SIZE (mode) > UNITS_PER_WORD)
|
||||
return false;
|
||||
|
||||
/* Otherwise check whether the constant can be loaded in a single
|
||||
instruction. */
|
||||
return !LU12I_INT (op) && !IMM12_INT (op) && !IMM12_INT_UNSIGNED (op)
|
||||
&& !LU52I_INT (op);
|
||||
})
|
||||
|
||||
(define_predicate "move_operand"
|
||||
(match_operand 0 "general_operand")
|
||||
{
|
||||
enum loongarch_symbol_type symbol_type;
|
||||
|
||||
/* The thinking here is as follows:
|
||||
|
||||
(1) The move expanders should split complex load sequences into
|
||||
individual instructions. Those individual instructions can
|
||||
then be optimized by all rtl passes.
|
||||
|
||||
(2) The target of pre-reload load sequences should not be used
|
||||
to store temporary results. If the target register is only
|
||||
assigned one value, reload can rematerialize that value
|
||||
on demand, rather than spill it to the stack.
|
||||
|
||||
(3) If we allowed pre-reload passes like combine and cse to recreate
|
||||
complex load sequences, we would want to be able to split the
|
||||
sequences before reload as well, so that the pre-reload scheduler
|
||||
can see the individual instructions. This falls foul of (2);
|
||||
the splitter would be forced to reuse the target register for
|
||||
intermediate results.
|
||||
|
||||
(4) We want to define complex load splitters for combine. These
|
||||
splitters can request a temporary scratch register, which avoids
|
||||
the problem in (2). They allow things like:
|
||||
|
||||
(set (reg T1) (high SYM))
|
||||
(set (reg T2) (low (reg T1) SYM))
|
||||
(set (reg X) (plus (reg T2) (const_int OFFSET)))
|
||||
|
||||
to be combined into:
|
||||
|
||||
(set (reg T3) (high SYM+OFFSET))
|
||||
(set (reg X) (lo_sum (reg T3) SYM+OFFSET))
|
||||
|
||||
if T2 is only used this once. */
|
||||
switch (GET_CODE (op))
|
||||
{
|
||||
case CONST_INT:
|
||||
return !splittable_const_int_operand (op, mode);
|
||||
|
||||
case CONST:
|
||||
case SYMBOL_REF:
|
||||
case LABEL_REF:
|
||||
return (loongarch_symbolic_constant_p (op, &symbol_type));
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
})
|
||||
|
||||
(define_predicate "symbolic_operand"
|
||||
(match_code "const,symbol_ref,label_ref")
|
||||
{
|
||||
enum loongarch_symbol_type type;
|
||||
return loongarch_symbolic_constant_p (op, &type);
|
||||
})
|
||||
|
||||
(define_predicate "equality_operator"
|
||||
(match_code "eq,ne"))
|
||||
|
||||
(define_predicate "order_operator"
|
||||
(match_code "lt,ltu,le,leu,ge,geu,gt,gtu"))
|
||||
|
||||
;; For NE, cstore uses sltu instructions in which the first operand is $0.
|
||||
|
||||
(define_predicate "loongarch_cstore_operator"
|
||||
(match_code "ne,eq,gt,gtu,ge,geu,lt,ltu,le,leu"))
|
||||
|
||||
(define_predicate "small_data_pattern"
|
||||
(and (match_code "set,parallel,unspec,unspec_volatile,prefetch")
|
||||
(match_test "loongarch_small_data_pattern_p (op)")))
|
||||
|
||||
;; Return 1 if the operand is in non-volatile memory.
|
||||
(define_predicate "non_volatile_mem_operand"
|
||||
(and (match_operand 0 "memory_operand")
|
||||
(not (match_test "MEM_VOLATILE_P (op)"))))
|
|
@ -0,0 +1,574 @@
|
|||
;; Machine description for LoongArch atomic operations.
|
||||
;; Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
;; Contributed by Loongson Ltd.
|
||||
;; Based on MIPS and RISC-V target for GNU compiler.
|
||||
|
||||
;; 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/>.
|
||||
|
||||
(define_c_enum "unspec" [
|
||||
UNSPEC_COMPARE_AND_SWAP
|
||||
UNSPEC_COMPARE_AND_SWAP_ADD
|
||||
UNSPEC_COMPARE_AND_SWAP_SUB
|
||||
UNSPEC_COMPARE_AND_SWAP_AND
|
||||
UNSPEC_COMPARE_AND_SWAP_XOR
|
||||
UNSPEC_COMPARE_AND_SWAP_OR
|
||||
UNSPEC_COMPARE_AND_SWAP_NAND
|
||||
UNSPEC_SYNC_OLD_OP
|
||||
UNSPEC_SYNC_EXCHANGE
|
||||
UNSPEC_ATOMIC_STORE
|
||||
UNSPEC_MEMORY_BARRIER
|
||||
])
|
||||
|
||||
(define_code_iterator any_atomic [plus ior xor and])
|
||||
(define_code_attr atomic_optab
|
||||
[(plus "add") (ior "or") (xor "xor") (and "and")])
|
||||
|
||||
;; This attribute gives the format suffix for atomic memory operations.
|
||||
(define_mode_attr amo [(SI "w") (DI "d")])
|
||||
|
||||
;; <amop> expands to the name of the atomic operand that implements a
|
||||
;; particular code.
|
||||
(define_code_attr amop [(ior "or") (xor "xor") (and "and") (plus "add")])
|
||||
|
||||
;; Memory barriers.
|
||||
|
||||
(define_expand "mem_thread_fence"
|
||||
[(match_operand:SI 0 "const_int_operand" "")] ;; model
|
||||
""
|
||||
{
|
||||
if (INTVAL (operands[0]) != MEMMODEL_RELAXED)
|
||||
{
|
||||
rtx mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
|
||||
MEM_VOLATILE_P (mem) = 1;
|
||||
emit_insn (gen_mem_thread_fence_1 (mem, operands[0]));
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
;; Until the LoongArch memory model (hence its mapping from C++) is finalized,
|
||||
;; conservatively emit a full FENCE.
|
||||
(define_insn "mem_thread_fence_1"
|
||||
[(set (match_operand:BLK 0 "" "")
|
||||
(unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))
|
||||
(match_operand:SI 1 "const_int_operand" "")] ;; model
|
||||
""
|
||||
"dbar\t0")
|
||||
|
||||
;; Atomic memory operations.
|
||||
|
||||
;; Implement atomic stores with amoswap. Fall back to fences for atomic loads.
|
||||
(define_insn "atomic_store<mode>"
|
||||
[(set (match_operand:GPR 0 "memory_operand" "+ZB")
|
||||
(unspec_volatile:GPR
|
||||
[(match_operand:GPR 1 "reg_or_0_operand" "rJ")
|
||||
(match_operand:SI 2 "const_int_operand")] ;; model
|
||||
UNSPEC_ATOMIC_STORE))]
|
||||
""
|
||||
"amswap%A2.<amo>\t$zero,%z1,%0"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_<atomic_optab><mode>"
|
||||
[(set (match_operand:GPR 0 "memory_operand" "+ZB")
|
||||
(unspec_volatile:GPR
|
||||
[(any_atomic:GPR (match_dup 0)
|
||||
(match_operand:GPR 1 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 2 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
"am<amop>%A2.<amo>\t$zero,%z1,%0"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_fetch_<atomic_optab><mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(match_operand:GPR 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR
|
||||
[(any_atomic:GPR (match_dup 1)
|
||||
(match_operand:GPR 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
"am<amop>%A3.<amo>\t%0,%z2,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_exchange<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(unspec_volatile:GPR
|
||||
[(match_operand:GPR 1 "memory_operand" "+ZB")
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_EXCHANGE))
|
||||
(set (match_dup 1)
|
||||
(match_operand:GPR 2 "register_operand" "r"))]
|
||||
""
|
||||
"amswap%A3.<amo>\t%0,%z2,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_insn "atomic_cas_value_strong<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ")
|
||||
(match_operand:SI 4 "const_int_operand") ;; mod_s
|
||||
(match_operand:SI 5 "const_int_operand")] ;; mod_f
|
||||
UNSPEC_COMPARE_AND_SWAP))
|
||||
(clobber (match_scratch:GPR 6 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G5\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"bne\\t%0,%z2,2f\\n\\t"
|
||||
"or%i3\\t%6,$zero,%3\\n\\t"
|
||||
"sc.<amo>\\t%6,%1\\n\\t"
|
||||
"beq\\t$zero,%6,1b\\n\\t"
|
||||
"b\\t3f\\n\\t"
|
||||
"2:\\n\\t"
|
||||
"dbar\\t0x700\\n\\t"
|
||||
"3:\\n\\t";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_expand "atomic_compare_and_swap<mode>"
|
||||
[(match_operand:SI 0 "register_operand" "") ;; bool output
|
||||
(match_operand:GPR 1 "register_operand" "") ;; val output
|
||||
(match_operand:GPR 2 "memory_operand" "") ;; memory
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "") ;; expected value
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "") ;; desired value
|
||||
(match_operand:SI 5 "const_int_operand" "") ;; is_weak
|
||||
(match_operand:SI 6 "const_int_operand" "") ;; mod_s
|
||||
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
|
||||
""
|
||||
{
|
||||
emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
|
||||
operands[3], operands[4],
|
||||
operands[6], operands[7]));
|
||||
|
||||
rtx compare = operands[1];
|
||||
if (operands[3] != const0_rtx)
|
||||
{
|
||||
rtx difference = gen_rtx_MINUS (<MODE>mode, operands[1], operands[3]);
|
||||
compare = gen_reg_rtx (<MODE>mode);
|
||||
emit_insn (gen_rtx_SET (compare, difference));
|
||||
}
|
||||
|
||||
if (word_mode != <MODE>mode)
|
||||
{
|
||||
rtx reg = gen_reg_rtx (word_mode);
|
||||
emit_insn (gen_rtx_SET (reg, gen_rtx_SIGN_EXTEND (word_mode, compare)));
|
||||
compare = reg;
|
||||
}
|
||||
|
||||
emit_insn (gen_rtx_SET (operands[0],
|
||||
gen_rtx_EQ (SImode, compare, const0_rtx)));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_test_and_set"
|
||||
[(match_operand:QI 0 "register_operand" "") ;; bool output
|
||||
(match_operand:QI 1 "memory_operand" "+ZB") ;; memory
|
||||
(match_operand:SI 2 "const_int_operand" "")] ;; model
|
||||
""
|
||||
{
|
||||
/* We have no QImode atomics, so use the address LSBs to form a mask,
|
||||
then use an aligned SImode atomic. */
|
||||
rtx result = operands[0];
|
||||
rtx mem = operands[1];
|
||||
rtx model = operands[2];
|
||||
rtx addr = force_reg (Pmode, XEXP (mem, 0));
|
||||
rtx tmp_reg = gen_reg_rtx (Pmode);
|
||||
rtx zero_reg = gen_rtx_REG (Pmode, 0);
|
||||
|
||||
rtx aligned_addr = gen_reg_rtx (Pmode);
|
||||
emit_move_insn (tmp_reg, gen_rtx_PLUS (Pmode, zero_reg, GEN_INT (-4)));
|
||||
emit_move_insn (aligned_addr, gen_rtx_AND (Pmode, addr, tmp_reg));
|
||||
|
||||
rtx aligned_mem = change_address (mem, SImode, aligned_addr);
|
||||
set_mem_alias_set (aligned_mem, 0);
|
||||
|
||||
rtx offset = gen_reg_rtx (SImode);
|
||||
emit_move_insn (offset, gen_rtx_AND (SImode, gen_lowpart (SImode, addr),
|
||||
GEN_INT (3)));
|
||||
|
||||
rtx tmp = gen_reg_rtx (SImode);
|
||||
emit_move_insn (tmp, GEN_INT (1));
|
||||
|
||||
rtx shmt = gen_reg_rtx (SImode);
|
||||
emit_move_insn (shmt, gen_rtx_ASHIFT (SImode, offset, GEN_INT (3)));
|
||||
|
||||
rtx word = gen_reg_rtx (SImode);
|
||||
emit_move_insn (word, gen_rtx_ASHIFT (SImode, tmp, shmt));
|
||||
|
||||
tmp = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_atomic_fetch_orsi (tmp, aligned_mem, word, model));
|
||||
|
||||
emit_move_insn (gen_lowpart (SImode, result),
|
||||
gen_rtx_LSHIFTRT (SImode, tmp, shmt));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "atomic_cas_value_cmp_and_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ")
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ")
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ")
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ")
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%2\\n\\t"
|
||||
"bne\\t%7,%z4,2f\\n\\t"
|
||||
"and\\t%7,%0,%z3\\n\\t"
|
||||
"or%i5\\t%7,%7,%5\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b\\n\\t"
|
||||
"b\\t3f\\n\\t"
|
||||
"2:\\n\\t"
|
||||
"dbar\\t0x700\\n\\t"
|
||||
"3:\\n\\t";
|
||||
}
|
||||
[(set (attr "length") (const_int 40))])
|
||||
|
||||
(define_expand "atomic_compare_and_swap<mode>"
|
||||
[(match_operand:SI 0 "register_operand" "") ;; bool output
|
||||
(match_operand:SHORT 1 "register_operand" "") ;; val output
|
||||
(match_operand:SHORT 2 "memory_operand" "") ;; memory
|
||||
(match_operand:SHORT 3 "reg_or_0_operand" "") ;; expected value
|
||||
(match_operand:SHORT 4 "reg_or_0_operand" "") ;; desired value
|
||||
(match_operand:SI 5 "const_int_operand" "") ;; is_weak
|
||||
(match_operand:SI 6 "const_int_operand" "") ;; mod_s
|
||||
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_cmp_and_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[1], operands[2],
|
||||
operands[3], operands[4], operands[7]);
|
||||
|
||||
rtx compare = operands[1];
|
||||
if (operands[3] != const0_rtx)
|
||||
{
|
||||
machine_mode mode = GET_MODE (operands[3]);
|
||||
rtx op1 = convert_modes (SImode, mode, operands[1], true);
|
||||
rtx op3 = convert_modes (SImode, mode, operands[3], true);
|
||||
rtx difference = gen_rtx_MINUS (SImode, op1, op3);
|
||||
compare = gen_reg_rtx (SImode);
|
||||
emit_insn (gen_rtx_SET (compare, difference));
|
||||
}
|
||||
|
||||
if (word_mode != <MODE>mode)
|
||||
{
|
||||
rtx reg = gen_reg_rtx (word_mode);
|
||||
emit_insn (gen_rtx_SET (reg, gen_rtx_SIGN_EXTEND (word_mode, compare)));
|
||||
compare = reg;
|
||||
}
|
||||
|
||||
emit_insn (gen_rtx_SET (operands[0],
|
||||
gen_rtx_EQ (SImode, compare, const0_rtx)));
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "atomic_cas_value_add_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") ;; mask
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; inverted_mask
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ") ;; old val
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ") ;; new val
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP_ADD))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))
|
||||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"add.w\\t%8,%0,%z5\\n\\t"
|
||||
"and\\t%8,%8,%z2\\n\\t"
|
||||
"or%i8\\t%7,%7,%8\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_insn "atomic_cas_value_sub_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") ;; mask
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; inverted_mask
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ") ;; old val
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ") ;; new val
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP_SUB))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))
|
||||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"sub.w\\t%8,%0,%z5\\n\\t"
|
||||
"and\\t%8,%8,%z2\\n\\t"
|
||||
"or%i8\\t%7,%7,%8\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_insn "atomic_cas_value_and_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") ;; mask
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; inverted_mask
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ") ;; old val
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ") ;; new val
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP_AND))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))
|
||||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"and\\t%8,%0,%z5\\n\\t"
|
||||
"and\\t%8,%8,%z2\\n\\t"
|
||||
"or%i8\\t%7,%7,%8\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_insn "atomic_cas_value_xor_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") ;; mask
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; inverted_mask
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ") ;; old val
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ") ;; new val
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP_XOR))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))
|
||||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"xor\\t%8,%0,%z5\\n\\t"
|
||||
"and\\t%8,%8,%z2\\n\\t"
|
||||
"or%i8\\t%7,%7,%8\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_insn "atomic_cas_value_or_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") ;; mask
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; inverted_mask
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ") ;; old val
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ") ;; new val
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP_OR))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))
|
||||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"or\\t%8,%0,%z5\\n\\t"
|
||||
"and\\t%8,%8,%z2\\n\\t"
|
||||
"or%i8\\t%7,%7,%8\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_insn "atomic_cas_value_nand_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
(match_operand:GPR 1 "memory_operand" "+ZC"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "rJ") ;; mask
|
||||
(match_operand:GPR 3 "reg_or_0_operand" "rJ") ;; inverted_mask
|
||||
(match_operand:GPR 4 "reg_or_0_operand" "rJ") ;; old val
|
||||
(match_operand:GPR 5 "reg_or_0_operand" "rJ") ;; new val
|
||||
(match_operand:SI 6 "const_int_operand")] ;; model
|
||||
UNSPEC_COMPARE_AND_SWAP_NAND))
|
||||
(clobber (match_scratch:GPR 7 "=&r"))
|
||||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"and\\t%8,%0,%z5\\n\\t"
|
||||
"xor\\t%8,%8,%z2\\n\\t"
|
||||
"or%i8\\t%7,%7,%8\\n\\t"
|
||||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
|
||||
(define_expand "atomic_exchange<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand")
|
||||
(unspec_volatile:SHORT
|
||||
[(match_operand:SHORT 1 "memory_operand")
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_EXCHANGE))
|
||||
(set (match_dup 1)
|
||||
(match_operand:SHORT 2 "register_operand"))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_cmp_and_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_add<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:SHORT
|
||||
[(plus:SHORT (match_dup 1)
|
||||
(match_operand:SHORT 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_add_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_sub<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:SHORT
|
||||
[(minus:SHORT (match_dup 1)
|
||||
(match_operand:SHORT 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_sub_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_and<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:SHORT
|
||||
[(and:SHORT (match_dup 1)
|
||||
(match_operand:SHORT 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_and_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_xor<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:SHORT
|
||||
[(xor:SHORT (match_dup 1)
|
||||
(match_operand:SHORT 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_xor_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_or<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:SHORT
|
||||
[(ior:SHORT (match_dup 1)
|
||||
(match_operand:SHORT 2 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_or_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_expand "atomic_fetch_nand<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:SHORT
|
||||
[(not:SHORT (and:SHORT (match_dup 1)
|
||||
(match_operand:SHORT 2 "reg_or_0_operand" "rJ")))
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_nand_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
operands[1], operands[2], operands[3]);
|
||||
DONE;
|
||||
})
|
|
@ -0,0 +1,53 @@
|
|||
# Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# Multilib
|
||||
MULTILIB_OPTIONS = mabi=lp64d/mabi=lp64f/mabi=lp64s
|
||||
MULTILIB_DIRNAMES = base/lp64d base/lp64f base/lp64s
|
||||
|
||||
# The GCC driver always gets all abi-related options on the command line.
|
||||
# (see loongarch-driver.c:driver_get_normalized_m_opts)
|
||||
comma=,
|
||||
MULTILIB_REQUIRED = $(subst $(comma), ,$(TM_MULTILIB_CONFIG))
|
||||
|
||||
# Multiarch
|
||||
ifneq ($(call if_multiarch,yes),yes)
|
||||
# Define LA_DISABLE_MULTIARCH if multiarch is disabled.
|
||||
tm_defines += LA_DISABLE_MULTIARCH
|
||||
else
|
||||
# Only define MULTIARCH_DIRNAME when multiarch is enabled,
|
||||
# or it would always introduce ${target} into the search path.
|
||||
MULTIARCH_DIRNAME = $(LA_MULTIARCH_TRIPLET)
|
||||
endif
|
||||
|
||||
# Don't define MULTILIB_OSDIRNAMES if multilib is disabled.
|
||||
ifeq ($(filter LA_DISABLE_MULTILIB,$(tm_defines)),)
|
||||
|
||||
MULTILIB_OSDIRNAMES = \
|
||||
mabi.lp64d=../lib64$\
|
||||
$(call if_multiarch,:loongarch64-linux-gnuf64)
|
||||
|
||||
MULTILIB_OSDIRNAMES += \
|
||||
mabi.lp64f=../lib64/f32$\
|
||||
$(call if_multiarch,:loongarch64-linux-gnuf32)
|
||||
|
||||
MULTILIB_OSDIRNAMES += \
|
||||
mabi.lp64s=../lib64/sf$\
|
||||
$(call if_multiarch,:loongarch64-linux-gnusf)
|
||||
|
||||
endif
|
|
@ -0,0 +1,71 @@
|
|||
# Copyright (C) 2021-2022 Free Software Foundation, Inc.
|
||||
#
|
||||
# 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/>.
|
||||
|
||||
# Canonical target triplet from config.gcc
|
||||
LA_MULTIARCH_TRIPLET = $(patsubst LA_MULTIARCH_TRIPLET=%,%,$\
|
||||
$(filter LA_MULTIARCH_TRIPLET=%,$(tm_defines)))
|
||||
|
||||
# String definition header
|
||||
LA_STR_H = $(srcdir)/config/loongarch/loongarch-str.h
|
||||
|
||||
# String definition header
|
||||
$(LA_STR_H): s-loongarch-str ; @true
|
||||
s-loongarch-str: $(srcdir)/config/loongarch/genopts/genstr.sh \
|
||||
$(srcdir)/config/loongarch/genopts/loongarch-strings
|
||||
$(SHELL) $(srcdir)/config/loongarch/genopts/genstr.sh header \
|
||||
$(srcdir)/config/loongarch/genopts/loongarch-strings > \
|
||||
tmp-loongarch-str.h
|
||||
$(SHELL) $(srcdir)/../move-if-change tmp-loongarch-str.h \
|
||||
$(LA_STR_H)
|
||||
$(STAMP) s-loongarch-str
|
||||
|
||||
loongarch-c.o: $(srcdir)/config/loongarch/loongarch-c.cc $(CONFIG_H) $(SYSTEM_H) \
|
||||
coretypes.h $(TM_H) $(TREE_H) output.h $(C_COMMON_H) $(TARGET_H)
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
|
||||
$(srcdir)/config/loongarch/loongarch-c.cc
|
||||
|
||||
loongarch-builtins.o: $(srcdir)/config/loongarch/loongarch-builtins.cc $(CONFIG_H) \
|
||||
$(SYSTEM_H) coretypes.h $(TM_H) $(RTL_H) $(TREE_H) $(RECOG_H) langhooks.h \
|
||||
$(DIAGNOSTIC_CORE_H) $(OPTABS_H) $(srcdir)/config/loongarch/loongarch-ftypes.def \
|
||||
$(srcdir)/config/loongarch/loongarch-modes.def
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) \
|
||||
$(srcdir)/config/loongarch/loongarch-builtins.cc
|
||||
|
||||
loongarch-driver.o : $(srcdir)/config/loongarch/loongarch-driver.cc $(LA_STR_H) \
|
||||
$(CONFIG_H) $(SYSTEM_H)
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
|
||||
|
||||
loongarch-opts.o: $(srcdir)/config/loongarch/loongarch-opts.cc $(LA_STR_H)
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
|
||||
|
||||
loongarch-cpu.o: $(srcdir)/config/loongarch/loongarch-cpu.cc $(LA_STR_H)
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
|
||||
|
||||
loongarch-def.o: $(srcdir)/config/loongarch/loongarch-def.c $(LA_STR_H)
|
||||
$(CC) -c $(ALL_CFLAGS) $(INCLUDES) $<
|
||||
|
||||
$(srcdir)/config/loongarch/loongarch.opt: s-loongarch-opt ; @true
|
||||
s-loongarch-opt: $(srcdir)/config/loongarch/genopts/genstr.sh \
|
||||
$(srcdir)/config/loongarch/genopts/loongarch.opt.in \
|
||||
$(srcdir)/config/loongarch/genopts/loongarch-strings $(LA_STR_H)
|
||||
$(SHELL) $(srcdir)/config/loongarch/genopts/genstr.sh opt \
|
||||
$(srcdir)/config/loongarch/genopts/loongarch.opt.in \
|
||||
> tmp-loongarch.opt
|
||||
$(SHELL) $(srcdir)/../move-if-change tmp-loongarch.opt \
|
||||
$(srcdir)/config/loongarch/loongarch.opt
|
||||
$(STAMP) s-loongarch-opt
|
|
@ -12254,10 +12254,22 @@ mips_expand_prologue (void)
|
|||
/* Insert the RIPL into our copy of SR (k1) as the new IPL. */
|
||||
if (!cfun->machine->keep_interrupts_masked_p
|
||||
&& cfun->machine->int_mask == INT_MASK_EIC)
|
||||
emit_insn (gen_insvsi (gen_rtx_REG (SImode, K1_REG_NUM),
|
||||
GEN_INT (6),
|
||||
{
|
||||
emit_insn (gen_insvsi (gen_rtx_REG (SImode, K1_REG_NUM),
|
||||
TARGET_MCU ? GEN_INT (7) : GEN_INT (6),
|
||||
GEN_INT (SR_IPL),
|
||||
gen_rtx_REG (SImode, K0_REG_NUM)));
|
||||
if (TARGET_MCU)
|
||||
{
|
||||
emit_insn (gen_lshrsi3 (gen_rtx_REG (SImode, K0_REG_NUM),
|
||||
gen_rtx_REG (SImode, K0_REG_NUM),
|
||||
GEN_INT (7)));
|
||||
emit_insn (gen_insvsi (gen_rtx_REG (SImode, K1_REG_NUM),
|
||||
GEN_INT (1),
|
||||
GEN_INT (SR_IPL+8),
|
||||
gen_rtx_REG (SImode, K0_REG_NUM)));
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear all interrupt mask bits up to and including the
|
||||
handler's interrupt line. */
|
||||
|
|
|
@ -44,7 +44,7 @@ echo
|
|||
cat <<EOF
|
||||
Enum
|
||||
Name(ptx_isa) Type(int)
|
||||
Known PTX ISA versions (for use with the -misa= option):
|
||||
Known PTX ISA target architectures (for use with the -misa= option):
|
||||
EOF
|
||||
|
||||
# Separator.
|
||||
|
|
|
@ -49,5 +49,14 @@ nvptx_cpu_cpp_builtins (void)
|
|||
#include "nvptx-sm.def"
|
||||
#undef NVPTX_SM
|
||||
cpp_define (parse_in, ptx_sm);
|
||||
|
||||
{
|
||||
unsigned major
|
||||
= ptx_version_to_number ((ptx_version)ptx_version_option, true);
|
||||
unsigned minor
|
||||
= ptx_version_to_number ((ptx_version)ptx_version_option, false);
|
||||
cpp_define_formatted (parse_in, "__PTX_ISA_VERSION_MAJOR__=%u", major);
|
||||
cpp_define_formatted (parse_in, "__PTX_ISA_VERSION_MINOR__=%u", minor);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
|
||||
Enum
|
||||
Name(ptx_isa) Type(int)
|
||||
Known PTX ISA versions (for use with the -misa= option):
|
||||
Known PTX ISA target architectures (for use with the -misa= option):
|
||||
|
||||
EnumValue
|
||||
Enum(ptx_isa) String(sm_30) Value(PTX_ISA_SM30)
|
||||
|
|
|
@ -44,6 +44,7 @@ extern void nvptx_cpu_cpp_builtins (void);
|
|||
extern void nvptx_register_pragmas (void);
|
||||
extern unsigned int nvptx_data_alignment (const_tree, unsigned int);
|
||||
extern void nvptx_asm_output_def_from_decls (FILE *, tree, tree);
|
||||
extern unsigned int ptx_version_to_number (enum ptx_version, bool);
|
||||
|
||||
#ifdef RTX_CODE
|
||||
extern void nvptx_expand_oacc_fork (unsigned);
|
||||
|
|
|
@ -272,6 +272,28 @@ ptx_version_to_string (enum ptx_version v)
|
|||
}
|
||||
}
|
||||
|
||||
unsigned int
|
||||
ptx_version_to_number (enum ptx_version v, bool major_p)
|
||||
{
|
||||
switch (v)
|
||||
{
|
||||
case PTX_VERSION_3_0:
|
||||
return major_p ? 3 : 0;
|
||||
case PTX_VERSION_3_1:
|
||||
return major_p ? 3 : 1;
|
||||
case PTX_VERSION_4_2:
|
||||
return major_p ? 4 : 2;
|
||||
case PTX_VERSION_6_0:
|
||||
return major_p ? 6 : 0;
|
||||
case PTX_VERSION_6_3:
|
||||
return major_p ? 6 : 3;
|
||||
case PTX_VERSION_7_0:
|
||||
return major_p ? 7 : 0;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
|
||||
static const char *
|
||||
sm_version_to_string (enum ptx_isa sm)
|
||||
{
|
||||
|
|
|
@ -29,10 +29,24 @@
|
|||
|
||||
#define STARTFILE_SPEC "%{mmainkernel:crt0.o}"
|
||||
|
||||
/* Default needs to be in sync with default for misa in nvptx.opt.
|
||||
We add a default here to work around a hard-coded sm_30 default in
|
||||
nvptx-as. */
|
||||
#define ASM_SPEC "%{misa=*:-m %*; :-m sm_35}%{misa=sm_30:--no-verify}"
|
||||
/* Newer versions of CUDA no longer support sm_30, and nvptx-tools as
|
||||
currently doesn't handle that gracefully when verifying
|
||||
( https://github.com/MentorEmbedded/nvptx-tools/issues/30 ). Work around
|
||||
this by verifying with sm_35 when having misa=sm_30 (either implicitly
|
||||
or explicitly). */
|
||||
#define ASM_SPEC \
|
||||
"%{" \
|
||||
/* Explict misa=sm_30. */ \
|
||||
"misa=sm_30:-m sm_35" \
|
||||
/* Separator. */ \
|
||||
"; " \
|
||||
/* Catch-all. */ \
|
||||
"misa=*:-m %*" \
|
||||
/* Separator. */ \
|
||||
"; " \
|
||||
/* Implicit misa=sm_30. */ \
|
||||
":-m sm_35" \
|
||||
"}"
|
||||
|
||||
#define TARGET_CPU_CPP_BUILTINS() nvptx_cpu_cpp_builtins ()
|
||||
|
||||
|
|
|
@ -25,7 +25,8 @@
|
|||
|
||||
m64
|
||||
Target RejectNegative Mask(ABI64)
|
||||
Generate code for a 64-bit ABI.
|
||||
Ignored, but preserved for backward compatibility. Only 64-bit ABI is
|
||||
supported.
|
||||
|
||||
mmainkernel
|
||||
Target RejectNegative
|
||||
|
@ -54,11 +55,66 @@ Generate code for OpenMP offloading: enables -msoft-stack and -muniform-simt.
|
|||
; Default needs to be in sync with default in ASM_SPEC in nvptx.h.
|
||||
misa=
|
||||
Target RejectNegative ToLower Joined Enum(ptx_isa) Var(ptx_isa_option) Init(PTX_ISA_SM30)
|
||||
Specify the version of the ptx ISA to use.
|
||||
Specify the PTX ISA target architecture to use.
|
||||
|
||||
march=
|
||||
Target RejectNegative Joined Alias(misa=)
|
||||
Alias:
|
||||
|
||||
march-map=sm_30
|
||||
Target RejectNegative Alias(misa=,sm_30)
|
||||
|
||||
march-map=sm_32
|
||||
Target RejectNegative Alias(misa=,sm_30)
|
||||
|
||||
march-map=sm_35
|
||||
Target RejectNegative Alias(misa=,sm_35)
|
||||
|
||||
march-map=sm_37
|
||||
Target RejectNegative Alias(misa=,sm_35)
|
||||
|
||||
march-map=sm_50
|
||||
Target RejectNegative Alias(misa=,sm_35)
|
||||
|
||||
march-map=sm_52
|
||||
Target RejectNegative Alias(misa=,sm_35)
|
||||
|
||||
march-map=sm_53
|
||||
Target RejectNegative Alias(misa=,sm_53)
|
||||
|
||||
march-map=sm_60
|
||||
Target RejectNegative Alias(misa=,sm_53)
|
||||
|
||||
march-map=sm_61
|
||||
Target RejectNegative Alias(misa=,sm_53)
|
||||
|
||||
march-map=sm_62
|
||||
Target RejectNegative Alias(misa=,sm_53)
|
||||
|
||||
march-map=sm_70
|
||||
Target RejectNegative Alias(misa=,sm_70)
|
||||
|
||||
march-map=sm_72
|
||||
Target RejectNegative Alias(misa=,sm_70)
|
||||
|
||||
march-map=sm_75
|
||||
Target RejectNegative Alias(misa=,sm_75)
|
||||
|
||||
march-map=sm_80
|
||||
Target RejectNegative Alias(misa=,sm_80)
|
||||
|
||||
march-map=sm_86
|
||||
Target RejectNegative Alias(misa=,sm_80)
|
||||
|
||||
march-map=sm_87
|
||||
Target RejectNegative Alias(misa=,sm_80)
|
||||
|
||||
march-map=sm_90
|
||||
Target RejectNegative Alias(misa=,sm_80)
|
||||
|
||||
Enum
|
||||
Name(ptx_version) Type(int)
|
||||
Known PTX versions (for use with the -mptx= option):
|
||||
Known PTX ISA versions (for use with the -mptx= option):
|
||||
|
||||
EnumValue
|
||||
Enum(ptx_version) String(3.1) Value(PTX_VERSION_3_1)
|
||||
|
@ -77,7 +133,7 @@ Enum(ptx_version) String(_) Value(PTX_VERSION_default)
|
|||
|
||||
mptx=
|
||||
Target RejectNegative ToLower Joined Enum(ptx_version) Var(ptx_version_option)
|
||||
Specify the version of the ptx version to use.
|
||||
Specify the PTX ISA version to use.
|
||||
|
||||
minit-regs=
|
||||
Target Var(nvptx_init_regs) IntegerRange(0, 3) Joined UInteger Init(3)
|
||||
|
|
|
@ -23,7 +23,8 @@ s-nvptx-gen-h: $(srcdir)/config/nvptx/nvptx-sm.def
|
|||
$(STAMP) s-nvptx-gen-h
|
||||
|
||||
$(srcdir)/config/nvptx/nvptx-gen.opt: s-nvptx-gen-opt; @true
|
||||
s-nvptx-gen-opt: $(srcdir)/config/nvptx/nvptx-sm.def
|
||||
s-nvptx-gen-opt: $(srcdir)/config/nvptx/nvptx-sm.def \
|
||||
$(srcdir)/config/nvptx/gen-opt.sh
|
||||
$(SHELL) $(srcdir)/config/nvptx/gen-opt.sh "$(srcdir)/config/nvptx" \
|
||||
> tmp-nvptx-gen.opt
|
||||
$(SHELL) $(srcdir)/../move-if-change \
|
||||
|
|
|
@ -215,7 +215,7 @@
|
|||
; processors, this builtin automatically falls back to mffs on older
|
||||
; platforms. Thus it appears here in the [always] stanza.
|
||||
double __builtin_mffsl ();
|
||||
MFFSL rs6000_mffsl {}
|
||||
MFFSL rs6000_mffsl {nosoft}
|
||||
|
||||
; This is redundant with __builtin_pack_ibm128, as it requires long
|
||||
; double to be __ibm128. Should probably be deprecated.
|
||||
|
@ -226,10 +226,10 @@
|
|||
MFTB rs6000_mftb_di {32bit}
|
||||
|
||||
void __builtin_mtfsb0 (const int<5>);
|
||||
MTFSB0 rs6000_mtfsb0 {}
|
||||
MTFSB0 rs6000_mtfsb0 {nosoft}
|
||||
|
||||
void __builtin_mtfsb1 (const int<5>);
|
||||
MTFSB1 rs6000_mtfsb1 {}
|
||||
MTFSB1 rs6000_mtfsb1 {nosoft}
|
||||
|
||||
void __builtin_mtfsf (const int<8>, double);
|
||||
MTFSF rs6000_mtfsf {}
|
||||
|
@ -238,7 +238,7 @@
|
|||
PACK_IF packif {ibm128}
|
||||
|
||||
void __builtin_set_fpscr_rn (const int[0,3]);
|
||||
SET_FPSCR_RN rs6000_set_fpscr_rn {}
|
||||
SET_FPSCR_RN rs6000_set_fpscr_rn {nosoft}
|
||||
|
||||
const double __builtin_unpack_ibm128 (__ibm128, const int<1>);
|
||||
UNPACK_IF unpackif {ibm128}
|
||||
|
@ -410,6 +410,18 @@
|
|||
const vss __builtin_altivec_nabs_v8hi (vss);
|
||||
NABS_V8HI nabsv8hi2 {}
|
||||
|
||||
const vsc __builtin_altivec_neg_v16qi (vsc);
|
||||
NEG_V16QI negv16qi2 {}
|
||||
|
||||
const vf __builtin_altivec_neg_v4sf (vf);
|
||||
NEG_V4SF negv4sf2 {}
|
||||
|
||||
const vsi __builtin_altivec_neg_v4si (vsi);
|
||||
NEG_V4SI negv4si2 {}
|
||||
|
||||
const vss __builtin_altivec_neg_v8hi (vss);
|
||||
NEG_V8HI negv8hi2 {}
|
||||
|
||||
void __builtin_altivec_stvebx (vsc, signed long, void *);
|
||||
STVEBX altivec_stvebx {stvec}
|
||||
|
||||
|
@ -1175,6 +1187,12 @@
|
|||
const vsll __builtin_altivec_nabs_v2di (vsll);
|
||||
NABS_V2DI nabsv2di2 {}
|
||||
|
||||
const vd __builtin_altivec_neg_v2df (vd);
|
||||
NEG_V2DF negv2df2 {}
|
||||
|
||||
const vsll __builtin_altivec_neg_v2di (vsll);
|
||||
NEG_V2DI negv2di2 {}
|
||||
|
||||
void __builtin_altivec_stvx_v2df (vd, signed long, void *);
|
||||
STVX_V2DF altivec_stvx_v2df {stvec}
|
||||
|
||||
|
@ -2118,24 +2136,6 @@
|
|||
const vus __builtin_altivec_nand_v8hi_uns (vus, vus);
|
||||
NAND_V8HI_UNS nandv8hi3 {}
|
||||
|
||||
const vsc __builtin_altivec_neg_v16qi (vsc);
|
||||
NEG_V16QI negv16qi2 {}
|
||||
|
||||
const vd __builtin_altivec_neg_v2df (vd);
|
||||
NEG_V2DF negv2df2 {}
|
||||
|
||||
const vsll __builtin_altivec_neg_v2di (vsll);
|
||||
NEG_V2DI negv2di2 {}
|
||||
|
||||
const vf __builtin_altivec_neg_v4sf (vf);
|
||||
NEG_V4SF negv4sf2 {}
|
||||
|
||||
const vsi __builtin_altivec_neg_v4si (vsi);
|
||||
NEG_V4SI negv4si2 {}
|
||||
|
||||
const vss __builtin_altivec_neg_v8hi (vss);
|
||||
NEG_V8HI negv8hi2 {}
|
||||
|
||||
const vsc __builtin_altivec_orc_v16qi (vsc, vsc);
|
||||
ORC_V16QI orcv16qi3 {}
|
||||
|
||||
|
@ -2969,7 +2969,7 @@
|
|||
PACK_TD packtd {}
|
||||
|
||||
void __builtin_set_fpscr_drn (const int[0,7]);
|
||||
SET_FPSCR_DRN rs6000_set_fpscr_drn {}
|
||||
SET_FPSCR_DRN rs6000_set_fpscr_drn {nosoft,no32bit}
|
||||
|
||||
const unsigned long long __builtin_unpack_dec128 (_Decimal128, const int<1>);
|
||||
UNPACK_TD unpacktd {}
|
||||
|
|
|
@ -3397,15 +3397,12 @@
|
|||
;; Optimize cases were we can do a simple or direct move.
|
||||
;; Or see if we can avoid doing the move at all
|
||||
|
||||
;; There are some unresolved problems with reload that show up if an Altivec
|
||||
;; register was picked. Limit the scalar value to FPRs for now.
|
||||
|
||||
(define_insn "vsx_extract_<mode>"
|
||||
[(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=d, d, wr, wr")
|
||||
[(set (match_operand:<VS_scalar> 0 "gpc_reg_operand" "=wa, wa, wr, wr")
|
||||
(vec_select:<VS_scalar>
|
||||
(match_operand:VSX_D 1 "gpc_reg_operand" "wa, wa, wa, wa")
|
||||
(match_operand:VSX_D 1 "gpc_reg_operand" "wa, wa, wa, wa")
|
||||
(parallel
|
||||
[(match_operand:QI 2 "const_0_to_1_operand" "wD, n, wD, n")])))]
|
||||
[(match_operand:QI 2 "const_0_to_1_operand" "wD, n, wD, n")])))]
|
||||
"VECTOR_MEM_VSX_P (<MODE>mode)"
|
||||
{
|
||||
int element = INTVAL (operands[2]);
|
||||
|
|
|
@ -5442,6 +5442,9 @@ case "${target}" in
|
|||
# sets the default TLS model and affects inlining.
|
||||
PICFLAG_FOR_TARGET=-fPIC
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
PICFLAG_FOR_TARGET=-fpic
|
||||
;;
|
||||
mips-sgi-irix6*)
|
||||
# PIC is the default.
|
||||
;;
|
||||
|
@ -7963,6 +7966,9 @@ else
|
|||
mips*-*-*)
|
||||
enable_fixed_point=yes
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
enable_fixed_point=yes
|
||||
;;
|
||||
*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: fixed-point is not supported for this target, ignored" >&5
|
||||
$as_echo "$as_me: WARNING: fixed-point is not supported for this target, ignored" >&2;}
|
||||
|
@ -19667,7 +19673,7 @@ else
|
|||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 19670 "configure"
|
||||
#line 19676 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -19773,7 +19779,7 @@ else
|
|||
lt_dlunknown=0; lt_dlno_uscore=1; lt_dlneed_uscore=2
|
||||
lt_status=$lt_dlunknown
|
||||
cat > conftest.$ac_ext <<_LT_EOF
|
||||
#line 19776 "configure"
|
||||
#line 19782 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
#if HAVE_DLFCN_H
|
||||
|
@ -25556,6 +25562,17 @@ foo: data8 25
|
|||
movl r24 = @tprel(foo#)'
|
||||
tls_as_opt=--fatal-warnings
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
x: .word 2
|
||||
.text
|
||||
la.tls.gd $a0,x
|
||||
bl __tls_get_addr'
|
||||
tls_first_major=0
|
||||
tls_first_minor=0
|
||||
tls_as_opt='--fatal-warnings'
|
||||
;;
|
||||
microblaze*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
|
@ -28780,6 +28797,43 @@ $as_echo "#define HAVE_AS_MARCH_ZIFENCEI 1" >>confdefs.h
|
|||
fi
|
||||
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .dtprelword support" >&5
|
||||
$as_echo_n "checking assembler for .dtprelword support... " >&6; }
|
||||
if ${gcc_cv_as_loongarch_dtprelword+:} false; then :
|
||||
$as_echo_n "(cached) " >&6
|
||||
else
|
||||
gcc_cv_as_loongarch_dtprelword=no
|
||||
if test x$gcc_cv_as != x; then
|
||||
$as_echo '' > conftest.s
|
||||
if { ac_try='$gcc_cv_as $gcc_cv_as_flags 2,18,0 -o conftest.o conftest.s >&5'
|
||||
{ { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
|
||||
(eval $ac_try) 2>&5
|
||||
ac_status=$?
|
||||
$as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
|
||||
test $ac_status = 0; }; }
|
||||
then
|
||||
.section .tdata,"awT",@progbits
|
||||
x:
|
||||
.word 2
|
||||
.text
|
||||
.dtprelword x+0x8000
|
||||
else
|
||||
echo "configure: failed program was" >&5
|
||||
cat conftest.s >&5
|
||||
fi
|
||||
rm -f conftest.o conftest.s
|
||||
fi
|
||||
fi
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $gcc_cv_as_loongarch_dtprelword" >&5
|
||||
$as_echo "$gcc_cv_as_loongarch_dtprelword" >&6; }
|
||||
|
||||
if test $gcc_cv_as_loongarch_dtprelword != yes; then
|
||||
|
||||
$as_echo "#define HAVE_AS_DTPRELWORD 1" >>confdefs.h
|
||||
|
||||
fi
|
||||
;;
|
||||
s390*-*-*)
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking assembler for .gnu_attribute support" >&5
|
||||
$as_echo_n "checking assembler for .gnu_attribute support... " >&6; }
|
||||
|
@ -28943,11 +28997,11 @@ fi
|
|||
;;
|
||||
esac
|
||||
|
||||
# Mips and HP-UX need the GNU assembler.
|
||||
# Mips, LoongArch and HP-UX need the GNU assembler.
|
||||
# Linux on IA64 might be able to use the Intel assembler.
|
||||
|
||||
case "$target" in
|
||||
mips*-*-* | *-*-hpux* )
|
||||
mips*-*-* | loongarch*-*-* | *-*-hpux* )
|
||||
if test x$gas_flag = xyes \
|
||||
|| test x"$host" != x"$build" \
|
||||
|| test ! -x "$gcc_cv_as" \
|
||||
|
@ -29384,8 +29438,8 @@ esac
|
|||
# ??? Once 2.11 is released, probably need to add first known working
|
||||
# version to the per-target configury.
|
||||
case "$cpu_type" in
|
||||
aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | m32c | m68k \
|
||||
| microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \
|
||||
aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | loongarch | m32c \
|
||||
| m68k | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \
|
||||
| tilegx | tilepro | visium | xstormy16 | xtensa)
|
||||
insn="nop"
|
||||
;;
|
||||
|
|
|
@ -951,6 +951,9 @@ AC_ARG_ENABLE(fixed-point,
|
|||
mips*-*-*)
|
||||
enable_fixed_point=yes
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
enable_fixed_point=yes
|
||||
;;
|
||||
*)
|
||||
AC_MSG_WARN([fixed-point is not supported for this target, ignored])
|
||||
enable_fixed_point=no
|
||||
|
@ -3838,6 +3841,17 @@ foo: data8 25
|
|||
movl r24 = @tprel(foo#)'
|
||||
tls_as_opt=--fatal-warnings
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
x: .word 2
|
||||
.text
|
||||
la.tls.gd $a0,x
|
||||
bl __tls_get_addr'
|
||||
tls_first_major=0
|
||||
tls_first_minor=0
|
||||
tls_as_opt='--fatal-warnings'
|
||||
;;
|
||||
microblaze*-*-*)
|
||||
conftest_s='
|
||||
.section .tdata,"awT",@progbits
|
||||
|
@ -5300,6 +5314,17 @@ configured with --enable-newlib-nano-formatted-io.])
|
|||
[AC_DEFINE(HAVE_AS_MARCH_ZIFENCEI, 1,
|
||||
[Define if the assembler understands -march=rv*_zifencei.])])
|
||||
;;
|
||||
loongarch*-*-*)
|
||||
gcc_GAS_CHECK_FEATURE([.dtprelword support],
|
||||
gcc_cv_as_loongarch_dtprelword, [2,18,0],,
|
||||
[.section .tdata,"awT",@progbits
|
||||
x:
|
||||
.word 2
|
||||
.text
|
||||
.dtprelword x+0x8000],,
|
||||
[AC_DEFINE(HAVE_AS_DTPRELWORD, 1,
|
||||
[Define if your assembler supports .dtprelword.])])
|
||||
;;
|
||||
s390*-*-*)
|
||||
gcc_GAS_CHECK_FEATURE([.gnu_attribute support],
|
||||
gcc_cv_as_s390_gnu_attribute,,
|
||||
|
@ -5333,11 +5358,11 @@ configured with --enable-newlib-nano-formatted-io.])
|
|||
;;
|
||||
esac
|
||||
|
||||
# Mips and HP-UX need the GNU assembler.
|
||||
# Mips, LoongArch and HP-UX need the GNU assembler.
|
||||
# Linux on IA64 might be able to use the Intel assembler.
|
||||
|
||||
case "$target" in
|
||||
mips*-*-* | *-*-hpux* )
|
||||
mips*-*-* | loongarch*-*-* | *-*-hpux* )
|
||||
if test x$gas_flag = xyes \
|
||||
|| test x"$host" != x"$build" \
|
||||
|| test ! -x "$gcc_cv_as" \
|
||||
|
@ -5494,8 +5519,8 @@ esac
|
|||
# ??? Once 2.11 is released, probably need to add first known working
|
||||
# version to the per-target configury.
|
||||
case "$cpu_type" in
|
||||
aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | m32c | m68k \
|
||||
| microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \
|
||||
aarch64 | alpha | arc | arm | avr | bfin | cris | csky | i386 | loongarch | m32c \
|
||||
| m68k | microblaze | mips | nds32 | nios2 | pa | riscv | rs6000 | score | sparc \
|
||||
| tilegx | tilepro | visium | xstormy16 | xtensa)
|
||||
insn="nop"
|
||||
;;
|
||||
|
|
175
gcc/cp/ChangeLog
175
gcc/cp/ChangeLog
|
@ -1,3 +1,178 @@
|
|||
2022-03-31 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/96645
|
||||
* parser.cc (cp_parser_early_parsing_nsdmi): New.
|
||||
(cp_parser_member_declaration): Call it.
|
||||
|
||||
2022-03-30 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
PR c++/100474
|
||||
* constraint.cc (diagnose_trait_expr): Handle all remaining
|
||||
traits appropriately. Remove default case.
|
||||
|
||||
2022-03-30 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/93280
|
||||
PR c++/104583
|
||||
* init.cc (get_nsdmi): Set TARGET_EXPR_DIRECT_INIT_P to in_ctor.
|
||||
|
||||
2022-03-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/105092
|
||||
* pt.cc (tsubst_omp_clause_decl): When handling iterators, set
|
||||
DECL_CONTEXT of the iterator var to current_function_decl and
|
||||
call pushdecl.
|
||||
|
||||
2022-03-30 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/105061
|
||||
* parser.cc (cp_parser_template_introduction): If member_p, temporarily
|
||||
clear parser->colon_corrects_to_scope_p around tentative parsing of
|
||||
nested name specifier.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
* pt.cc (determine_specialization): Add comment.
|
||||
|
||||
2022-03-28 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
PR c++/105067
|
||||
* pt.cc (finish_concept_definition): Check that a concept is
|
||||
declared with exactly one template parameter list.
|
||||
|
||||
2022-03-28 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
PR c++/105064
|
||||
* constraint.cc (maybe_substitute_reqs_for): Don't assume
|
||||
DECL_TEMPLATE_INFO is available.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/105003
|
||||
PR c++/104008
|
||||
PR c++/102869
|
||||
* pt.cc (complex_alias_template_r): walk_tree callback, replacing
|
||||
uses_all_template_parms_r, complex_pack_expansion_r.
|
||||
(complex_alias_template_p): Adjust.
|
||||
* tree.cc (strip_typedefs): Revert r12-7710 change.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/102071
|
||||
* init.cc (build_new_1): Include cookie in alignment. Omit
|
||||
constexpr wrapper from alloc_call.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/103291
|
||||
* name-lookup.cc (push_local_extern_decl_alias): Call
|
||||
determine_visibility.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/102123
|
||||
* pt.cc (tsubst_copy): Use make_unbound_class_template for rewriting
|
||||
a type template reference.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/103968
|
||||
* pt.cc (value_dependent_expression_p): Check
|
||||
has_value_dependent_address for conversion to reference.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/103943
|
||||
* pt.cc (tsubst_qualified_id): Handle getting SCOPE_REF from
|
||||
tsubst_baselink.
|
||||
(instantiation_dependent_scope_ref_p): Check dependent_scope_p.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/102045
|
||||
* call.cc (make_base_init_ok): Call make_used.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/104847
|
||||
* mangle.cc (write_expression): Don't write a union designator when
|
||||
undigested.
|
||||
|
||||
2022-03-28 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/99445
|
||||
PR c++/103769
|
||||
* tree.cc (strip_typedefs): Use build_distinct_type_copy.
|
||||
|
||||
2022-03-26 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
PR c++/105050
|
||||
* constexpr.cc (potential_constant_expression_1) <case IF_STMT>:
|
||||
Clarify error message when a if-stmt is non-constant because its
|
||||
branches are non-constant.
|
||||
|
||||
2022-03-26 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
PR c++/103455
|
||||
* call.cc (add_builtin_candidate) <case MEMBER_REF>: Test
|
||||
CLASS_TYPE_P instead of MAYBE_CLASS_TYPE_P.
|
||||
|
||||
2022-03-26 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* parser.cc (cp_parser_postfix_expression)
|
||||
<case RID_BILTIN_CONVERTVECTOR, case RID_BUILTIN_BIT_CAST>: Don't
|
||||
return cp_build_{vec,convert,bit_cast} result right away, instead
|
||||
set postfix_expression to it and break.
|
||||
|
||||
2022-03-25 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/104944
|
||||
* typeck.cc (cxx_sizeof_or_alignof_type): Diagnose alignof(void).
|
||||
(cxx_alignas_expr): Call cxx_sizeof_or_alignof_type with
|
||||
complain == true.
|
||||
|
||||
2022-03-24 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/104284
|
||||
* decl.cc (check_initializer): Don't call build_aggr_init in
|
||||
a template.
|
||||
|
||||
2022-03-24 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/96645
|
||||
* cp-tree.h (type_has_default_ctor_to_be_synthesized): Declare.
|
||||
* class.cc (type_has_default_ctor_to_be_synthesized): New.
|
||||
(type_has_non_user_provided_default_constructor_1): Support it.
|
||||
(type_has_non_user_provided_default_constructor): Now a wrapper.
|
||||
* method.cc (complain_about_unparsed_dmi): New.
|
||||
(constructible_expr): Call it.
|
||||
|
||||
2022-03-24 Marek Polacek <polacek@redhat.com>
|
||||
|
||||
PR c++/102990
|
||||
* typeck2.cc (massage_init_elt): Avoid folding CONSTRUCTORs.
|
||||
|
||||
2022-03-24 Patrick Palka <ppalka@redhat.com>
|
||||
|
||||
PR c++/104620
|
||||
* call.cc (build_over_call): Use cxx_constant_value_sfinae
|
||||
instead of cxx_constant_value to evaluate a consteval call.
|
||||
* constexpr.cc (cxx_constant_value_sfinae): Add decl parameter
|
||||
and pass it to cxx_eval_outermost_constant_expr.
|
||||
* cp-tree.h (cxx_constant_value_sfinae): Add decl parameter.
|
||||
* pt.cc (fold_targs_r): Pass NULL_TREE as decl parameter to
|
||||
cxx_constant_value_sfinae.
|
||||
|
||||
2022-03-24 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/104994
|
||||
* constexpr.cc (cxx_eval_constant_expression): Don't diagnose passing
|
||||
through extern thread_local declarations. Change wording from
|
||||
declaration to definition.
|
||||
(potential_constant_expression_1): Don't diagnose extern thread_local
|
||||
declarations. Change wording from declared to defined.
|
||||
* decl.cc (start_decl): Likewise.
|
||||
|
||||
2022-03-23 Jason Merrill <jason@redhat.com>
|
||||
|
||||
PR c++/103337
|
||||
|
|
|
@ -2821,7 +2821,7 @@ add_builtin_candidate (struct z_candidate **candidates, enum tree_code code,
|
|||
tree c1 = TREE_TYPE (type1);
|
||||
tree c2 = TYPE_PTRMEM_CLASS_TYPE (type2);
|
||||
|
||||
if (MAYBE_CLASS_TYPE_P (c1) && DERIVED_FROM_P (c2, c1)
|
||||
if (CLASS_TYPE_P (c1) && DERIVED_FROM_P (c2, c1)
|
||||
&& (TYPE_PTRMEMFUNC_P (type2)
|
||||
|| is_complete (TYPE_PTRMEM_POINTED_TO_TYPE (type2))))
|
||||
break;
|
||||
|
@ -8958,6 +8958,7 @@ make_base_init_ok (tree exp)
|
|||
call target. It would be possible to splice in the appropriate
|
||||
arguments, but probably not worth the complexity. */
|
||||
return false;
|
||||
mark_used (fn);
|
||||
AGGR_INIT_EXPR_FN (exp) = build_address (fn);
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -5415,10 +5415,11 @@ type_has_user_provided_or_explicit_constructor (tree t)
|
|||
|
||||
/* Returns true iff class T has a non-user-provided (i.e. implicitly
|
||||
declared or explicitly defaulted in the class body) default
|
||||
constructor. */
|
||||
constructor. If SYNTH, only return true if it hasn't been
|
||||
implicitly defined yet. */
|
||||
|
||||
bool
|
||||
type_has_non_user_provided_default_constructor (tree t)
|
||||
static bool
|
||||
type_has_non_user_provided_default_constructor_1 (tree t, bool synth)
|
||||
{
|
||||
if (!TYPE_HAS_DEFAULT_CONSTRUCTOR (t))
|
||||
return false;
|
||||
|
@ -5431,12 +5432,28 @@ type_has_non_user_provided_default_constructor (tree t)
|
|||
if (TREE_CODE (fn) == FUNCTION_DECL
|
||||
&& default_ctor_p (fn)
|
||||
&& !user_provided_p (fn))
|
||||
return true;
|
||||
{
|
||||
if (synth)
|
||||
return !DECL_INITIAL (fn);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
type_has_non_user_provided_default_constructor (tree t)
|
||||
{
|
||||
return type_has_non_user_provided_default_constructor_1 (t, false);
|
||||
}
|
||||
|
||||
bool
|
||||
type_has_default_ctor_to_be_synthesized (tree t)
|
||||
{
|
||||
return type_has_non_user_provided_default_constructor_1 (t, true);
|
||||
}
|
||||
|
||||
/* TYPE is being used as a virtual base, and has a non-trivial move
|
||||
assignment. Return true if this is due to there being a user-provided
|
||||
move assignment in TYPE or one of its subobjects; if there isn't, then
|
||||
|
|
|
@ -9439,7 +9439,12 @@ potential_constant_expression_1 (tree t, bool want_rval, bool strict, bool now,
|
|||
}
|
||||
}
|
||||
if (flags & tf_error)
|
||||
error_at (loc, "expression %qE is not a constant expression", t);
|
||||
{
|
||||
if (TREE_CODE (t) == IF_STMT)
|
||||
error_at (loc, "neither branch of %<if%> is a constant expression");
|
||||
else
|
||||
error_at (loc, "expression %qE is not a constant expression", t);
|
||||
}
|
||||
return false;
|
||||
|
||||
case VEC_INIT_EXPR:
|
||||
|
|
|
@ -1268,20 +1268,15 @@ remove_constraints (tree t)
|
|||
for declaration matching. */
|
||||
|
||||
tree
|
||||
maybe_substitute_reqs_for (tree reqs, const_tree decl_)
|
||||
maybe_substitute_reqs_for (tree reqs, const_tree decl)
|
||||
{
|
||||
if (reqs == NULL_TREE)
|
||||
return NULL_TREE;
|
||||
|
||||
tree decl = CONST_CAST_TREE (decl_);
|
||||
tree result = STRIP_TEMPLATE (decl);
|
||||
|
||||
if (DECL_UNIQUE_FRIEND_P (result))
|
||||
decl = STRIP_TEMPLATE (decl);
|
||||
if (DECL_UNIQUE_FRIEND_P (decl) && DECL_TEMPLATE_INFO (decl))
|
||||
{
|
||||
tree tmpl = decl;
|
||||
if (TREE_CODE (decl) != TEMPLATE_DECL)
|
||||
tmpl = DECL_TI_TEMPLATE (result);
|
||||
|
||||
tree tmpl = DECL_TI_TEMPLATE (decl);
|
||||
tree gargs = generic_targs_for (tmpl);
|
||||
processing_template_decl_sentinel s;
|
||||
if (uses_template_parms (gargs))
|
||||
|
@ -3659,8 +3654,49 @@ diagnose_trait_expr (tree expr, tree args)
|
|||
case CPTK_IS_UNION:
|
||||
inform (loc, " %qT is not a union", t1);
|
||||
break;
|
||||
default:
|
||||
case CPTK_IS_AGGREGATE:
|
||||
inform (loc, " %qT is not an aggregate", t1);
|
||||
break;
|
||||
case CPTK_IS_TRIVIALLY_COPYABLE:
|
||||
inform (loc, " %qT is not trivially copyable", t1);
|
||||
break;
|
||||
case CPTK_IS_ASSIGNABLE:
|
||||
inform (loc, " %qT is not assignable from %qT", t1, t2);
|
||||
break;
|
||||
case CPTK_IS_TRIVIALLY_ASSIGNABLE:
|
||||
inform (loc, " %qT is not trivially assignable from %qT", t1, t2);
|
||||
break;
|
||||
case CPTK_IS_NOTHROW_ASSIGNABLE:
|
||||
inform (loc, " %qT is not %<nothrow%> assignable from %qT", t1, t2);
|
||||
break;
|
||||
case CPTK_IS_CONSTRUCTIBLE:
|
||||
if (!t2)
|
||||
inform (loc, " %qT is not default constructible", t1);
|
||||
else
|
||||
inform (loc, " %qT is not constructible from %qE", t1, t2);
|
||||
break;
|
||||
case CPTK_IS_TRIVIALLY_CONSTRUCTIBLE:
|
||||
if (!t2)
|
||||
inform (loc, " %qT is not trivially default constructible", t1);
|
||||
else
|
||||
inform (loc, " %qT is not trivially constructible from %qE", t1, t2);
|
||||
break;
|
||||
case CPTK_IS_NOTHROW_CONSTRUCTIBLE:
|
||||
if (!t2)
|
||||
inform (loc, " %qT is not %<nothrow%> default constructible", t1);
|
||||
else
|
||||
inform (loc, " %qT is not %<nothrow%> constructible from %qE", t1, t2);
|
||||
break;
|
||||
case CPTK_HAS_UNIQUE_OBJ_REPRESENTATIONS:
|
||||
inform (loc, " %qT does not have unique object representations", t1);
|
||||
break;
|
||||
case CPTK_BASES:
|
||||
case CPTK_DIRECT_BASES:
|
||||
case CPTK_UNDERLYING_TYPE:
|
||||
/* We shouldn't see these non-expression traits. */
|
||||
gcc_unreachable ();
|
||||
/* We deliberately omit the default case so that when adding a new
|
||||
trait we'll get reminded (by way of a warning) to handle it here. */
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6720,6 +6720,7 @@ extern tree in_class_defaulted_default_constructor (tree);
|
|||
extern bool user_provided_p (tree);
|
||||
extern bool type_has_user_provided_constructor (tree);
|
||||
extern bool type_has_non_user_provided_default_constructor (tree);
|
||||
extern bool type_has_default_ctor_to_be_synthesized (tree);
|
||||
extern bool vbase_has_user_provided_move_assign (tree);
|
||||
extern tree default_init_uninitialized_part (tree);
|
||||
extern bool trivial_default_constructor_is_constexpr (tree);
|
||||
|
|
|
@ -7332,6 +7332,10 @@ check_initializer (tree decl, tree init, int flags, vec<tree, va_gc> **cleanups)
|
|||
&& !(init && BRACE_ENCLOSED_INITIALIZER_P (init)
|
||||
&& CP_AGGREGATE_TYPE_P (type)
|
||||
&& (CLASS_TYPE_P (type)
|
||||
/* The call to build_aggr_init below could end up
|
||||
calling build_vec_init, which may break when we
|
||||
are processing a template. */
|
||||
|| processing_template_decl
|
||||
|| !TYPE_NEEDS_CONSTRUCTING (type)
|
||||
|| type_has_extended_temps (type))))
|
||||
|| (DECL_DECOMPOSITION_P (decl) && TREE_CODE (type) == ARRAY_TYPE))
|
||||
|
|
|
@ -679,10 +679,10 @@ get_nsdmi (tree member, bool in_ctor, tsubst_flags_t complain)
|
|||
if (simple_target)
|
||||
init = TARGET_EXPR_INITIAL (init);
|
||||
init = break_out_target_exprs (init, /*loc*/true);
|
||||
if (in_ctor && init && TREE_CODE (init) == TARGET_EXPR)
|
||||
/* This expresses the full initialization, prevent perform_member_init from
|
||||
calling another constructor (58162). */
|
||||
TARGET_EXPR_DIRECT_INIT_P (init) = true;
|
||||
if (init && TREE_CODE (init) == TARGET_EXPR)
|
||||
/* In a constructor, this expresses the full initialization, prevent
|
||||
perform_member_init from calling another constructor (58162). */
|
||||
TARGET_EXPR_DIRECT_INIT_P (init) = in_ctor;
|
||||
if (simple_target && TREE_CODE (init) != CONSTRUCTOR)
|
||||
/* Now put it back so C++17 copy elision works. */
|
||||
init = get_target_expr (init);
|
||||
|
@ -3284,7 +3284,13 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
|||
|
||||
tree align_arg = NULL_TREE;
|
||||
if (type_has_new_extended_alignment (elt_type))
|
||||
align_arg = build_int_cst (align_type_node, TYPE_ALIGN_UNIT (elt_type));
|
||||
{
|
||||
unsigned align = TYPE_ALIGN_UNIT (elt_type);
|
||||
/* Also consider the alignment of the cookie, if any. */
|
||||
if (TYPE_VEC_NEW_USES_COOKIE (elt_type))
|
||||
align = MAX (align, TYPE_ALIGN_UNIT (size_type_node));
|
||||
align_arg = build_int_cst (align_type_node, align);
|
||||
}
|
||||
|
||||
alloc_fn = NULL_TREE;
|
||||
|
||||
|
@ -3473,18 +3479,19 @@ build_new_1 (vec<tree, va_gc> **placement, tree type, tree nelts,
|
|||
}
|
||||
}
|
||||
|
||||
alloc_expr = alloc_call;
|
||||
if (cookie_size)
|
||||
alloc_call = maybe_wrap_new_for_constexpr (alloc_call, type,
|
||||
alloc_expr = maybe_wrap_new_for_constexpr (alloc_expr, type,
|
||||
cookie_size);
|
||||
|
||||
/* In the simple case, we can stop now. */
|
||||
pointer_type = build_pointer_type (type);
|
||||
if (!cookie_size && !is_initialized && !member_delete_p)
|
||||
return build_nop (pointer_type, alloc_call);
|
||||
return build_nop (pointer_type, alloc_expr);
|
||||
|
||||
/* Store the result of the allocation call in a variable so that we can
|
||||
use it more than once. */
|
||||
alloc_expr = get_target_expr (alloc_call);
|
||||
alloc_expr = get_target_expr (alloc_expr);
|
||||
alloc_node = TARGET_EXPR_SLOT (alloc_expr);
|
||||
|
||||
/* Strip any COMPOUND_EXPRs from ALLOC_CALL. */
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue