Merge branch 'master' into devel/modula-2.

This commit is contained in:
Gaius Mulley 2022-04-01 20:20:02 +01:00
commit eae2c45ec9
351 changed files with 26990 additions and 3041 deletions

View File

@ -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.

View File

@ -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>

View File

@ -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

View File

@ -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.
;;

32
configure vendored
View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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 \

View File

@ -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

View File

@ -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):

View File

@ -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

View File

@ -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

View File

@ -1 +1 @@
20220324
20220401

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

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

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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 */

View File

@ -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. */

View File

@ -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);

View File

@ -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. */

View File

@ -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

View File

@ -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)

View File

@ -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,

View File

@ -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.

View File

@ -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

View File

@ -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
{

View File

@ -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));
}

View File

@ -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)

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

@ -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

View File

@ -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;

View File

@ -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.

View File

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

View File

@ -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")

View File

@ -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>

View File

@ -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 "" "")]

View File

@ -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

View File

@ -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

View File

@ -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 \

View File

@ -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))

View File

@ -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))

View File

@ -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))")))

View File

@ -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")

View File

@ -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 "$@"

View File

@ -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

View File

@ -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.

View File

@ -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)

View File

@ -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

View File

@ -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 */

View File

@ -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

View File

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

View File

@ -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);
}

View File

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

View File

@ -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 */

View File

@ -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},
},
};

View File

@ -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 */

View File

@ -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 *);
}

View File

@ -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 */

View File

@ -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))

View File

@ -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);

View File

@ -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 *);
}

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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.

View File

@ -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)"))))

View File

@ -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;
})

View File

@ -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

View File

@ -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

View File

@ -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. */

View File

@ -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.

View File

@ -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);
}
}

View File

@ -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)

View File

@ -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);

View File

@ -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)
{

View File

@ -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 ()

View File

@ -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)

View File

@ -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 \

View File

@ -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 {}

View File

@ -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]);

66
gcc/configure vendored
View File

@ -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"
;;

View File

@ -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"
;;

View File

@ -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

View File

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

View File

@ -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

View File

@ -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:

View File

@ -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. */
}
}

View File

@ -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);

View File

@ -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))

View File

@ -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