mirror of git://gcc.gnu.org/git/gcc.git
Merge commit '56ca59a03150cf44cea340f58967c990ed6bf43c^' into HEAD
This commit is contained in:
commit
b3a1373731
41
ChangeLog
41
ChangeLog
|
|
@ -1,3 +1,44 @@
|
|||
2023-11-18 Petter Tomner <tomner@bahnhof.se>
|
||||
|
||||
* MAINTAINERS: Update my email address.
|
||||
|
||||
2023-11-18 Frederik Harwath <frederik@harwath.name>
|
||||
|
||||
* MAINTAINERS: Change my address.
|
||||
|
||||
2023-11-16 Michal Jires <mjires@suse.cz>
|
||||
|
||||
* MAINTAINERS: Add myself.
|
||||
|
||||
2023-11-13 Arsen Arsenović <arsen@aarsen.me>
|
||||
|
||||
PR bootstrap/12596
|
||||
* .gitignore: Add '/gettext*'.
|
||||
* configure.ac (host_libs): Replace intl with gettext.
|
||||
(hbaseargs, bbaseargs, baseargs): Split baseargs into
|
||||
{h,b}baseargs.
|
||||
(skip_barg): New flag. Skips appending current flag to
|
||||
bbaseargs.
|
||||
<library exemptions>: Exempt --with-libintl-{type,prefix} from
|
||||
target and build machine argument passing.
|
||||
* configure: Regenerate.
|
||||
* Makefile.def (host_modules): Replace intl module with gettext
|
||||
module.
|
||||
(configure-ld): Depend on configure-gettext.
|
||||
* Makefile.in: Regenerate.
|
||||
|
||||
2023-11-13 Arsen Arsenović <arsen@aarsen.me>
|
||||
|
||||
* intl/*: Remove.
|
||||
|
||||
2023-11-09 Jivan Hakobyan <jivanhakobyan9@gmail.com>
|
||||
|
||||
* MAINTAINERS: Add myself.
|
||||
|
||||
2023-11-09 YunQiang Su <yunqiang.su@cipunited.com>
|
||||
|
||||
* MAINTAINERS: Update my email address.
|
||||
|
||||
2023-11-06 Carl Love <cel@linux.ibm.com>
|
||||
|
||||
* MAINTAINERS: Update my email address.
|
||||
|
|
|
|||
|
|
@ -448,7 +448,7 @@ Naveen H.S <naveenh@marvell.com>
|
|||
Mostafa Hagog <hagog@gcc.gnu.org>
|
||||
Jivan Hakobyan <jivanhakobyan9@gmail.com>
|
||||
Andrew Haley <aph@redhat.com>
|
||||
Frederik Harwath <frederik@codesourcery.com>
|
||||
Frederik Harwath <frederik@harwath.name>
|
||||
Stuart Hastings <stuart@apple.com>
|
||||
Michael Haubenwallner <michael.haubenwallner@ssi-schaefer.com>
|
||||
Pat Haugen <pthaugen@us.ibm.com>
|
||||
|
|
@ -487,6 +487,7 @@ Fariborz Jahanian <fjahanian@apple.com>
|
|||
Surya Kumari Jangala <jskumari@linux.ibm.com>
|
||||
Haochen Jiang <haochen.jiang@intel.com>
|
||||
Qian Jianhua <qianjh@fujitsu.com>
|
||||
Michal Jires <mjires@suse.cz>
|
||||
Janis Johnson <janis.marie.johnson@gmail.com>
|
||||
Teresa Johnson <tejohnson@google.com>
|
||||
Kean Johnston <jkj@sco.com>
|
||||
|
|
@ -682,7 +683,7 @@ Dinar Temirbulatov <dtemirbulatov@gmail.com>
|
|||
Kresten Krab Thorup <krab@gcc.gnu.org>
|
||||
Kai Tietz <ktietz70@googlemail.com>
|
||||
Ilya Tocar <tocarip@gmail.com>
|
||||
Petter Tomner <tomner@kth.se>
|
||||
Petter Tomner <tomner@bahnhof.se>
|
||||
Philipp Tomsich <philipp.tomsich@vrull.eu>
|
||||
Daniel Towner <dant@picochip.com>
|
||||
Konrad Trifunovic <konrad.trifunovic@inria.fr>
|
||||
|
|
@ -754,6 +755,7 @@ information.
|
|||
|
||||
Robin Dapp <rdapp.gcc@gmail.com>
|
||||
Robin Dapp <rdapp@ventanamicro.com>
|
||||
Michal Jires <mjires@suse.cz>
|
||||
Matthias Kretz <m.kretz@gsi.de>
|
||||
Tim Lange <mail@tim-lange.me>
|
||||
Jeff Law <jeffreyalaw@gmail.com>
|
||||
|
|
@ -768,7 +770,7 @@ 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>
|
||||
Petter Tomner <tomner@bahnhof.se>
|
||||
Martin Uecker <uecker@gcc.gnu.org>
|
||||
Jonathan Wakely <jwakely@redhat.com>
|
||||
Chung-Ju Wu <jasonwucj@gmail.com>
|
||||
|
|
|
|||
|
|
@ -1,3 +1,11 @@
|
|||
2023-11-13 Arsen Arsenović <arsen@aarsen.me>
|
||||
|
||||
* intlmacosx.m4: Import from gettext-0.22 (serial 8).
|
||||
* gettext.m4: Sync with gettext-0.22 (serial 77).
|
||||
* gettext-sister.m4 (ZW_GNU_GETTEXT_SISTER_DIR): Load gettext's
|
||||
uninstalled-config.sh, or call AM_GNU_GETTEXT if missing.
|
||||
* iconv.m4: Sync with gettext-0.22 (serial 26).
|
||||
|
||||
2023-09-15 Yang Yujie <yangyujie@loongson.cn>
|
||||
|
||||
* mt-loongarch-mlib: New file. Pass -fmultiflags when building
|
||||
|
|
|
|||
|
|
@ -1,3 +1,26 @@
|
|||
2023-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* unicode/README: Adjust glibc git commit hash, number of Unicode
|
||||
data files to be updated and latest Unicode version.
|
||||
* unicode/from_glibc/utf8_gen.py: Update from glibc.
|
||||
* unicode/UnicodeData.txt: Update from Unicode 15.1.
|
||||
* unicode/EastAsianWidth.txt: Likewise.
|
||||
* unicode/DerivedNormalizationProps.txt: Likewise.
|
||||
* unicode/NameAliases.txt: Likewise.
|
||||
* unicode/DerivedCoreProperties.txt: Likewise.
|
||||
* unicode/PropList.txt: Likewise.
|
||||
|
||||
2023-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
* gcc-changelog/git_update_version.py: Add
|
||||
040e5b0edbca861196d9e2ea2af5e805769c8d5d to ignored commits.
|
||||
|
||||
2023-11-13 Arsen Arsenović <arsen@aarsen.me>
|
||||
|
||||
* prerequisites.sha512: Add gettext.
|
||||
* prerequisites.md5: Add gettext.
|
||||
* download_prerequisites: Add gettext.
|
||||
|
||||
2023-10-05 Andrea Corallo <andrea.corallo@arm.com>
|
||||
|
||||
* mdcompact/mdcompact-testsuite.el: New file.
|
||||
|
|
|
|||
|
|
@ -37,7 +37,8 @@ IGNORED_COMMITS = (
|
|||
'3ab5c8cd03d92bf4ec41e351820349d92fbc40c4',
|
||||
'86d8e0c0652ef5236a460b75c25e4f7093cc0651',
|
||||
'e4cba49413ca429dc82f6aa2e88129ecb3fdd943',
|
||||
'1957bedf29a1b2cc231972aba680fe80199d5498')
|
||||
'1957bedf29a1b2cc231972aba680fe80199d5498',
|
||||
'040e5b0edbca861196d9e2ea2af5e805769c8d5d')
|
||||
|
||||
FORMAT = '%(asctime)s:%(levelname)s:%(name)s:%(message)s'
|
||||
logging.basicConfig(level=logging.INFO, format=FORMAT,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# DerivedCoreProperties-15.0.0.txt
|
||||
# Date: 2022-08-05, 22:17:05 GMT
|
||||
# © 2022 Unicode®, Inc.
|
||||
# DerivedCoreProperties-15.1.0.txt
|
||||
# Date: 2023-08-07, 15:21:24 GMT
|
||||
# © 2023 Unicode®, Inc.
|
||||
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
|
||||
# For terms of use, see https://www.unicode.org/terms_of_use.html
|
||||
#
|
||||
|
|
@ -1397,11 +1397,12 @@ FFDA..FFDC ; Alphabetic # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANG
|
|||
2B740..2B81D ; Alphabetic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; Alphabetic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; Alphabetic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; Alphabetic # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; Alphabetic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; Alphabetic # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; Alphabetic # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
|
||||
# Total code points: 137765
|
||||
# Total code points: 138387
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -6853,11 +6854,12 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
2B740..2B81D ; ID_Start # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; ID_Start # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; ID_Start # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; ID_Start # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; ID_Start # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; ID_Start # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; ID_Start # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
|
||||
# Total code points: 136345
|
||||
# Total code points: 136967
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -7438,6 +7440,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
1FE0..1FEC ; ID_Continue # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA
|
||||
1FF2..1FF4 ; ID_Continue # L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
|
||||
1FF6..1FFC ; ID_Continue # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
|
||||
200C..200D ; ID_Continue # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
|
||||
203F..2040 ; ID_Continue # Pc [2] UNDERTIE..CHARACTER TIE
|
||||
2054 ; ID_Continue # Pc INVERTED UNDERTIE
|
||||
2071 ; ID_Continue # Lm SUPERSCRIPT LATIN SMALL LETTER I
|
||||
|
|
@ -7504,6 +7507,7 @@ FFDA..FFDC ; ID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGUL
|
|||
309D..309E ; ID_Continue # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
|
||||
309F ; ID_Continue # Lo HIRAGANA DIGRAPH YORI
|
||||
30A1..30FA ; ID_Continue # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO
|
||||
30FB ; ID_Continue # Po KATAKANA MIDDLE DOT
|
||||
30FC..30FE ; ID_Continue # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
|
||||
30FF ; ID_Continue # Lo KATAKANA DIGRAPH KOTO
|
||||
3105..312F ; ID_Continue # Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN
|
||||
|
|
@ -7683,6 +7687,7 @@ FF10..FF19 ; ID_Continue # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NIN
|
|||
FF21..FF3A ; ID_Continue # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
|
||||
FF3F ; ID_Continue # Pc FULLWIDTH LOW LINE
|
||||
FF41..FF5A ; ID_Continue # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
|
||||
FF65 ; ID_Continue # Po HALFWIDTH KATAKANA MIDDLE DOT
|
||||
FF66..FF6F ; ID_Continue # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU
|
||||
FF70 ; ID_Continue # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
|
||||
FF71..FF9D ; ID_Continue # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N
|
||||
|
|
@ -8207,12 +8212,13 @@ FFDA..FFDC ; ID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HAN
|
|||
2B740..2B81D ; ID_Continue # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; ID_Continue # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; ID_Continue # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; ID_Continue # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; ID_Continue # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; ID_Continue # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; ID_Continue # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
E0100..E01EF ; ID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
|
||||
|
||||
# Total code points: 139482
|
||||
# Total code points: 140108
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -8962,11 +8968,12 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU
|
|||
2B740..2B81D ; XID_Start # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; XID_Start # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; XID_Start # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; XID_Start # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; XID_Start # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; XID_Start # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; XID_Start # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
|
||||
# Total code points: 136322
|
||||
# Total code points: 136944
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -9543,6 +9550,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU
|
|||
1FE0..1FEC ; XID_Continue # L& [13] GREEK SMALL LETTER UPSILON WITH VRACHY..GREEK CAPITAL LETTER RHO WITH DASIA
|
||||
1FF2..1FF4 ; XID_Continue # L& [3] GREEK SMALL LETTER OMEGA WITH VARIA AND YPOGEGRAMMENI..GREEK SMALL LETTER OMEGA WITH OXIA AND YPOGEGRAMMENI
|
||||
1FF6..1FFC ; XID_Continue # L& [7] GREEK SMALL LETTER OMEGA WITH PERISPOMENI..GREEK CAPITAL LETTER OMEGA WITH PROSGEGRAMMENI
|
||||
200C..200D ; XID_Continue # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
|
||||
203F..2040 ; XID_Continue # Pc [2] UNDERTIE..CHARACTER TIE
|
||||
2054 ; XID_Continue # Pc INVERTED UNDERTIE
|
||||
2071 ; XID_Continue # Lm SUPERSCRIPT LATIN SMALL LETTER I
|
||||
|
|
@ -9608,6 +9616,7 @@ FFDA..FFDC ; XID_Start # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HANGU
|
|||
309D..309E ; XID_Continue # Lm [2] HIRAGANA ITERATION MARK..HIRAGANA VOICED ITERATION MARK
|
||||
309F ; XID_Continue # Lo HIRAGANA DIGRAPH YORI
|
||||
30A1..30FA ; XID_Continue # Lo [90] KATAKANA LETTER SMALL A..KATAKANA LETTER VO
|
||||
30FB ; XID_Continue # Po KATAKANA MIDDLE DOT
|
||||
30FC..30FE ; XID_Continue # Lm [3] KATAKANA-HIRAGANA PROLONGED SOUND MARK..KATAKANA VOICED ITERATION MARK
|
||||
30FF ; XID_Continue # Lo KATAKANA DIGRAPH KOTO
|
||||
3105..312F ; XID_Continue # Lo [43] BOPOMOFO LETTER B..BOPOMOFO LETTER NN
|
||||
|
|
@ -9793,6 +9802,7 @@ FF10..FF19 ; XID_Continue # Nd [10] FULLWIDTH DIGIT ZERO..FULLWIDTH DIGIT NI
|
|||
FF21..FF3A ; XID_Continue # L& [26] FULLWIDTH LATIN CAPITAL LETTER A..FULLWIDTH LATIN CAPITAL LETTER Z
|
||||
FF3F ; XID_Continue # Pc FULLWIDTH LOW LINE
|
||||
FF41..FF5A ; XID_Continue # L& [26] FULLWIDTH LATIN SMALL LETTER A..FULLWIDTH LATIN SMALL LETTER Z
|
||||
FF65 ; XID_Continue # Po HALFWIDTH KATAKANA MIDDLE DOT
|
||||
FF66..FF6F ; XID_Continue # Lo [10] HALFWIDTH KATAKANA LETTER WO..HALFWIDTH KATAKANA LETTER SMALL TU
|
||||
FF70 ; XID_Continue # Lm HALFWIDTH KATAKANA-HIRAGANA PROLONGED SOUND MARK
|
||||
FF71..FF9D ; XID_Continue # Lo [45] HALFWIDTH KATAKANA LETTER A..HALFWIDTH KATAKANA LETTER N
|
||||
|
|
@ -10317,12 +10327,13 @@ FFDA..FFDC ; XID_Continue # Lo [3] HALFWIDTH HANGUL LETTER EU..HALFWIDTH HA
|
|||
2B740..2B81D ; XID_Continue # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; XID_Continue # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; XID_Continue # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; XID_Continue # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; XID_Continue # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; XID_Continue # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; XID_Continue # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
E0100..E01EF ; XID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTOR-256
|
||||
|
||||
# Total code points: 139463
|
||||
# Total code points: 140089
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -10335,6 +10346,15 @@ E0100..E01EF ; XID_Continue # Mn [240] VARIATION SELECTOR-17..VARIATION SELECTO
|
|||
# - FFF9..FFFB (Interlinear annotation format characters)
|
||||
# - 13430..13440 (Egyptian hieroglyph format characters)
|
||||
# - Prepended_Concatenation_Mark (Exceptional format characters that should be visible)
|
||||
#
|
||||
# There are currently no stability guarantees for DICP. However, the
|
||||
# values of DICP interact with the derivation of XID_Continue
|
||||
# and NFKC_CF, for which there are stability guarantees.
|
||||
# Maintainers of this property should note that in the
|
||||
# unlikely case that the DICP value changes for an existing character
|
||||
# which is also XID_Continue=Yes, then exceptions must be put
|
||||
# in place to ensure that the NFKC_CF mapping value for that
|
||||
# existing character does not change.
|
||||
|
||||
00AD ; Default_Ignorable_Code_Point # Cf SOFT HYPHEN
|
||||
034F ; Default_Ignorable_Code_Point # Mn COMBINING GRAPHEME JOINER
|
||||
|
|
@ -11602,7 +11622,7 @@ E0100..E01EF ; Grapheme_Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELE
|
|||
2E80..2E99 ; Grapheme_Base # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP
|
||||
2E9B..2EF3 ; Grapheme_Base # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
|
||||
2F00..2FD5 ; Grapheme_Base # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
|
||||
2FF0..2FFB ; Grapheme_Base # So [12] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
|
||||
2FF0..2FFF ; Grapheme_Base # So [16] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION
|
||||
3000 ; Grapheme_Base # Zs IDEOGRAPHIC SPACE
|
||||
3001..3003 ; Grapheme_Base # Po [3] IDEOGRAPHIC COMMA..DITTO MARK
|
||||
3004 ; Grapheme_Base # So JAPANESE INDUSTRIAL STANDARD SYMBOL
|
||||
|
|
@ -11657,6 +11677,7 @@ E0100..E01EF ; Grapheme_Extend # Mn [240] VARIATION SELECTOR-17..VARIATION SELE
|
|||
3196..319F ; Grapheme_Base # So [10] IDEOGRAPHIC ANNOTATION TOP MARK..IDEOGRAPHIC ANNOTATION MAN MARK
|
||||
31A0..31BF ; Grapheme_Base # Lo [32] BOPOMOFO LETTER BU..BOPOMOFO LETTER AH
|
||||
31C0..31E3 ; Grapheme_Base # So [36] CJK STROKE T..CJK STROKE Q
|
||||
31EF ; Grapheme_Base # So IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION
|
||||
31F0..31FF ; Grapheme_Base # Lo [16] KATAKANA LETTER SMALL KU..KATAKANA LETTER SMALL RO
|
||||
3200..321E ; Grapheme_Base # So [31] PARENTHESIZED HANGUL KIYEOK..PARENTHESIZED KOREAN CHARACTER O HU
|
||||
3220..3229 ; Grapheme_Base # No [10] PARENTHESIZED IDEOGRAPH ONE..PARENTHESIZED IDEOGRAPH TEN
|
||||
|
|
@ -12497,11 +12518,12 @@ FFFC..FFFD ; Grapheme_Base # So [2] OBJECT REPLACEMENT CHARACTER..REPLACEME
|
|||
2B740..2B81D ; Grapheme_Base # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; Grapheme_Base # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; Grapheme_Base # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; Grapheme_Base # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; Grapheme_Base # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; Grapheme_Base # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; Grapheme_Base # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
|
||||
# Total code points: 146986
|
||||
# Total code points: 147613
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -12572,4 +12594,239 @@ ABED ; Grapheme_Link # Mn MEETEI MAYEK APUN IYEK
|
|||
|
||||
# Total code points: 65
|
||||
|
||||
# ================================================
|
||||
|
||||
# Derived Property: Indic_Conjunct_Break
|
||||
# Generated from the Grapheme_Cluster_Break, Indic_Syllabic_Category,
|
||||
# Canonical_Combining_Class, and Script properties as described in UAX #44:
|
||||
# https://www.unicode.org/reports/tr44/.
|
||||
|
||||
# All code points not explicitly listed for Indic_Conjunct_Break
|
||||
# have the value None.
|
||||
|
||||
# @missing: 0000..10FFFF; InCB; None
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Conjunct_Break=Linker
|
||||
|
||||
094D ; InCB; Linker # Mn DEVANAGARI SIGN VIRAMA
|
||||
09CD ; InCB; Linker # Mn BENGALI SIGN VIRAMA
|
||||
0ACD ; InCB; Linker # Mn GUJARATI SIGN VIRAMA
|
||||
0B4D ; InCB; Linker # Mn ORIYA SIGN VIRAMA
|
||||
0C4D ; InCB; Linker # Mn TELUGU SIGN VIRAMA
|
||||
0D4D ; InCB; Linker # Mn MALAYALAM SIGN VIRAMA
|
||||
|
||||
# Total code points: 6
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Conjunct_Break=Consonant
|
||||
|
||||
0915..0939 ; InCB; Consonant # Lo [37] DEVANAGARI LETTER KA..DEVANAGARI LETTER HA
|
||||
0958..095F ; InCB; Consonant # Lo [8] DEVANAGARI LETTER QA..DEVANAGARI LETTER YYA
|
||||
0978..097F ; InCB; Consonant # Lo [8] DEVANAGARI LETTER MARWARI DDA..DEVANAGARI LETTER BBA
|
||||
0995..09A8 ; InCB; Consonant # Lo [20] BENGALI LETTER KA..BENGALI LETTER NA
|
||||
09AA..09B0 ; InCB; Consonant # Lo [7] BENGALI LETTER PA..BENGALI LETTER RA
|
||||
09B2 ; InCB; Consonant # Lo BENGALI LETTER LA
|
||||
09B6..09B9 ; InCB; Consonant # Lo [4] BENGALI LETTER SHA..BENGALI LETTER HA
|
||||
09DC..09DD ; InCB; Consonant # Lo [2] BENGALI LETTER RRA..BENGALI LETTER RHA
|
||||
09DF ; InCB; Consonant # Lo BENGALI LETTER YYA
|
||||
09F0..09F1 ; InCB; Consonant # Lo [2] BENGALI LETTER RA WITH MIDDLE DIAGONAL..BENGALI LETTER RA WITH LOWER DIAGONAL
|
||||
0A95..0AA8 ; InCB; Consonant # Lo [20] GUJARATI LETTER KA..GUJARATI LETTER NA
|
||||
0AAA..0AB0 ; InCB; Consonant # Lo [7] GUJARATI LETTER PA..GUJARATI LETTER RA
|
||||
0AB2..0AB3 ; InCB; Consonant # Lo [2] GUJARATI LETTER LA..GUJARATI LETTER LLA
|
||||
0AB5..0AB9 ; InCB; Consonant # Lo [5] GUJARATI LETTER VA..GUJARATI LETTER HA
|
||||
0AF9 ; InCB; Consonant # Lo GUJARATI LETTER ZHA
|
||||
0B15..0B28 ; InCB; Consonant # Lo [20] ORIYA LETTER KA..ORIYA LETTER NA
|
||||
0B2A..0B30 ; InCB; Consonant # Lo [7] ORIYA LETTER PA..ORIYA LETTER RA
|
||||
0B32..0B33 ; InCB; Consonant # Lo [2] ORIYA LETTER LA..ORIYA LETTER LLA
|
||||
0B35..0B39 ; InCB; Consonant # Lo [5] ORIYA LETTER VA..ORIYA LETTER HA
|
||||
0B5C..0B5D ; InCB; Consonant # Lo [2] ORIYA LETTER RRA..ORIYA LETTER RHA
|
||||
0B5F ; InCB; Consonant # Lo ORIYA LETTER YYA
|
||||
0B71 ; InCB; Consonant # Lo ORIYA LETTER WA
|
||||
0C15..0C28 ; InCB; Consonant # Lo [20] TELUGU LETTER KA..TELUGU LETTER NA
|
||||
0C2A..0C39 ; InCB; Consonant # Lo [16] TELUGU LETTER PA..TELUGU LETTER HA
|
||||
0C58..0C5A ; InCB; Consonant # Lo [3] TELUGU LETTER TSA..TELUGU LETTER RRRA
|
||||
0D15..0D3A ; InCB; Consonant # Lo [38] MALAYALAM LETTER KA..MALAYALAM LETTER TTTA
|
||||
|
||||
# Total code points: 240
|
||||
|
||||
# ================================================
|
||||
|
||||
# Indic_Conjunct_Break=Extend
|
||||
|
||||
0300..034E ; InCB; Extend # Mn [79] COMBINING GRAVE ACCENT..COMBINING UPWARDS ARROW BELOW
|
||||
0350..036F ; InCB; Extend # Mn [32] COMBINING RIGHT ARROWHEAD ABOVE..COMBINING LATIN SMALL LETTER X
|
||||
0483..0487 ; InCB; Extend # Mn [5] COMBINING CYRILLIC TITLO..COMBINING CYRILLIC POKRYTIE
|
||||
0591..05BD ; InCB; Extend # Mn [45] HEBREW ACCENT ETNAHTA..HEBREW POINT METEG
|
||||
05BF ; InCB; Extend # Mn HEBREW POINT RAFE
|
||||
05C1..05C2 ; InCB; Extend # Mn [2] HEBREW POINT SHIN DOT..HEBREW POINT SIN DOT
|
||||
05C4..05C5 ; InCB; Extend # Mn [2] HEBREW MARK UPPER DOT..HEBREW MARK LOWER DOT
|
||||
05C7 ; InCB; Extend # Mn HEBREW POINT QAMATS QATAN
|
||||
0610..061A ; InCB; Extend # Mn [11] ARABIC SIGN SALLALLAHOU ALAYHE WASSALLAM..ARABIC SMALL KASRA
|
||||
064B..065F ; InCB; Extend # Mn [21] ARABIC FATHATAN..ARABIC WAVY HAMZA BELOW
|
||||
0670 ; InCB; Extend # Mn ARABIC LETTER SUPERSCRIPT ALEF
|
||||
06D6..06DC ; InCB; Extend # Mn [7] ARABIC SMALL HIGH LIGATURE SAD WITH LAM WITH ALEF MAKSURA..ARABIC SMALL HIGH SEEN
|
||||
06DF..06E4 ; InCB; Extend # Mn [6] ARABIC SMALL HIGH ROUNDED ZERO..ARABIC SMALL HIGH MADDA
|
||||
06E7..06E8 ; InCB; Extend # Mn [2] ARABIC SMALL HIGH YEH..ARABIC SMALL HIGH NOON
|
||||
06EA..06ED ; InCB; Extend # Mn [4] ARABIC EMPTY CENTRE LOW STOP..ARABIC SMALL LOW MEEM
|
||||
0711 ; InCB; Extend # Mn SYRIAC LETTER SUPERSCRIPT ALAPH
|
||||
0730..074A ; InCB; Extend # Mn [27] SYRIAC PTHAHA ABOVE..SYRIAC BARREKH
|
||||
07EB..07F3 ; InCB; Extend # Mn [9] NKO COMBINING SHORT HIGH TONE..NKO COMBINING DOUBLE DOT ABOVE
|
||||
07FD ; InCB; Extend # Mn NKO DANTAYALAN
|
||||
0816..0819 ; InCB; Extend # Mn [4] SAMARITAN MARK IN..SAMARITAN MARK DAGESH
|
||||
081B..0823 ; InCB; Extend # Mn [9] SAMARITAN MARK EPENTHETIC YUT..SAMARITAN VOWEL SIGN A
|
||||
0825..0827 ; InCB; Extend # Mn [3] SAMARITAN VOWEL SIGN SHORT A..SAMARITAN VOWEL SIGN U
|
||||
0829..082D ; InCB; Extend # Mn [5] SAMARITAN VOWEL SIGN LONG I..SAMARITAN MARK NEQUDAA
|
||||
0859..085B ; InCB; Extend # Mn [3] MANDAIC AFFRICATION MARK..MANDAIC GEMINATION MARK
|
||||
0898..089F ; InCB; Extend # Mn [8] ARABIC SMALL HIGH WORD AL-JUZ..ARABIC HALF MADDA OVER MADDA
|
||||
08CA..08E1 ; InCB; Extend # Mn [24] ARABIC SMALL HIGH FARSI YEH..ARABIC SMALL HIGH SIGN SAFHA
|
||||
08E3..08FF ; InCB; Extend # Mn [29] ARABIC TURNED DAMMA BELOW..ARABIC MARK SIDEWAYS NOON GHUNNA
|
||||
093C ; InCB; Extend # Mn DEVANAGARI SIGN NUKTA
|
||||
0951..0954 ; InCB; Extend # Mn [4] DEVANAGARI STRESS SIGN UDATTA..DEVANAGARI ACUTE ACCENT
|
||||
09BC ; InCB; Extend # Mn BENGALI SIGN NUKTA
|
||||
09FE ; InCB; Extend # Mn BENGALI SANDHI MARK
|
||||
0A3C ; InCB; Extend # Mn GURMUKHI SIGN NUKTA
|
||||
0ABC ; InCB; Extend # Mn GUJARATI SIGN NUKTA
|
||||
0B3C ; InCB; Extend # Mn ORIYA SIGN NUKTA
|
||||
0C3C ; InCB; Extend # Mn TELUGU SIGN NUKTA
|
||||
0C55..0C56 ; InCB; Extend # Mn [2] TELUGU LENGTH MARK..TELUGU AI LENGTH MARK
|
||||
0CBC ; InCB; Extend # Mn KANNADA SIGN NUKTA
|
||||
0D3B..0D3C ; InCB; Extend # Mn [2] MALAYALAM SIGN VERTICAL BAR VIRAMA..MALAYALAM SIGN CIRCULAR VIRAMA
|
||||
0E38..0E3A ; InCB; Extend # Mn [3] THAI CHARACTER SARA U..THAI CHARACTER PHINTHU
|
||||
0E48..0E4B ; InCB; Extend # Mn [4] THAI CHARACTER MAI EK..THAI CHARACTER MAI CHATTAWA
|
||||
0EB8..0EBA ; InCB; Extend # Mn [3] LAO VOWEL SIGN U..LAO SIGN PALI VIRAMA
|
||||
0EC8..0ECB ; InCB; Extend # Mn [4] LAO TONE MAI EK..LAO TONE MAI CATAWA
|
||||
0F18..0F19 ; InCB; Extend # Mn [2] TIBETAN ASTROLOGICAL SIGN -KHYUD PA..TIBETAN ASTROLOGICAL SIGN SDONG TSHUGS
|
||||
0F35 ; InCB; Extend # Mn TIBETAN MARK NGAS BZUNG NYI ZLA
|
||||
0F37 ; InCB; Extend # Mn TIBETAN MARK NGAS BZUNG SGOR RTAGS
|
||||
0F39 ; InCB; Extend # Mn TIBETAN MARK TSA -PHRU
|
||||
0F71..0F72 ; InCB; Extend # Mn [2] TIBETAN VOWEL SIGN AA..TIBETAN VOWEL SIGN I
|
||||
0F74 ; InCB; Extend # Mn TIBETAN VOWEL SIGN U
|
||||
0F7A..0F7D ; InCB; Extend # Mn [4] TIBETAN VOWEL SIGN E..TIBETAN VOWEL SIGN OO
|
||||
0F80 ; InCB; Extend # Mn TIBETAN VOWEL SIGN REVERSED I
|
||||
0F82..0F84 ; InCB; Extend # Mn [3] TIBETAN SIGN NYI ZLA NAA DA..TIBETAN MARK HALANTA
|
||||
0F86..0F87 ; InCB; Extend # Mn [2] TIBETAN SIGN LCI RTAGS..TIBETAN SIGN YANG RTAGS
|
||||
0FC6 ; InCB; Extend # Mn TIBETAN SYMBOL PADMA GDAN
|
||||
1037 ; InCB; Extend # Mn MYANMAR SIGN DOT BELOW
|
||||
1039..103A ; InCB; Extend # Mn [2] MYANMAR SIGN VIRAMA..MYANMAR SIGN ASAT
|
||||
108D ; InCB; Extend # Mn MYANMAR SIGN SHAN COUNCIL EMPHATIC TONE
|
||||
135D..135F ; InCB; Extend # Mn [3] ETHIOPIC COMBINING GEMINATION AND VOWEL LENGTH MARK..ETHIOPIC COMBINING GEMINATION MARK
|
||||
1714 ; InCB; Extend # Mn TAGALOG SIGN VIRAMA
|
||||
17D2 ; InCB; Extend # Mn KHMER SIGN COENG
|
||||
17DD ; InCB; Extend # Mn KHMER SIGN ATTHACAN
|
||||
18A9 ; InCB; Extend # Mn MONGOLIAN LETTER ALI GALI DAGALGA
|
||||
1939..193B ; InCB; Extend # Mn [3] LIMBU SIGN MUKPHRENG..LIMBU SIGN SA-I
|
||||
1A17..1A18 ; InCB; Extend # Mn [2] BUGINESE VOWEL SIGN I..BUGINESE VOWEL SIGN U
|
||||
1A60 ; InCB; Extend # Mn TAI THAM SIGN SAKOT
|
||||
1A75..1A7C ; InCB; Extend # Mn [8] TAI THAM SIGN TONE-1..TAI THAM SIGN KHUEN-LUE KARAN
|
||||
1A7F ; InCB; Extend # Mn TAI THAM COMBINING CRYPTOGRAMMIC DOT
|
||||
1AB0..1ABD ; InCB; Extend # Mn [14] COMBINING DOUBLED CIRCUMFLEX ACCENT..COMBINING PARENTHESES BELOW
|
||||
1ABF..1ACE ; InCB; Extend # Mn [16] COMBINING LATIN SMALL LETTER W BELOW..COMBINING LATIN SMALL LETTER INSULAR T
|
||||
1B34 ; InCB; Extend # Mn BALINESE SIGN REREKAN
|
||||
1B6B..1B73 ; InCB; Extend # Mn [9] BALINESE MUSICAL SYMBOL COMBINING TEGEH..BALINESE MUSICAL SYMBOL COMBINING GONG
|
||||
1BAB ; InCB; Extend # Mn SUNDANESE SIGN VIRAMA
|
||||
1BE6 ; InCB; Extend # Mn BATAK SIGN TOMPI
|
||||
1C37 ; InCB; Extend # Mn LEPCHA SIGN NUKTA
|
||||
1CD0..1CD2 ; InCB; Extend # Mn [3] VEDIC TONE KARSHANA..VEDIC TONE PRENKHA
|
||||
1CD4..1CE0 ; InCB; Extend # Mn [13] VEDIC SIGN YAJURVEDIC MIDLINE SVARITA..VEDIC TONE RIGVEDIC KASHMIRI INDEPENDENT SVARITA
|
||||
1CE2..1CE8 ; InCB; Extend # Mn [7] VEDIC SIGN VISARGA SVARITA..VEDIC SIGN VISARGA ANUDATTA WITH TAIL
|
||||
1CED ; InCB; Extend # Mn VEDIC SIGN TIRYAK
|
||||
1CF4 ; InCB; Extend # Mn VEDIC TONE CANDRA ABOVE
|
||||
1CF8..1CF9 ; InCB; Extend # Mn [2] VEDIC TONE RING ABOVE..VEDIC TONE DOUBLE RING ABOVE
|
||||
1DC0..1DFF ; InCB; Extend # Mn [64] COMBINING DOTTED GRAVE ACCENT..COMBINING RIGHT ARROWHEAD AND DOWN ARROWHEAD BELOW
|
||||
200D ; InCB; Extend # Cf ZERO WIDTH JOINER
|
||||
20D0..20DC ; InCB; Extend # Mn [13] COMBINING LEFT HARPOON ABOVE..COMBINING FOUR DOTS ABOVE
|
||||
20E1 ; InCB; Extend # Mn COMBINING LEFT RIGHT ARROW ABOVE
|
||||
20E5..20F0 ; InCB; Extend # Mn [12] COMBINING REVERSE SOLIDUS OVERLAY..COMBINING ASTERISK ABOVE
|
||||
2CEF..2CF1 ; InCB; Extend # Mn [3] COPTIC COMBINING NI ABOVE..COPTIC COMBINING SPIRITUS LENIS
|
||||
2D7F ; InCB; Extend # Mn TIFINAGH CONSONANT JOINER
|
||||
2DE0..2DFF ; InCB; Extend # Mn [32] COMBINING CYRILLIC LETTER BE..COMBINING CYRILLIC LETTER IOTIFIED BIG YUS
|
||||
302A..302D ; InCB; Extend # Mn [4] IDEOGRAPHIC LEVEL TONE MARK..IDEOGRAPHIC ENTERING TONE MARK
|
||||
302E..302F ; InCB; Extend # Mc [2] HANGUL SINGLE DOT TONE MARK..HANGUL DOUBLE DOT TONE MARK
|
||||
3099..309A ; InCB; Extend # Mn [2] COMBINING KATAKANA-HIRAGANA VOICED SOUND MARK..COMBINING KATAKANA-HIRAGANA SEMI-VOICED SOUND MARK
|
||||
A66F ; InCB; Extend # Mn COMBINING CYRILLIC VZMET
|
||||
A674..A67D ; InCB; Extend # Mn [10] COMBINING CYRILLIC LETTER UKRAINIAN IE..COMBINING CYRILLIC PAYEROK
|
||||
A69E..A69F ; InCB; Extend # Mn [2] COMBINING CYRILLIC LETTER EF..COMBINING CYRILLIC LETTER IOTIFIED E
|
||||
A6F0..A6F1 ; InCB; Extend # Mn [2] BAMUM COMBINING MARK KOQNDON..BAMUM COMBINING MARK TUKWENTIS
|
||||
A82C ; InCB; Extend # Mn SYLOTI NAGRI SIGN ALTERNATE HASANTA
|
||||
A8E0..A8F1 ; InCB; Extend # Mn [18] COMBINING DEVANAGARI DIGIT ZERO..COMBINING DEVANAGARI SIGN AVAGRAHA
|
||||
A92B..A92D ; InCB; Extend # Mn [3] KAYAH LI TONE PLOPHU..KAYAH LI TONE CALYA PLOPHU
|
||||
A9B3 ; InCB; Extend # Mn JAVANESE SIGN CECAK TELU
|
||||
AAB0 ; InCB; Extend # Mn TAI VIET MAI KANG
|
||||
AAB2..AAB4 ; InCB; Extend # Mn [3] TAI VIET VOWEL I..TAI VIET VOWEL U
|
||||
AAB7..AAB8 ; InCB; Extend # Mn [2] TAI VIET MAI KHIT..TAI VIET VOWEL IA
|
||||
AABE..AABF ; InCB; Extend # Mn [2] TAI VIET VOWEL AM..TAI VIET TONE MAI EK
|
||||
AAC1 ; InCB; Extend # Mn TAI VIET TONE MAI THO
|
||||
AAF6 ; InCB; Extend # Mn MEETEI MAYEK VIRAMA
|
||||
ABED ; InCB; Extend # Mn MEETEI MAYEK APUN IYEK
|
||||
FB1E ; InCB; Extend # Mn HEBREW POINT JUDEO-SPANISH VARIKA
|
||||
FE20..FE2F ; InCB; Extend # Mn [16] COMBINING LIGATURE LEFT HALF..COMBINING CYRILLIC TITLO RIGHT HALF
|
||||
101FD ; InCB; Extend # Mn PHAISTOS DISC SIGN COMBINING OBLIQUE STROKE
|
||||
102E0 ; InCB; Extend # Mn COPTIC EPACT THOUSANDS MARK
|
||||
10376..1037A ; InCB; Extend # Mn [5] COMBINING OLD PERMIC LETTER AN..COMBINING OLD PERMIC LETTER SII
|
||||
10A0D ; InCB; Extend # Mn KHAROSHTHI SIGN DOUBLE RING BELOW
|
||||
10A0F ; InCB; Extend # Mn KHAROSHTHI SIGN VISARGA
|
||||
10A38..10A3A ; InCB; Extend # Mn [3] KHAROSHTHI SIGN BAR ABOVE..KHAROSHTHI SIGN DOT BELOW
|
||||
10A3F ; InCB; Extend # Mn KHAROSHTHI VIRAMA
|
||||
10AE5..10AE6 ; InCB; Extend # Mn [2] MANICHAEAN ABBREVIATION MARK ABOVE..MANICHAEAN ABBREVIATION MARK BELOW
|
||||
10D24..10D27 ; InCB; Extend # Mn [4] HANIFI ROHINGYA SIGN HARBAHAY..HANIFI ROHINGYA SIGN TASSI
|
||||
10EAB..10EAC ; InCB; Extend # Mn [2] YEZIDI COMBINING HAMZA MARK..YEZIDI COMBINING MADDA MARK
|
||||
10EFD..10EFF ; InCB; Extend # Mn [3] ARABIC SMALL LOW WORD SAKTA..ARABIC SMALL LOW WORD MADDA
|
||||
10F46..10F50 ; InCB; Extend # Mn [11] SOGDIAN COMBINING DOT BELOW..SOGDIAN COMBINING STROKE BELOW
|
||||
10F82..10F85 ; InCB; Extend # Mn [4] OLD UYGHUR COMBINING DOT ABOVE..OLD UYGHUR COMBINING TWO DOTS BELOW
|
||||
11070 ; InCB; Extend # Mn BRAHMI SIGN OLD TAMIL VIRAMA
|
||||
1107F ; InCB; Extend # Mn BRAHMI NUMBER JOINER
|
||||
110BA ; InCB; Extend # Mn KAITHI SIGN NUKTA
|
||||
11100..11102 ; InCB; Extend # Mn [3] CHAKMA SIGN CANDRABINDU..CHAKMA SIGN VISARGA
|
||||
11133..11134 ; InCB; Extend # Mn [2] CHAKMA VIRAMA..CHAKMA MAAYYAA
|
||||
11173 ; InCB; Extend # Mn MAHAJANI SIGN NUKTA
|
||||
111CA ; InCB; Extend # Mn SHARADA SIGN NUKTA
|
||||
11236 ; InCB; Extend # Mn KHOJKI SIGN NUKTA
|
||||
112E9..112EA ; InCB; Extend # Mn [2] KHUDAWADI SIGN NUKTA..KHUDAWADI SIGN VIRAMA
|
||||
1133B..1133C ; InCB; Extend # Mn [2] COMBINING BINDU BELOW..GRANTHA SIGN NUKTA
|
||||
11366..1136C ; InCB; Extend # Mn [7] COMBINING GRANTHA DIGIT ZERO..COMBINING GRANTHA DIGIT SIX
|
||||
11370..11374 ; InCB; Extend # Mn [5] COMBINING GRANTHA LETTER A..COMBINING GRANTHA LETTER PA
|
||||
11446 ; InCB; Extend # Mn NEWA SIGN NUKTA
|
||||
1145E ; InCB; Extend # Mn NEWA SANDHI MARK
|
||||
114C3 ; InCB; Extend # Mn TIRHUTA SIGN NUKTA
|
||||
115C0 ; InCB; Extend # Mn SIDDHAM SIGN NUKTA
|
||||
116B7 ; InCB; Extend # Mn TAKRI SIGN NUKTA
|
||||
1172B ; InCB; Extend # Mn AHOM SIGN KILLER
|
||||
1183A ; InCB; Extend # Mn DOGRA SIGN NUKTA
|
||||
1193E ; InCB; Extend # Mn DIVES AKURU VIRAMA
|
||||
11943 ; InCB; Extend # Mn DIVES AKURU SIGN NUKTA
|
||||
11A34 ; InCB; Extend # Mn ZANABAZAR SQUARE SIGN VIRAMA
|
||||
11A47 ; InCB; Extend # Mn ZANABAZAR SQUARE SUBJOINER
|
||||
11A99 ; InCB; Extend # Mn SOYOMBO SUBJOINER
|
||||
11D42 ; InCB; Extend # Mn MASARAM GONDI SIGN NUKTA
|
||||
11D44..11D45 ; InCB; Extend # Mn [2] MASARAM GONDI SIGN HALANTA..MASARAM GONDI VIRAMA
|
||||
11D97 ; InCB; Extend # Mn GUNJALA GONDI VIRAMA
|
||||
11F42 ; InCB; Extend # Mn KAWI CONJOINER
|
||||
16AF0..16AF4 ; InCB; Extend # Mn [5] BASSA VAH COMBINING HIGH TONE..BASSA VAH COMBINING HIGH-LOW TONE
|
||||
16B30..16B36 ; InCB; Extend # Mn [7] PAHAWH HMONG MARK CIM TUB..PAHAWH HMONG MARK CIM TAUM
|
||||
1BC9E ; InCB; Extend # Mn DUPLOYAN DOUBLE MARK
|
||||
1D165 ; InCB; Extend # Mc MUSICAL SYMBOL COMBINING STEM
|
||||
1D167..1D169 ; InCB; Extend # Mn [3] MUSICAL SYMBOL COMBINING TREMOLO-1..MUSICAL SYMBOL COMBINING TREMOLO-3
|
||||
1D16E..1D172 ; InCB; Extend # Mc [5] MUSICAL SYMBOL COMBINING FLAG-1..MUSICAL SYMBOL COMBINING FLAG-5
|
||||
1D17B..1D182 ; InCB; Extend # Mn [8] MUSICAL SYMBOL COMBINING ACCENT..MUSICAL SYMBOL COMBINING LOURE
|
||||
1D185..1D18B ; InCB; Extend # Mn [7] MUSICAL SYMBOL COMBINING DOIT..MUSICAL SYMBOL COMBINING TRIPLE TONGUE
|
||||
1D1AA..1D1AD ; InCB; Extend # Mn [4] MUSICAL SYMBOL COMBINING DOWN BOW..MUSICAL SYMBOL COMBINING SNAP PIZZICATO
|
||||
1D242..1D244 ; InCB; Extend # Mn [3] COMBINING GREEK MUSICAL TRISEME..COMBINING GREEK MUSICAL PENTASEME
|
||||
1E000..1E006 ; InCB; Extend # Mn [7] COMBINING GLAGOLITIC LETTER AZU..COMBINING GLAGOLITIC LETTER ZHIVETE
|
||||
1E008..1E018 ; InCB; Extend # Mn [17] COMBINING GLAGOLITIC LETTER ZEMLJA..COMBINING GLAGOLITIC LETTER HERU
|
||||
1E01B..1E021 ; InCB; Extend # Mn [7] COMBINING GLAGOLITIC LETTER SHTA..COMBINING GLAGOLITIC LETTER YATI
|
||||
1E023..1E024 ; InCB; Extend # Mn [2] COMBINING GLAGOLITIC LETTER YU..COMBINING GLAGOLITIC LETTER SMALL YUS
|
||||
1E026..1E02A ; InCB; Extend # Mn [5] COMBINING GLAGOLITIC LETTER YO..COMBINING GLAGOLITIC LETTER FITA
|
||||
1E08F ; InCB; Extend # Mn COMBINING CYRILLIC SMALL LETTER BYELORUSSIAN-UKRAINIAN I
|
||||
1E130..1E136 ; InCB; Extend # Mn [7] NYIAKENG PUACHUE HMONG TONE-B..NYIAKENG PUACHUE HMONG TONE-D
|
||||
1E2AE ; InCB; Extend # Mn TOTO SIGN RISING TONE
|
||||
1E2EC..1E2EF ; InCB; Extend # Mn [4] WANCHO TONE TUP..WANCHO TONE KOINI
|
||||
1E4EC..1E4EF ; InCB; Extend # Mn [4] NAG MUNDARI SIGN MUHOR..NAG MUNDARI SIGN SUTUH
|
||||
1E8D0..1E8D6 ; InCB; Extend # Mn [7] MENDE KIKAKUI COMBINING NUMBER TEENS..MENDE KIKAKUI COMBINING NUMBER MILLIONS
|
||||
1E944..1E94A ; InCB; Extend # Mn [7] ADLAM ALIF LENGTHENER..ADLAM NUKTA
|
||||
|
||||
# Total code points: 884
|
||||
|
||||
# EOF
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
|
@ -1,6 +1,6 @@
|
|||
# NameAliases-15.0.0.txt
|
||||
# Date: 2022-07-26, 20:13:00 GMT [KW]
|
||||
# © 2022 Unicode®, Inc.
|
||||
# NameAliases-15.1.0.txt
|
||||
# Date: 2023-01-05
|
||||
# © 2023 Unicode®, Inc.
|
||||
# For terms of use, see https://www.unicode.org/terms_of_use.html
|
||||
#
|
||||
# Unicode Character Database
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# PropList-15.0.0.txt
|
||||
# Date: 2022-08-05, 22:17:16 GMT
|
||||
# © 2022 Unicode®, Inc.
|
||||
# PropList-15.1.0.txt
|
||||
# Date: 2023-08-01, 21:56:53 GMT
|
||||
# © 2023 Unicode®, Inc.
|
||||
# Unicode and the Unicode Logo are registered trademarks of Unicode, Inc. in the U.S. and other countries.
|
||||
# For terms of use, see https://www.unicode.org/terms_of_use.html
|
||||
#
|
||||
|
|
@ -856,11 +856,12 @@ FA70..FAD9 ; Ideographic # Lo [106] CJK COMPATIBILITY IDEOGRAPH-FA70..CJK COM
|
|||
2B740..2B81D ; Ideographic # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; Ideographic # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; Ideographic # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; Ideographic # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
2F800..2FA1D ; Ideographic # Lo [542] CJK COMPATIBILITY IDEOGRAPH-2F800..CJK COMPATIBILITY IDEOGRAPH-2FA1D
|
||||
30000..3134A ; Ideographic # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; Ideographic # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
|
||||
# Total code points: 105854
|
||||
# Total code points: 106476
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -1241,9 +1242,10 @@ E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
|
|||
# ================================================
|
||||
|
||||
2FF0..2FF1 ; IDS_Binary_Operator # So [2] IDEOGRAPHIC DESCRIPTION CHARACTER LEFT TO RIGHT..IDEOGRAPHIC DESCRIPTION CHARACTER ABOVE TO BELOW
|
||||
2FF4..2FFB ; IDS_Binary_Operator # So [8] IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND..IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID
|
||||
2FF4..2FFD ; IDS_Binary_Operator # So [10] IDEOGRAPHIC DESCRIPTION CHARACTER FULL SURROUND..IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER RIGHT
|
||||
31EF ; IDS_Binary_Operator # So IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION
|
||||
|
||||
# Total code points: 10
|
||||
# Total code points: 13
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -1253,6 +1255,12 @@ E0020..E007F ; Other_Grapheme_Extend # Cf [96] TAG SPACE..CANCEL TAG
|
|||
|
||||
# ================================================
|
||||
|
||||
2FFE..2FFF ; IDS_Unary_Operator # So [2] IDEOGRAPHIC DESCRIPTION CHARACTER HORIZONTAL REFLECTION..IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION
|
||||
|
||||
# Total code points: 2
|
||||
|
||||
# ================================================
|
||||
|
||||
2E80..2E99 ; Radical # So [26] CJK RADICAL REPEAT..CJK RADICAL RAP
|
||||
2E9B..2EF3 ; Radical # So [89] CJK RADICAL CHOKE..CJK RADICAL C-SIMPLIFIED TURTLE
|
||||
2F00..2FD5 ; Radical # So [214] KANGXI RADICAL ONE..KANGXI RADICAL FLUTE
|
||||
|
|
@ -1275,10 +1283,11 @@ FA27..FA29 ; Unified_Ideograph # Lo [3] CJK COMPATIBILITY IDEOGRAPH-FA27..C
|
|||
2B740..2B81D ; Unified_Ideograph # Lo [222] CJK UNIFIED IDEOGRAPH-2B740..CJK UNIFIED IDEOGRAPH-2B81D
|
||||
2B820..2CEA1 ; Unified_Ideograph # Lo [5762] CJK UNIFIED IDEOGRAPH-2B820..CJK UNIFIED IDEOGRAPH-2CEA1
|
||||
2CEB0..2EBE0 ; Unified_Ideograph # Lo [7473] CJK UNIFIED IDEOGRAPH-2CEB0..CJK UNIFIED IDEOGRAPH-2EBE0
|
||||
2EBF0..2EE5D ; Unified_Ideograph # Lo [622] CJK UNIFIED IDEOGRAPH-2EBF0..CJK UNIFIED IDEOGRAPH-2EE5D
|
||||
30000..3134A ; Unified_Ideograph # Lo [4939] CJK UNIFIED IDEOGRAPH-30000..CJK UNIFIED IDEOGRAPH-3134A
|
||||
31350..323AF ; Unified_Ideograph # Lo [4192] CJK UNIFIED IDEOGRAPH-31350..CJK UNIFIED IDEOGRAPH-323AF
|
||||
|
||||
# Total code points: 97058
|
||||
# Total code points: 97680
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -1376,8 +1385,58 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET
|
|||
0387 ; Other_ID_Continue # Po GREEK ANO TELEIA
|
||||
1369..1371 ; Other_ID_Continue # No [9] ETHIOPIC DIGIT ONE..ETHIOPIC DIGIT NINE
|
||||
19DA ; Other_ID_Continue # No NEW TAI LUE THAM DIGIT ONE
|
||||
200C..200D ; Other_ID_Continue # Cf [2] ZERO WIDTH NON-JOINER..ZERO WIDTH JOINER
|
||||
30FB ; Other_ID_Continue # Po KATAKANA MIDDLE DOT
|
||||
FF65 ; Other_ID_Continue # Po HALFWIDTH KATAKANA MIDDLE DOT
|
||||
|
||||
# Total code points: 12
|
||||
# Total code points: 16
|
||||
|
||||
# ================================================
|
||||
|
||||
00B2..00B3 ; ID_Compat_Math_Continue # No [2] SUPERSCRIPT TWO..SUPERSCRIPT THREE
|
||||
00B9 ; ID_Compat_Math_Continue # No SUPERSCRIPT ONE
|
||||
2070 ; ID_Compat_Math_Continue # No SUPERSCRIPT ZERO
|
||||
2074..2079 ; ID_Compat_Math_Continue # No [6] SUPERSCRIPT FOUR..SUPERSCRIPT NINE
|
||||
207A..207C ; ID_Compat_Math_Continue # Sm [3] SUPERSCRIPT PLUS SIGN..SUPERSCRIPT EQUALS SIGN
|
||||
207D ; ID_Compat_Math_Continue # Ps SUPERSCRIPT LEFT PARENTHESIS
|
||||
207E ; ID_Compat_Math_Continue # Pe SUPERSCRIPT RIGHT PARENTHESIS
|
||||
2080..2089 ; ID_Compat_Math_Continue # No [10] SUBSCRIPT ZERO..SUBSCRIPT NINE
|
||||
208A..208C ; ID_Compat_Math_Continue # Sm [3] SUBSCRIPT PLUS SIGN..SUBSCRIPT EQUALS SIGN
|
||||
208D ; ID_Compat_Math_Continue # Ps SUBSCRIPT LEFT PARENTHESIS
|
||||
208E ; ID_Compat_Math_Continue # Pe SUBSCRIPT RIGHT PARENTHESIS
|
||||
2202 ; ID_Compat_Math_Continue # Sm PARTIAL DIFFERENTIAL
|
||||
2207 ; ID_Compat_Math_Continue # Sm NABLA
|
||||
221E ; ID_Compat_Math_Continue # Sm INFINITY
|
||||
1D6C1 ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD NABLA
|
||||
1D6DB ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
|
||||
1D6FB ; ID_Compat_Math_Continue # Sm MATHEMATICAL ITALIC NABLA
|
||||
1D715 ; ID_Compat_Math_Continue # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
|
||||
1D735 ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD ITALIC NABLA
|
||||
1D74F ; ID_Compat_Math_Continue # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
|
||||
1D76F ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD NABLA
|
||||
1D789 ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
|
||||
1D7A9 ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
|
||||
1D7C3 ; ID_Compat_Math_Continue # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
|
||||
|
||||
# Total code points: 43
|
||||
|
||||
# ================================================
|
||||
|
||||
2202 ; ID_Compat_Math_Start # Sm PARTIAL DIFFERENTIAL
|
||||
2207 ; ID_Compat_Math_Start # Sm NABLA
|
||||
221E ; ID_Compat_Math_Start # Sm INFINITY
|
||||
1D6C1 ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD NABLA
|
||||
1D6DB ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD PARTIAL DIFFERENTIAL
|
||||
1D6FB ; ID_Compat_Math_Start # Sm MATHEMATICAL ITALIC NABLA
|
||||
1D715 ; ID_Compat_Math_Start # Sm MATHEMATICAL ITALIC PARTIAL DIFFERENTIAL
|
||||
1D735 ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD ITALIC NABLA
|
||||
1D74F ; ID_Compat_Math_Start # Sm MATHEMATICAL BOLD ITALIC PARTIAL DIFFERENTIAL
|
||||
1D76F ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD NABLA
|
||||
1D789 ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD PARTIAL DIFFERENTIAL
|
||||
1D7A9 ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC NABLA
|
||||
1D7C3 ; ID_Compat_Math_Start # Sm MATHEMATICAL SANS-SERIF BOLD ITALIC PARTIAL DIFFERENTIAL
|
||||
|
||||
# Total code points: 13
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
@ -1398,6 +1457,7 @@ AABB..AABC ; Logical_Order_Exception # Lo [2] TAI VIET VOWEL AUE..TAI VIET
|
|||
1367..1368 ; Sentence_Terminal # Po [2] ETHIOPIC QUESTION MARK..ETHIOPIC PARAGRAPH SEPARATOR
|
||||
166E ; Sentence_Terminal # Po CANADIAN SYLLABICS FULL STOP
|
||||
1735..1736 ; Sentence_Terminal # Po [2] PHILIPPINE SINGLE PUNCTUATION..PHILIPPINE DOUBLE PUNCTUATION
|
||||
17D4..17D5 ; Sentence_Terminal # Po [2] KHMER SIGN KHAN..KHMER SIGN BARIYOOSAN
|
||||
1803 ; Sentence_Terminal # Po MONGOLIAN FULL STOP
|
||||
1809 ; Sentence_Terminal # Po MONGOLIAN MANCHU FULL STOP
|
||||
1944..1945 ; Sentence_Terminal # Po [2] LIMBU EXCLAMATION MARK..LIMBU QUESTION MARK
|
||||
|
|
@ -1462,7 +1522,7 @@ FF61 ; Sentence_Terminal # Po HALFWIDTH IDEOGRAPHIC FULL STOP
|
|||
1BC9F ; Sentence_Terminal # Po DUPLOYAN PUNCTUATION CHINOOK FULL STOP
|
||||
1DA88 ; Sentence_Terminal # Po SIGNWRITING FULL STOP
|
||||
|
||||
# Total code points: 154
|
||||
# Total code points: 156
|
||||
|
||||
# ================================================
|
||||
|
||||
|
|
|
|||
|
|
@ -30,7 +30,7 @@ localedata/unicode-gen/unicode_utils.py
|
|||
localedata/unicode-gen/utf8_gen.py
|
||||
|
||||
And the most recent versions added to GCC are from glibc git commit:
|
||||
4c721f24fc190d1dc935eb0bab283de7cf13182e
|
||||
71de3aead9fffe89556e80ebc94aa918d8ee7bca
|
||||
|
||||
The script gen_wcwidth.py found here contains the GCC-specific code to
|
||||
map glibc's output to the lookup tables we require. This script should not need
|
||||
|
|
@ -40,14 +40,14 @@ produce ucnid.h.
|
|||
|
||||
The procedure to update GCC's Unicode support is the following:
|
||||
|
||||
1. Update the five Unicode data files from the above URLs.
|
||||
1. Update the six Unicode data files from the above URLs.
|
||||
|
||||
2. Update the two glibc files in from_glibc/ from glibc's git. Update
|
||||
the commit number above in this README.
|
||||
|
||||
3. Run ./gen_wcwidth.py X.Y > ../../libcpp/generated_cpp_wcwidth.h
|
||||
(where X.Y is the version of the Unicode standard corresponding to the
|
||||
Unicode data files being used, most recently, 15.0.0).
|
||||
Unicode data files being used, most recently, 15.1.0).
|
||||
|
||||
4. Update Unicode Copyright years in libcpp/makeucnid.cc and in
|
||||
libcpp/makeuname2c.cc up to the year in which the Unicode
|
||||
|
|
|
|||
|
|
@ -11231,6 +11231,10 @@
|
|||
2FF9;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM UPPER RIGHT;So;0;ON;;;;;N;;;;;
|
||||
2FFA;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER LEFT;So;0;ON;;;;;N;;;;;
|
||||
2FFB;IDEOGRAPHIC DESCRIPTION CHARACTER OVERLAID;So;0;ON;;;;;N;;;;;
|
||||
2FFC;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM RIGHT;So;0;ON;;;;;N;;;;;
|
||||
2FFD;IDEOGRAPHIC DESCRIPTION CHARACTER SURROUND FROM LOWER RIGHT;So;0;ON;;;;;N;;;;;
|
||||
2FFE;IDEOGRAPHIC DESCRIPTION CHARACTER HORIZONTAL REFLECTION;So;0;ON;;;;;N;;;;;
|
||||
2FFF;IDEOGRAPHIC DESCRIPTION CHARACTER ROTATION;So;0;ON;;;;;N;;;;;
|
||||
3000;IDEOGRAPHIC SPACE;Zs;0;WS;<wide> 0020;;;;N;;;;;
|
||||
3001;IDEOGRAPHIC COMMA;Po;0;ON;;;;;N;;;;;
|
||||
3002;IDEOGRAPHIC FULL STOP;Po;0;ON;;;;;N;IDEOGRAPHIC PERIOD;;;;
|
||||
|
|
@ -11705,6 +11709,7 @@
|
|||
31E1;CJK STROKE HZZZG;So;0;ON;;;;;N;;;;;
|
||||
31E2;CJK STROKE PG;So;0;ON;;;;;N;;;;;
|
||||
31E3;CJK STROKE Q;So;0;ON;;;;;N;;;;;
|
||||
31EF;IDEOGRAPHIC DESCRIPTION CHARACTER SUBTRACTION;So;0;ON;;;;;N;;;;;
|
||||
31F0;KATAKANA LETTER SMALL KU;Lo;0;L;;;;;N;;;;;
|
||||
31F1;KATAKANA LETTER SMALL SI;Lo;0;L;;;;;N;;;;;
|
||||
31F2;KATAKANA LETTER SMALL SU;Lo;0;L;;;;;N;;;;;
|
||||
|
|
@ -34035,6 +34040,8 @@ FFFD;REPLACEMENT CHARACTER;So;0;ON;;;;;N;;;;;
|
|||
2CEA1;<CJK Ideograph Extension E, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2CEB0;<CJK Ideograph Extension F, First>;Lo;0;L;;;;;N;;;;;
|
||||
2EBE0;<CJK Ideograph Extension F, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2EBF0;<CJK Ideograph Extension I, First>;Lo;0;L;;;;;N;;;;;
|
||||
2EE5D;<CJK Ideograph Extension I, Last>;Lo;0;L;;;;;N;;;;;
|
||||
2F800;CJK COMPATIBILITY IDEOGRAPH-2F800;Lo;0;L;4E3D;;;;N;;;;;
|
||||
2F801;CJK COMPATIBILITY IDEOGRAPH-2F801;Lo;0;L;4E38;;;;N;;;;;
|
||||
2F802;CJK COMPATIBILITY IDEOGRAPH-2F802;Lo;0;L;4E41;;;;N;;;;;
|
||||
|
|
|
|||
|
|
@ -350,7 +350,7 @@ if __name__ == "__main__":
|
|||
# the EastAsianWidth.txt file.
|
||||
if re.match(r'.*<reserved-.+>\.\.<reserved-.+>.*', LINE):
|
||||
continue
|
||||
if re.match(r'^[^;]*;[WF]', LINE):
|
||||
if re.match(r'^[^;]*;\s*[WF]\s*', LINE):
|
||||
EAST_ASIAN_WIDTH_LINES.append(LINE.strip())
|
||||
with open(ARGS.prop_list_file, mode='r') as PROP_LIST_FILE:
|
||||
PROP_LIST_LINES = []
|
||||
|
|
|
|||
1873
gcc/ChangeLog
1873
gcc/ChangeLog
File diff suppressed because it is too large
Load Diff
|
|
@ -1 +1 @@
|
|||
20231109
|
||||
20231119
|
||||
|
|
|
|||
|
|
@ -1038,6 +1038,7 @@ SYSTEM_H = system.h hwint.h $(srcdir)/../include/libiberty.h \
|
|||
$(HASHTAB_H)
|
||||
PREDICT_H = predict.h predict.def
|
||||
CPPLIB_H = $(srcdir)/../libcpp/include/line-map.h \
|
||||
$(srcdir)/../libcpp/include/rich-location.h \
|
||||
$(srcdir)/../libcpp/include/cpplib.h
|
||||
CODYLIB_H = $(srcdir)/../libcody/cody.hh
|
||||
INPUT_H = $(srcdir)/../libcpp/include/line-map.h input.h
|
||||
|
|
@ -1324,6 +1325,7 @@ ANALYZER_OBJS = \
|
|||
analyzer/engine.o \
|
||||
analyzer/feasible-graph.o \
|
||||
analyzer/function-set.o \
|
||||
analyzer/infinite-loop.o \
|
||||
analyzer/infinite-recursion.o \
|
||||
analyzer/kf.o \
|
||||
analyzer/kf-analyzer.o \
|
||||
|
|
|
|||
|
|
@ -1,3 +1,23 @@
|
|||
2023-11-16 Eric Botcazou <ebotcazou@adacore.com>
|
||||
|
||||
* gcc-interface/decl.cc (gnat_to_gnu_subprog_type): Also create a
|
||||
TYPE_DECL for the return type built for the CI/CO mechanism.
|
||||
|
||||
2023-11-10 Andris Pavēnis <andris.pavenis@iki.fi>
|
||||
|
||||
* expect.c (__gnat_waitpid): fix syntax errors
|
||||
|
||||
2023-11-09 Simon Wright <simon@pushface.org>
|
||||
|
||||
PR ada/111813
|
||||
* libgnat/a-calfor.adb (Value (2)): Allow values of
|
||||
parameter Elapsed_Time greater than or equal to 24 hours, by doing
|
||||
the hour calculations in Natural rather than Hour_Number (0 ..
|
||||
23). Calculate the result directly rather than by using Seconds_Of
|
||||
(whose Hour parameter is of type Hour_Number).
|
||||
If an exception occurs of type Constraint_Error, re-raise it
|
||||
rather than raising a new CE.
|
||||
|
||||
2023-11-07 Joseph Myers <joseph@codesourcery.com>
|
||||
|
||||
* gcc-interface/utils.cc (flag_isoc2x): Rename to flag_isoc23.
|
||||
|
|
|
|||
|
|
@ -6329,6 +6329,12 @@ gnat_to_gnu_subprog_type (Entity_Id gnat_subprog, bool definition,
|
|||
|
||||
if (debug_info_p)
|
||||
rest_of_record_type_compilation (gnu_cico_return_type);
|
||||
|
||||
/* Declare it now since it will never be declared otherwise. This
|
||||
is necessary to ensure that its subtrees are properly marked. */
|
||||
create_type_decl (TYPE_NAME (gnu_cico_return_type),
|
||||
gnu_cico_return_type,
|
||||
true, debug_info_p, gnat_subprog);
|
||||
}
|
||||
|
||||
gnu_return_type = gnu_cico_return_type;
|
||||
|
|
|
|||
|
|
@ -1,3 +1,121 @@
|
|||
2023-11-18 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/106147
|
||||
* analyzer.opt (Wanalyzer-infinite-loop): New option.
|
||||
(fdump-analyzer-infinite-loop): New option.
|
||||
* checker-event.h (start_cfg_edge_event::get_desc): Drop "final".
|
||||
(start_cfg_edge_event::maybe_describe_condition): Convert from
|
||||
private to protected.
|
||||
* checker-path.h (checker_path::get_logger): New.
|
||||
* diagnostic-manager.cc (process_worklist_item): Update for
|
||||
new context param of maybe_update_for_edge.
|
||||
* engine.cc
|
||||
(impl_region_model_context::impl_region_model_context): Add
|
||||
out_could_have_done_work param to both ctors and use it to
|
||||
initialize mm_out_could_have_done_work.
|
||||
(impl_region_model_context::maybe_did_work): New vfunc
|
||||
implementation.
|
||||
(exploded_node::on_stmt): Add out_could_have_done_work param and
|
||||
pass to ctxt ctor.
|
||||
(exploded_node::on_stmt_pre): Treat setjmp and longjmp as "doing
|
||||
work".
|
||||
(exploded_node::on_longjmp): Likewise.
|
||||
(exploded_edge::exploded_edge): Add "could_do_work" param and use
|
||||
it to initialize m_could_do_work_p.
|
||||
(exploded_edge::dump_dot_label): Add result of could_do_work_p.
|
||||
(exploded_graph::add_function_entry): Mark edge as doing no work.
|
||||
(exploded_graph::add_edge): Add "could_do_work" param and pass to
|
||||
exploded_edge ctor.
|
||||
(add_tainted_args_callback): Treat as doing no work.
|
||||
(exploded_graph::process_worklist): Likewise when merging nodes.
|
||||
(maybe_process_run_of_before_supernode_enodes::item): Likewise.
|
||||
(exploded_graph::maybe_create_dynamic_call): Likewise.
|
||||
(exploded_graph::process_node): Likewise for phi nodes.
|
||||
Pass in a "could_have_done_work" bool when handling stmts and use
|
||||
when creating edges. Assume work is done at bifurcation.
|
||||
(exploded_path::feasible_p): Update for new context param of
|
||||
maybe_update_for_edge.
|
||||
(feasibility_state::feasibility_state): New ctor.
|
||||
(feasibility_state::operator=): New.
|
||||
(feasibility_state::maybe_update_for_edge): Add ctxt param and use
|
||||
it. Fix missing newline when logging state.
|
||||
(impl_run_checkers): Call exploded_graph::detect_infinite_loops.
|
||||
* exploded-graph.h
|
||||
(impl_region_model_context::impl_region_model_context): Add
|
||||
out_could_have_done_work param to both ctors.
|
||||
(impl_region_model_context::maybe_did_work): New decl.
|
||||
(impl_region_model_context::checking_for_infinite_loop_p): New.
|
||||
(impl_region_model_context::on_unusable_in_infinite_loop): New.
|
||||
(impl_region_model_context::m_out_could_have_done_work): New
|
||||
field.
|
||||
(exploded_node::on_stmt): Add "out_could_have_done_work" param.
|
||||
(exploded_edge::exploded_edge): Add "could_do_work" param.
|
||||
(exploded_edge::could_do_work_p): New accessor.
|
||||
(exploded_edge::m_could_do_work_p): New field.
|
||||
(exploded_graph::add_edge): Add "could_do_work" param.
|
||||
(exploded_graph::detect_infinite_loops): New decl.
|
||||
(feasibility_state::feasibility_state): New ctor.
|
||||
(feasibility_state::operator=): New decl.
|
||||
(feasibility_state::maybe_update_for_edge): Add ctxt param.
|
||||
* infinite-loop.cc: New file.
|
||||
* program-state.cc (program_state::on_edge): Log the rejected
|
||||
constraint when region_model::maybe_update_for_edge fails.
|
||||
* region-model.cc (region_model::on_assignment): Treat any writes
|
||||
other than to the stack as "doing work".
|
||||
(region_model::on_stmt_pre): Treat all asm stmts as "doing work".
|
||||
(region_model::on_call_post): Likewise for all calls to functions
|
||||
with unknown side effects.
|
||||
(region_model::handle_phi): Add svals_changing_meaning param.
|
||||
Mark widening svalue in phi nodes as changing meaning.
|
||||
(unusable_in_infinite_loop_constraint_p): New.
|
||||
(region_model::add_constraint): If we're checking for an infinite
|
||||
loop, bail out on unusable svalues, or if we don't have a definite
|
||||
true/false for the constraint.
|
||||
(region_model::update_for_phis): Gather all svalues changing
|
||||
meaning in phi nodes, and purge constraints involving them.
|
||||
(region_model::replay_call_summary): Treat all call summaries as
|
||||
doing work.
|
||||
(region_model::can_merge_with_p): Purge constraints involving
|
||||
svalues that change meaning.
|
||||
(model_merger::on_widening_reuse): New.
|
||||
(test_iteration_1): Likewise.
|
||||
(selftest::test_iteration_1): Remove assertion that model6 "knows"
|
||||
that i < 157.
|
||||
* region-model.h (region_model::handle_phi): Add
|
||||
svals_changing_meaning param
|
||||
(region_model_context::maybe_did_work): New pure virtual func.
|
||||
(region_model_context::checking_for_infinite_loop_p): Likewise.
|
||||
(region_model_context::on_unusable_in_infinite_loop): Likewise.
|
||||
(noop_region_model_context::maybe_did_work): Implement.
|
||||
(noop_region_model_context::checking_for_infinite_loop_p):
|
||||
Likewise.
|
||||
(noop_region_model_context::on_unusable_in_infinite_loop):
|
||||
Likewise.
|
||||
(region_model_context_decorator::maybe_did_work): Implement.
|
||||
(region_model_context_decorator::checking_for_infinite_loop_p):
|
||||
Likewise.
|
||||
(region_model_context_decorator::on_unusable_in_infinite_loop):
|
||||
Likewise.
|
||||
(model_merger::on_widening_reuse): New decl.
|
||||
(model_merger::m_svals_changing_meaning): New field.
|
||||
* sm-signal.cc (register_signal_handler::impl_transition): Assume
|
||||
the edge "does work".
|
||||
* supergraph.cc (supernode::get_start_location): Use CFG edge's
|
||||
goto_locus if available.
|
||||
(supernode::get_end_location): Likewise.
|
||||
(cfg_superedge::dump_label_to_pp): Dump edges with a "goto_locus"
|
||||
* supergraph.h (cfg_superedge::get_goto_locus): New.
|
||||
* svalue.cc (svalue::can_merge_p): Call on_widening_reuse for
|
||||
widening values.
|
||||
(involvement_visitor::visit_widening_svalue): New.
|
||||
(svalue::involves_p): Update assertion to allow widening svalues.
|
||||
|
||||
2023-11-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
PR analyzer/103533
|
||||
* sm-taint.cc: Remove "experimental" from comment.
|
||||
* sm.cc (make_checkers): Always add taint state machine.
|
||||
|
||||
2023-11-04 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* bounds-checking.cc: Update for changes to diagnostic_context.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef GCC_ANALYZER_ANALYZER_H
|
||||
#define GCC_ANALYZER_ANALYZER_H
|
||||
|
||||
#include "rich-location.h"
|
||||
#include "function.h"
|
||||
#include "json.h"
|
||||
#include "tristate.h"
|
||||
|
|
@ -326,7 +327,8 @@ public:
|
|||
void impl_call_pre (const call_details &cd) const override;
|
||||
};
|
||||
|
||||
extern void register_known_functions (known_function_manager &mgr);
|
||||
extern void register_known_functions (known_function_manager &kfm,
|
||||
region_model_manager &rmm);
|
||||
extern void register_known_analyzer_functions (known_function_manager &kfm);
|
||||
extern void register_known_fd_functions (known_function_manager &kfm);
|
||||
extern void register_known_file_functions (known_function_manager &kfm);
|
||||
|
|
|
|||
|
|
@ -134,6 +134,10 @@ Wanalyzer-imprecise-fp-arithmetic
|
|||
Common Var(warn_analyzer_imprecise_fp_arithmetic) Init(1) Warning
|
||||
Warn about code paths in which floating-point arithmetic is used in locations where precise computation is needed.
|
||||
|
||||
Wanalyzer-infinite-loop
|
||||
Common Var(warn_analyzer_infinite_loop) Init(1) Warning
|
||||
Warn about code paths which appear to lead to an infinite loop.
|
||||
|
||||
Wanalyzer-infinite-recursion
|
||||
Common Var(warn_analyzer_infinite_recursion) Init(1) Warning
|
||||
Warn about code paths which appear to lead to infinite recursion.
|
||||
|
|
@ -218,6 +222,10 @@ Wanalyzer-tainted-size
|
|||
Common Var(warn_analyzer_tainted_size) Init(1) Warning
|
||||
Warn about code paths in which an unsanitized value is used as a size.
|
||||
|
||||
Wanalyzer-undefined-behavior-strtok
|
||||
Common Var(warn_analyzer_undefined_behavior_strtok) Init(1) Warning
|
||||
Warn about code paths in in which a call is made to strtok with undefined behavior.
|
||||
|
||||
Wanalyzer-use-after-free
|
||||
Common Var(warn_analyzer_use_after_free) Init(1) Warning
|
||||
Warn about code paths in which a freed value is used.
|
||||
|
|
@ -354,6 +362,10 @@ fdump-analyzer-feasibility
|
|||
Common RejectNegative Var(flag_dump_analyzer_feasibility)
|
||||
Dump various analyzer internals to SRCFILE.*.fg.dot and SRCFILE.*.tg.dot.
|
||||
|
||||
fdump-analyzer-infinite-loop
|
||||
Common RejectNegative Var(flag_dump_analyzer_infinite_loop)
|
||||
Dump various analyzer internals to SRCFILE.*.infinite-loop.dot.
|
||||
|
||||
fdump-analyzer-json
|
||||
Common RejectNegative Var(flag_dump_analyzer_json)
|
||||
Dump analyzer-specific data to a SRCFILE.analyzer.json.gz file.
|
||||
|
|
|
|||
|
|
@ -585,6 +585,7 @@ call_summary_replay::convert_region_from_summary_1 (const region *summary_reg)
|
|||
case RK_STRING:
|
||||
case RK_ERRNO:
|
||||
case RK_UNKNOWN:
|
||||
case RK_PRIVATE:
|
||||
/* We can reuse these regions directly. */
|
||||
return summary_reg;
|
||||
|
||||
|
|
|
|||
|
|
@ -444,11 +444,12 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override;
|
||||
label_text get_desc (bool can_colorize) const override;
|
||||
|
||||
private:
|
||||
protected:
|
||||
label_text maybe_describe_condition (bool can_colorize) const;
|
||||
|
||||
private:
|
||||
static label_text maybe_describe_condition (bool can_colorize,
|
||||
tree lhs,
|
||||
enum tree_code op,
|
||||
|
|
|
|||
|
|
@ -65,6 +65,7 @@ public:
|
|||
void dump (pretty_printer *pp) const;
|
||||
void debug () const;
|
||||
|
||||
logger *get_logger () const { return m_logger; }
|
||||
void maybe_log (logger *logger, const char *desc) const;
|
||||
|
||||
void add_event (std::unique_ptr<checker_event> event);
|
||||
|
|
|
|||
|
|
@ -517,7 +517,7 @@ process_worklist_item (feasible_worklist *worklist,
|
|||
|
||||
feasibility_state succ_state (fnode->get_state ());
|
||||
std::unique_ptr<rejected_constraint> rc;
|
||||
if (succ_state.maybe_update_for_edge (logger, succ_eedge, &rc))
|
||||
if (succ_state.maybe_update_for_edge (logger, succ_eedge, nullptr, &rc))
|
||||
{
|
||||
gcc_assert (rc == NULL);
|
||||
feasible_node *succ_fnode
|
||||
|
|
|
|||
|
|
@ -85,7 +85,8 @@ impl_region_model_context (exploded_graph &eg,
|
|||
uncertainty_t *uncertainty,
|
||||
path_context *path_ctxt,
|
||||
const gimple *stmt,
|
||||
stmt_finder *stmt_finder)
|
||||
stmt_finder *stmt_finder,
|
||||
bool *out_could_have_done_work)
|
||||
: m_eg (&eg), m_logger (eg.get_logger ()),
|
||||
m_enode_for_diag (enode_for_diag),
|
||||
m_old_state (old_state),
|
||||
|
|
@ -94,7 +95,8 @@ impl_region_model_context (exploded_graph &eg,
|
|||
m_stmt_finder (stmt_finder),
|
||||
m_ext_state (eg.get_ext_state ()),
|
||||
m_uncertainty (uncertainty),
|
||||
m_path_ctxt (path_ctxt)
|
||||
m_path_ctxt (path_ctxt),
|
||||
m_out_could_have_done_work (out_could_have_done_work)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -110,7 +112,8 @@ impl_region_model_context (program_state *state,
|
|||
m_stmt_finder (NULL),
|
||||
m_ext_state (ext_state),
|
||||
m_uncertainty (uncertainty),
|
||||
m_path_ctxt (NULL)
|
||||
m_path_ctxt (NULL),
|
||||
m_out_could_have_done_work (nullptr)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -1024,6 +1027,17 @@ impl_region_model_context::on_unexpected_tree_code (tree t,
|
|||
m_new_state->m_valid = false;
|
||||
}
|
||||
|
||||
/* Implementation of region_model_context::maybe_did_work vfunc.
|
||||
Mark that "externally visible work" has occurred, and thus we
|
||||
shouldn't report an infinite loop here. */
|
||||
|
||||
void
|
||||
impl_region_model_context::maybe_did_work ()
|
||||
{
|
||||
if (m_out_could_have_done_work)
|
||||
*m_out_could_have_done_work = true;
|
||||
}
|
||||
|
||||
/* struct point_and_state. */
|
||||
|
||||
/* Assert that this object is sane. */
|
||||
|
|
@ -1439,6 +1453,7 @@ exploded_node::on_stmt (exploded_graph &eg,
|
|||
const gimple *stmt,
|
||||
program_state *state,
|
||||
uncertainty_t *uncertainty,
|
||||
bool *out_could_have_done_work,
|
||||
path_context *path_ctxt)
|
||||
{
|
||||
logger *logger = eg.get_logger ();
|
||||
|
|
@ -1464,7 +1479,8 @@ exploded_node::on_stmt (exploded_graph &eg,
|
|||
|
||||
impl_region_model_context ctxt (eg, this,
|
||||
&old_state, state, uncertainty,
|
||||
path_ctxt, stmt);
|
||||
path_ctxt, stmt, nullptr,
|
||||
out_could_have_done_work);
|
||||
|
||||
/* Handle call summaries here. */
|
||||
if (cgraph_edge *cgedge
|
||||
|
|
@ -1551,12 +1567,16 @@ exploded_node::on_stmt_pre (exploded_graph &eg,
|
|||
else if (is_setjmp_call_p (call))
|
||||
{
|
||||
state->m_region_model->on_setjmp (call, this, ctxt);
|
||||
if (ctxt)
|
||||
ctxt->maybe_did_work ();
|
||||
return;
|
||||
}
|
||||
else if (is_longjmp_call_p (call))
|
||||
{
|
||||
on_longjmp (eg, call, state, ctxt);
|
||||
*out_terminate_path = true;
|
||||
if (ctxt)
|
||||
ctxt->maybe_did_work ();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -1938,8 +1958,9 @@ exploded_node::on_longjmp (exploded_graph &eg,
|
|||
if (next)
|
||||
{
|
||||
exploded_edge *eedge
|
||||
= eg.add_edge (const_cast<exploded_node *> (this), next, NULL,
|
||||
make_unique<rewind_info_t> (tmp_setjmp_record, longjmp_call));
|
||||
= eg.add_edge (const_cast<exploded_node *> (this), next, NULL, true,
|
||||
make_unique<rewind_info_t> (tmp_setjmp_record,
|
||||
longjmp_call));
|
||||
|
||||
/* For any diagnostics that were queued here (such as leaks) we want
|
||||
the checker_path to show the rewinding events after the "final event"
|
||||
|
|
@ -2161,10 +2182,11 @@ rewind_info_t::add_events_to_path (checker_path *emission_path,
|
|||
/* exploded_edge's ctor. */
|
||||
|
||||
exploded_edge::exploded_edge (exploded_node *src, exploded_node *dest,
|
||||
const superedge *sedge,
|
||||
const superedge *sedge, bool could_do_work,
|
||||
std::unique_ptr<custom_edge_info> custom_info)
|
||||
: dedge<eg_traits> (src, dest), m_sedge (sedge),
|
||||
m_custom_info (std::move (custom_info))
|
||||
m_custom_info (std::move (custom_info)),
|
||||
m_could_do_work_p (could_do_work)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -2228,6 +2250,9 @@ exploded_edge::dump_dot_label (pretty_printer *pp) const
|
|||
else if (m_custom_info)
|
||||
m_custom_info->print (pp);
|
||||
|
||||
pp_printf (pp, "%s",
|
||||
could_do_work_p () ? "(could do work)" : "DOES NO WORK");
|
||||
|
||||
//pp_write_text_as_dot_label_to_stream (pp, /*for_record=*/false);
|
||||
|
||||
pp_printf (pp, "\"];\n");
|
||||
|
|
@ -2790,7 +2815,7 @@ exploded_graph::add_function_entry (function *fun)
|
|||
if (!enode)
|
||||
return NULL;
|
||||
|
||||
add_edge (m_origin, enode, NULL, std::move (edge_info));
|
||||
add_edge (m_origin, enode, NULL, false, std::move (edge_info));
|
||||
|
||||
m_functions_with_enodes.add (fun);
|
||||
|
||||
|
|
@ -2988,18 +3013,19 @@ exploded_graph::get_or_create_node (const program_point &point,
|
|||
|
||||
/* Add an exploded_edge from SRC to DEST, recording its association
|
||||
with SEDGE (which may be NULL), and, if non-NULL, taking ownership
|
||||
of CUSTOM_INFO.
|
||||
of CUSTOM_INFO. COULD_DO_WORK is used for detecting infinite loops.
|
||||
Return the newly-created eedge. */
|
||||
|
||||
exploded_edge *
|
||||
exploded_graph::add_edge (exploded_node *src, exploded_node *dest,
|
||||
const superedge *sedge,
|
||||
const superedge *sedge, bool could_do_work,
|
||||
std::unique_ptr<custom_edge_info> custom_info)
|
||||
{
|
||||
if (get_logger ())
|
||||
get_logger ()->log ("creating edge EN: %i -> EN: %i",
|
||||
src->m_index, dest->m_index);
|
||||
exploded_edge *e = new exploded_edge (src, dest, sedge,
|
||||
exploded_edge *e
|
||||
= new exploded_edge (src, dest, sedge, could_do_work,
|
||||
std::move (custom_info));
|
||||
digraph<eg_traits>::add_edge (e);
|
||||
return e;
|
||||
|
|
@ -3249,7 +3275,7 @@ add_tainted_args_callback (exploded_graph *eg, tree field, tree fndecl,
|
|||
}
|
||||
}
|
||||
|
||||
eg->add_edge (eg->get_origin (), enode, NULL,
|
||||
eg->add_edge (eg->get_origin (), enode, NULL, false,
|
||||
make_unique<tainted_args_call_info> (field, fndecl, loc));
|
||||
}
|
||||
|
||||
|
|
@ -3403,7 +3429,7 @@ exploded_graph::process_worklist ()
|
|||
if (merged_state == state)
|
||||
{
|
||||
/* Then merge node_2 into node by adding an edge. */
|
||||
add_edge (node_2, node, NULL);
|
||||
add_edge (node_2, node, NULL, false);
|
||||
|
||||
/* Remove node_2 from the worklist. */
|
||||
m_worklist.take_next ();
|
||||
|
|
@ -3416,7 +3442,7 @@ exploded_graph::process_worklist ()
|
|||
/* Then merge node into node_2, and leave node_2
|
||||
in the worklist, to be processed on the next
|
||||
iteration. */
|
||||
add_edge (node, node_2, NULL);
|
||||
add_edge (node, node_2, NULL, false);
|
||||
node->set_status (exploded_node::STATUS_MERGER);
|
||||
continue;
|
||||
}
|
||||
|
|
@ -3461,7 +3487,7 @@ exploded_graph::process_worklist ()
|
|||
m_worklist.add_node (merged_enode);
|
||||
else
|
||||
{
|
||||
add_edge (node, merged_enode, NULL);
|
||||
add_edge (node, merged_enode, NULL, false);
|
||||
node->set_status (exploded_node::STATUS_MERGER);
|
||||
}
|
||||
|
||||
|
|
@ -3469,7 +3495,7 @@ exploded_graph::process_worklist ()
|
|||
m_worklist.add_node (merged_enode);
|
||||
else
|
||||
{
|
||||
add_edge (node_2, merged_enode, NULL);
|
||||
add_edge (node_2, merged_enode, NULL, false);
|
||||
node_2->set_status (exploded_node::STATUS_MERGER);
|
||||
}
|
||||
|
||||
|
|
@ -3704,7 +3730,8 @@ maybe_process_run_of_before_supernode_enodes (exploded_node *enode)
|
|||
{
|
||||
exploded_node *next = next_enodes[it->m_merger_idx];
|
||||
if (next)
|
||||
add_edge (it->m_input_enode, next, NULL);
|
||||
add_edge (it->m_input_enode, next, NULL,
|
||||
false); /* no "work" is done during merger. */
|
||||
it->m_input_enode->set_status (exploded_node::STATUS_BULK_MERGED);
|
||||
}
|
||||
|
||||
|
|
@ -3847,6 +3874,7 @@ exploded_graph::maybe_create_dynamic_call (const gcall *call,
|
|||
node);
|
||||
if (enode)
|
||||
add_edge (node,enode, NULL,
|
||||
false, /* No work is done by the call itself. */
|
||||
make_unique<dynamic_call_info_t> (call));
|
||||
return true;
|
||||
}
|
||||
|
|
@ -4039,7 +4067,8 @@ exploded_graph::process_node (exploded_node *node)
|
|||
program_point next_point (point.get_next ());
|
||||
exploded_node *next = get_or_create_node (next_point, next_state, node);
|
||||
if (next)
|
||||
add_edge (node, next, NULL);
|
||||
add_edge (node, next, NULL,
|
||||
false); /* Assume no work is done at phi nodes. */
|
||||
}
|
||||
break;
|
||||
case PK_BEFORE_STMT:
|
||||
|
|
@ -4067,6 +4096,7 @@ exploded_graph::process_node (exploded_node *node)
|
|||
|
||||
impl_path_context path_ctxt (&next_state, logger);
|
||||
|
||||
bool could_have_done_work = false;
|
||||
uncertainty_t uncertainty;
|
||||
const supernode *snode = point.get_supernode ();
|
||||
unsigned stmt_idx;
|
||||
|
|
@ -4090,7 +4120,7 @@ exploded_graph::process_node (exploded_node *node)
|
|||
/* Process the stmt. */
|
||||
exploded_node::on_stmt_flags flags
|
||||
= node->on_stmt (*this, snode, stmt, &next_state, &uncertainty,
|
||||
&path_ctxt);
|
||||
&could_have_done_work, &path_ctxt);
|
||||
node->m_num_processed_stmts++;
|
||||
|
||||
/* If flags.m_terminate_path, stop analyzing; any nodes/edges
|
||||
|
|
@ -4147,7 +4177,7 @@ exploded_graph::process_node (exploded_node *node)
|
|||
node->m_num_processed_stmts--;
|
||||
if (logger)
|
||||
logger->log ("creating edge to split_enode");
|
||||
add_edge (node, split_enode, NULL);
|
||||
add_edge (node, split_enode, NULL, could_have_done_work);
|
||||
return;
|
||||
}
|
||||
else
|
||||
|
|
@ -4174,7 +4204,7 @@ exploded_graph::process_node (exploded_node *node)
|
|||
exploded_node *next
|
||||
= get_or_create_node (next_point, next_state, node);
|
||||
if (next)
|
||||
add_edge (node, next, NULL);
|
||||
add_edge (node, next, NULL, could_have_done_work);
|
||||
}
|
||||
|
||||
/* If we have custom edge infos, "bifurcate" the state
|
||||
|
|
@ -4212,7 +4242,9 @@ exploded_graph::process_node (exploded_node *node)
|
|||
exploded_node *next2
|
||||
= get_or_create_node (next_point, bifurcated_new_state, node);
|
||||
if (next2)
|
||||
add_edge (node, next2, NULL, std::move (edge_info));
|
||||
add_edge (node, next2, NULL,
|
||||
true /* assume that work could be done */,
|
||||
std::move (edge_info));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -4327,7 +4359,8 @@ exploded_graph::process_node (exploded_node *node)
|
|||
next_state,
|
||||
node);
|
||||
if (next)
|
||||
add_edge (node, next, succ);
|
||||
add_edge (node, next, succ,
|
||||
true /* assume that work is done */);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4343,7 +4376,7 @@ exploded_graph::process_node (exploded_node *node)
|
|||
node);
|
||||
if (next)
|
||||
{
|
||||
add_edge (node, next, succ);
|
||||
add_edge (node, next, succ, false);
|
||||
|
||||
/* We might have a function entrypoint. */
|
||||
detect_infinite_recursion (next);
|
||||
|
|
@ -4377,7 +4410,7 @@ exploded_graph::process_node (exploded_node *node)
|
|||
next_state,
|
||||
node);
|
||||
if (enode)
|
||||
add_edge (node, enode, NULL,
|
||||
add_edge (node, enode, NULL, false,
|
||||
make_unique<dynamic_call_info_t> (call, true));
|
||||
}
|
||||
}
|
||||
|
|
@ -4708,7 +4741,7 @@ exploded_path::feasible_p (logger *logger,
|
|||
eedge->m_dest->m_index);
|
||||
|
||||
std::unique_ptr <rejected_constraint> rc;
|
||||
if (!state.maybe_update_for_edge (logger, eedge, &rc))
|
||||
if (!state.maybe_update_for_edge (logger, eedge, nullptr, &rc))
|
||||
{
|
||||
gcc_assert (rc);
|
||||
if (out)
|
||||
|
|
@ -4835,6 +4868,21 @@ feasibility_state::feasibility_state (const feasibility_state &other)
|
|||
bitmap_copy (m_snodes_visited, other.m_snodes_visited);
|
||||
}
|
||||
|
||||
feasibility_state::feasibility_state (const region_model &model,
|
||||
const supergraph &sg)
|
||||
: m_model (model),
|
||||
m_snodes_visited (sg.m_nodes.length ())
|
||||
{
|
||||
}
|
||||
|
||||
feasibility_state &
|
||||
feasibility_state::operator= (const feasibility_state &other)
|
||||
{
|
||||
m_model = other.m_model;
|
||||
bitmap_copy (m_snodes_visited, other.m_snodes_visited);
|
||||
return *this;
|
||||
}
|
||||
|
||||
/* The heart of feasibility-checking.
|
||||
|
||||
Attempt to update this state in-place based on traversing EEDGE
|
||||
|
|
@ -4849,6 +4897,7 @@ bool
|
|||
feasibility_state::
|
||||
maybe_update_for_edge (logger *logger,
|
||||
const exploded_edge *eedge,
|
||||
region_model_context *ctxt,
|
||||
std::unique_ptr<rejected_constraint> *out_rc)
|
||||
{
|
||||
const exploded_node &src_enode = *eedge->m_src;
|
||||
|
|
@ -4887,12 +4936,14 @@ maybe_update_for_edge (logger *logger,
|
|||
}
|
||||
|
||||
const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
|
||||
if (!m_model.maybe_update_for_edge (*sedge, last_stmt, NULL, out_rc))
|
||||
if (!m_model.maybe_update_for_edge (*sedge, last_stmt, ctxt, out_rc))
|
||||
{
|
||||
if (logger)
|
||||
{
|
||||
logger->log ("rejecting due to region model");
|
||||
logger->start_log_line ();
|
||||
logger->log_partial ("rejecting due to region model: ");
|
||||
m_model.dump_to_pp (logger->get_printer (), true, false);
|
||||
logger->end_log_line ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
|
@ -4908,13 +4959,13 @@ maybe_update_for_edge (logger *logger,
|
|||
== PK_BEFORE_SUPERNODE);
|
||||
function *fun = eedge->m_dest->get_function ();
|
||||
gcc_assert (fun);
|
||||
m_model.push_frame (fun, NULL, NULL);
|
||||
m_model.push_frame (fun, NULL, ctxt);
|
||||
if (logger)
|
||||
logger->log (" pushing frame for %qD", fun->decl);
|
||||
}
|
||||
else if (eedge->m_custom_info)
|
||||
{
|
||||
eedge->m_custom_info->update_model (&m_model, eedge, NULL);
|
||||
eedge->m_custom_info->update_model (&m_model, eedge, ctxt);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4933,7 +4984,7 @@ maybe_update_for_edge (logger *logger,
|
|||
logger->log (" update for phis");
|
||||
m_model.update_for_phis (src_enode.get_supernode (),
|
||||
last_cfg_superedge,
|
||||
NULL);
|
||||
ctxt);
|
||||
/* If we've entering an snode that we've already visited on this
|
||||
epath, then we need do fix things up for loops; see the
|
||||
comment for store::loop_replay_fixup.
|
||||
|
|
@ -6123,7 +6174,8 @@ impl_run_checkers (logger *logger)
|
|||
auto_delete_vec <state_machine> checkers;
|
||||
make_checkers (checkers, logger);
|
||||
|
||||
register_known_functions (*eng.get_known_function_manager ());
|
||||
register_known_functions (*eng.get_known_function_manager (),
|
||||
*eng.get_model_manager ());
|
||||
|
||||
plugin_analyzer_init_impl data (&checkers,
|
||||
eng.get_known_function_manager (),
|
||||
|
|
@ -6153,6 +6205,9 @@ impl_run_checkers (logger *logger)
|
|||
/* Now process the worklist, exploring the <point, state> graph. */
|
||||
eg.process_worklist ();
|
||||
|
||||
if (warn_analyzer_infinite_loop)
|
||||
eg.detect_infinite_loops ();
|
||||
|
||||
if (flag_dump_analyzer_exploded_graph)
|
||||
{
|
||||
auto_timevar tv (TV_ANALYZER_DUMP);
|
||||
|
|
|
|||
|
|
@ -49,7 +49,9 @@ class impl_region_model_context : public region_model_context
|
|||
path_context *path_ctxt,
|
||||
|
||||
const gimple *stmt,
|
||||
stmt_finder *stmt_finder = NULL);
|
||||
stmt_finder *stmt_finder = NULL,
|
||||
|
||||
bool *out_could_have_done_work = nullptr);
|
||||
|
||||
impl_region_model_context (program_state *state,
|
||||
const extrinsic_state &ext_state,
|
||||
|
|
@ -110,6 +112,10 @@ class impl_region_model_context : public region_model_context
|
|||
const gimple *get_stmt () const override { return m_stmt; }
|
||||
const exploded_graph *get_eg () const override { return m_eg; }
|
||||
|
||||
void maybe_did_work () override;
|
||||
bool checking_for_infinite_loop_p () const override { return false; }
|
||||
void on_unusable_in_infinite_loop () override {}
|
||||
|
||||
exploded_graph *m_eg;
|
||||
log_user m_logger;
|
||||
exploded_node *m_enode_for_diag;
|
||||
|
|
@ -120,6 +126,7 @@ class impl_region_model_context : public region_model_context
|
|||
const extrinsic_state &m_ext_state;
|
||||
uncertainty_t *m_uncertainty;
|
||||
path_context *m_path_ctxt;
|
||||
bool *m_out_could_have_done_work;
|
||||
};
|
||||
|
||||
/* A <program_point, program_state> pair, used internally by
|
||||
|
|
@ -260,6 +267,7 @@ class exploded_node : public dnode<eg_traits>
|
|||
const gimple *stmt,
|
||||
program_state *state,
|
||||
uncertainty_t *uncertainty,
|
||||
bool *out_could_have_done_work,
|
||||
path_context *path_ctxt);
|
||||
void on_stmt_pre (exploded_graph &eg,
|
||||
const gimple *stmt,
|
||||
|
|
@ -373,7 +381,7 @@ class exploded_edge : public dedge<eg_traits>
|
|||
{
|
||||
public:
|
||||
exploded_edge (exploded_node *src, exploded_node *dest,
|
||||
const superedge *sedge,
|
||||
const superedge *sedge, bool could_do_work,
|
||||
std::unique_ptr<custom_edge_info> custom_info);
|
||||
void dump_dot (graphviz_out *gv, const dump_args_t &args)
|
||||
const final override;
|
||||
|
|
@ -389,8 +397,25 @@ class exploded_edge : public dedge<eg_traits>
|
|||
a signal is delivered to a signal-handler. */
|
||||
std::unique_ptr<custom_edge_info> m_custom_info;
|
||||
|
||||
bool could_do_work_p () const { return m_could_do_work_p; }
|
||||
|
||||
private:
|
||||
DISABLE_COPY_AND_ASSIGN (exploded_edge);
|
||||
|
||||
/* For -Wanalyzer-infinite-loop.
|
||||
Set to true during processing if any of the activity along
|
||||
this edge is "externally-visible work" (and thus ruling this
|
||||
out as being part of an infinite loop.
|
||||
|
||||
For example, given:
|
||||
|
||||
while (1)
|
||||
do_something ();
|
||||
|
||||
although it is an infinite loop, presumably the point of the
|
||||
program is the loop body, and thus reporting this as an infinite
|
||||
loop is likely to be unhelpful to the user. */
|
||||
bool m_could_do_work_p;
|
||||
};
|
||||
|
||||
/* Extra data for an exploded_edge that represents dynamic call info ( calls
|
||||
|
|
@ -804,7 +829,7 @@ public:
|
|||
const program_state &state,
|
||||
exploded_node *enode_for_diag);
|
||||
exploded_edge *add_edge (exploded_node *src, exploded_node *dest,
|
||||
const superedge *sedge,
|
||||
const superedge *sedge, bool could_do_work,
|
||||
std::unique_ptr<custom_edge_info> custom = NULL);
|
||||
|
||||
per_program_point_data *
|
||||
|
|
@ -856,6 +881,9 @@ public:
|
|||
|
||||
void on_escaped_function (tree fndecl);
|
||||
|
||||
/* In infinite-loop.cc */
|
||||
void detect_infinite_loops ();
|
||||
|
||||
/* In infinite-recursion.cc */
|
||||
void detect_infinite_recursion (exploded_node *enode);
|
||||
exploded_node *find_previous_entry_to (function *top_of_stack_fun,
|
||||
|
|
@ -970,10 +998,15 @@ class feasibility_state
|
|||
public:
|
||||
feasibility_state (region_model_manager *manager,
|
||||
const supergraph &sg);
|
||||
feasibility_state (const region_model &model,
|
||||
const supergraph &sg);
|
||||
feasibility_state (const feasibility_state &other);
|
||||
|
||||
feasibility_state &operator= (const feasibility_state &other);
|
||||
|
||||
bool maybe_update_for_edge (logger *logger,
|
||||
const exploded_edge *eedge,
|
||||
region_model_context *ctxt,
|
||||
std::unique_ptr<rejected_constraint> *out_rc);
|
||||
void update_for_stmt (const gimple *stmt);
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,565 @@
|
|||
/* Detection of infinite loops.
|
||||
Copyright (C) 2022-2023 Free Software Foundation, Inc.
|
||||
Contributed by David Malcolm <dmalcolm@redhat.com>.
|
||||
|
||||
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"
|
||||
#define INCLUDE_MEMORY
|
||||
#define INCLUDE_VECTOR
|
||||
#include "system.h"
|
||||
#include "coretypes.h"
|
||||
#include "tree.h"
|
||||
#include "fold-const.h"
|
||||
#include "gcc-rich-location.h"
|
||||
#include "alloc-pool.h"
|
||||
#include "fibonacci_heap.h"
|
||||
#include "shortest-paths.h"
|
||||
#include "diagnostic-core.h"
|
||||
#include "diagnostic-event-id.h"
|
||||
#include "diagnostic-path.h"
|
||||
#include "diagnostic-metadata.h"
|
||||
#include "function.h"
|
||||
#include "pretty-print.h"
|
||||
#include "sbitmap.h"
|
||||
#include "bitmap.h"
|
||||
#include "tristate.h"
|
||||
#include "ordered-hash-map.h"
|
||||
#include "selftest.h"
|
||||
#include "json.h"
|
||||
#include "analyzer/analyzer.h"
|
||||
#include "analyzer/analyzer-logging.h"
|
||||
#include "analyzer/call-string.h"
|
||||
#include "analyzer/program-point.h"
|
||||
#include "analyzer/store.h"
|
||||
#include "analyzer/region-model.h"
|
||||
#include "analyzer/constraint-manager.h"
|
||||
#include "analyzer/sm.h"
|
||||
#include "analyzer/pending-diagnostic.h"
|
||||
#include "analyzer/diagnostic-manager.h"
|
||||
#include "cfg.h"
|
||||
#include "basic-block.h"
|
||||
#include "gimple.h"
|
||||
#include "gimple-iterator.h"
|
||||
#include "gimple-pretty-print.h"
|
||||
#include "cgraph.h"
|
||||
#include "digraph.h"
|
||||
#include "analyzer/supergraph.h"
|
||||
#include "analyzer/program-state.h"
|
||||
#include "analyzer/exploded-graph.h"
|
||||
#include "analyzer/checker-path.h"
|
||||
#include "analyzer/feasible-graph.h"
|
||||
#include "make-unique.h"
|
||||
|
||||
/* A bundle of data characterizing a particular infinite loop
|
||||
identified within the exploded graph. */
|
||||
|
||||
struct infinite_loop
|
||||
{
|
||||
infinite_loop (const exploded_node &enode,
|
||||
location_t loc,
|
||||
std::vector<const exploded_edge *> eedges,
|
||||
logger *logger)
|
||||
: m_enode (enode),
|
||||
m_loc (loc),
|
||||
m_eedge_vec (eedges)
|
||||
{
|
||||
LOG_SCOPE (logger);
|
||||
if (logger)
|
||||
{
|
||||
logger->start_log_line ();
|
||||
logger->log_partial ("infinite loop: EN: %i", m_enode.m_index);
|
||||
for (auto eedge : m_eedge_vec)
|
||||
{
|
||||
logger->log_partial (" ->");
|
||||
if (const superedge *sedge = eedge->m_sedge)
|
||||
{
|
||||
sedge->dump_label_to_pp (logger->get_printer (), false);
|
||||
}
|
||||
logger->log_partial (" EN: %i", eedge->m_dest->m_index);
|
||||
}
|
||||
logger->end_log_line ();
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
operator== (const infinite_loop &other) const
|
||||
{
|
||||
/* Compare underlying supernode, rather than enodes, so that
|
||||
we don't get duplicates in functions that are called from
|
||||
elsewhere. */
|
||||
return (m_enode.get_supernode () == other.m_enode.get_supernode ()
|
||||
&& m_loc == other.m_loc);
|
||||
}
|
||||
|
||||
const exploded_node &m_enode;
|
||||
location_t m_loc;
|
||||
std::vector<const exploded_edge *> m_eedge_vec;
|
||||
};
|
||||
|
||||
/* A custom subclass of start_cfg_edge_event that rewords the
|
||||
message to indicate that the CFG edge is *always* taken on
|
||||
subsequent iterations, assuming it's been taken once. */
|
||||
|
||||
class perpetual_start_cfg_edge_event : public start_cfg_edge_event
|
||||
{
|
||||
public:
|
||||
perpetual_start_cfg_edge_event (const exploded_edge &eedge,
|
||||
const event_loc_info &loc_info)
|
||||
: start_cfg_edge_event (eedge, loc_info)
|
||||
{
|
||||
}
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override
|
||||
{
|
||||
bool user_facing = !flag_analyzer_verbose_edges;
|
||||
label_text edge_desc (m_sedge->get_description (user_facing));
|
||||
if (user_facing)
|
||||
{
|
||||
if (edge_desc.get () && strlen (edge_desc.get ()) > 0)
|
||||
{
|
||||
label_text cond_desc = maybe_describe_condition (can_colorize);
|
||||
label_text result;
|
||||
if (cond_desc.get ())
|
||||
return make_label_text
|
||||
(can_colorize,
|
||||
"%s: always following %qs branch...",
|
||||
cond_desc.get (), edge_desc.get ());
|
||||
else
|
||||
return make_label_text
|
||||
(can_colorize,
|
||||
"if it ever follows %qs branch, it will always do so...",
|
||||
edge_desc.get ());
|
||||
}
|
||||
}
|
||||
return start_cfg_edge_event::get_desc (can_colorize);
|
||||
}
|
||||
};
|
||||
|
||||
/* A subclass of pending_diagnostic for complaining about suspected
|
||||
infinite loops. */
|
||||
|
||||
class infinite_loop_diagnostic
|
||||
: public pending_diagnostic_subclass<infinite_loop_diagnostic>
|
||||
{
|
||||
public:
|
||||
infinite_loop_diagnostic (std::unique_ptr<infinite_loop> inf_loop)
|
||||
: m_inf_loop (std::move (inf_loop))
|
||||
{
|
||||
gcc_assert (m_inf_loop != nullptr);
|
||||
}
|
||||
|
||||
const char *get_kind () const final override
|
||||
{
|
||||
return "infinite_loop_diagnostic";
|
||||
}
|
||||
|
||||
bool operator== (const infinite_loop_diagnostic &other) const
|
||||
{
|
||||
return *m_inf_loop == *other.m_inf_loop;
|
||||
}
|
||||
|
||||
int get_controlling_option () const final override
|
||||
{
|
||||
return OPT_Wanalyzer_infinite_loop;
|
||||
}
|
||||
|
||||
bool emit (rich_location *rich_loc, logger *) final override
|
||||
{
|
||||
/* "CWE-835: Loop with Unreachable Exit Condition ('Infinite Loop')". */
|
||||
diagnostic_metadata m;
|
||||
m.add_cwe (835);
|
||||
return warning_meta (rich_loc, m, get_controlling_option (),
|
||||
"infinite loop");
|
||||
}
|
||||
|
||||
bool maybe_add_custom_events_for_superedge (const exploded_edge &,
|
||||
checker_path *)
|
||||
final override
|
||||
{
|
||||
/* Don't add any regular events; instead we add them after pruning as
|
||||
part of the "final" warning. */
|
||||
return true;
|
||||
}
|
||||
|
||||
label_text describe_final_event (const evdesc::final_event &ev) final override
|
||||
{
|
||||
return ev.formatted_print ("infinite loop here");
|
||||
}
|
||||
|
||||
/* Customize the location where the warning_event appears. */
|
||||
void add_final_event (const state_machine *,
|
||||
const exploded_node *enode,
|
||||
const gimple *,
|
||||
tree,
|
||||
state_machine::state_t,
|
||||
checker_path *emission_path) final override
|
||||
{
|
||||
emission_path->add_event
|
||||
(make_unique<warning_event>
|
||||
(event_loc_info (m_inf_loop->m_loc,
|
||||
enode->get_function ()->decl,
|
||||
enode->get_stack_depth ()),
|
||||
enode,
|
||||
NULL, NULL, NULL));
|
||||
|
||||
logger *logger = emission_path->get_logger ();
|
||||
|
||||
/* EMISSION_PATH has the path to the entry of the infinite loop.
|
||||
Add extra edges showing the loop itself. */
|
||||
for (auto eedge : m_inf_loop->m_eedge_vec)
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("EN: %i -> EN: %i",
|
||||
eedge->m_src->m_index,
|
||||
eedge->m_dest->m_index);
|
||||
if (!eedge->m_sedge)
|
||||
continue;
|
||||
|
||||
const cfg_superedge *cfg_sedge
|
||||
= eedge->m_sedge->dyn_cast_cfg_superedge ();
|
||||
if (!cfg_sedge)
|
||||
continue;
|
||||
|
||||
const exploded_node *src_node = eedge->m_src;
|
||||
const program_point &src_point = src_node->get_point ();
|
||||
const exploded_node *dst_node = eedge->m_dest;
|
||||
const program_point &dst_point = dst_node->get_point ();
|
||||
const int src_stack_depth = src_point.get_stack_depth ();
|
||||
const int dst_stack_depth = dst_point.get_stack_depth ();
|
||||
const gimple *last_stmt = src_point.get_supernode ()->get_last_stmt ();
|
||||
|
||||
event_loc_info loc_info_from
|
||||
(last_stmt ? last_stmt->location : cfg_sedge->get_goto_locus (),
|
||||
src_point.get_fndecl (),
|
||||
src_stack_depth);
|
||||
event_loc_info loc_info_to
|
||||
(dst_point.get_supernode ()->get_start_location (),
|
||||
dst_point.get_fndecl (),
|
||||
dst_stack_depth);
|
||||
|
||||
if (const switch_cfg_superedge *switch_cfg_sedge
|
||||
= cfg_sedge->dyn_cast_switch_cfg_superedge ())
|
||||
{
|
||||
if (switch_cfg_sedge->implicitly_created_default_p ())
|
||||
{
|
||||
emission_path->add_event
|
||||
(make_unique<perpetual_start_cfg_edge_event> (*eedge,
|
||||
loc_info_from));
|
||||
emission_path->add_event
|
||||
(make_unique<end_cfg_edge_event>
|
||||
(*eedge,
|
||||
loc_info_to));
|
||||
}
|
||||
}
|
||||
|
||||
if (cfg_sedge->true_value_p ())
|
||||
{
|
||||
emission_path->add_event
|
||||
(make_unique<perpetual_start_cfg_edge_event> (*eedge,
|
||||
loc_info_from));
|
||||
emission_path->add_event
|
||||
(make_unique<end_cfg_edge_event>
|
||||
(*eedge,
|
||||
loc_info_to));
|
||||
}
|
||||
else if (cfg_sedge->false_value_p ())
|
||||
{
|
||||
emission_path->add_event
|
||||
(make_unique<perpetual_start_cfg_edge_event> (*eedge,
|
||||
loc_info_from));
|
||||
emission_path->add_event
|
||||
(make_unique<end_cfg_edge_event>
|
||||
(*eedge,
|
||||
loc_info_to));
|
||||
}
|
||||
else if (cfg_sedge->back_edge_p ())
|
||||
{
|
||||
emission_path->add_event
|
||||
(make_unique<precanned_custom_event>
|
||||
(loc_info_from, "looping back..."));
|
||||
emission_path->add_event
|
||||
(make_unique<end_cfg_edge_event>
|
||||
(*eedge,
|
||||
loc_info_to));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
std::unique_ptr<infinite_loop> m_inf_loop;
|
||||
};
|
||||
|
||||
/* If ENODE has an in-edge corresponding to a CFG backedge, return that
|
||||
exploded in-edge.
|
||||
Otherwise, return nullptr. */
|
||||
|
||||
static const exploded_edge *
|
||||
get_in_edge_back_edge (const exploded_node &enode)
|
||||
{
|
||||
for (auto in_edge : enode.m_preds)
|
||||
{
|
||||
const superedge *sedge = in_edge->m_sedge;
|
||||
if (!sedge)
|
||||
continue;
|
||||
const cfg_superedge *cfg_sedge = sedge->dyn_cast_cfg_superedge ();
|
||||
if (!cfg_sedge)
|
||||
continue;
|
||||
if (cfg_sedge->back_edge_p ())
|
||||
return in_edge;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Subclass of region_model_context that rejects conditional branches that
|
||||
aren't known for definite. */
|
||||
|
||||
class infinite_loop_checking_context : public noop_region_model_context
|
||||
{
|
||||
public:
|
||||
infinite_loop_checking_context () : m_unusable (false) {}
|
||||
|
||||
bool checking_for_infinite_loop_p () const override { return true; }
|
||||
void on_unusable_in_infinite_loop () override { m_unusable = true; }
|
||||
|
||||
bool unusable_p () const { return m_unusable; }
|
||||
|
||||
private:
|
||||
bool m_unusable;
|
||||
};
|
||||
|
||||
/* Determine if an infinite loop starts at ENODE.
|
||||
Return the loop if it is found, nullptr otherwise.
|
||||
|
||||
Look for cycles in the exploded graph in which:
|
||||
- no externally visible work occurs
|
||||
- no escape from the cycle
|
||||
- the program state is "sufficiently concrete" at each step:
|
||||
- no unknown activity could be occurring
|
||||
- the worklist was fully drained for each enode in the cycle
|
||||
i.e. every enode in the cycle is processed. */
|
||||
|
||||
static std::unique_ptr<infinite_loop>
|
||||
starts_infinite_loop_p (const exploded_node &enode,
|
||||
const exploded_graph &eg,
|
||||
logger *logger)
|
||||
{
|
||||
LOG_FUNC_1 (logger, "considering EN: %i", enode.m_index);
|
||||
|
||||
/* Only consider enodes that have a CFG back edge as an in-edge. */
|
||||
if (const exploded_edge *back_edge = get_in_edge_back_edge (enode))
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("got backedge from EN: %i",
|
||||
back_edge->m_src->m_index);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("rejecting: no backedge in in-edges");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
/* Support for dumping an .infinite-loop.dot file visualizing the
|
||||
traversal for this enode. */
|
||||
std::unique_ptr<feasible_graph> fg;
|
||||
feasible_node *curr_fnode = nullptr;
|
||||
|
||||
if (flag_dump_analyzer_infinite_loop)
|
||||
fg = ::make_unique<feasible_graph> ();
|
||||
|
||||
location_t first_loc = UNKNOWN_LOCATION;
|
||||
const exploded_node *iter = &enode;
|
||||
feasibility_state state (*enode.get_state ().m_region_model,
|
||||
eg.get_supergraph ());
|
||||
|
||||
if (fg)
|
||||
curr_fnode = fg->add_node (&enode, state, 0);
|
||||
|
||||
hash_set<const exploded_node *> visited;
|
||||
std::vector<const exploded_edge *> eedges;
|
||||
while (1)
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("iter: EN: %i", iter->m_index);
|
||||
/* Analysis bailed out before processing this node. */
|
||||
if (iter->get_status () == exploded_node::STATUS_WORKLIST)
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("rejecting: EN: %i is still in worklist",
|
||||
iter->m_index);
|
||||
return nullptr;
|
||||
}
|
||||
if (visited.contains (iter))
|
||||
{
|
||||
/* We've looped back on ourselves. ENODE is in the loop
|
||||
itself if ENODE is the first place we looped back,
|
||||
as opposed to being on a path to a loop. */
|
||||
if (iter == &enode)
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("accepting: looped back to EN: %i",
|
||||
iter->m_index);
|
||||
if (fg)
|
||||
{
|
||||
auto_timevar tv (TV_ANALYZER_DUMP);
|
||||
pretty_printer pp;
|
||||
pp_printf (&pp, "%s.en%i.infinite-loop.dot",
|
||||
dump_base_name, enode.m_index);
|
||||
char *filename = xstrdup (pp_formatted_text (&pp));
|
||||
feasible_graph::dump_args_t dump_args (eg);
|
||||
fg->dump_dot (filename, nullptr, dump_args);
|
||||
free (filename);
|
||||
}
|
||||
return ::make_unique<infinite_loop> (enode,
|
||||
first_loc,
|
||||
eedges,
|
||||
logger);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("rejecting: looped back to EN: %i, not to EN: %i",
|
||||
iter->m_index, enode.m_index);
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
visited.add (iter);
|
||||
if (first_loc == UNKNOWN_LOCATION)
|
||||
{
|
||||
location_t enode_loc = iter->get_point ().get_location ();
|
||||
if (enode_loc != UNKNOWN_LOCATION)
|
||||
first_loc = enode_loc;
|
||||
}
|
||||
|
||||
/* Find the out-edges that are feasible, given the
|
||||
constraints here. */
|
||||
typedef std::pair<feasibility_state, const exploded_edge *> pair_t;
|
||||
std::vector<pair_t> succs;
|
||||
for (auto out_edge : iter->m_succs)
|
||||
{
|
||||
log_scope s (logger, "considering out-edge",
|
||||
"EN:%i -> EN:%i",
|
||||
out_edge->m_src->m_index,
|
||||
out_edge->m_dest->m_index);
|
||||
feasibility_state next_state (state);
|
||||
|
||||
/* Use this context to require edge conditions to be known,
|
||||
rather than be merely "possible". */
|
||||
infinite_loop_checking_context ctxt;
|
||||
if (next_state.maybe_update_for_edge (logger,
|
||||
out_edge,
|
||||
&ctxt,
|
||||
nullptr))
|
||||
succs.push_back (pair_t (next_state, out_edge));
|
||||
if (ctxt.unusable_p ())
|
||||
{
|
||||
/* If we get here, then we have e.g. a gcond where
|
||||
the condition is UNKNOWN, or a condition
|
||||
based on a widening_svalue. Reject such paths. */
|
||||
if (logger)
|
||||
logger->log ("rejecting: unusable");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
if (succs.size () != 1)
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("rejecting: %i feasible successors",
|
||||
(int)succs.size ());
|
||||
return nullptr;
|
||||
}
|
||||
const feasibility_state &next_state = succs[0].first;
|
||||
const exploded_edge *out_eedge = succs[0].second;
|
||||
if (out_eedge->could_do_work_p ())
|
||||
{
|
||||
if (logger)
|
||||
logger->log ("rejecting: edge could do work");
|
||||
return nullptr;
|
||||
}
|
||||
if (fg)
|
||||
{
|
||||
feasible_node *next_fnode = fg->add_node (out_eedge->m_dest,
|
||||
next_state,
|
||||
fg->m_nodes.length ());
|
||||
fg->add_edge (new feasible_edge (curr_fnode, next_fnode, out_eedge));
|
||||
curr_fnode = next_fnode;
|
||||
}
|
||||
state = next_state;
|
||||
eedges.push_back (out_eedge);
|
||||
if (first_loc == UNKNOWN_LOCATION)
|
||||
{
|
||||
if (out_eedge->m_sedge)
|
||||
if (::edge cfg_edge = out_eedge->m_sedge->get_any_cfg_edge ())
|
||||
if (cfg_edge->goto_locus > BUILTINS_LOCATION)
|
||||
first_loc = cfg_edge->goto_locus;
|
||||
}
|
||||
iter = out_eedge->m_dest;
|
||||
}
|
||||
}
|
||||
|
||||
/* Implementation of -Wanalyzer-infinite-loop. */
|
||||
|
||||
void
|
||||
exploded_graph::detect_infinite_loops ()
|
||||
{
|
||||
LOG_FUNC (get_logger ());
|
||||
auto_timevar tv (TV_ANALYZER_INFINITE_LOOPS);
|
||||
|
||||
/* Track all enodes we've warned for; both the loop entrypoints
|
||||
and all the enodes within those loops. */
|
||||
hash_set<const exploded_node *> warned_for;
|
||||
|
||||
for (auto enode : m_nodes)
|
||||
{
|
||||
if (get_logger ())
|
||||
get_logger ()->log ("visited: %i out of %i",
|
||||
(int)warned_for.elements (), m_nodes.length ());
|
||||
|
||||
/* Only warn about the first enode we encounter in each cycle. */
|
||||
if (warned_for.contains(enode))
|
||||
continue;
|
||||
|
||||
if (std::unique_ptr<infinite_loop> inf_loop
|
||||
= starts_infinite_loop_p (*enode, *this, get_logger ()))
|
||||
{
|
||||
const supernode *snode = enode->get_supernode ();
|
||||
|
||||
if (get_logger ())
|
||||
get_logger ()->log ("EN: %i from starts_infinite_loop_p",
|
||||
enode->m_index);
|
||||
|
||||
for (auto iter : inf_loop->m_eedge_vec)
|
||||
warned_for.add (iter->m_src);
|
||||
gcc_assert (warned_for.contains(enode));
|
||||
|
||||
if (inf_loop->m_loc == UNKNOWN_LOCATION)
|
||||
{
|
||||
if (get_logger ())
|
||||
get_logger ()->log
|
||||
("no location available for reporting infinite loop");
|
||||
continue;
|
||||
}
|
||||
|
||||
pending_location ploc (enode, snode, inf_loop->m_loc);
|
||||
auto d
|
||||
= ::make_unique<infinite_loop_diagnostic> (std::move (inf_loop));
|
||||
get_diagnostic_manager ().add_diagnostic (ploc, std::move (d));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -40,6 +40,40 @@ along with GCC; see the file COPYING3. If not see
|
|||
|
||||
namespace ana {
|
||||
|
||||
/* Abstract subclass for describing undefined behavior of an API. */
|
||||
|
||||
class undefined_function_behavior
|
||||
: public pending_diagnostic_subclass<undefined_function_behavior>
|
||||
{
|
||||
public:
|
||||
undefined_function_behavior (const call_details &cd)
|
||||
: m_call_stmt (cd.get_call_stmt ()),
|
||||
m_callee_fndecl (cd.get_fndecl_for_call ())
|
||||
{
|
||||
gcc_assert (m_call_stmt);
|
||||
gcc_assert (m_callee_fndecl);
|
||||
}
|
||||
|
||||
const char *get_kind () const final override
|
||||
{
|
||||
return "undefined_behavior";
|
||||
}
|
||||
|
||||
bool operator== (const undefined_function_behavior &other) const
|
||||
{
|
||||
return (m_call_stmt == other.m_call_stmt
|
||||
&& m_callee_fndecl == other.m_callee_fndecl);
|
||||
}
|
||||
|
||||
bool terminate_path_p () const final override { return true; }
|
||||
|
||||
tree get_callee_fndecl () const { return m_callee_fndecl; }
|
||||
|
||||
private:
|
||||
const gimple *m_call_stmt;
|
||||
tree m_callee_fndecl;
|
||||
};
|
||||
|
||||
/* class pure_known_function_with_default_return : public known_function. */
|
||||
|
||||
void
|
||||
|
|
@ -1679,6 +1713,288 @@ kf_strstr::impl_call_post (const call_details &cd) const
|
|||
}
|
||||
}
|
||||
|
||||
/* Handle calls to "strtok".
|
||||
See e.g.
|
||||
https://en.cppreference.com/w/c/string/byte/strtok
|
||||
https://man7.org/linux/man-pages/man3/strtok.3.html */
|
||||
|
||||
class kf_strtok : public known_function
|
||||
{
|
||||
public:
|
||||
class undefined_behavior : public undefined_function_behavior
|
||||
{
|
||||
public:
|
||||
undefined_behavior (const call_details &cd)
|
||||
: undefined_function_behavior (cd)
|
||||
{
|
||||
}
|
||||
int get_controlling_option () const final override
|
||||
{
|
||||
return OPT_Wanalyzer_undefined_behavior_strtok;
|
||||
}
|
||||
|
||||
bool emit (rich_location *rich_loc, logger *) final override
|
||||
{
|
||||
/* CWE-476: NULL Pointer Dereference. */
|
||||
diagnostic_metadata m;
|
||||
m.add_cwe (476);
|
||||
if (warning_meta
|
||||
(rich_loc, m, get_controlling_option (),
|
||||
"calling %qD for first time with NULL as argument 1"
|
||||
" has undefined behavior",
|
||||
get_callee_fndecl ()))
|
||||
{
|
||||
inform (rich_loc->get_loc (),
|
||||
"some implementations of %qD may crash on such input",
|
||||
get_callee_fndecl ());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
label_text describe_final_event (const evdesc::final_event &ev)
|
||||
final override
|
||||
{
|
||||
return ev.formatted_print
|
||||
("calling %qD for first time with NULL as argument 1"
|
||||
" has undefined behavior",
|
||||
get_callee_fndecl ());
|
||||
}
|
||||
};
|
||||
|
||||
/* An outcome of a "strtok" call.
|
||||
We have a four-way bifurcation of the analysis via the
|
||||
4 combinations of two flags:
|
||||
- m_nonnull_str covers whether the "str" param was null or non-null
|
||||
- m_found covers whether the result is null or non-null
|
||||
*/
|
||||
class strtok_call_info : public call_info
|
||||
{
|
||||
public:
|
||||
strtok_call_info (const call_details &cd,
|
||||
const private_region &private_reg,
|
||||
bool nonnull_str,
|
||||
bool found)
|
||||
: call_info (cd),
|
||||
m_private_reg (private_reg),
|
||||
m_nonnull_str (nonnull_str),
|
||||
m_found (found)
|
||||
{
|
||||
}
|
||||
|
||||
label_text get_desc (bool can_colorize) const final override
|
||||
{
|
||||
if (m_nonnull_str)
|
||||
{
|
||||
if (m_found)
|
||||
return make_label_text
|
||||
(can_colorize,
|
||||
"when %qE on non-NULL string returns non-NULL",
|
||||
get_fndecl ());
|
||||
else
|
||||
return make_label_text
|
||||
(can_colorize,
|
||||
"when %qE on non-NULL string returns NULL",
|
||||
get_fndecl ());
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_found)
|
||||
return make_label_text
|
||||
(can_colorize,
|
||||
"when %qE with NULL string (using prior) returns non-NULL",
|
||||
get_fndecl ());
|
||||
else
|
||||
return make_label_text
|
||||
(can_colorize,
|
||||
"when %qE with NULL string (using prior) returns NULL",
|
||||
get_fndecl ());
|
||||
}
|
||||
}
|
||||
|
||||
bool update_model (region_model *model,
|
||||
const exploded_edge *,
|
||||
region_model_context *ctxt) const final override
|
||||
{
|
||||
region_model_manager *mgr = model->get_manager ();
|
||||
const call_details cd (get_call_details (model, ctxt));
|
||||
const svalue *str_sval = cd.get_arg_svalue (0);
|
||||
/* const svalue *delim_sval = cd.get_arg_svalue (1); */
|
||||
|
||||
cd.check_for_null_terminated_string_arg (1);
|
||||
/* We check that either arg 0 or the private region is null
|
||||
terminated below. */
|
||||
|
||||
const svalue *null_ptr_sval
|
||||
= mgr->get_or_create_null_ptr (cd.get_arg_type (0));;
|
||||
if (!model->add_constraint (str_sval,
|
||||
m_nonnull_str ? NE_EXPR : EQ_EXPR,
|
||||
null_ptr_sval,
|
||||
cd.get_ctxt ()))
|
||||
return false;
|
||||
|
||||
if (m_nonnull_str)
|
||||
{
|
||||
/* Update internal buffer. */
|
||||
model->set_value (&m_private_reg,
|
||||
mgr->get_or_create_unmergeable (str_sval),
|
||||
ctxt);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Read from internal buffer. */
|
||||
str_sval = model->get_store_value (&m_private_reg, ctxt);
|
||||
|
||||
/* The initial value of the private region is NULL when we're
|
||||
on a path from main. */
|
||||
if (const initial_svalue *initial_sval
|
||||
= str_sval->dyn_cast_initial_svalue ())
|
||||
if (initial_sval->get_region () == &m_private_reg
|
||||
&& model->called_from_main_p ())
|
||||
{
|
||||
/* Implementations of strtok do not necessarily check for NULL
|
||||
here, and may crash; see PR analyzer/107573.
|
||||
Warn for this, if we were definitely passed NULL. */
|
||||
if (cd.get_arg_svalue (0)->all_zeroes_p ())
|
||||
{
|
||||
if (ctxt)
|
||||
ctxt->warn (::make_unique<undefined_behavior> (cd));
|
||||
}
|
||||
|
||||
/* Assume that "str" was actually non-null; terminate
|
||||
this path. */
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Now assume str_sval is non-null. */
|
||||
if (!model->add_constraint (str_sval,
|
||||
NE_EXPR,
|
||||
null_ptr_sval,
|
||||
cd.get_ctxt ()))
|
||||
return false;
|
||||
}
|
||||
|
||||
const region *buf_reg = model->deref_rvalue (str_sval, NULL_TREE, ctxt);
|
||||
model->scan_for_null_terminator (buf_reg,
|
||||
NULL_TREE,
|
||||
nullptr,
|
||||
ctxt);
|
||||
|
||||
if (m_found)
|
||||
{
|
||||
const region *str_reg
|
||||
= model->deref_rvalue (str_sval, cd.get_arg_tree (0),
|
||||
cd.get_ctxt ());
|
||||
/* We want to figure out the start and nul terminator
|
||||
for the token.
|
||||
For each, we want str_sval + OFFSET for some unknown OFFSET.
|
||||
Use a conjured_svalue to represent the offset,
|
||||
using the str_reg as the id of the conjured_svalue. */
|
||||
const svalue *start_offset
|
||||
= mgr->get_or_create_conjured_svalue (size_type_node,
|
||||
cd.get_call_stmt (),
|
||||
str_reg,
|
||||
conjured_purge (model,
|
||||
ctxt),
|
||||
0);
|
||||
const svalue *nul_offset
|
||||
= mgr->get_or_create_conjured_svalue (size_type_node,
|
||||
cd.get_call_stmt (),
|
||||
str_reg,
|
||||
conjured_purge (model,
|
||||
ctxt),
|
||||
1);
|
||||
|
||||
tree char_ptr_type = build_pointer_type (char_type_node);
|
||||
const svalue *result
|
||||
= mgr->get_or_create_binop (char_ptr_type, POINTER_PLUS_EXPR,
|
||||
str_sval, start_offset);
|
||||
cd.maybe_set_lhs (result);
|
||||
|
||||
/* nul_offset + 1; the offset to use for the next call. */
|
||||
const svalue *next_offset
|
||||
= mgr->get_or_create_binop (size_type_node, PLUS_EXPR,
|
||||
nul_offset,
|
||||
mgr->get_or_create_int_cst
|
||||
(char_type_node, 1));
|
||||
|
||||
/* Write '\0' to str_sval[nul_offset]. */
|
||||
const svalue *ptr_to_term
|
||||
= mgr->get_or_create_binop (char_ptr_type, POINTER_PLUS_EXPR,
|
||||
str_sval, nul_offset);
|
||||
const region *terminator_reg
|
||||
= model->deref_rvalue (ptr_to_term, NULL_TREE, cd.get_ctxt ());
|
||||
model->set_value (terminator_reg,
|
||||
mgr->get_or_create_unmergeable
|
||||
(mgr->get_or_create_int_cst (char_type_node,
|
||||
0)),
|
||||
cd.get_ctxt ());
|
||||
|
||||
/* Update saved ptr to be at [nul_offset + 1]. */
|
||||
const svalue *ptr_to_next
|
||||
= mgr->get_or_create_binop (cd.get_lhs_type (), POINTER_PLUS_EXPR,
|
||||
str_sval, next_offset);
|
||||
model->set_value (&m_private_reg, ptr_to_next, ctxt);
|
||||
}
|
||||
else
|
||||
if (tree lhs_type = cd.get_lhs_type ())
|
||||
{
|
||||
const svalue *result
|
||||
= mgr->get_or_create_int_cst (lhs_type, 0);
|
||||
cd.maybe_set_lhs (result);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
private:
|
||||
const private_region &m_private_reg;
|
||||
bool m_nonnull_str;
|
||||
bool m_found;
|
||||
}; // class strtok_call_info
|
||||
|
||||
kf_strtok (region_model_manager &mgr)
|
||||
: m_private_reg (mgr.alloc_symbol_id (),
|
||||
mgr.get_root_region (),
|
||||
get_region_type (),
|
||||
"strtok buffer")
|
||||
{
|
||||
}
|
||||
|
||||
bool matches_call_types_p (const call_details &cd) const final override
|
||||
{
|
||||
return (cd.num_args () == 2
|
||||
&& POINTER_TYPE_P (cd.get_arg_type (0))
|
||||
&& POINTER_TYPE_P (cd.get_arg_type (1)));
|
||||
}
|
||||
|
||||
void impl_call_post (const call_details &cd) const final override
|
||||
{
|
||||
if (cd.get_ctxt ())
|
||||
{
|
||||
/* Four-way bifurcation, based on whether:
|
||||
- the str is non-null
|
||||
- the result is non-null
|
||||
Typically the str is either null or non-null at a particular site,
|
||||
so hopefully this will generally just lead to two out-edges. */
|
||||
cd.get_ctxt ()->bifurcate
|
||||
(make_unique<strtok_call_info> (cd, m_private_reg, false, false));
|
||||
cd.get_ctxt ()->bifurcate
|
||||
(make_unique<strtok_call_info> (cd, m_private_reg, false, true));
|
||||
cd.get_ctxt ()->bifurcate
|
||||
(make_unique<strtok_call_info> (cd, m_private_reg, true, false));
|
||||
cd.get_ctxt ()->bifurcate
|
||||
(make_unique<strtok_call_info> (cd, m_private_reg, true, true));
|
||||
cd.get_ctxt ()->terminate_path ();
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
static tree get_region_type ()
|
||||
{
|
||||
return build_pointer_type (char_type_node);
|
||||
}
|
||||
const private_region m_private_reg;
|
||||
};
|
||||
|
||||
class kf_ubsan_bounds : public internal_known_function
|
||||
{
|
||||
/* Empty. */
|
||||
|
|
@ -1823,7 +2139,8 @@ register_atomic_builtins (known_function_manager &kfm)
|
|||
analyzer (as opposed to plugins). */
|
||||
|
||||
void
|
||||
register_known_functions (known_function_manager &kfm)
|
||||
register_known_functions (known_function_manager &kfm,
|
||||
region_model_manager &rmm)
|
||||
{
|
||||
/* Debugging/test support functions, all with a "__analyzer_" prefix. */
|
||||
register_known_analyzer_functions (kfm);
|
||||
|
|
@ -1911,6 +2228,7 @@ register_known_functions (known_function_manager &kfm)
|
|||
{
|
||||
kfm.add ("fopen", make_unique<kf_fopen> ());
|
||||
kfm.add ("putenv", make_unique<kf_putenv> ());
|
||||
kfm.add ("strtok", make_unique<kf_strtok> (rmm));
|
||||
|
||||
register_known_fd_functions (kfm);
|
||||
register_known_file_functions (kfm);
|
||||
|
|
|
|||
|
|
@ -1145,15 +1145,22 @@ program_state::on_edge (exploded_graph &eg,
|
|||
this,
|
||||
uncertainty, &path_ctxt,
|
||||
last_stmt);
|
||||
std::unique_ptr<rejected_constraint> rc;
|
||||
logger * const logger = eg.get_logger ();
|
||||
if (!m_region_model->maybe_update_for_edge (*succ,
|
||||
last_stmt,
|
||||
&ctxt, NULL))
|
||||
&ctxt,
|
||||
logger ? &rc : nullptr))
|
||||
{
|
||||
logger * const logger = eg.get_logger ();
|
||||
if (logger)
|
||||
logger->log ("edge to SN: %i is impossible"
|
||||
" due to region_model constraints",
|
||||
{
|
||||
logger->start_log_line ();
|
||||
logger->log_partial ("edge to SN: %i is impossible"
|
||||
" due to region_model constraint: ",
|
||||
succ->m_dest->m_index);
|
||||
rc->dump_to_pp (logger->get_printer ());
|
||||
logger->end_log_line ();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (terminated)
|
||||
|
|
|
|||
|
|
@ -1261,7 +1261,8 @@ conjured_purge::purge (const conjured_svalue *sval) const
|
|||
}
|
||||
|
||||
/* Return the svalue * of type TYPE for the value conjured for ID_REG
|
||||
at STMT, creating it if necessary.
|
||||
at STMT (using IDX for any further disambiguation),
|
||||
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. */
|
||||
|
||||
|
|
@ -1269,9 +1270,10 @@ const svalue *
|
|||
region_model_manager::get_or_create_conjured_svalue (tree type,
|
||||
const gimple *stmt,
|
||||
const region *id_reg,
|
||||
const conjured_purge &p)
|
||||
const conjured_purge &p,
|
||||
unsigned idx)
|
||||
{
|
||||
conjured_svalue::key_t key (type, stmt, id_reg);
|
||||
conjured_svalue::key_t key (type, stmt, id_reg, idx);
|
||||
if (conjured_svalue **slot = m_conjured_values_map.get (key))
|
||||
{
|
||||
const conjured_svalue *sval = *slot;
|
||||
|
|
@ -1283,7 +1285,7 @@ region_model_manager::get_or_create_conjured_svalue (tree type,
|
|||
return sval;
|
||||
}
|
||||
conjured_svalue *conjured_sval
|
||||
= new conjured_svalue (alloc_symbol_id (), type, stmt, id_reg);
|
||||
= new conjured_svalue (alloc_symbol_id (), type, stmt, id_reg, idx);
|
||||
RETURN_UNKNOWN_IF_TOO_COMPLEX (conjured_sval);
|
||||
m_conjured_values_map.put (key, conjured_sval);
|
||||
return conjured_sval;
|
||||
|
|
|
|||
|
|
@ -79,7 +79,8 @@ public:
|
|||
const binding_map &map);
|
||||
const svalue *get_or_create_conjured_svalue (tree type, const gimple *stmt,
|
||||
const region *id_reg,
|
||||
const conjured_purge &p);
|
||||
const conjured_purge &p,
|
||||
unsigned idx = 0);
|
||||
const svalue *
|
||||
get_or_create_asm_output_svalue (tree type,
|
||||
const gasm *asm_stmt,
|
||||
|
|
@ -105,6 +106,7 @@ public:
|
|||
const svalue *create_unique_svalue (tree type);
|
||||
|
||||
/* region consolidation. */
|
||||
const root_region *get_root_region () const { return &m_root_region; }
|
||||
const stack_region * get_stack_region () const { return &m_stack_region; }
|
||||
const heap_region *get_heap_region () const { return &m_heap_region; }
|
||||
const code_region *get_code_region () const { return &m_code_region; }
|
||||
|
|
|
|||
|
|
@ -1179,6 +1179,15 @@ region_model::on_assignment (const gassign *assign, region_model_context *ctxt)
|
|||
|
||||
const region *lhs_reg = get_lvalue (lhs, ctxt);
|
||||
|
||||
/* Any writes other than to the stack are treated
|
||||
as externally visible. */
|
||||
if (ctxt)
|
||||
{
|
||||
enum memory_space memspace = lhs_reg->get_memory_space ();
|
||||
if (memspace != MEMSPACE_STACK)
|
||||
ctxt->maybe_did_work ();
|
||||
}
|
||||
|
||||
/* Most assignments are handled by:
|
||||
set_value (lhs_reg, SVALUE, CTXT)
|
||||
for some SVALUE. */
|
||||
|
|
@ -1277,6 +1286,8 @@ region_model::on_stmt_pre (const gimple *stmt,
|
|||
{
|
||||
const gasm *asm_stmt = as_a <const gasm *> (stmt);
|
||||
on_asm_stmt (asm_stmt, ctxt);
|
||||
if (ctxt)
|
||||
ctxt->maybe_did_work ();
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -1701,7 +1712,11 @@ region_model::on_call_post (const gcall *call,
|
|||
}
|
||||
|
||||
if (unknown_side_effects)
|
||||
{
|
||||
handle_unrecognized_call (call, ctxt);
|
||||
if (ctxt)
|
||||
ctxt->maybe_did_work ();
|
||||
}
|
||||
}
|
||||
|
||||
/* Purge state involving SVAL from this region_model, using CTXT
|
||||
|
|
@ -2236,6 +2251,7 @@ void
|
|||
region_model::handle_phi (const gphi *phi,
|
||||
tree lhs, tree rhs,
|
||||
const region_model &old_state,
|
||||
hash_set<const svalue *> &svals_changing_meaning,
|
||||
region_model_context *ctxt)
|
||||
{
|
||||
/* For now, don't bother tracking the .MEM SSA names. */
|
||||
|
|
@ -2247,6 +2263,10 @@ region_model::handle_phi (const gphi *phi,
|
|||
const svalue *src_sval = old_state.get_rvalue (rhs, ctxt);
|
||||
const region *dst_reg = old_state.get_lvalue (lhs, ctxt);
|
||||
|
||||
const svalue *sval = old_state.get_rvalue (lhs, nullptr);
|
||||
if (sval->get_kind () == SK_WIDENING)
|
||||
svals_changing_meaning.add (sval);
|
||||
|
||||
set_value (dst_reg, src_sval, ctxt);
|
||||
|
||||
if (ctxt)
|
||||
|
|
@ -3864,8 +3884,10 @@ region_model::scan_for_null_terminator (const region *reg,
|
|||
byte_range bytes_to_read (src_byte_offset, 1);
|
||||
const svalue *sval = get_store_bytes (base_reg, bytes_to_read, ctxt);
|
||||
tree byte_expr
|
||||
= get_tree_for_byte_offset (expr,
|
||||
src_byte_offset - initial_src_byte_offset);
|
||||
= (expr
|
||||
? get_tree_for_byte_offset (expr,
|
||||
src_byte_offset - initial_src_byte_offset)
|
||||
: NULL_TREE);
|
||||
check_for_poison (sval, byte_expr, nullptr, ctxt);
|
||||
if (base_reg->can_have_initial_svalue_p ())
|
||||
{
|
||||
|
|
@ -4661,6 +4683,14 @@ region_model::add_constraint (tree lhs, enum tree_code op, tree rhs,
|
|||
return add_constraint (lhs_sval, op, rhs_sval, ctxt);
|
||||
}
|
||||
|
||||
static bool
|
||||
unusable_in_infinite_loop_constraint_p (const svalue *sval)
|
||||
{
|
||||
if (sval->get_kind () == SK_WIDENING)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Attempt to add the constraint "LHS OP RHS" to this region_model.
|
||||
If it is consistent with existing constraints, add it, and return true.
|
||||
Return false if it contradicts existing constraints.
|
||||
|
|
@ -4672,6 +4702,20 @@ region_model::add_constraint (const svalue *lhs,
|
|||
const svalue *rhs,
|
||||
region_model_context *ctxt)
|
||||
{
|
||||
const bool checking_for_infinite_loop
|
||||
= ctxt ? ctxt->checking_for_infinite_loop_p () : false;
|
||||
|
||||
if (checking_for_infinite_loop)
|
||||
{
|
||||
if (unusable_in_infinite_loop_constraint_p (lhs)
|
||||
|| unusable_in_infinite_loop_constraint_p (rhs))
|
||||
{
|
||||
gcc_assert (ctxt);
|
||||
ctxt->on_unusable_in_infinite_loop ();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
tristate t_cond = eval_condition (lhs, op, rhs);
|
||||
|
||||
/* If we already have the condition, do nothing. */
|
||||
|
|
@ -4683,6 +4727,15 @@ region_model::add_constraint (const svalue *lhs,
|
|||
if (t_cond.is_false ())
|
||||
return false;
|
||||
|
||||
if (checking_for_infinite_loop)
|
||||
{
|
||||
/* Here, we don't have a definite true/false value, so bail out
|
||||
when checking for infinite loops. */
|
||||
gcc_assert (ctxt);
|
||||
ctxt->on_unusable_in_infinite_loop ();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool out;
|
||||
if (add_constraints_from_binop (lhs, op, rhs, &out, ctxt))
|
||||
return out;
|
||||
|
|
@ -5026,6 +5079,7 @@ region_model::get_representative_path_var_1 (const region *reg,
|
|||
case RK_VAR_ARG:
|
||||
case RK_ERRNO:
|
||||
case RK_UNKNOWN:
|
||||
case RK_PRIVATE:
|
||||
return path_var (NULL_TREE, 0);
|
||||
}
|
||||
}
|
||||
|
|
@ -5068,6 +5122,8 @@ region_model::update_for_phis (const supernode *snode,
|
|||
are effectively handled simultaneously. */
|
||||
const region_model old_state (*this);
|
||||
|
||||
hash_set<const svalue *> svals_changing_meaning;
|
||||
|
||||
for (gphi_iterator gpi = const_cast<supernode *>(snode)->start_phis ();
|
||||
!gsi_end_p (gpi); gsi_next (&gpi))
|
||||
{
|
||||
|
|
@ -5077,8 +5133,11 @@ region_model::update_for_phis (const supernode *snode,
|
|||
tree lhs = gimple_phi_result (phi);
|
||||
|
||||
/* Update next_state based on phi and old_state. */
|
||||
handle_phi (phi, lhs, src, old_state, ctxt);
|
||||
handle_phi (phi, lhs, src, old_state, svals_changing_meaning, ctxt);
|
||||
}
|
||||
|
||||
for (auto iter : svals_changing_meaning)
|
||||
m_constraints->purge_state_involving (iter);
|
||||
}
|
||||
|
||||
/* Attempt to update this model for taking EDGE (where the last statement
|
||||
|
|
@ -5246,6 +5305,9 @@ region_model::replay_call_summary (call_summary_replay &r,
|
|||
|
||||
m_store.replay_call_summary (r, summary.m_store);
|
||||
|
||||
if (r.get_ctxt ())
|
||||
r.get_ctxt ()->maybe_did_work ();
|
||||
|
||||
if (!m_constraints->replay_call_summary (r, *summary.m_constraints))
|
||||
return false;
|
||||
|
||||
|
|
@ -5807,6 +5869,9 @@ region_model::can_merge_with_p (const region_model &other_model,
|
|||
*other_model.m_constraints,
|
||||
out_model->m_constraints);
|
||||
|
||||
for (auto iter : m.m_svals_changing_meaning)
|
||||
out_model->m_constraints->purge_state_involving (iter);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
@ -6658,6 +6723,14 @@ model_merger::mergeable_svalue_p (const svalue *sval) const
|
|||
return true;
|
||||
}
|
||||
|
||||
/* Mark WIDENING_SVAL as changing meaning during the merge. */
|
||||
|
||||
void
|
||||
model_merger::on_widening_reuse (const widening_svalue *widening_sval)
|
||||
{
|
||||
m_svals_changing_meaning.add (widening_sval);
|
||||
}
|
||||
|
||||
} // namespace ana
|
||||
|
||||
/* Dump RMODEL fully to stderr (i.e. without summarization). */
|
||||
|
|
@ -8364,7 +8437,6 @@ test_iteration_1 ()
|
|||
tree int_0 = build_int_cst (integer_type_node, 0);
|
||||
tree int_1 = build_int_cst (integer_type_node, 1);
|
||||
tree int_256 = build_int_cst (integer_type_node, 256);
|
||||
tree int_257 = build_int_cst (integer_type_node, 257);
|
||||
tree i = build_global_decl ("i", integer_type_node);
|
||||
|
||||
test_region_model_context ctxt;
|
||||
|
|
@ -8426,8 +8498,6 @@ test_iteration_1 ()
|
|||
ASSERT_TRUE (model5.can_merge_with_p (model2, point, &model6));
|
||||
const svalue *merged_widening = model6.get_rvalue (i, &ctxt);
|
||||
ASSERT_EQ (merged_widening->get_kind (), SK_WIDENING);
|
||||
|
||||
ASSERT_CONDITION_TRUE (model6, i, LT_EXPR, int_257);
|
||||
}
|
||||
|
||||
/* Verify that if we mark a pointer to a malloc-ed region as non-NULL,
|
||||
|
|
|
|||
|
|
@ -328,6 +328,7 @@ class region_model
|
|||
|
||||
void handle_phi (const gphi *phi, tree lhs, tree rhs,
|
||||
const region_model &old_state,
|
||||
hash_set<const svalue *> &svals_changing_meaning,
|
||||
region_model_context *ctxt);
|
||||
|
||||
bool maybe_update_for_edge (const superedge &edge,
|
||||
|
|
@ -558,6 +559,8 @@ class region_model
|
|||
callback (model, prev_model, retval, ctxt);
|
||||
}
|
||||
|
||||
bool called_from_main_p () const;
|
||||
|
||||
private:
|
||||
const region *get_lvalue_1 (path_var pv, region_model_context *ctxt) const;
|
||||
const svalue *get_rvalue_1 (path_var pv, region_model_context *ctxt) const;
|
||||
|
|
@ -605,7 +608,6 @@ private:
|
|||
bool nonnull,
|
||||
region_model_context *ctxt);
|
||||
|
||||
bool called_from_main_p () const;
|
||||
const svalue *get_initial_value_for_global (const region *reg) const;
|
||||
|
||||
const region * get_region_for_poisoned_expr (tree expr) const;
|
||||
|
|
@ -804,6 +806,11 @@ class region_model_context
|
|||
virtual const gimple *get_stmt () const = 0;
|
||||
|
||||
virtual const exploded_graph *get_eg () const = 0;
|
||||
|
||||
/* Hooks for detecting infinite loops. */
|
||||
virtual void maybe_did_work () = 0;
|
||||
virtual bool checking_for_infinite_loop_p () const = 0;
|
||||
virtual void on_unusable_in_infinite_loop () = 0;
|
||||
};
|
||||
|
||||
/* A "do nothing" subclass of region_model_context. */
|
||||
|
|
@ -861,6 +868,9 @@ public:
|
|||
|
||||
const gimple *get_stmt () const override { return NULL; }
|
||||
const exploded_graph *get_eg () const override { return NULL; }
|
||||
void maybe_did_work () override {}
|
||||
bool checking_for_infinite_loop_p () const override { return false; }
|
||||
void on_unusable_in_infinite_loop () override {}
|
||||
};
|
||||
|
||||
/* A subclass of region_model_context for determining if operations fail
|
||||
|
|
@ -1036,6 +1046,24 @@ class region_model_context_decorator : public region_model_context
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
void maybe_did_work () override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->maybe_did_work ();
|
||||
}
|
||||
|
||||
bool checking_for_infinite_loop_p () const override
|
||||
{
|
||||
if (m_inner)
|
||||
return m_inner->checking_for_infinite_loop_p ();
|
||||
return false;
|
||||
}
|
||||
void on_unusable_in_infinite_loop () override
|
||||
{
|
||||
if (m_inner)
|
||||
m_inner->on_unusable_in_infinite_loop ();
|
||||
}
|
||||
|
||||
protected:
|
||||
region_model_context_decorator (region_model_context *inner)
|
||||
: m_inner (inner)
|
||||
|
|
@ -1108,6 +1136,8 @@ struct model_merger
|
|||
return m_point.get_function_point ();
|
||||
}
|
||||
|
||||
void on_widening_reuse (const widening_svalue *widening_sval);
|
||||
|
||||
const region_model *m_model_a;
|
||||
const region_model *m_model_b;
|
||||
const program_point &m_point;
|
||||
|
|
@ -1116,6 +1146,8 @@ struct model_merger
|
|||
const extrinsic_state *m_ext_state;
|
||||
const program_state *m_state_a;
|
||||
const program_state *m_state_b;
|
||||
|
||||
hash_set<const svalue *> m_svals_changing_meaning;
|
||||
};
|
||||
|
||||
/* A record that can (optionally) be written out when
|
||||
|
|
|
|||
|
|
@ -514,6 +514,8 @@ region::get_memory_space () const
|
|||
return MEMSPACE_HEAP;
|
||||
case RK_STRING:
|
||||
return MEMSPACE_READONLY_DATA;
|
||||
case RK_PRIVATE:
|
||||
return MEMSPACE_PRIVATE;
|
||||
}
|
||||
if (iter->get_kind () == RK_CAST)
|
||||
iter = iter->dyn_cast_cast_region ()->get_original_region ();
|
||||
|
|
@ -543,6 +545,7 @@ region::can_have_initial_svalue_p () const
|
|||
case MEMSPACE_CODE:
|
||||
case MEMSPACE_GLOBALS:
|
||||
case MEMSPACE_READONLY_DATA:
|
||||
case MEMSPACE_PRIVATE:
|
||||
/* Such regions have initial_svalues. */
|
||||
return true;
|
||||
|
||||
|
|
@ -2259,6 +2262,17 @@ errno_region::dump_to_pp (pretty_printer *pp, bool simple) const
|
|||
pp_string (pp, "errno_region()");
|
||||
}
|
||||
|
||||
/* class private_region : public region. */
|
||||
|
||||
void
|
||||
private_region::dump_to_pp (pretty_printer *pp, bool simple) const
|
||||
{
|
||||
if (simple)
|
||||
pp_printf (pp, "PRIVATE_REG(%qs)", m_desc);
|
||||
else
|
||||
pp_printf (pp, "private_region(%qs)", m_desc);
|
||||
}
|
||||
|
||||
/* class unknown_region : public region. */
|
||||
|
||||
/* Implementation of region::dump_to_pp vfunc for unknown_region. */
|
||||
|
|
|
|||
|
|
@ -35,7 +35,8 @@ enum memory_space
|
|||
MEMSPACE_STACK,
|
||||
MEMSPACE_HEAP,
|
||||
MEMSPACE_READONLY_DATA,
|
||||
MEMSPACE_THREAD_LOCAL
|
||||
MEMSPACE_THREAD_LOCAL,
|
||||
MEMSPACE_PRIVATE
|
||||
};
|
||||
|
||||
/* An enum for discriminating between the different concrete subclasses
|
||||
|
|
@ -65,6 +66,7 @@ enum region_kind
|
|||
RK_BIT_RANGE,
|
||||
RK_VAR_ARG,
|
||||
RK_ERRNO,
|
||||
RK_PRIVATE,
|
||||
RK_UNKNOWN,
|
||||
};
|
||||
|
||||
|
|
@ -108,6 +110,7 @@ enum region_kind
|
|||
var_arg_region (RK_VAR_ARG): a region for the N-th vararg within a
|
||||
frame_region for a variadic call
|
||||
errno_region (RK_ERRNO): a region for holding "errno"
|
||||
private_region (RK_PRIVATE): a region for internal state of an API
|
||||
unknown_region (RK_UNKNOWN): for handling unimplemented tree codes. */
|
||||
|
||||
/* Abstract base class for representing ways of accessing chunks of memory.
|
||||
|
|
@ -1434,6 +1437,42 @@ is_a_helper <const errno_region *>::test (const region *reg)
|
|||
|
||||
namespace ana {
|
||||
|
||||
/* Similar to a decl region, but we don't have the decl.
|
||||
For implementing e.g. static buffers of known_functions,
|
||||
or other internal state of an API.
|
||||
|
||||
These are owned by known_function instances, rather than the
|
||||
region_model_manager. */
|
||||
|
||||
class private_region : public region
|
||||
{
|
||||
public:
|
||||
private_region (unsigned id, const region *parent, tree type,
|
||||
const char *desc)
|
||||
: region (complexity (parent), id, parent, type),
|
||||
m_desc (desc)
|
||||
{}
|
||||
|
||||
enum region_kind get_kind () const final override { return RK_PRIVATE; }
|
||||
|
||||
void dump_to_pp (pretty_printer *pp, bool simple) const final override;
|
||||
|
||||
private:
|
||||
const char *m_desc;
|
||||
};
|
||||
|
||||
} // namespace ana
|
||||
|
||||
template <>
|
||||
template <>
|
||||
inline bool
|
||||
is_a_helper <const private_region *>::test (const region *reg)
|
||||
{
|
||||
return reg->get_kind () == RK_PRIVATE;
|
||||
}
|
||||
|
||||
namespace ana {
|
||||
|
||||
/* An unknown region, for handling unimplemented tree codes. */
|
||||
|
||||
class unknown_region : public region
|
||||
|
|
|
|||
|
|
@ -279,6 +279,7 @@ public:
|
|||
src_enode);
|
||||
if (dst_enode)
|
||||
eg->add_edge (src_enode, dst_enode, NULL, /*state_change (),*/
|
||||
true, /* assume does work */
|
||||
make_unique<signal_delivery_edge_info_t> ());
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
/* An experimental state machine, for tracking "taint": unsanitized uses
|
||||
/* A state machine for tracking "taint": unsanitized uses
|
||||
of data potentially under an attacker's control.
|
||||
|
||||
Copyright (C) 2019-2023 Free Software Foundation, Inc.
|
||||
|
|
|
|||
|
|
@ -188,9 +188,6 @@ make_checkers (auto_delete_vec <state_machine> &out, logger *logger)
|
|||
out.safe_push (make_malloc_state_machine (logger));
|
||||
out.safe_push (make_fileptr_state_machine (logger));
|
||||
out.safe_push (make_fd_state_machine (logger));
|
||||
/* The "taint" checker must be explicitly enabled (as it currently
|
||||
leads to state explosions that stop the other checkers working). */
|
||||
if (flag_analyzer_checker)
|
||||
out.safe_push (make_taint_state_machine (logger));
|
||||
out.safe_push (make_sensitive_state_machine (logger));
|
||||
out.safe_push (make_signal_state_machine (logger));
|
||||
|
|
|
|||
|
|
@ -3372,6 +3372,7 @@ store::replay_call_summary_cluster (call_summary_replay &r,
|
|||
case RK_HEAP_ALLOCATED:
|
||||
case RK_DECL:
|
||||
case RK_ERRNO:
|
||||
case RK_PRIVATE:
|
||||
{
|
||||
const region *caller_dest_reg
|
||||
= r.convert_region_from_summary (summary_base_reg);
|
||||
|
|
|
|||
|
|
@ -790,6 +790,13 @@ supernode::get_start_location () const
|
|||
if (return_p ())
|
||||
return m_fun->function_end_locus;
|
||||
|
||||
/* We have no locations for stmts. If we have a single out-edge that's
|
||||
a CFG edge, the goto_locus of that edge is a better location for this
|
||||
than UNKNOWN_LOCATION. */
|
||||
if (m_succs.length () == 1)
|
||||
if (const cfg_superedge *cfg_sedge = m_succs[0]->dyn_cast_cfg_superedge ())
|
||||
return cfg_sedge->get_goto_locus ();
|
||||
|
||||
return UNKNOWN_LOCATION;
|
||||
}
|
||||
|
||||
|
|
@ -813,6 +820,12 @@ supernode::get_end_location () const
|
|||
if (return_p ())
|
||||
return m_fun->function_end_locus;
|
||||
|
||||
/* If we have a single out-edge that's a CFG edge, use the goto_locus of
|
||||
that edge. */
|
||||
if (m_succs.length () == 1)
|
||||
if (const cfg_superedge *cfg_sedge = m_succs[0]->dyn_cast_cfg_superedge ())
|
||||
return cfg_sedge->get_goto_locus ();
|
||||
|
||||
return UNKNOWN_LOCATION;
|
||||
}
|
||||
|
||||
|
|
@ -1063,6 +1076,9 @@ cfg_superedge::dump_label_to_pp (pretty_printer *pp,
|
|||
pp_string (pp, ")");
|
||||
}
|
||||
|
||||
if (m_cfg_edge->goto_locus > BUILTINS_LOCATION)
|
||||
pp_string (pp, " (has goto_locus)");
|
||||
|
||||
/* Otherwise, no label. */
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -532,6 +532,8 @@ class cfg_superedge : public superedge
|
|||
size_t get_phi_arg_idx () const;
|
||||
tree get_phi_arg (const gphi *phi) const;
|
||||
|
||||
location_t get_goto_locus () const { return m_cfg_edge->goto_locus; }
|
||||
|
||||
private:
|
||||
const ::edge m_cfg_edge;
|
||||
};
|
||||
|
|
|
|||
|
|
@ -251,6 +251,7 @@ svalue::can_merge_p (const svalue *other,
|
|||
a descending chain of constraints. */
|
||||
if (other == widen_arg0)
|
||||
{
|
||||
merger->on_widening_reuse (widen_arg0);
|
||||
return widen_arg0;
|
||||
}
|
||||
|
||||
|
|
@ -606,6 +607,12 @@ public:
|
|||
m_found = true;
|
||||
}
|
||||
|
||||
void visit_widening_svalue (const widening_svalue *candidate) final override
|
||||
{
|
||||
if (candidate == m_needle)
|
||||
m_found = true;
|
||||
}
|
||||
|
||||
bool found_p () const { return m_found; }
|
||||
|
||||
private:
|
||||
|
|
@ -620,7 +627,8 @@ svalue::involves_p (const svalue *other) const
|
|||
{
|
||||
/* Currently only implemented for these kinds. */
|
||||
gcc_assert (other->get_kind () == SK_INITIAL
|
||||
|| other->get_kind () == SK_CONJURED);
|
||||
|| other->get_kind () == SK_CONJURED
|
||||
|| other->get_kind () == SK_WIDENING);
|
||||
|
||||
involvement_visitor v (other);
|
||||
accept (&v);
|
||||
|
|
|
|||
|
|
@ -1360,8 +1360,8 @@ public:
|
|||
/* A support class for uniquifying instances of conjured_svalue. */
|
||||
struct key_t
|
||||
{
|
||||
key_t (tree type, const gimple *stmt, const region *id_reg)
|
||||
: m_type (type), m_stmt (stmt), m_id_reg (id_reg)
|
||||
key_t (tree type, const gimple *stmt, const region *id_reg, unsigned idx)
|
||||
: m_type (type), m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
|
||||
{}
|
||||
|
||||
hashval_t hash () const
|
||||
|
|
@ -1377,7 +1377,8 @@ public:
|
|||
{
|
||||
return (m_type == other.m_type
|
||||
&& m_stmt == other.m_stmt
|
||||
&& m_id_reg == other.m_id_reg);
|
||||
&& m_id_reg == other.m_id_reg
|
||||
&& m_idx == other.m_idx);
|
||||
}
|
||||
|
||||
/* Use m_stmt to mark empty/deleted, as m_type can be NULL for
|
||||
|
|
@ -1393,12 +1394,13 @@ public:
|
|||
tree m_type;
|
||||
const gimple *m_stmt;
|
||||
const region *m_id_reg;
|
||||
unsigned m_idx;
|
||||
};
|
||||
|
||||
conjured_svalue (symbol::id_t id, tree type, const gimple *stmt,
|
||||
const region *id_reg)
|
||||
const region *id_reg, unsigned idx)
|
||||
: svalue (complexity (id_reg), id, type),
|
||||
m_stmt (stmt), m_id_reg (id_reg)
|
||||
m_stmt (stmt), m_id_reg (id_reg), m_idx (idx)
|
||||
{
|
||||
gcc_assert (m_stmt != NULL);
|
||||
}
|
||||
|
|
@ -1419,6 +1421,7 @@ public:
|
|||
private:
|
||||
const gimple *m_stmt;
|
||||
const region *m_id_reg;
|
||||
unsigned m_idx;
|
||||
};
|
||||
|
||||
} // namespace ana
|
||||
|
|
|
|||
277
gcc/builtins.cc
277
gcc/builtins.cc
|
|
@ -9573,6 +9573,271 @@ fold_builtin_arith_overflow (location_t loc, enum built_in_function fcode,
|
|||
return build2_loc (loc, COMPOUND_EXPR, boolean_type_node, store, ovfres);
|
||||
}
|
||||
|
||||
/* Fold __builtin_{clz,ctz,clrsb,ffs,parity,popcount}g into corresponding
|
||||
internal function. */
|
||||
|
||||
static tree
|
||||
fold_builtin_bit_query (location_t loc, enum built_in_function fcode,
|
||||
tree arg0, tree arg1)
|
||||
{
|
||||
enum internal_fn ifn;
|
||||
enum built_in_function fcodei, fcodel, fcodell;
|
||||
tree arg0_type = TREE_TYPE (arg0);
|
||||
tree cast_type = NULL_TREE;
|
||||
int addend = 0;
|
||||
|
||||
switch (fcode)
|
||||
{
|
||||
case BUILT_IN_CLZG:
|
||||
if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
|
||||
return NULL_TREE;
|
||||
ifn = IFN_CLZ;
|
||||
fcodei = BUILT_IN_CLZ;
|
||||
fcodel = BUILT_IN_CLZL;
|
||||
fcodell = BUILT_IN_CLZLL;
|
||||
break;
|
||||
case BUILT_IN_CTZG:
|
||||
if (arg1 && TREE_CODE (arg1) != INTEGER_CST)
|
||||
return NULL_TREE;
|
||||
ifn = IFN_CTZ;
|
||||
fcodei = BUILT_IN_CTZ;
|
||||
fcodel = BUILT_IN_CTZL;
|
||||
fcodell = BUILT_IN_CTZLL;
|
||||
break;
|
||||
case BUILT_IN_CLRSBG:
|
||||
ifn = IFN_CLRSB;
|
||||
fcodei = BUILT_IN_CLRSB;
|
||||
fcodel = BUILT_IN_CLRSBL;
|
||||
fcodell = BUILT_IN_CLRSBLL;
|
||||
break;
|
||||
case BUILT_IN_FFSG:
|
||||
ifn = IFN_FFS;
|
||||
fcodei = BUILT_IN_FFS;
|
||||
fcodel = BUILT_IN_FFSL;
|
||||
fcodell = BUILT_IN_FFSLL;
|
||||
break;
|
||||
case BUILT_IN_PARITYG:
|
||||
ifn = IFN_PARITY;
|
||||
fcodei = BUILT_IN_PARITY;
|
||||
fcodel = BUILT_IN_PARITYL;
|
||||
fcodell = BUILT_IN_PARITYLL;
|
||||
break;
|
||||
case BUILT_IN_POPCOUNTG:
|
||||
ifn = IFN_POPCOUNT;
|
||||
fcodei = BUILT_IN_POPCOUNT;
|
||||
fcodel = BUILT_IN_POPCOUNTL;
|
||||
fcodell = BUILT_IN_POPCOUNTLL;
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
||||
if (TYPE_PRECISION (arg0_type)
|
||||
<= TYPE_PRECISION (long_long_unsigned_type_node))
|
||||
{
|
||||
if (TYPE_PRECISION (arg0_type) <= TYPE_PRECISION (unsigned_type_node))
|
||||
|
||||
cast_type = (TYPE_UNSIGNED (arg0_type)
|
||||
? unsigned_type_node : integer_type_node);
|
||||
else if (TYPE_PRECISION (arg0_type)
|
||||
<= TYPE_PRECISION (long_unsigned_type_node))
|
||||
{
|
||||
cast_type = (TYPE_UNSIGNED (arg0_type)
|
||||
? long_unsigned_type_node : long_integer_type_node);
|
||||
fcodei = fcodel;
|
||||
}
|
||||
else
|
||||
{
|
||||
cast_type = (TYPE_UNSIGNED (arg0_type)
|
||||
? long_long_unsigned_type_node
|
||||
: long_long_integer_type_node);
|
||||
fcodei = fcodell;
|
||||
}
|
||||
}
|
||||
else if (TYPE_PRECISION (arg0_type) <= MAX_FIXED_MODE_SIZE)
|
||||
{
|
||||
cast_type
|
||||
= build_nonstandard_integer_type (MAX_FIXED_MODE_SIZE,
|
||||
TYPE_UNSIGNED (arg0_type));
|
||||
gcc_assert (TYPE_PRECISION (cast_type)
|
||||
== 2 * TYPE_PRECISION (long_long_unsigned_type_node));
|
||||
fcodei = END_BUILTINS;
|
||||
}
|
||||
else
|
||||
fcodei = END_BUILTINS;
|
||||
if (cast_type)
|
||||
{
|
||||
switch (fcode)
|
||||
{
|
||||
case BUILT_IN_CLZG:
|
||||
case BUILT_IN_CLRSBG:
|
||||
addend = TYPE_PRECISION (arg0_type) - TYPE_PRECISION (cast_type);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
arg0 = fold_convert (cast_type, arg0);
|
||||
arg0_type = cast_type;
|
||||
}
|
||||
|
||||
if (arg1)
|
||||
arg1 = fold_convert (integer_type_node, arg1);
|
||||
|
||||
tree arg2 = arg1;
|
||||
if (fcode == BUILT_IN_CLZG && addend)
|
||||
{
|
||||
if (arg1)
|
||||
arg0 = save_expr (arg0);
|
||||
arg2 = NULL_TREE;
|
||||
}
|
||||
tree call = NULL_TREE, tem;
|
||||
if (TYPE_PRECISION (arg0_type) == MAX_FIXED_MODE_SIZE
|
||||
&& (TYPE_PRECISION (arg0_type)
|
||||
== 2 * TYPE_PRECISION (long_long_unsigned_type_node)))
|
||||
{
|
||||
/* __int128 expansions using up to 2 long long builtins. */
|
||||
arg0 = save_expr (arg0);
|
||||
tree type = (TYPE_UNSIGNED (arg0_type)
|
||||
? long_long_unsigned_type_node
|
||||
: long_long_integer_type_node);
|
||||
tree hi = fold_build2 (RSHIFT_EXPR, arg0_type, arg0,
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE / 2));
|
||||
hi = fold_convert (type, hi);
|
||||
tree lo = fold_convert (type, arg0);
|
||||
switch (fcode)
|
||||
{
|
||||
case BUILT_IN_CLZG:
|
||||
call = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
|
||||
call = fold_build2 (PLUS_EXPR, integer_type_node, call,
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE / 2));
|
||||
if (arg2)
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
lo, build_zero_cst (type)),
|
||||
call, arg2);
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
hi, build_zero_cst (type)),
|
||||
fold_builtin_bit_query (loc, fcode, hi,
|
||||
NULL_TREE),
|
||||
call);
|
||||
break;
|
||||
case BUILT_IN_CTZG:
|
||||
call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
|
||||
call = fold_build2 (PLUS_EXPR, integer_type_node, call,
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE / 2));
|
||||
if (arg2)
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
hi, build_zero_cst (type)),
|
||||
call, arg2);
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
lo, build_zero_cst (type)),
|
||||
fold_builtin_bit_query (loc, fcode, lo,
|
||||
NULL_TREE),
|
||||
call);
|
||||
break;
|
||||
case BUILT_IN_CLRSBG:
|
||||
tem = fold_builtin_bit_query (loc, fcode, lo, NULL_TREE);
|
||||
tem = fold_build2 (PLUS_EXPR, integer_type_node, tem,
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE / 2));
|
||||
tem = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (LT_EXPR, boolean_type_node,
|
||||
fold_build2 (BIT_XOR_EXPR, type,
|
||||
lo, hi),
|
||||
build_zero_cst (type)),
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE / 2 - 1),
|
||||
tem);
|
||||
call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
|
||||
call = save_expr (call);
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
call,
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE
|
||||
/ 2 - 1)),
|
||||
call, tem);
|
||||
break;
|
||||
case BUILT_IN_FFSG:
|
||||
call = fold_builtin_bit_query (loc, fcode, hi, NULL_TREE);
|
||||
call = fold_build2 (PLUS_EXPR, integer_type_node, call,
|
||||
build_int_cst (integer_type_node,
|
||||
MAX_FIXED_MODE_SIZE / 2));
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
hi, build_zero_cst (type)),
|
||||
call, integer_zero_node);
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
lo, build_zero_cst (type)),
|
||||
fold_builtin_bit_query (loc, fcode, lo,
|
||||
NULL_TREE),
|
||||
call);
|
||||
break;
|
||||
case BUILT_IN_PARITYG:
|
||||
call = fold_builtin_bit_query (loc, fcode,
|
||||
fold_build2 (BIT_XOR_EXPR, type,
|
||||
lo, hi), NULL_TREE);
|
||||
break;
|
||||
case BUILT_IN_POPCOUNTG:
|
||||
call = fold_build2 (PLUS_EXPR, integer_type_node,
|
||||
fold_builtin_bit_query (loc, fcode, hi,
|
||||
NULL_TREE),
|
||||
fold_builtin_bit_query (loc, fcode, lo,
|
||||
NULL_TREE));
|
||||
break;
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Only keep second argument to IFN_CLZ/IFN_CTZ if it is the
|
||||
value defined at zero during GIMPLE, or for large/huge _BitInt
|
||||
(which are then lowered during bitint lowering). */
|
||||
if (arg2 && TREE_CODE (TREE_TYPE (arg0)) != BITINT_TYPE)
|
||||
{
|
||||
int val;
|
||||
if (fcode == BUILT_IN_CLZG)
|
||||
{
|
||||
if (CLZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
|
||||
val) != 2
|
||||
|| wi::to_widest (arg2) != val)
|
||||
arg2 = NULL_TREE;
|
||||
}
|
||||
else if (CTZ_DEFINED_VALUE_AT_ZERO (SCALAR_TYPE_MODE (arg0_type),
|
||||
val) != 2
|
||||
|| wi::to_widest (arg2) != val)
|
||||
arg2 = NULL_TREE;
|
||||
if (!direct_internal_fn_supported_p (ifn, arg0_type,
|
||||
OPTIMIZE_FOR_BOTH))
|
||||
arg2 = NULL_TREE;
|
||||
}
|
||||
if (fcodei == END_BUILTINS || arg2)
|
||||
call = build_call_expr_internal_loc (loc, ifn, integer_type_node,
|
||||
arg2 ? 2 : 1, arg0, arg2);
|
||||
else
|
||||
call = build_call_expr_loc (loc, builtin_decl_explicit (fcodei), 1,
|
||||
arg0);
|
||||
}
|
||||
if (addend)
|
||||
call = fold_build2 (PLUS_EXPR, integer_type_node, call,
|
||||
build_int_cst (integer_type_node, addend));
|
||||
if (arg1 && arg2 == NULL_TREE)
|
||||
call = fold_build3 (COND_EXPR, integer_type_node,
|
||||
fold_build2 (NE_EXPR, boolean_type_node,
|
||||
arg0, build_zero_cst (arg0_type)),
|
||||
call, arg1);
|
||||
|
||||
return call;
|
||||
}
|
||||
|
||||
/* Fold __builtin_{add,sub}c{,l,ll} into pair of internal functions
|
||||
that return both result of arithmetics and overflowed boolean
|
||||
flag in a complex integer result. */
|
||||
|
|
@ -9824,6 +10089,14 @@ fold_builtin_1 (location_t loc, tree expr, tree fndecl, tree arg0)
|
|||
return build_empty_stmt (loc);
|
||||
break;
|
||||
|
||||
case BUILT_IN_CLZG:
|
||||
case BUILT_IN_CTZG:
|
||||
case BUILT_IN_CLRSBG:
|
||||
case BUILT_IN_FFSG:
|
||||
case BUILT_IN_PARITYG:
|
||||
case BUILT_IN_POPCOUNTG:
|
||||
return fold_builtin_bit_query (loc, fcode, arg0, NULL_TREE);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -9913,6 +10186,10 @@ fold_builtin_2 (location_t loc, tree expr, tree fndecl, tree arg0, tree arg1)
|
|||
case BUILT_IN_ATOMIC_IS_LOCK_FREE:
|
||||
return fold_builtin_atomic_is_lock_free (arg0, arg1);
|
||||
|
||||
case BUILT_IN_CLZG:
|
||||
case BUILT_IN_CTZG:
|
||||
return fold_builtin_bit_query (loc, fcode, arg0, arg1);
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -962,15 +962,18 @@ DEF_GCC_BUILTIN (BUILT_IN_CLZ, "clz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_
|
|||
DEF_GCC_BUILTIN (BUILT_IN_CLZIMAX, "clzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZL, "clzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZLL, "clzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLZG, "clzg", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CONSTANT_P, "constant_p", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZ, "ctz", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZIMAX, "ctzimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZL, "ctzl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZLL, "ctzll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CTZG, "ctzg", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLRSB, "clrsb", BT_FN_INT_INT, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLRSBIMAX, "clrsbimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLRSBL, "clrsbl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLRSBLL, "clrsbll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_CLRSBG, "clrsbg", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_DCGETTEXT, "dcgettext", BT_FN_STRING_CONST_STRING_CONST_STRING_INT, ATTR_FORMAT_ARG_2)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_DGETTEXT, "dgettext", BT_FN_STRING_CONST_STRING_CONST_STRING, ATTR_FORMAT_ARG_2)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_DWARF_CFA, "dwarf_cfa", BT_FN_PTR, ATTR_NULL)
|
||||
|
|
@ -993,6 +996,7 @@ DEF_EXT_LIB_BUILTIN (BUILT_IN_FFS, "ffs", BT_FN_INT_INT, ATTR_CONST_NOTHROW_L
|
|||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSIMAX, "ffsimax", BT_FN_INT_INTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSL, "ffsl", BT_FN_INT_LONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FFSLL, "ffsll", BT_FN_INT_LONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_FFSG, "ffsg", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_FORK, "fork", BT_FN_PID, ATTR_NOTHROW_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_FRAME_ADDRESS, "frame_address", BT_FN_PTR_UINT, ATTR_NULL)
|
||||
/* [trans-mem]: Adjust BUILT_IN_TM_FREE if BUILT_IN_FREE is changed. */
|
||||
|
|
@ -1041,10 +1045,12 @@ DEF_GCC_BUILTIN (BUILT_IN_PARITY, "parity", BT_FN_INT_UINT, ATTR_CONST_NO
|
|||
DEF_GCC_BUILTIN (BUILT_IN_PARITYIMAX, "parityimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYL, "parityl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYLL, "parityll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PARITYG, "parityg", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNT, "popcount", BT_FN_INT_UINT, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTIMAX, "popcountimax", BT_FN_INT_UINTMAX, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTL, "popcountl", BT_FN_INT_ULONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTLL, "popcountll", BT_FN_INT_ULONGLONG, ATTR_CONST_NOTHROW_LEAF_LIST)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_POPCOUNTG, "popcountg", BT_FN_INT_VAR, ATTR_CONST_NOTHROW_TYPEGENERIC_LEAF)
|
||||
DEF_EXT_LIB_BUILTIN (BUILT_IN_POSIX_MEMALIGN, "posix_memalign", BT_FN_INT_PTRPTR_SIZE_SIZE, ATTR_NOTHROW_NONNULL_LEAF)
|
||||
DEF_GCC_BUILTIN (BUILT_IN_PREFETCH, "prefetch", BT_FN_VOID_CONST_PTR_VAR, ATTR_NOVOPS_LEAF_LIST)
|
||||
DEF_LIB_BUILTIN (BUILT_IN_REALLOC, "realloc", BT_FN_PTR_PTR_SIZE, ATTR_ALLOC_WARN_UNUSED_RESULT_SIZE_2_NOTHROW_LEAF_LIST)
|
||||
|
|
|
|||
|
|
@ -1,3 +1,72 @@
|
|||
2023-11-18 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* c-cppbuiltin.cc (c_cpp_builtins): Define
|
||||
__LIBGCC_HAVE_LIBATOMIC for libgcov.
|
||||
|
||||
2023-11-18 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
Revert:
|
||||
2021-08-16 Sebastian Huber <sebastian.huber@embedded-brains.de>
|
||||
|
||||
* c-cppbuiltin.c (c_cpp_builtins): Define
|
||||
__LIBGCC_GCOV_TYPE_SIZE if flag_building_libgcc is true.
|
||||
|
||||
2023-11-17 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c++/107571
|
||||
* c-gimplify.cc (genericize_c_loop): For C++ mark IFN_FALLTHROUGH
|
||||
call at the end of loop body as TREE_NOTHROW.
|
||||
|
||||
2023-11-14 Lewis Hyatt <lhyatt@gmail.com>
|
||||
|
||||
PR pch/9471
|
||||
PR pch/47857
|
||||
* c-opts.cc (c_common_post_options): Set cpp_opts->main_search
|
||||
so libcpp knows it is compiling a header file separately.
|
||||
|
||||
2023-11-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* c-warn.cc (conversion_warning): Update call to
|
||||
global_dc->m_option_enabled to use option_enabled_p.
|
||||
|
||||
2023-11-14 David Malcolm <dmalcolm@redhat.com>
|
||||
|
||||
* c-common.cc (c_get_substring_location): Use global_dc's
|
||||
file_cache.
|
||||
* c-format.cc (get_corrected_substring): Likewise.
|
||||
* c-indentation.cc (get_visual_column): Add file_cache param.
|
||||
(get_first_nws_vis_column): Likewise.
|
||||
(detect_intervening_unindent): Likewise.
|
||||
(should_warn_for_misleading_indentation): Use global_dc's
|
||||
file_cache.
|
||||
(assert_get_visual_column_succeeds): Add file_cache param.
|
||||
(ASSERT_GET_VISUAL_COLUMN_SUCCEEDS): Likewise.
|
||||
(assert_get_visual_column_fails): Likewise.
|
||||
(define ASSERT_GET_VISUAL_COLUMN_FAILS): Likewise.
|
||||
(selftest::test_get_visual_column): Create and use a temporary
|
||||
file_cache.
|
||||
|
||||
2023-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/111309
|
||||
* c-common.cc (check_builtin_function_arguments): Handle
|
||||
BUILT_IN_{CLZ,CTZ,CLRSB,FFS,PARITY,POPCOUNT}G.
|
||||
* c-gimplify.cc (c_gimplify_expr): If __builtin_c[lt]zg second
|
||||
argument hasn't been folded into constant yet, transform it to one
|
||||
argument call inside of a COND_EXPR which for first argument 0
|
||||
returns the second argument.
|
||||
|
||||
2023-11-11 Martin Uecker <uecker@tugraz.at>
|
||||
|
||||
PR c/110815
|
||||
PR c/112428
|
||||
* c-attribs.cc (build_attr_access_from_parms): Synthesize
|
||||
nonnull attribute for parameters declared with `static`.
|
||||
|
||||
2023-11-09 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* c.opt (Wreturn-mismatch): New.
|
||||
|
||||
2023-11-08 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* c.opt (fpermissive): Enable for C and ObjC.
|
||||
|
|
|
|||
|
|
@ -894,7 +894,9 @@ c_get_substring_location (const substring_loc &substr_loc,
|
|||
if (tok_type == CPP_OTHER)
|
||||
return "unrecognized string type";
|
||||
|
||||
return get_location_within_string (parse_in, g_string_concat_db,
|
||||
return get_location_within_string (parse_in,
|
||||
global_dc->get_file_cache (),
|
||||
g_string_concat_db,
|
||||
substr_loc.get_fmt_string_loc (),
|
||||
tok_type,
|
||||
substr_loc.get_caret_idx (),
|
||||
|
|
@ -6475,14 +6477,14 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
|
|||
}
|
||||
if (TREE_CODE (TREE_TYPE (args[2])) == ENUMERAL_TYPE)
|
||||
{
|
||||
error_at (ARG_LOCATION (2), "argument 3 in call to function "
|
||||
"%qE has enumerated type", fndecl);
|
||||
error_at (ARG_LOCATION (2), "argument %u in call to function "
|
||||
"%qE has enumerated type", 3, fndecl);
|
||||
return false;
|
||||
}
|
||||
else if (TREE_CODE (TREE_TYPE (args[2])) == BOOLEAN_TYPE)
|
||||
{
|
||||
error_at (ARG_LOCATION (2), "argument 3 in call to function "
|
||||
"%qE has boolean type", fndecl);
|
||||
error_at (ARG_LOCATION (2), "argument %u in call to function "
|
||||
"%qE has boolean type", 3, fndecl);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
|
@ -6522,6 +6524,72 @@ check_builtin_function_arguments (location_t loc, vec<location_t> arg_loc,
|
|||
}
|
||||
return false;
|
||||
|
||||
case BUILT_IN_CLZG:
|
||||
case BUILT_IN_CTZG:
|
||||
case BUILT_IN_CLRSBG:
|
||||
case BUILT_IN_FFSG:
|
||||
case BUILT_IN_PARITYG:
|
||||
case BUILT_IN_POPCOUNTG:
|
||||
if (nargs == 2
|
||||
&& (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CLZG
|
||||
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CTZG))
|
||||
{
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (args[1])))
|
||||
{
|
||||
error_at (ARG_LOCATION (1), "argument %u in call to function "
|
||||
"%qE does not have integral type", 2, fndecl);
|
||||
return false;
|
||||
}
|
||||
if ((TYPE_PRECISION (TREE_TYPE (args[1]))
|
||||
> TYPE_PRECISION (integer_type_node))
|
||||
|| (TYPE_PRECISION (TREE_TYPE (args[1]))
|
||||
== TYPE_PRECISION (integer_type_node)
|
||||
&& TYPE_UNSIGNED (TREE_TYPE (args[1]))))
|
||||
{
|
||||
error_at (ARG_LOCATION (1), "argument %u in call to function "
|
||||
"%qE does not have %<int%> type", 2, fndecl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!builtin_function_validate_nargs (loc, fndecl, nargs, 1))
|
||||
return false;
|
||||
|
||||
if (!INTEGRAL_TYPE_P (TREE_TYPE (args[0])))
|
||||
{
|
||||
error_at (ARG_LOCATION (0), "argument %u in call to function "
|
||||
"%qE does not have integral type", 1, fndecl);
|
||||
return false;
|
||||
}
|
||||
if (TREE_CODE (TREE_TYPE (args[0])) == ENUMERAL_TYPE)
|
||||
{
|
||||
error_at (ARG_LOCATION (0), "argument %u in call to function "
|
||||
"%qE has enumerated type", 1, fndecl);
|
||||
return false;
|
||||
}
|
||||
if (TREE_CODE (TREE_TYPE (args[0])) == BOOLEAN_TYPE)
|
||||
{
|
||||
error_at (ARG_LOCATION (0), "argument %u in call to function "
|
||||
"%qE has boolean type", 1, fndecl);
|
||||
return false;
|
||||
}
|
||||
if (DECL_FUNCTION_CODE (fndecl) == BUILT_IN_FFSG
|
||||
|| DECL_FUNCTION_CODE (fndecl) == BUILT_IN_CLRSBG)
|
||||
{
|
||||
if (TYPE_UNSIGNED (TREE_TYPE (args[0])))
|
||||
{
|
||||
error_at (ARG_LOCATION (0), "argument 1 in call to function "
|
||||
"%qE has unsigned type", fndecl);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else if (!TYPE_UNSIGNED (TREE_TYPE (args[0])))
|
||||
{
|
||||
error_at (ARG_LOCATION (0), "argument 1 in call to function "
|
||||
"%qE has signed type", fndecl);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1567,8 +1567,8 @@ c_cpp_builtins (cpp_reader *pfile)
|
|||
/* For libgcov. */
|
||||
builtin_define_with_int_value ("__LIBGCC_VTABLE_USES_DESCRIPTORS__",
|
||||
TARGET_VTABLE_USES_DESCRIPTORS);
|
||||
builtin_define_with_int_value ("__LIBGCC_GCOV_TYPE_SIZE",
|
||||
targetm.gcov_type_size());
|
||||
builtin_define_with_int_value ("__LIBGCC_HAVE_LIBATOMIC",
|
||||
targetm.have_libatomic);
|
||||
}
|
||||
|
||||
/* For use in assembly language. */
|
||||
|
|
|
|||
|
|
@ -4570,7 +4570,8 @@ get_corrected_substring (const substring_loc &fmt_loc,
|
|||
if (caret.column > finish.column)
|
||||
return NULL;
|
||||
|
||||
char_span line = location_get_source_line (start.file, start.line);
|
||||
char_span line
|
||||
= global_dc->get_file_cache ().get_source_line (start.file, start.line);
|
||||
if (!line)
|
||||
return NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -307,6 +307,27 @@ genericize_c_loop (tree *stmt_p, location_t start_locus, tree cond, tree body,
|
|||
}
|
||||
|
||||
append_to_statement_list (body, &stmt_list);
|
||||
if (c_dialect_cxx ()
|
||||
&& stmt_list
|
||||
&& TREE_CODE (stmt_list) == STATEMENT_LIST)
|
||||
{
|
||||
tree_stmt_iterator tsi = tsi_last (stmt_list);
|
||||
if (!tsi_end_p (tsi))
|
||||
{
|
||||
tree t = *tsi;
|
||||
while (TREE_CODE (t) == CLEANUP_POINT_EXPR
|
||||
|| TREE_CODE (t) == EXPR_STMT
|
||||
|| CONVERT_EXPR_CODE_P (TREE_CODE (t)))
|
||||
t = TREE_OPERAND (t, 0);
|
||||
/* For C++, if iteration statement body ends with fallthrough
|
||||
statement, mark it such that we diagnose it even if next
|
||||
statement would be labeled statement with case/default label. */
|
||||
if (TREE_CODE (t) == CALL_EXPR
|
||||
&& !CALL_EXPR_FN (t)
|
||||
&& CALL_EXPR_IFN (t) == IFN_FALLTHROUGH)
|
||||
TREE_NOTHROW (t) = 1;
|
||||
}
|
||||
}
|
||||
finish_bc_block (&stmt_list, bc_continue, clab);
|
||||
if (incr)
|
||||
{
|
||||
|
|
@ -818,6 +839,28 @@ c_gimplify_expr (tree *expr_p, gimple_seq *pre_p ATTRIBUTE_UNUSED,
|
|||
break;
|
||||
}
|
||||
|
||||
case CALL_EXPR:
|
||||
{
|
||||
tree fndecl = get_callee_fndecl (*expr_p);
|
||||
if (fndecl
|
||||
&& fndecl_built_in_p (fndecl, BUILT_IN_CLZG, BUILT_IN_CTZG)
|
||||
&& call_expr_nargs (*expr_p) == 2
|
||||
&& TREE_CODE (CALL_EXPR_ARG (*expr_p, 1)) != INTEGER_CST)
|
||||
{
|
||||
tree a = save_expr (CALL_EXPR_ARG (*expr_p, 0));
|
||||
tree c = build_call_expr_loc (EXPR_LOCATION (*expr_p),
|
||||
fndecl, 1, a);
|
||||
*expr_p = build3_loc (EXPR_LOCATION (*expr_p), COND_EXPR,
|
||||
integer_type_node,
|
||||
build2_loc (EXPR_LOCATION (*expr_p),
|
||||
NE_EXPR, boolean_type_node, a,
|
||||
build_zero_cst (TREE_TYPE (a))),
|
||||
c, CALL_EXPR_ARG (*expr_p, 1));
|
||||
return GS_OK;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
default:;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -45,12 +45,13 @@ next_tab_stop (unsigned int vis_column, unsigned int tab_width)
|
|||
on the line (up to or before EXPLOC). */
|
||||
|
||||
static bool
|
||||
get_visual_column (expanded_location exploc,
|
||||
get_visual_column (file_cache &fc,
|
||||
expanded_location exploc,
|
||||
unsigned int *out,
|
||||
unsigned int *first_nws,
|
||||
unsigned int tab_width)
|
||||
{
|
||||
char_span line = location_get_source_line (exploc.file, exploc.line);
|
||||
char_span line = fc.get_source_line (exploc.file, exploc.line);
|
||||
if (!line)
|
||||
return false;
|
||||
if ((size_t)exploc.column > line.length ())
|
||||
|
|
@ -87,13 +88,14 @@ get_visual_column (expanded_location exploc,
|
|||
Otherwise, return false, leaving *FIRST_NWS untouched. */
|
||||
|
||||
static bool
|
||||
get_first_nws_vis_column (const char *file, int line_num,
|
||||
get_first_nws_vis_column (file_cache &fc,
|
||||
const char *file, int line_num,
|
||||
unsigned int *first_nws,
|
||||
unsigned int tab_width)
|
||||
{
|
||||
gcc_assert (first_nws);
|
||||
|
||||
char_span line = location_get_source_line (file, line_num);
|
||||
char_span line = fc.get_source_line (file, line_num);
|
||||
if (!line)
|
||||
return false;
|
||||
unsigned int vis_column = 0;
|
||||
|
|
@ -158,7 +160,8 @@ get_first_nws_vis_column (const char *file, int line_num,
|
|||
Return true if such an unindent/outdent is detected. */
|
||||
|
||||
static bool
|
||||
detect_intervening_unindent (const char *file,
|
||||
detect_intervening_unindent (file_cache &fc,
|
||||
const char *file,
|
||||
int body_line,
|
||||
int next_stmt_line,
|
||||
unsigned int vis_column,
|
||||
|
|
@ -170,7 +173,7 @@ detect_intervening_unindent (const char *file,
|
|||
for (int line = body_line + 1; line < next_stmt_line; line++)
|
||||
{
|
||||
unsigned int line_vis_column;
|
||||
if (get_first_nws_vis_column (file, line, &line_vis_column, tab_width))
|
||||
if (get_first_nws_vis_column (fc, file, line, &line_vis_column, tab_width))
|
||||
if (line_vis_column < vis_column)
|
||||
return true;
|
||||
}
|
||||
|
|
@ -337,6 +340,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
|
|||
if (next_stmt_exploc.file != body_exploc.file)
|
||||
return false;
|
||||
|
||||
file_cache &fc = global_dc->get_file_cache ();
|
||||
|
||||
/* If NEXT_STMT_LOC and BODY_LOC are on the same line, consider
|
||||
the location of the guard.
|
||||
|
||||
|
|
@ -376,7 +381,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
|
|||
gcc_assert (guard_exploc.line == next_stmt_exploc.line);
|
||||
unsigned int guard_vis_column;
|
||||
unsigned int guard_line_first_nws;
|
||||
if (!get_visual_column (guard_exploc,
|
||||
if (!get_visual_column (fc,
|
||||
guard_exploc,
|
||||
&guard_vis_column,
|
||||
&guard_line_first_nws, tab_width))
|
||||
return false;
|
||||
|
|
@ -436,15 +442,18 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
|
|||
the case for input files containing #line directives, and these
|
||||
are often for autogenerated sources (e.g. from .md files), where
|
||||
it's not clear that it's meaningful to look at indentation. */
|
||||
if (!get_visual_column (next_stmt_exploc,
|
||||
if (!get_visual_column (fc,
|
||||
next_stmt_exploc,
|
||||
&next_stmt_vis_column,
|
||||
&next_stmt_line_first_nws, tab_width))
|
||||
return false;
|
||||
if (!get_visual_column (body_exploc,
|
||||
if (!get_visual_column (fc,
|
||||
body_exploc,
|
||||
&body_vis_column,
|
||||
&body_line_first_nws, tab_width))
|
||||
return false;
|
||||
if (!get_visual_column (guard_exploc,
|
||||
if (!get_visual_column (fc,
|
||||
guard_exploc,
|
||||
&guard_vis_column,
|
||||
&guard_line_first_nws, tab_width))
|
||||
return false;
|
||||
|
|
@ -528,7 +537,8 @@ should_warn_for_misleading_indentation (const token_indent_info &guard_tinfo,
|
|||
|
||||
/* Don't warn if there is an unindent between the two statements. */
|
||||
int vis_column = MIN (next_stmt_vis_column, body_vis_column);
|
||||
if (detect_intervening_unindent (body_exploc.file, body_exploc.line,
|
||||
if (detect_intervening_unindent (fc,
|
||||
body_exploc.file, body_exploc.line,
|
||||
next_stmt_exploc.line,
|
||||
vis_column, tab_width))
|
||||
return false;
|
||||
|
|
@ -686,6 +696,7 @@ test_next_tab_stop ()
|
|||
|
||||
static void
|
||||
assert_get_visual_column_succeeds (const location &loc,
|
||||
file_cache &fc,
|
||||
const char *file, int line, int column,
|
||||
const unsigned int tab_width,
|
||||
unsigned int expected_visual_column,
|
||||
|
|
@ -699,7 +710,8 @@ assert_get_visual_column_succeeds (const location &loc,
|
|||
exploc.sysp = false;
|
||||
unsigned int actual_visual_column;
|
||||
unsigned int actual_first_nws;
|
||||
bool result = get_visual_column (exploc,
|
||||
bool result = get_visual_column (fc,
|
||||
exploc,
|
||||
&actual_visual_column,
|
||||
&actual_first_nws, tab_width);
|
||||
ASSERT_TRUE_AT (loc, result);
|
||||
|
|
@ -710,12 +722,14 @@ assert_get_visual_column_succeeds (const location &loc,
|
|||
/* Verify that the given call to get_visual_column succeeds, with
|
||||
the given results. */
|
||||
|
||||
#define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILENAME, LINE, COLUMN, \
|
||||
#define ASSERT_GET_VISUAL_COLUMN_SUCCEEDS(FILE_CACHE, \
|
||||
FILENAME, LINE, COLUMN, \
|
||||
TAB_WIDTH, \
|
||||
EXPECTED_VISUAL_COLUMN, \
|
||||
EXPECTED_FIRST_NWS) \
|
||||
SELFTEST_BEGIN_STMT \
|
||||
assert_get_visual_column_succeeds (SELFTEST_LOCATION, \
|
||||
FILE_CACHE, \
|
||||
FILENAME, LINE, COLUMN, \
|
||||
TAB_WIDTH, \
|
||||
EXPECTED_VISUAL_COLUMN, \
|
||||
|
|
@ -726,6 +740,7 @@ assert_get_visual_column_succeeds (const location &loc,
|
|||
|
||||
static void
|
||||
assert_get_visual_column_fails (const location &loc,
|
||||
file_cache &fc,
|
||||
const char *file, int line, int column,
|
||||
const unsigned int tab_width)
|
||||
{
|
||||
|
|
@ -737,7 +752,8 @@ assert_get_visual_column_fails (const location &loc,
|
|||
exploc.sysp = false;
|
||||
unsigned int actual_visual_column;
|
||||
unsigned int actual_first_nws;
|
||||
bool result = get_visual_column (exploc,
|
||||
bool result = get_visual_column (fc,
|
||||
exploc,
|
||||
&actual_visual_column,
|
||||
&actual_first_nws, tab_width);
|
||||
ASSERT_FALSE_AT (loc, result);
|
||||
|
|
@ -745,10 +761,12 @@ assert_get_visual_column_fails (const location &loc,
|
|||
|
||||
/* Verify that the given call to get_visual_column fails gracefully. */
|
||||
|
||||
#define ASSERT_GET_VISUAL_COLUMN_FAILS(FILENAME, LINE, COLUMN, \
|
||||
#define ASSERT_GET_VISUAL_COLUMN_FAILS(FILE_CACHE, \
|
||||
FILENAME, LINE, COLUMN, \
|
||||
TAB_WIDTH) \
|
||||
SELFTEST_BEGIN_STMT \
|
||||
assert_get_visual_column_fails (SELFTEST_LOCATION, \
|
||||
FILE_CACHE, \
|
||||
FILENAME, LINE, COLUMN, \
|
||||
TAB_WIDTH); \
|
||||
SELFTEST_END_STMT
|
||||
|
|
@ -770,6 +788,7 @@ test_get_visual_column ()
|
|||
"\t line 2\n");
|
||||
line_table_test ltt;
|
||||
temp_source_file tmp (SELFTEST_LOCATION, ".txt", content);
|
||||
file_cache fc;
|
||||
|
||||
const unsigned int tab_width = 8;
|
||||
const char *file = tmp.get_filename ();
|
||||
|
|
@ -777,27 +796,27 @@ test_get_visual_column ()
|
|||
/* Line 1 (space-based indentation). */
|
||||
{
|
||||
const int line = 1;
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 1, 1);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 2, 2);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 1, tab_width, 0, 0);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 2, tab_width, 1, 1);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 3, tab_width, 2, 2);
|
||||
/* first_nws should have stopped increasing. */
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 3, 2);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 4, tab_width, 3, 2);
|
||||
/* Verify the end-of-line boundary. */
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 7, 2);
|
||||
ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 8, tab_width, 7, 2);
|
||||
ASSERT_GET_VISUAL_COLUMN_FAILS (fc, file, line, 9, tab_width);
|
||||
}
|
||||
|
||||
/* Line 2 (tab-based indentation). */
|
||||
{
|
||||
const int line = 2;
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 1, tab_width, 0, 0);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 2, tab_width, 8, 8);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 3, tab_width, 9, 9);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 1, tab_width, 0, 0);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 2, tab_width, 8, 8);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 3, tab_width, 9, 9);
|
||||
/* first_nws should have stopped increasing. */
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 4, tab_width, 10, 9);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 4, tab_width, 10, 9);
|
||||
/* Verify the end-of-line boundary. */
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (file, line, 8, tab_width, 14, 9);
|
||||
ASSERT_GET_VISUAL_COLUMN_FAILS (file, line, 9, tab_width);
|
||||
ASSERT_GET_VISUAL_COLUMN_SUCCEEDS (fc, file, line, 8, tab_width, 14, 9);
|
||||
ASSERT_GET_VISUAL_COLUMN_FAILS (fc, file, line, 9, tab_width);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "file-prefix-map.h" /* remap_macro_filename() */
|
||||
#include "langhooks.h"
|
||||
#include "attribs.h"
|
||||
#include "rich-location.h"
|
||||
|
||||
/* We may keep statistics about how long which files took to compile. */
|
||||
static int header_time, body_time;
|
||||
|
|
|
|||
|
|
@ -1174,6 +1174,9 @@ c_common_post_options (const char **pfilename)
|
|||
"the %qs debug info cannot be used with "
|
||||
"pre-compiled headers",
|
||||
debug_set_names (write_symbols & ~DWARF2_DEBUG));
|
||||
/* Let libcpp know that the main file is a header so it won't
|
||||
complain about things like #include_next and #pragma once. */
|
||||
cpp_opts->main_search = CMS_header;
|
||||
}
|
||||
else if (write_symbols != NO_DEBUG && write_symbols != DWARF2_DEBUG)
|
||||
c_common_no_more_pch ();
|
||||
|
|
|
|||
|
|
@ -1350,9 +1350,7 @@ conversion_warning (location_t loc, tree type, tree expr, tree result)
|
|||
break;
|
||||
|
||||
if (arith_ops
|
||||
&& global_dc->m_option_enabled (warnopt,
|
||||
global_dc->m_lang_mask,
|
||||
global_dc->m_option_state))
|
||||
&& global_dc->option_enabled_p (warnopt))
|
||||
{
|
||||
for (int i = 0; i < arith_ops; ++i)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1,3 +1,21 @@
|
|||
2023-11-14 Jakub Jelinek <jakub@redhat.com>
|
||||
|
||||
PR c/111309
|
||||
* c-typeck.cc (convert_arguments): Don't promote first argument
|
||||
of BUILT_IN_{CLZ,CTZ,CLRSB,FFS,PARITY,POPCOUNT}G.
|
||||
|
||||
2023-11-10 Martin Uecker <uecker@tugraz.at>
|
||||
|
||||
* c-typeck.cc (struct comptypes_data): Add anon_field flag.
|
||||
(comptypes, comptypes_check_unum_int,
|
||||
comptypes_check_different_types): Remove old cache.
|
||||
(tagged_tu_types_compatible_p): Rewrite.
|
||||
|
||||
2023-11-09 Florian Weimer <fweimer@redhat.com>
|
||||
|
||||
* c-typeck.cc (c_finish_return): Use pedwarn with
|
||||
OPT_Wreturn_mismatch for missing/extra return expressions.
|
||||
|
||||
2023-11-07 Kwok Cheung Yeung <kcy@codesourcery.com>
|
||||
|
||||
* c-decl.cc (c_decl_attributes): Add attribute for indirect
|
||||
|
|
|
|||
|
|
@ -3416,6 +3416,7 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
|
|||
&& lookup_attribute ("type generic", TYPE_ATTRIBUTES (TREE_TYPE (fundecl)));
|
||||
bool type_generic_remove_excess_precision = false;
|
||||
bool type_generic_overflow_p = false;
|
||||
bool type_generic_bit_query = false;
|
||||
tree selector;
|
||||
|
||||
/* Change pointer to function to the function itself for
|
||||
|
|
@ -3471,6 +3472,17 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
|
|||
type_generic_overflow_p = true;
|
||||
break;
|
||||
|
||||
case BUILT_IN_CLZG:
|
||||
case BUILT_IN_CTZG:
|
||||
case BUILT_IN_CLRSBG:
|
||||
case BUILT_IN_FFSG:
|
||||
case BUILT_IN_PARITYG:
|
||||
case BUILT_IN_POPCOUNTG:
|
||||
/* The first argument of these type-generic builtins
|
||||
should not be promoted. */
|
||||
type_generic_bit_query = true;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -3606,11 +3618,13 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree typelist,
|
|||
}
|
||||
}
|
||||
else if ((excess_precision && !type_generic)
|
||||
|| (type_generic_overflow_p && parmnum == 2))
|
||||
|| (type_generic_overflow_p && parmnum == 2)
|
||||
|| (type_generic_bit_query && parmnum == 0))
|
||||
/* A "double" argument with excess precision being passed
|
||||
without a prototype or in variable arguments.
|
||||
The last argument of __builtin_*_overflow_p should not be
|
||||
promoted. */
|
||||
promoted, similarly the first argument of
|
||||
__builtin_{clz,ctz,clrsb,ffs,parity,popcount}g. */
|
||||
parmval = convert (valtype, val);
|
||||
else if ((invalid_func_diag =
|
||||
targetm.calls.invalid_arg_for_unprototyped_fn (typelist, fundecl, val)))
|
||||
|
|
|
|||
|
|
@ -1017,15 +1017,24 @@ riscv_subset_list::parse_std_ext (const char *p)
|
|||
std_ext = *p;
|
||||
|
||||
/* Checking canonical order. */
|
||||
const char *prior_std_exts = std_exts;
|
||||
|
||||
while (*std_exts && std_ext != *std_exts)
|
||||
std_exts++;
|
||||
|
||||
subset[0] = std_ext;
|
||||
if (std_ext != *std_exts && standard_extensions_p (subset))
|
||||
{
|
||||
error_at (m_loc,
|
||||
"%<-march=%s%>: ISA string is not in canonical order. "
|
||||
"%<%c%>",
|
||||
m_arch, *p);
|
||||
/* Extension ordering is invalid. Ignore this extension and keep
|
||||
searching for other issues with remaining extensions. */
|
||||
std_exts = prior_std_exts;
|
||||
p++;
|
||||
continue;
|
||||
}
|
||||
|
||||
std_exts++;
|
||||
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ riscv*)
|
|||
extra_objs="riscv-builtins.o riscv-c.o riscv-sr.o riscv-shorten-memrefs.o riscv-selftests.o riscv-string.o"
|
||||
extra_objs="${extra_objs} riscv-v.o riscv-vsetvl.o riscv-vector-costs.o riscv-avlprop.o"
|
||||
extra_objs="${extra_objs} riscv-vector-builtins.o riscv-vector-builtins-shapes.o riscv-vector-builtins-bases.o"
|
||||
extra_objs="${extra_objs} thead.o"
|
||||
extra_objs="${extra_objs} thead.o riscv-target-attr.o"
|
||||
d_target_objs="riscv-d.o"
|
||||
extra_headers="riscv_vector.h"
|
||||
target_gtfiles="$target_gtfiles \$(srcdir)/config/riscv/riscv-vector-builtins.cc"
|
||||
|
|
@ -571,6 +571,7 @@ s390*-*-*)
|
|||
d_target_objs="s390-d.o"
|
||||
extra_options="${extra_options} fused-madd.opt"
|
||||
extra_headers="s390intrin.h htmintrin.h htmxlintrin.h vecintrin.h"
|
||||
target_gtfiles="./s390-gen-builtins.h"
|
||||
;;
|
||||
# Note the 'l'; we need to be able to match e.g. "shle" or "shl".
|
||||
sh[123456789lbe]*-*-* | sh-*-*)
|
||||
|
|
@ -5038,7 +5039,7 @@ case "${target}" in
|
|||
|
||||
# Perform initial sanity checks on --with-* options.
|
||||
case ${with_arch} in
|
||||
"" | abi-default | loongarch64 | la464) ;; # OK, append here.
|
||||
"" | abi-default | loongarch64 | la[46]64) ;; # OK, append here.
|
||||
native)
|
||||
if test x${host} != x${target}; then
|
||||
echo "--with-arch=native is illegal for cross-compiler." 1>&2
|
||||
|
|
@ -5087,7 +5088,7 @@ case "${target}" in
|
|||
case ${abi_base}/${abi_ext} in
|
||||
lp64*/base)
|
||||
# architectures that support lp64* ABI
|
||||
arch_pattern="native|abi-default|loongarch64|la464"
|
||||
arch_pattern="native|abi-default|loongarch64|la[46]64"
|
||||
# default architecture for lp64* ABI
|
||||
arch_default="abi-default"
|
||||
;;
|
||||
|
|
@ -5162,7 +5163,7 @@ case "${target}" in
|
|||
# Check default with_tune configuration using with_arch.
|
||||
case ${with_arch} in
|
||||
loongarch64)
|
||||
tune_pattern="native|abi-default|loongarch64|la464"
|
||||
tune_pattern="native|abi-default|loongarch64|la[46]64"
|
||||
;;
|
||||
*)
|
||||
# By default, $with_tune == $with_arch
|
||||
|
|
@ -5218,7 +5219,7 @@ case "${target}" in
|
|||
# Fixed: use the default gcc configuration for all multilib
|
||||
# builds by default.
|
||||
with_multilib_default="" ;;
|
||||
arch,native|arch,loongarch64|arch,la464) # OK, append here.
|
||||
arch,native|arch,loongarch64|arch,la[46]64) # OK, append here.
|
||||
with_multilib_default="/march=${component}" ;;
|
||||
arch,*)
|
||||
with_multilib_default="/march=abi-default"
|
||||
|
|
@ -5306,7 +5307,7 @@ case "${target}" in
|
|||
if test x${parse_state} = x"arch"; then
|
||||
# -march option
|
||||
case ${component} in
|
||||
native | abi-default | loongarch64 | la464) # OK, append here.
|
||||
native | abi-default | loongarch64 | la[46]64) # OK, append here.
|
||||
# Append -march spec for each multilib variant.
|
||||
loongarch_multilib_list_make="${loongarch_multilib_list_make}/march=${component}"
|
||||
parse_state="opts"
|
||||
|
|
|
|||
|
|
@ -386,6 +386,12 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define if your assembler supports conditional branch relaxation. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_AS_COND_BRANCH_RELAXATION
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if your assembler supports the --debug-prefix-map option. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_AS_DEBUG_PREFIX_MAP
|
||||
|
|
@ -775,6 +781,12 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define if your assembler supports call36 relocation. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_AS_SUPPORT_CALL36
|
||||
#endif
|
||||
|
||||
|
||||
/* Define if your assembler and linker support thread-local storage. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_AS_TLS
|
||||
|
|
@ -820,6 +832,20 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if you have the Mac OS X function
|
||||
CFLocaleCopyPreferredLanguages in the CoreFoundation framework. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_CFLOCALECOPYPREFERREDLANGUAGES
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if you have the Mac OS X function CFPreferencesCopyAppValue in
|
||||
the CoreFoundation framework. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_CFPREFERENCESCOPYAPPVALUE
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if you have the `clearerr_unlocked' function. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_CLEARERR_UNLOCKED
|
||||
|
|
@ -844,6 +870,13 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define if the GNU dcgettext() function is already present or preinstalled.
|
||||
*/
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_DCGETTEXT
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if we found a declaration for 'abort', otherwise define to 0.
|
||||
*/
|
||||
#ifndef USED_FOR_TARGET
|
||||
|
|
@ -1516,6 +1549,12 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define if the GNU gettext() function is already present or preinstalled. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_GETTEXT
|
||||
#endif
|
||||
|
||||
|
||||
/* Define to 1 if you have the `gettimeofday' function. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_GETTIMEOFDAY
|
||||
|
|
@ -1547,7 +1586,7 @@
|
|||
#endif
|
||||
|
||||
|
||||
/* Define if you have the iconv() function. */
|
||||
/* Define if you have the iconv() function and it works. */
|
||||
#ifndef USED_FOR_TARGET
|
||||
#undef HAVE_ICONV
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -13695,8 +13695,11 @@ mve_vector_mem_operand (machine_mode mode, rtx op, bool strict)
|
|||
}
|
||||
code = GET_CODE (op);
|
||||
|
||||
if (code == POST_INC || code == PRE_DEC
|
||||
|| code == PRE_INC || code == POST_DEC)
|
||||
if ((code == POST_INC
|
||||
|| code == PRE_DEC
|
||||
|| code == PRE_INC
|
||||
|| code == POST_DEC)
|
||||
&& REG_P (XEXP (op, 0)))
|
||||
{
|
||||
reg_no = arm_effective_regno (XEXP (op, 0), strict);
|
||||
return (((mode == E_V8QImode || mode == E_V4QImode || mode == E_V4HImode)
|
||||
|
|
|
|||
|
|
@ -10873,7 +10873,12 @@ avr_asm_init_sections (void)
|
|||
static void
|
||||
avr_asm_named_section (const char *name, unsigned int flags, tree decl)
|
||||
{
|
||||
if (flags & AVR_SECTION_PROGMEM)
|
||||
if (flags & AVR_SECTION_PROGMEM
|
||||
// Only use section .progmem*.data if there is no attribute section.
|
||||
&& ! (decl
|
||||
&& DECL_SECTION_NAME (decl)
|
||||
&& symtab_node::get (decl)
|
||||
&& ! symtab_node::get (decl)->implicit_section))
|
||||
{
|
||||
addr_space_t as = (flags & AVR_SECTION_PROGMEM) / SECTION_MACH_DEP;
|
||||
const char *old_prefix = ".rodata";
|
||||
|
|
@ -10942,6 +10947,7 @@ avr_section_type_flags (tree decl, const char *name, int reloc)
|
|||
flags |= as * SECTION_MACH_DEP;
|
||||
flags &= ~SECTION_WRITE;
|
||||
flags &= ~SECTION_BSS;
|
||||
flags &= ~SECTION_NOTYPE;
|
||||
}
|
||||
|
||||
return flags;
|
||||
|
|
|
|||
|
|
@ -77,6 +77,9 @@
|
|||
(define_register_constraint "v" "VGPR_REGS"
|
||||
"VGPR registers")
|
||||
|
||||
(define_register_constraint "a" "TARGET_CDNA1_PLUS ? AVGPR_REGS : NO_REGS"
|
||||
"Accumulator VGPR registers")
|
||||
|
||||
(define_register_constraint "Sg" "SGPR_REGS"
|
||||
"SGPR registers")
|
||||
|
||||
|
|
|
|||
|
|
@ -449,12 +449,16 @@
|
|||
(set_attr "length" "0")])
|
||||
|
||||
(define_insn "*mov<mode>"
|
||||
[(set (match_operand:V_1REG 0 "nonimmediate_operand" "=v,v")
|
||||
(match_operand:V_1REG 1 "general_operand" "vA,B"))]
|
||||
[(set (match_operand:V_1REG 0 "nonimmediate_operand")
|
||||
(match_operand:V_1REG 1 "general_operand"))]
|
||||
""
|
||||
"v_mov_b32\t%0, %1"
|
||||
[(set_attr "type" "vop1,vop1")
|
||||
(set_attr "length" "4,8")])
|
||||
{@ [cons: =0, 1; attrs: type, length, gcn_version]
|
||||
[v ,vA;vop1 ,4,* ] v_mov_b32\t%0, %1
|
||||
[v ,B ;vop1 ,8,* ] ^
|
||||
[v ,a ;vop3p_mai,8,* ] v_accvgpr_read_b32\t%0, %1
|
||||
[$a ,v ;vop3p_mai,8,* ] v_accvgpr_write_b32\t%0, %1
|
||||
[a ,a ;vop1 ,4,cdna2] v_accvgpr_mov_b32\t%0, %1
|
||||
})
|
||||
|
||||
(define_insn "mov<mode>_exec"
|
||||
[(set (match_operand:V_1REG 0 "nonimmediate_operand")
|
||||
|
|
@ -493,17 +497,29 @@
|
|||
; (set_attr "length" "4,8,16,16")])
|
||||
|
||||
(define_insn "*mov<mode>"
|
||||
[(set (match_operand:V_2REG 0 "nonimmediate_operand" "=v")
|
||||
(match_operand:V_2REG 1 "general_operand" "vDB"))]
|
||||
[(set (match_operand:V_2REG 0 "nonimmediate_operand" "=v, v,$a,a")
|
||||
(match_operand:V_2REG 1 "general_operand" "vDB,a, v,a"))]
|
||||
""
|
||||
{
|
||||
if (!REG_P (operands[1]) || REGNO (operands[0]) <= REGNO (operands[1]))
|
||||
return "v_mov_b32\t%L0, %L1\;v_mov_b32\t%H0, %H1";
|
||||
else
|
||||
return "v_mov_b32\t%H0, %H1\;v_mov_b32\t%L0, %L1";
|
||||
}
|
||||
[(set_attr "type" "vmult")
|
||||
(set_attr "length" "16")])
|
||||
"@
|
||||
* if (!REG_P (operands[1]) || REGNO (operands[0]) <= REGNO (operands[1])) \
|
||||
return \"v_mov_b32\t%L0, %L1\;v_mov_b32\t%H0, %H1\"; \
|
||||
else \
|
||||
return \"v_mov_b32\t%H0, %H1\;v_mov_b32\t%L0, %L1\";
|
||||
* if (REGNO (operands[0]) <= REGNO (operands[1])) \
|
||||
return \"v_accvgpr_read_b32\t%L0, %L1\;v_accvgpr_read_b32\t%H0, %H1\"; \
|
||||
else \
|
||||
return \"v_accvgpr_read_b32\t%H0, %H1\;v_accvgpr_read_b32\t%L0, %L1\";
|
||||
* if (REGNO (operands[0]) <= REGNO (operands[1])) \
|
||||
return \"v_accvgpr_write_b32\t%L0, %L1\;v_accvgpr_write_b32\t%H0, %H1\"; \
|
||||
else \
|
||||
return \"v_accvgpr_write_b32\t%H0, %H1\;v_accvgpr_write_b32\t%L0, %L1\";
|
||||
* if (REGNO (operands[0]) <= REGNO (operands[1])) \
|
||||
return \"v_accvgpr_mov_b32\t%L0, %L1\;v_accvgpr_mov_b32\t%H0, %H1\"; \
|
||||
else \
|
||||
return \"v_accvgpr_mov_b32\t%H0, %H1\;v_accvgpr_mov_b32\t%L0, %L1\";"
|
||||
[(set_attr "type" "vmult,vmult,vmult,vmult")
|
||||
(set_attr "length" "16,16,16,8")
|
||||
(set_attr "gcn_version" "*,*,*,cdna2")])
|
||||
|
||||
(define_insn "mov<mode>_exec"
|
||||
[(set (match_operand:V_2REG 0 "nonimmediate_operand" "= v, v, v, v, m")
|
||||
|
|
@ -546,17 +562,15 @@
|
|||
(set_attr "length" "16,16,16,16,16")])
|
||||
|
||||
(define_insn "*mov<mode>_4reg"
|
||||
[(set (match_operand:V_4REG 0 "nonimmediate_operand" "=v")
|
||||
(match_operand:V_4REG 1 "general_operand" "vDB"))]
|
||||
[(set (match_operand:V_4REG 0 "nonimmediate_operand")
|
||||
(match_operand:V_4REG 1 "general_operand"))]
|
||||
""
|
||||
{
|
||||
return "v_mov_b32\t%L0, %L1\;"
|
||||
"v_mov_b32\t%H0, %H1\;"
|
||||
"v_mov_b32\t%J0, %J1\;"
|
||||
"v_mov_b32\t%K0, %K1\;";
|
||||
}
|
||||
[(set_attr "type" "vmult")
|
||||
(set_attr "length" "16")])
|
||||
{@ [cons: =0, 1; attrs: type, length, gcn_version]
|
||||
[v,vDB;vmult,16,* ] v_mov_b32\t%L0, %L1\; v_mov_b32\t%H0, %H1\; v_mov_b32\t%J0, %J1\; v_mov_b32\t%K0, %K1
|
||||
[v,a ;vmult,32,* ] v_accvgpr_read_b32\t%L0, %L1\; v_accvgpr_read_b32\t%H0, %H1\; v_accvgpr_read_b32\t%J0, %J1\; v_accvgpr_read_b32\t%K0, %K1
|
||||
[a,v ;vmult,32,* ] v_accvgpr_write_b32\t%L0, %L1\;v_accvgpr_write_b32\t%H0, %H1\;v_accvgpr_write_b32\t%J0, %J1\;v_accvgpr_write_b32\t%K0, %K1
|
||||
[a,a ;vmult,32,cdna2] v_accvgpr_mov_b32\t%L0, %L1\; v_accvgpr_mov_b32\t%H0, %H1\; v_accvgpr_mov_b32\t%J0, %J1\; v_accvgpr_mov_b32\t%K0, %K1
|
||||
})
|
||||
|
||||
(define_insn "mov<mode>_exec"
|
||||
[(set (match_operand:V_4REG 0 "nonimmediate_operand" "= v, v, v, v, m")
|
||||
|
|
@ -641,26 +655,28 @@
|
|||
; vT += Sv
|
||||
; flat_load v, vT
|
||||
|
||||
(define_insn "mov<mode>_sgprbase"
|
||||
(define_insn "@mov<mode>_sgprbase"
|
||||
[(set (match_operand:V_1REG 0 "nonimmediate_operand")
|
||||
(unspec:V_1REG
|
||||
[(match_operand:V_1REG 1 "general_operand")]
|
||||
UNSPEC_SGPRBASE))
|
||||
(clobber (match_operand:<VnDI> 2 "register_operand"))]
|
||||
"lra_in_progress || reload_completed"
|
||||
{@ [cons: =0, 1, =2; attrs: type, length]
|
||||
[v,vA,&v;vop1,4 ] v_mov_b32\t%0, %1
|
||||
[v,vB,&v;vop1,8 ] ^
|
||||
[v,m ,&v;* ,12] #
|
||||
[m,v ,&v;* ,12] #
|
||||
{@ [cons: =0, 1, =2; attrs: type, length, gcn_version]
|
||||
[v,vA,&v;vop1,4 ,* ] v_mov_b32\t%0, %1
|
||||
[v,vB,&v;vop1,8 ,* ] ^
|
||||
[v,m ,&v;* ,12,* ] #
|
||||
[m,v ,&v;* ,12,* ] #
|
||||
[a,m ,&v;* ,12,cdna2] #
|
||||
[m,a ,&v;* ,12,cdna2] #
|
||||
})
|
||||
|
||||
(define_insn "mov<mode>_sgprbase"
|
||||
[(set (match_operand:V_2REG 0 "nonimmediate_operand" "= v, v, m")
|
||||
(define_insn "@mov<mode>_sgprbase"
|
||||
[(set (match_operand:V_2REG 0 "nonimmediate_operand" "= v, v, m, a, m")
|
||||
(unspec:V_2REG
|
||||
[(match_operand:V_2REG 1 "general_operand" "vDB, m, v")]
|
||||
[(match_operand:V_2REG 1 "general_operand" "vDB, m, v, m, a")]
|
||||
UNSPEC_SGPRBASE))
|
||||
(clobber (match_operand:<VnDI> 2 "register_operand" "=&v,&v,&v"))]
|
||||
(clobber (match_operand:<VnDI> 2 "register_operand" "=&v,&v,&v,&v,&v"))]
|
||||
"lra_in_progress || reload_completed"
|
||||
"@
|
||||
* if (!REG_P (operands[1]) || REGNO (operands[0]) <= REGNO (operands[1])) \
|
||||
|
|
@ -668,11 +684,14 @@
|
|||
else \
|
||||
return \"v_mov_b32\t%H0, %H1\;v_mov_b32\t%L0, %L1\";
|
||||
#
|
||||
#
|
||||
#
|
||||
#"
|
||||
[(set_attr "type" "vmult,*,*")
|
||||
(set_attr "length" "8,12,12")])
|
||||
[(set_attr "type" "vmult,*,*,*,*")
|
||||
(set_attr "length" "8,12,12,12,12")
|
||||
(set_attr "gcn_version" "*,*,*,cdna2,cdna2")])
|
||||
|
||||
(define_insn "mov<mode>_sgprbase"
|
||||
(define_insn "@mov<mode>_sgprbase"
|
||||
[(set (match_operand:V_4REG 0 "nonimmediate_operand")
|
||||
(unspec:V_4REG
|
||||
[(match_operand:V_4REG 1 "general_operand")]
|
||||
|
|
@ -685,31 +704,6 @@
|
|||
[m,v ,&v;* ,12] #
|
||||
})
|
||||
|
||||
; reload_in was once a standard name, but here it's only referenced by
|
||||
; gcn_secondary_reload. It allows a reload with a scratch register.
|
||||
|
||||
(define_expand "reload_in<mode>"
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "= v")
|
||||
(match_operand:V_MOV 1 "memory_operand" " m"))
|
||||
(clobber (match_operand:<VnDI> 2 "register_operand" "=&v"))]
|
||||
""
|
||||
{
|
||||
emit_insn (gen_mov<mode>_sgprbase (operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
; reload_out is similar to reload_in, above.
|
||||
|
||||
(define_expand "reload_out<mode>"
|
||||
[(set (match_operand:V_MOV 0 "memory_operand" "= m")
|
||||
(match_operand:V_MOV 1 "register_operand" " v"))
|
||||
(clobber (match_operand:<VnDI> 2 "register_operand" "=&v"))]
|
||||
""
|
||||
{
|
||||
emit_insn (gen_mov<mode>_sgprbase (operands[0], operands[1], operands[2]));
|
||||
DONE;
|
||||
})
|
||||
|
||||
; Expand scalar addresses into gather/scatter patterns
|
||||
|
||||
(define_split
|
||||
|
|
@ -1151,13 +1145,13 @@
|
|||
{})
|
||||
|
||||
(define_insn "gather<mode>_insn_1offset<exec>"
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "=v")
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "=v,a")
|
||||
(unspec:V_MOV
|
||||
[(plus:<VnDI> (match_operand:<VnDI> 1 "register_operand" " v")
|
||||
[(plus:<VnDI> (match_operand:<VnDI> 1 "register_operand" " v,v")
|
||||
(vec_duplicate:<VnDI>
|
||||
(match_operand 2 "immediate_operand" " n")))
|
||||
(match_operand 3 "immediate_operand" " n")
|
||||
(match_operand 4 "immediate_operand" " n")
|
||||
(match_operand 2 "immediate_operand" " n,n")))
|
||||
(match_operand 3 "immediate_operand" " n,n")
|
||||
(match_operand 4 "immediate_operand" " n,n")
|
||||
(mem:BLK (scratch))]
|
||||
UNSPEC_GATHER))]
|
||||
"(AS_FLAT_P (INTVAL (operands[3]))
|
||||
|
|
@ -1187,16 +1181,17 @@
|
|||
return buf;
|
||||
}
|
||||
[(set_attr "type" "flat")
|
||||
(set_attr "length" "12")])
|
||||
(set_attr "length" "12")
|
||||
(set_attr "gcn_version" "*,cdna2")])
|
||||
|
||||
(define_insn "gather<mode>_insn_1offset_ds<exec>"
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "=v")
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "=v,a")
|
||||
(unspec:V_MOV
|
||||
[(plus:<VnSI> (match_operand:<VnSI> 1 "register_operand" " v")
|
||||
[(plus:<VnSI> (match_operand:<VnSI> 1 "register_operand" " v,v")
|
||||
(vec_duplicate:<VnSI>
|
||||
(match_operand 2 "immediate_operand" " n")))
|
||||
(match_operand 3 "immediate_operand" " n")
|
||||
(match_operand 4 "immediate_operand" " n")
|
||||
(match_operand 2 "immediate_operand" " n,n")))
|
||||
(match_operand 3 "immediate_operand" " n,n")
|
||||
(match_operand 4 "immediate_operand" " n,n")
|
||||
(mem:BLK (scratch))]
|
||||
UNSPEC_GATHER))]
|
||||
"(AS_ANY_DS_P (INTVAL (operands[3]))
|
||||
|
|
@ -1209,20 +1204,22 @@
|
|||
return buf;
|
||||
}
|
||||
[(set_attr "type" "ds")
|
||||
(set_attr "length" "12")])
|
||||
(set_attr "length" "12")
|
||||
(set_attr "gcn_version" "*,cdna2")])
|
||||
|
||||
(define_insn "gather<mode>_insn_2offsets<exec>"
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "=v")
|
||||
[(set (match_operand:V_MOV 0 "register_operand" "=v,a")
|
||||
(unspec:V_MOV
|
||||
[(plus:<VnDI>
|
||||
(plus:<VnDI>
|
||||
(vec_duplicate:<VnDI>
|
||||
(match_operand:DI 1 "register_operand" "Sv"))
|
||||
(match_operand:DI 1 "register_operand" "Sv,Sv"))
|
||||
(sign_extend:<VnDI>
|
||||
(match_operand:<VnSI> 2 "register_operand" " v")))
|
||||
(vec_duplicate:<VnDI> (match_operand 3 "immediate_operand" " n")))
|
||||
(match_operand 4 "immediate_operand" " n")
|
||||
(match_operand 5 "immediate_operand" " n")
|
||||
(match_operand:<VnSI> 2 "register_operand" " v,v")))
|
||||
(vec_duplicate:<VnDI> (match_operand 3 "immediate_operand"
|
||||
" n,n")))
|
||||
(match_operand 4 "immediate_operand" " n,n")
|
||||
(match_operand 5 "immediate_operand" " n,n")
|
||||
(mem:BLK (scratch))]
|
||||
UNSPEC_GATHER))]
|
||||
"(AS_GLOBAL_P (INTVAL (operands[4]))
|
||||
|
|
@ -1241,7 +1238,8 @@
|
|||
return buf;
|
||||
}
|
||||
[(set_attr "type" "flat")
|
||||
(set_attr "length" "12")])
|
||||
(set_attr "length" "12")
|
||||
(set_attr "gcn_version" "*,cdna2")])
|
||||
|
||||
(define_expand "scatter_store<mode><vnsi>"
|
||||
[(match_operand:DI 0 "register_operand")
|
||||
|
|
@ -1280,12 +1278,12 @@
|
|||
(define_insn "scatter<mode>_insn_1offset<exec_scatter>"
|
||||
[(set (mem:BLK (scratch))
|
||||
(unspec:BLK
|
||||
[(plus:<VnDI> (match_operand:<VnDI> 0 "register_operand" "v")
|
||||
[(plus:<VnDI> (match_operand:<VnDI> 0 "register_operand" "v,v")
|
||||
(vec_duplicate:<VnDI>
|
||||
(match_operand 1 "immediate_operand" "n")))
|
||||
(match_operand:V_MOV 2 "register_operand" "v")
|
||||
(match_operand 3 "immediate_operand" "n")
|
||||
(match_operand 4 "immediate_operand" "n")]
|
||||
(match_operand 1 "immediate_operand" "n,n")))
|
||||
(match_operand:V_MOV 2 "register_operand" "v,a")
|
||||
(match_operand 3 "immediate_operand" "n,n")
|
||||
(match_operand 4 "immediate_operand" "n,n")]
|
||||
UNSPEC_SCATTER))]
|
||||
"(AS_FLAT_P (INTVAL (operands[3]))
|
||||
&& (INTVAL(operands[1]) == 0
|
||||
|
|
@ -1313,17 +1311,18 @@
|
|||
return buf;
|
||||
}
|
||||
[(set_attr "type" "flat")
|
||||
(set_attr "length" "12")])
|
||||
(set_attr "length" "12")
|
||||
(set_attr "gcn_version" "*,cdna2")])
|
||||
|
||||
(define_insn "scatter<mode>_insn_1offset_ds<exec_scatter>"
|
||||
[(set (mem:BLK (scratch))
|
||||
(unspec:BLK
|
||||
[(plus:<VnSI> (match_operand:<VnSI> 0 "register_operand" "v")
|
||||
[(plus:<VnSI> (match_operand:<VnSI> 0 "register_operand" "v,v")
|
||||
(vec_duplicate:<VnSI>
|
||||
(match_operand 1 "immediate_operand" "n")))
|
||||
(match_operand:V_MOV 2 "register_operand" "v")
|
||||
(match_operand 3 "immediate_operand" "n")
|
||||
(match_operand 4 "immediate_operand" "n")]
|
||||
(match_operand 1 "immediate_operand" "n,n")))
|
||||
(match_operand:V_MOV 2 "register_operand" "v,a")
|
||||
(match_operand 3 "immediate_operand" "n,n")
|
||||
(match_operand 4 "immediate_operand" "n,n")]
|
||||
UNSPEC_SCATTER))]
|
||||
"(AS_ANY_DS_P (INTVAL (operands[3]))
|
||||
&& ((unsigned HOST_WIDE_INT)INTVAL(operands[1]) < 0x10000))"
|
||||
|
|
@ -1335,7 +1334,8 @@
|
|||
return buf;
|
||||
}
|
||||
[(set_attr "type" "ds")
|
||||
(set_attr "length" "12")])
|
||||
(set_attr "length" "12")
|
||||
(set_attr "gcn_version" "*,cdna2")])
|
||||
|
||||
(define_insn "scatter<mode>_insn_2offsets<exec_scatter>"
|
||||
[(set (mem:BLK (scratch))
|
||||
|
|
@ -1343,13 +1343,13 @@
|
|||
[(plus:<VnDI>
|
||||
(plus:<VnDI>
|
||||
(vec_duplicate:<VnDI>
|
||||
(match_operand:DI 0 "register_operand" "Sv"))
|
||||
(match_operand:DI 0 "register_operand" "Sv,Sv"))
|
||||
(sign_extend:<VnDI>
|
||||
(match_operand:<VnSI> 1 "register_operand" " v")))
|
||||
(vec_duplicate:<VnDI> (match_operand 2 "immediate_operand" " n")))
|
||||
(match_operand:V_MOV 3 "register_operand" " v")
|
||||
(match_operand 4 "immediate_operand" " n")
|
||||
(match_operand 5 "immediate_operand" " n")]
|
||||
(match_operand:<VnSI> 1 "register_operand" "v,v")))
|
||||
(vec_duplicate:<VnDI> (match_operand 2 "immediate_operand" "n,n")))
|
||||
(match_operand:V_MOV 3 "register_operand" "v,a")
|
||||
(match_operand 4 "immediate_operand" "n,n")
|
||||
(match_operand 5 "immediate_operand" "n,n")]
|
||||
UNSPEC_SCATTER))]
|
||||
"(AS_GLOBAL_P (INTVAL (operands[4]))
|
||||
&& (((unsigned HOST_WIDE_INT)INTVAL(operands[2]) + 0x1000) < 0x2000))"
|
||||
|
|
@ -1366,7 +1366,8 @@
|
|||
return buf;
|
||||
}
|
||||
[(set_attr "type" "flat")
|
||||
(set_attr "length" "12")])
|
||||
(set_attr "length" "12")
|
||||
(set_attr "gcn_version" "*,cdna2")])
|
||||
|
||||
;; }}}
|
||||
;; {{{ Permutations
|
||||
|
|
|
|||
|
|
@ -96,6 +96,7 @@ static hash_map<tree, int> lds_allocs;
|
|||
|
||||
#define MAX_NORMAL_SGPR_COUNT 62 // i.e. 64 with VCC
|
||||
#define MAX_NORMAL_VGPR_COUNT 24
|
||||
#define MAX_NORMAL_AVGPR_COUNT 24
|
||||
|
||||
/* }}} */
|
||||
/* {{{ Initialization and options. */
|
||||
|
|
@ -483,7 +484,8 @@ gcn_class_max_nregs (reg_class_t rclass, machine_mode mode)
|
|||
{
|
||||
/* Scalar registers are 32bit, vector registers are in fact tuples of
|
||||
64 lanes. */
|
||||
if (rclass == VGPR_REGS)
|
||||
if (rclass == VGPR_REGS || rclass == AVGPR_REGS
|
||||
|| rclass == ALL_VGPR_REGS)
|
||||
{
|
||||
if (vgpr_1reg_mode_p (mode))
|
||||
return 1;
|
||||
|
|
@ -583,7 +585,7 @@ gcn_hard_regno_mode_ok (unsigned int regno, machine_mode mode)
|
|||
return (sgpr_1reg_mode_p (mode)
|
||||
|| (!((regno - FIRST_SGPR_REG) & 1) && sgpr_2reg_mode_p (mode))
|
||||
|| (((regno - FIRST_SGPR_REG) & 3) == 0 && mode == TImode));
|
||||
if (VGPR_REGNO_P (regno))
|
||||
if (VGPR_REGNO_P (regno) || (AVGPR_REGNO_P (regno) && TARGET_CDNA1_PLUS))
|
||||
/* Vector instructions do not care about the alignment of register
|
||||
pairs, but where there is no 64-bit instruction, many of the
|
||||
define_split do not work if the input and output registers partially
|
||||
|
|
@ -623,6 +625,8 @@ gcn_regno_reg_class (int regno)
|
|||
}
|
||||
if (VGPR_REGNO_P (regno))
|
||||
return VGPR_REGS;
|
||||
if (AVGPR_REGNO_P (regno))
|
||||
return AVGPR_REGS;
|
||||
if (SGPR_REGNO_P (regno))
|
||||
return SGPR_REGS;
|
||||
if (regno < FIRST_VGPR_REG)
|
||||
|
|
@ -813,7 +817,7 @@ gcn_spill_class (reg_class_t c, machine_mode /*mode */ )
|
|||
|| c == VCC_CONDITIONAL_REG || c == EXEC_MASK_REG)
|
||||
return SGPR_REGS;
|
||||
else
|
||||
return NO_REGS;
|
||||
return c == VGPR_REGS && TARGET_CDNA1_PLUS ? AVGPR_REGS : NO_REGS;
|
||||
}
|
||||
|
||||
/* Implement TARGET_IRA_CHANGE_PSEUDO_ALLOCNO_CLASS.
|
||||
|
|
@ -1388,64 +1392,6 @@ GEN_VN_NOEXEC (vec_series,si, A(rtx dest, rtx x, rtx c), A(dest, x, c))
|
|||
#undef GET_VN_FN
|
||||
#undef A
|
||||
|
||||
/* Get icode for vector instructions without an optab. */
|
||||
|
||||
#define CODE_FOR(PREFIX, SUFFIX) \
|
||||
static int \
|
||||
get_code_for_##PREFIX##vN##SUFFIX (int nunits) \
|
||||
{ \
|
||||
switch (nunits) \
|
||||
{ \
|
||||
case 2: return CODE_FOR_##PREFIX##v2##SUFFIX; \
|
||||
case 4: return CODE_FOR_##PREFIX##v4##SUFFIX; \
|
||||
case 8: return CODE_FOR_##PREFIX##v8##SUFFIX; \
|
||||
case 16: return CODE_FOR_##PREFIX##v16##SUFFIX; \
|
||||
case 32: return CODE_FOR_##PREFIX##v32##SUFFIX; \
|
||||
case 64: return CODE_FOR_##PREFIX##v64##SUFFIX; \
|
||||
} \
|
||||
\
|
||||
gcc_unreachable (); \
|
||||
return CODE_FOR_nothing; \
|
||||
}
|
||||
|
||||
#define CODE_FOR_OP(PREFIX) \
|
||||
CODE_FOR (PREFIX, qi) \
|
||||
CODE_FOR (PREFIX, hi) \
|
||||
CODE_FOR (PREFIX, hf) \
|
||||
CODE_FOR (PREFIX, si) \
|
||||
CODE_FOR (PREFIX, sf) \
|
||||
CODE_FOR (PREFIX, di) \
|
||||
CODE_FOR (PREFIX, df) \
|
||||
CODE_FOR (PREFIX, ti) \
|
||||
static int \
|
||||
get_code_for_##PREFIX (machine_mode mode) \
|
||||
{ \
|
||||
int vf = GET_MODE_NUNITS (mode); \
|
||||
machine_mode smode = GET_MODE_INNER (mode); \
|
||||
\
|
||||
switch (smode) \
|
||||
{ \
|
||||
case E_QImode: return get_code_for_##PREFIX##vNqi (vf); \
|
||||
case E_HImode: return get_code_for_##PREFIX##vNhi (vf); \
|
||||
case E_HFmode: return get_code_for_##PREFIX##vNhf (vf); \
|
||||
case E_SImode: return get_code_for_##PREFIX##vNsi (vf); \
|
||||
case E_SFmode: return get_code_for_##PREFIX##vNsf (vf); \
|
||||
case E_DImode: return get_code_for_##PREFIX##vNdi (vf); \
|
||||
case E_DFmode: return get_code_for_##PREFIX##vNdf (vf); \
|
||||
case E_TImode: return get_code_for_##PREFIX##vNti (vf); \
|
||||
default: break; \
|
||||
} \
|
||||
\
|
||||
gcc_unreachable (); \
|
||||
return CODE_FOR_nothing; \
|
||||
}
|
||||
|
||||
CODE_FOR_OP (reload_in)
|
||||
CODE_FOR_OP (reload_out)
|
||||
|
||||
#undef CODE_FOR_OP
|
||||
#undef CODE_FOR
|
||||
|
||||
/* Return true if OP is a PARALLEL of CONST_INTs that form a linear
|
||||
series with step STEP. */
|
||||
|
||||
|
|
@ -2406,12 +2352,15 @@ gcn_sgpr_move_p (rtx op0, rtx op1)
|
|||
return true;
|
||||
if (MEM_P (op1) && AS_SCALAR_FLAT_P (MEM_ADDR_SPACE (op1)))
|
||||
return true;
|
||||
if (!REG_P (op0) || REGNO (op0) >= FIRST_PSEUDO_REGISTER
|
||||
|| VGPR_REGNO_P (REGNO (op0)))
|
||||
if (!REG_P (op0)
|
||||
|| REGNO (op0) >= FIRST_PSEUDO_REGISTER
|
||||
|| VGPR_REGNO_P (REGNO (op0))
|
||||
|| AVGPR_REGNO_P (REGNO (op0)))
|
||||
return false;
|
||||
if (REG_P (op1)
|
||||
&& REGNO (op1) < FIRST_PSEUDO_REGISTER
|
||||
&& !VGPR_REGNO_P (REGNO (op1)))
|
||||
&& !VGPR_REGNO_P (REGNO (op1))
|
||||
&& !AVGPR_REGNO_P (REGNO (op1)))
|
||||
return true;
|
||||
return immediate_operand (op1, VOIDmode) || memory_operand (op1, VOIDmode);
|
||||
}
|
||||
|
|
@ -2472,10 +2421,7 @@ gcn_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
|
|||
if (GET_MODE_CLASS (reload_mode) == MODE_VECTOR_INT
|
||||
|| GET_MODE_CLASS (reload_mode) == MODE_VECTOR_FLOAT)
|
||||
{
|
||||
if (in_p)
|
||||
sri->icode = get_code_for_reload_in (reload_mode);
|
||||
else
|
||||
sri->icode = get_code_for_reload_out (reload_mode);
|
||||
sri->icode = code_for_mov_sgprbase (reload_mode);
|
||||
break;
|
||||
}
|
||||
/* Fallthrough. */
|
||||
|
|
@ -2485,6 +2431,11 @@ gcn_secondary_reload (bool in_p, rtx x, reg_class_t rclass,
|
|||
result = (rclass == VGPR_REGS ? NO_REGS : VGPR_REGS);
|
||||
break;
|
||||
}
|
||||
|
||||
/* CDNA1 doesn't have an instruction for going between the accumulator
|
||||
registers and memory. Go via a VGPR in this case. */
|
||||
if (TARGET_CDNA1 && rclass == AVGPR_REGS && result != VGPR_REGS)
|
||||
result = VGPR_REGS;
|
||||
}
|
||||
|
||||
if (dump_file && (dump_flags & TDF_DETAILS))
|
||||
|
|
@ -2506,7 +2457,8 @@ gcn_conditional_register_usage (void)
|
|||
|
||||
if (cfun->machine->normal_function)
|
||||
{
|
||||
/* Restrict the set of SGPRs and VGPRs used by non-kernel functions. */
|
||||
/* Restrict the set of SGPRs, VGPRs and AVGPRs used by non-kernel
|
||||
functions. */
|
||||
for (int i = SGPR_REGNO (MAX_NORMAL_SGPR_COUNT);
|
||||
i <= LAST_SGPR_REG; i++)
|
||||
fixed_regs[i] = 1, call_used_regs[i] = 1;
|
||||
|
|
@ -2515,6 +2467,9 @@ gcn_conditional_register_usage (void)
|
|||
i <= LAST_VGPR_REG; i++)
|
||||
fixed_regs[i] = 1, call_used_regs[i] = 1;
|
||||
|
||||
for (int i = AVGPR_REGNO (MAX_NORMAL_AVGPR_COUNT);
|
||||
i <= LAST_AVGPR_REG; i++)
|
||||
fixed_regs[i] = 1, call_used_regs[i] = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2568,6 +2523,16 @@ gcn_conditional_register_usage (void)
|
|||
fixed_regs[cfun->machine->args.reg[WORK_ITEM_ID_Z_ARG]] = 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
gcn_vgpr_equivalent_register_operand (rtx x, machine_mode mode)
|
||||
{
|
||||
if (gcn_vgpr_register_operand (x, mode))
|
||||
return true;
|
||||
if (TARGET_CDNA2_PLUS && gcn_avgpr_register_operand (x, mode))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Determine if a load or store is valid, according to the register classes
|
||||
and address space. Used primarily by the machine description to decide
|
||||
when to split a move into two steps. */
|
||||
|
|
@ -2576,21 +2541,36 @@ bool
|
|||
gcn_valid_move_p (machine_mode mode, rtx dest, rtx src)
|
||||
{
|
||||
if (!MEM_P (dest) && !MEM_P (src))
|
||||
{
|
||||
if (gcn_vgpr_register_operand (src, mode)
|
||||
&& gcn_avgpr_register_operand (dest, mode))
|
||||
return true;
|
||||
if (gcn_avgpr_register_operand (src, mode)
|
||||
&& gcn_vgpr_register_operand (dest, mode))
|
||||
return true;
|
||||
if (TARGET_CDNA2_PLUS
|
||||
&& gcn_avgpr_register_operand (src, mode)
|
||||
&& gcn_avgpr_register_operand (dest, mode))
|
||||
return true;
|
||||
if (gcn_avgpr_hard_register_operand (src, mode)
|
||||
|| gcn_avgpr_hard_register_operand (dest, mode))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (MEM_P (dest)
|
||||
&& AS_FLAT_P (MEM_ADDR_SPACE (dest))
|
||||
&& (gcn_flat_address_p (XEXP (dest, 0), mode)
|
||||
|| GET_CODE (XEXP (dest, 0)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (dest, 0)) == LABEL_REF)
|
||||
&& gcn_vgpr_register_operand (src, mode))
|
||||
&& gcn_vgpr_equivalent_register_operand (src, mode))
|
||||
return true;
|
||||
else if (MEM_P (src)
|
||||
&& AS_FLAT_P (MEM_ADDR_SPACE (src))
|
||||
&& (gcn_flat_address_p (XEXP (src, 0), mode)
|
||||
|| GET_CODE (XEXP (src, 0)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (src, 0)) == LABEL_REF)
|
||||
&& gcn_vgpr_register_operand (dest, mode))
|
||||
&& gcn_vgpr_equivalent_register_operand (dest, mode))
|
||||
return true;
|
||||
|
||||
if (MEM_P (dest)
|
||||
|
|
@ -2598,14 +2578,14 @@ gcn_valid_move_p (machine_mode mode, rtx dest, rtx src)
|
|||
&& (gcn_global_address_p (XEXP (dest, 0))
|
||||
|| GET_CODE (XEXP (dest, 0)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (dest, 0)) == LABEL_REF)
|
||||
&& gcn_vgpr_register_operand (src, mode))
|
||||
&& gcn_vgpr_equivalent_register_operand (src, mode))
|
||||
return true;
|
||||
else if (MEM_P (src)
|
||||
&& AS_GLOBAL_P (MEM_ADDR_SPACE (src))
|
||||
&& (gcn_global_address_p (XEXP (src, 0))
|
||||
|| GET_CODE (XEXP (src, 0)) == SYMBOL_REF
|
||||
|| GET_CODE (XEXP (src, 0)) == LABEL_REF)
|
||||
&& gcn_vgpr_register_operand (dest, mode))
|
||||
&& gcn_vgpr_equivalent_register_operand (dest, mode))
|
||||
return true;
|
||||
|
||||
if (MEM_P (dest)
|
||||
|
|
@ -2626,12 +2606,12 @@ gcn_valid_move_p (machine_mode mode, rtx dest, rtx src)
|
|||
if (MEM_P (dest)
|
||||
&& AS_ANY_DS_P (MEM_ADDR_SPACE (dest))
|
||||
&& gcn_ds_address_p (XEXP (dest, 0))
|
||||
&& gcn_vgpr_register_operand (src, mode))
|
||||
&& gcn_vgpr_equivalent_register_operand (src, mode))
|
||||
return true;
|
||||
else if (MEM_P (src)
|
||||
&& AS_ANY_DS_P (MEM_ADDR_SPACE (src))
|
||||
&& gcn_ds_address_p (XEXP (src, 0))
|
||||
&& gcn_vgpr_register_operand (dest, mode))
|
||||
&& gcn_vgpr_equivalent_register_operand (dest, mode))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
|
|
@ -3067,7 +3047,8 @@ gcn_compute_frame_offsets (void)
|
|||
if ((df_regs_ever_live_p (regno) && !call_used_or_fixed_reg_p (regno))
|
||||
|| ((regno & ~1) == HARD_FRAME_POINTER_REGNUM
|
||||
&& frame_pointer_needed))
|
||||
offsets->callee_saves += (VGPR_REGNO_P (regno) ? 256 : 4);
|
||||
offsets->callee_saves += (VGPR_REGNO_P (regno)
|
||||
|| AVGPR_REGNO_P (regno) ? 256 : 4);
|
||||
|
||||
/* Round up to 64-bit boundary to maintain stack alignment. */
|
||||
offsets->callee_saves = (offsets->callee_saves + 7) & ~7;
|
||||
|
|
@ -4010,6 +3991,11 @@ gcn_memory_move_cost (machine_mode mode, reg_class_t regclass, bool in)
|
|||
if (in)
|
||||
return (LOAD_COST + 2) * nregs;
|
||||
return STORE_COST * nregs;
|
||||
case AVGPR_REGS:
|
||||
case ALL_VGPR_REGS:
|
||||
if (in)
|
||||
return (LOAD_COST + (TARGET_CDNA2_PLUS ? 2 : 4)) * nregs;
|
||||
return (STORE_COST + (TARGET_CDNA2_PLUS ? 0 : 2)) * nregs;
|
||||
case ALL_REGS:
|
||||
case ALL_GPR_REGS:
|
||||
case SRCDST_REGS:
|
||||
|
|
@ -4029,6 +4015,15 @@ gcn_memory_move_cost (machine_mode mode, reg_class_t regclass, bool in)
|
|||
static int
|
||||
gcn_register_move_cost (machine_mode, reg_class_t dst, reg_class_t src)
|
||||
{
|
||||
if (src == AVGPR_REGS)
|
||||
{
|
||||
if (dst == AVGPR_REGS)
|
||||
return TARGET_CDNA1 ? 6 : 2;
|
||||
if (dst != VGPR_REGS)
|
||||
return 6;
|
||||
}
|
||||
if (dst == AVGPR_REGS && src != VGPR_REGS)
|
||||
return 6;
|
||||
/* Increase cost of moving from and to vector registers. While this is
|
||||
fast in hardware (I think), it has hidden cost of setting up the exec
|
||||
flags. */
|
||||
|
|
@ -5735,6 +5730,7 @@ gcn_vmem_insn_p (attr_type type)
|
|||
case TYPE_MUBUF:
|
||||
case TYPE_MTBUF:
|
||||
case TYPE_FLAT:
|
||||
case TYPE_VOP3P_MAI:
|
||||
return true;
|
||||
case TYPE_UNKNOWN:
|
||||
case TYPE_SOP1:
|
||||
|
|
@ -5974,7 +5970,8 @@ gcn_md_reorg (void)
|
|||
FOR_EACH_SUBRTX (iter, array, PATTERN (insn), NONCONST)
|
||||
{
|
||||
const_rtx x = *iter;
|
||||
if (REG_P (x) && VGPR_REGNO_P (REGNO (x)))
|
||||
if (REG_P (x) && (VGPR_REGNO_P (REGNO (x))
|
||||
|| AVGPR_REGNO_P (REGNO (x))))
|
||||
{
|
||||
if (VECTOR_MODE_P (GET_MODE (x)))
|
||||
{
|
||||
|
|
@ -6130,17 +6127,16 @@ gcn_md_reorg (void)
|
|||
if (!prev_insn->insn)
|
||||
continue;
|
||||
|
||||
HARD_REG_SET depregs = prev_insn->writes & ireads;
|
||||
|
||||
/* VALU writes SGPR followed by VMEM reading the same SGPR
|
||||
requires 5 wait states. */
|
||||
if ((prev_insn->age + nops_rqd) < 5
|
||||
&& prev_insn->unit == UNIT_VECTOR
|
||||
&& gcn_vmem_insn_p (itype))
|
||||
{
|
||||
HARD_REG_SET regs = prev_insn->writes & ireads;
|
||||
if (hard_reg_set_intersect_p
|
||||
(regs, reg_class_contents[(int) SGPR_REGS]))
|
||||
&& gcn_vmem_insn_p (itype)
|
||||
&& hard_reg_set_intersect_p
|
||||
(depregs, reg_class_contents[(int) SGPR_REGS]))
|
||||
nops_rqd = 5 - prev_insn->age;
|
||||
}
|
||||
|
||||
/* VALU sets VCC/EXEC followed by VALU uses VCCZ/EXECZ
|
||||
requires 5 wait states. */
|
||||
|
|
@ -6162,15 +6158,12 @@ gcn_md_reorg (void)
|
|||
SGPR/VCC as lane select requires 4 wait states. */
|
||||
if ((prev_insn->age + nops_rqd) < 4
|
||||
&& prev_insn->unit == UNIT_VECTOR
|
||||
&& get_attr_laneselect (insn) == LANESELECT_YES)
|
||||
{
|
||||
HARD_REG_SET regs = prev_insn->writes & ireads;
|
||||
if (hard_reg_set_intersect_p
|
||||
(regs, reg_class_contents[(int) SGPR_REGS])
|
||||
&& get_attr_laneselect (insn) == LANESELECT_YES
|
||||
&& (hard_reg_set_intersect_p
|
||||
(depregs, reg_class_contents[(int) SGPR_REGS])
|
||||
|| hard_reg_set_intersect_p
|
||||
(regs, reg_class_contents[(int) VCC_CONDITIONAL_REG]))
|
||||
(depregs, reg_class_contents[(int) VCC_CONDITIONAL_REG])))
|
||||
nops_rqd = 4 - prev_insn->age;
|
||||
}
|
||||
|
||||
/* VALU writes VGPR followed by VALU_DPP reading that VGPR
|
||||
requires 2 wait states. */
|
||||
|
|
@ -6178,9 +6171,8 @@ gcn_md_reorg (void)
|
|||
&& prev_insn->unit == UNIT_VECTOR
|
||||
&& itype == TYPE_VOP_DPP)
|
||||
{
|
||||
HARD_REG_SET regs = prev_insn->writes & ireads;
|
||||
if (hard_reg_set_intersect_p
|
||||
(regs, reg_class_contents[(int) VGPR_REGS]))
|
||||
(depregs, reg_class_contents[(int) VGPR_REGS]))
|
||||
nops_rqd = 2 - prev_insn->age;
|
||||
}
|
||||
|
||||
|
|
@ -6199,6 +6191,35 @@ gcn_md_reorg (void)
|
|||
(prev_insn->writes,
|
||||
reg_class_contents[(int)VCC_CONDITIONAL_REG])))
|
||||
nops_rqd = ivccwait - prev_insn->age;
|
||||
|
||||
/* CDNA1: write VGPR before v_accvgpr_write reads it. */
|
||||
if (TARGET_CDNA1
|
||||
&& (prev_insn->age + nops_rqd) < 2
|
||||
&& hard_reg_set_intersect_p
|
||||
(depregs, reg_class_contents[(int) VGPR_REGS])
|
||||
&& hard_reg_set_intersect_p
|
||||
(iwrites, reg_class_contents[(int) AVGPR_REGS]))
|
||||
nops_rqd = 2 - prev_insn->age;
|
||||
|
||||
/* CDNA1: v_accvgpr_write writes AVGPR before v_accvgpr_read. */
|
||||
if (TARGET_CDNA1
|
||||
&& (prev_insn->age + nops_rqd) < 3
|
||||
&& hard_reg_set_intersect_p
|
||||
(depregs, reg_class_contents[(int) AVGPR_REGS])
|
||||
&& hard_reg_set_intersect_p
|
||||
(iwrites, reg_class_contents[(int) VGPR_REGS]))
|
||||
nops_rqd = 3 - prev_insn->age;
|
||||
|
||||
/* CDNA1: Undocumented(?!) read-after-write when restoring values
|
||||
from AVGPRs to VGPRS. Observed problem was for address register
|
||||
of flat_load instruction, but others may be affected? */
|
||||
if (TARGET_CDNA1
|
||||
&& (prev_insn->age + nops_rqd) < 2
|
||||
&& hard_reg_set_intersect_p
|
||||
(prev_insn->reads, reg_class_contents[(int) AVGPR_REGS])
|
||||
&& hard_reg_set_intersect_p
|
||||
(depregs, reg_class_contents[(int) VGPR_REGS]))
|
||||
nops_rqd = 2 - prev_insn->age;
|
||||
}
|
||||
|
||||
/* Insert the required number of NOPs. */
|
||||
|
|
@ -6490,7 +6511,7 @@ output_file_start (void)
|
|||
void
|
||||
gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
||||
{
|
||||
int sgpr, vgpr;
|
||||
int sgpr, vgpr, avgpr;
|
||||
bool xnack_enabled = TARGET_XNACK;
|
||||
|
||||
fputs ("\n\n", file);
|
||||
|
|
@ -6515,6 +6536,12 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
|||
if (df_regs_ever_live_p (FIRST_VGPR_REG + vgpr))
|
||||
break;
|
||||
vgpr++;
|
||||
for (avgpr = 255; avgpr >= 0; avgpr--)
|
||||
if (df_regs_ever_live_p (FIRST_AVGPR_REG + avgpr))
|
||||
break;
|
||||
avgpr++;
|
||||
vgpr = (vgpr + 3) & ~3;
|
||||
avgpr = (avgpr + 3) & ~3;
|
||||
|
||||
if (!leaf_function_p ())
|
||||
{
|
||||
|
|
@ -6523,6 +6550,8 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
|||
vgpr = MAX_NORMAL_VGPR_COUNT;
|
||||
if (sgpr < MAX_NORMAL_SGPR_COUNT)
|
||||
sgpr = MAX_NORMAL_SGPR_COUNT;
|
||||
if (avgpr < MAX_NORMAL_AVGPR_COUNT)
|
||||
avgpr = MAX_NORMAL_AVGPR_COUNT;
|
||||
}
|
||||
|
||||
/* The gfx90a accum_offset field can't represent 0 registers. */
|
||||
|
|
@ -6580,6 +6609,11 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
|||
? 2
|
||||
: cfun->machine->args.requested & (1 << WORK_ITEM_ID_Y_ARG)
|
||||
? 1 : 0);
|
||||
int next_free_vgpr = vgpr;
|
||||
if (TARGET_CDNA1 && avgpr > vgpr)
|
||||
next_free_vgpr = avgpr;
|
||||
if (TARGET_CDNA2_PLUS)
|
||||
next_free_vgpr += avgpr;
|
||||
fprintf (file,
|
||||
"\t .amdhsa_next_free_vgpr\t%i\n"
|
||||
"\t .amdhsa_next_free_sgpr\t%i\n"
|
||||
|
|
@ -6590,7 +6624,7 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
|||
"\t .amdhsa_group_segment_fixed_size\t%u\n"
|
||||
"\t .amdhsa_float_denorm_mode_32\t3\n"
|
||||
"\t .amdhsa_float_denorm_mode_16_64\t3\n",
|
||||
vgpr,
|
||||
next_free_vgpr,
|
||||
sgpr,
|
||||
xnack_enabled,
|
||||
LDS_SIZE);
|
||||
|
|
@ -6598,7 +6632,7 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
|||
fprintf (file,
|
||||
"\t .amdhsa_accum_offset\t%i\n"
|
||||
"\t .amdhsa_tg_split\t0\n",
|
||||
(vgpr+3)&~3); // I think this means the AGPRs come after the VGPRs
|
||||
vgpr); /* The AGPRs come after the VGPRs. */
|
||||
fputs ("\t.end_amdhsa_kernel\n", file);
|
||||
|
||||
#if 1
|
||||
|
|
@ -6625,9 +6659,9 @@ gcn_hsa_declare_function_name (FILE *file, const char *name, tree)
|
|||
cfun->machine->kernarg_segment_byte_size,
|
||||
cfun->machine->kernarg_segment_alignment,
|
||||
LDS_SIZE,
|
||||
sgpr, vgpr);
|
||||
if (gcn_arch == PROCESSOR_GFX90a)
|
||||
fprintf (file, " .agpr_count: 0\n"); // AGPRs are not used, yet
|
||||
sgpr, next_free_vgpr);
|
||||
if (gcn_arch == PROCESSOR_GFX90a || gcn_arch == PROCESSOR_GFX908)
|
||||
fprintf (file, " .agpr_count: %i\n", avgpr);
|
||||
fputs (" .end_amdgpu_metadata\n", file);
|
||||
#endif
|
||||
|
||||
|
|
@ -6723,6 +6757,9 @@ print_reg (FILE *file, rtx x)
|
|||
else if (VGPR_REGNO_P (REGNO (x)))
|
||||
fprintf (file, "v[%i:%i]", REGNO (x) - FIRST_VGPR_REG,
|
||||
REGNO (x) - FIRST_VGPR_REG + 1);
|
||||
else if (AVGPR_REGNO_P (REGNO (x)))
|
||||
fprintf (file, "a[%i:%i]", REGNO (x) - FIRST_AVGPR_REG,
|
||||
REGNO (x) - FIRST_AVGPR_REG + 1);
|
||||
else if (REGNO (x) == FLAT_SCRATCH_REG)
|
||||
fprintf (file, "flat_scratch");
|
||||
else if (REGNO (x) == EXEC_REG)
|
||||
|
|
@ -6741,6 +6778,9 @@ print_reg (FILE *file, rtx x)
|
|||
else if (VGPR_REGNO_P (REGNO (x)))
|
||||
fprintf (file, "v[%i:%i]", REGNO (x) - FIRST_VGPR_REG,
|
||||
REGNO (x) - FIRST_VGPR_REG + 3);
|
||||
else if (AVGPR_REGNO_P (REGNO (x)))
|
||||
fprintf (file, "a[%i:%i]", REGNO (x) - FIRST_AVGPR_REG,
|
||||
REGNO (x) - FIRST_AVGPR_REG + 3);
|
||||
else
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
|
@ -7664,6 +7704,8 @@ gcn_dwarf_register_number (unsigned int regno)
|
|||
}
|
||||
else if (VGPR_REGNO_P (regno))
|
||||
return (regno - FIRST_VGPR_REG + 2560);
|
||||
else if (AVGPR_REGNO_P (regno))
|
||||
return (regno - FIRST_AVGPR_REG + 3072);
|
||||
|
||||
/* Otherwise, there's nothing sensible to do. */
|
||||
return regno + 100000;
|
||||
|
|
|
|||
|
|
@ -146,6 +146,9 @@
|
|||
#define FIRST_VGPR_REG 160
|
||||
#define VGPR_REGNO(N) ((N)+FIRST_VGPR_REG)
|
||||
#define LAST_VGPR_REG 415
|
||||
#define FIRST_AVGPR_REG 416
|
||||
#define AVGPR_REGNO(N) ((N)+FIRST_AVGPR_REG)
|
||||
#define LAST_AVGPR_REG 671
|
||||
|
||||
/* Frame Registers, and other registers */
|
||||
|
||||
|
|
@ -157,10 +160,10 @@
|
|||
#define RETURN_VALUE_REG 168 /* Must be divisible by 4. */
|
||||
#define STATIC_CHAIN_REGNUM 30
|
||||
#define WORK_ITEM_ID_Z_REG 162
|
||||
#define SOFT_ARG_REG 416
|
||||
#define FRAME_POINTER_REGNUM 418
|
||||
#define DWARF_LINK_REGISTER 420
|
||||
#define FIRST_PSEUDO_REGISTER 421
|
||||
#define SOFT_ARG_REG 672
|
||||
#define FRAME_POINTER_REGNUM 674
|
||||
#define DWARF_LINK_REGISTER 676
|
||||
#define FIRST_PSEUDO_REGISTER 677
|
||||
|
||||
#define FIRST_PARM_REG (FIRST_SGPR_REG + 24)
|
||||
#define FIRST_VPARM_REG (FIRST_VGPR_REG + 8)
|
||||
|
|
@ -176,6 +179,7 @@
|
|||
#define SGPR_OR_VGPR_REGNO_P(N) ((N)>=FIRST_VGPR_REG && (N) <= LAST_SGPR_REG)
|
||||
#define SGPR_REGNO_P(N) ((N) <= LAST_SGPR_REG)
|
||||
#define VGPR_REGNO_P(N) ((N)>=FIRST_VGPR_REG && (N) <= LAST_VGPR_REG)
|
||||
#define AVGPR_REGNO_P(N) ((N)>=FIRST_AVGPR_REG && (N) <= LAST_AVGPR_REG)
|
||||
#define SSRC_REGNO_P(N) ((N) <= SCC_REG && (N) != VCCZ_REG)
|
||||
#define SDST_REGNO_P(N) ((N) <= EXEC_HI_REG && (N) != VCCZ_REG)
|
||||
#define CC_REG_P(X) (REG_P (X) && CC_REGNO_P (REGNO (X)))
|
||||
|
|
@ -206,7 +210,7 @@
|
|||
1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* VGRPs */ \
|
||||
/* VGPRs */ \
|
||||
0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
|
|
@ -223,6 +227,23 @@
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
/* Accumulation VGPRs */ \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
/* Other registers. */ \
|
||||
1, 1, 1, 1, 1 \
|
||||
}
|
||||
|
|
@ -244,7 +265,7 @@
|
|||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* VGRPs */ \
|
||||
/* VGPRs */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
|
|
@ -261,6 +282,23 @@
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
|
||||
/* Accumulation VGPRs */ \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
|
||||
/* Other registers. */ \
|
||||
1, 1, 1, 1, 1 \
|
||||
}
|
||||
|
|
@ -320,6 +358,8 @@ enum reg_class
|
|||
SGPR_SRC_REGS,
|
||||
GENERAL_REGS,
|
||||
VGPR_REGS,
|
||||
AVGPR_REGS,
|
||||
ALL_VGPR_REGS,
|
||||
ALL_GPR_REGS,
|
||||
SRCDST_REGS,
|
||||
AFP_REGS,
|
||||
|
|
@ -345,6 +385,8 @@ enum reg_class
|
|||
"SGPR_SRC_REGS", \
|
||||
"GENERAL_REGS", \
|
||||
"VGPR_REGS", \
|
||||
"AVGPR_REGS", \
|
||||
"ALL_VGPR_REGS", \
|
||||
"ALL_GPR_REGS", \
|
||||
"SRCDST_REGS", \
|
||||
"AFP_REGS", \
|
||||
|
|
@ -357,40 +399,58 @@ enum reg_class
|
|||
#define REG_CLASS_CONTENTS { \
|
||||
/* NO_REGS. */ \
|
||||
{0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SCC_CONDITIONAL_REG. */ \
|
||||
{0, 0, 0, 0, \
|
||||
NAMED_REG_MASK2 (SCC_REG), 0, 0, 0, \
|
||||
0, 0, 0, 0, 0}, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* VCCZ_CONDITIONAL_REG. */ \
|
||||
{0, 0, 0, NAMED_REG_MASK (VCCZ_REG), \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* VCC_CONDITIONAL_REG. */ \
|
||||
{0, 0, 0, NAMED_REG_MASK (VCC_LO_REG)|NAMED_REG_MASK (VCC_HI_REG), \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* EXECZ_CONDITIONAL_REG. */ \
|
||||
{0, 0, 0, 0, \
|
||||
NAMED_REG_MASK2 (EXECZ_REG), 0, 0, 0, \
|
||||
0, 0, 0, 0, 0}, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* ALL_CONDITIONAL_REGS. */ \
|
||||
{0, 0, 0, NAMED_REG_MASK (VCCZ_REG), \
|
||||
NAMED_REG_MASK2 (EXECZ_REG) | NAMED_REG_MASK2 (SCC_REG), 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* EXEC_MASK_REG. */ \
|
||||
{0, 0, 0, NAMED_REG_MASK (EXEC_LO_REG) | NAMED_REG_MASK (EXEC_HI_REG), \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SGPR_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, 0xf1, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SGPR_EXEC_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xf1 | NAMED_REG_MASK (EXEC_LO_REG) | NAMED_REG_MASK (EXEC_HI_REG), \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SGPR_VOP_SRC_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
|
|
@ -398,12 +458,16 @@ enum reg_class
|
|||
-NAMED_REG_MASK (EXEC_LO_REG) \
|
||||
-NAMED_REG_MASK (EXEC_HI_REG), \
|
||||
NAMED_REG_MASK2 (SCC_REG), 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SGPR_MEM_SRC_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff-NAMED_REG_MASK (VCCZ_REG)-NAMED_REG_MASK (M0_REG) \
|
||||
-NAMED_REG_MASK (EXEC_LO_REG)-NAMED_REG_MASK (EXEC_HI_REG), \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SGPR_DST_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
|
|
@ -413,30 +477,56 @@ enum reg_class
|
|||
/* SGPR_SRC_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
NAMED_REG_MASK2 (EXECZ_REG) | NAMED_REG_MASK2 (SCC_REG), 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* GENERAL_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, 0xf1, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* VGPR_REGS. */ \
|
||||
{0, 0, 0, 0, \
|
||||
0, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* AVGPR_REGS. */ \
|
||||
{0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0}, \
|
||||
/* ALL_VGPR_REGS. */ \
|
||||
{0, 0, 0, 0, \
|
||||
0, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0}, \
|
||||
/* ALL_GPR_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, 0xf1, \
|
||||
0, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0}, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* SRCDST_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff-NAMED_REG_MASK (VCCZ_REG), \
|
||||
0, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0}, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0}, \
|
||||
/* AFP_REGS. */ \
|
||||
{0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, \
|
||||
0, 0, 0, 0, 0, 0xf}, \
|
||||
/* ALL_REGS. */ \
|
||||
{0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, \
|
||||
0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0xffffffff, 0 }}
|
||||
|
||||
|
|
@ -541,6 +631,34 @@ enum gcn_address_spaces
|
|||
"v236", "v237", "v238", "v239", "v240", "v241", "v242", "v243", "v244", \
|
||||
"v245", "v246", "v247", "v248", "v249", "v250", "v251", "v252", "v253", \
|
||||
"v254", "v255", \
|
||||
"a0", "a1", "a2", "a3", "a4", "a5", "a6", "a7", "a8", "a9", "a10", \
|
||||
"a11", "a12", "a13", "a14", "a15", "a16", "a17", "a18", "a19", "a20", \
|
||||
"a21", "a22", "a23", "a24", "a25", "a26", "a27", "a28", "a29", "a30", \
|
||||
"a31", "a32", "a33", "a34", "a35", "a36", "a37", "a38", "a39", "a40", \
|
||||
"a41", "a42", "a43", "a44", "a45", "a46", "a47", "a48", "a49", "a50", \
|
||||
"a51", "a52", "a53", "a54", "a55", "a56", "a57", "a58", "a59", "a60", \
|
||||
"a61", "a62", "a63", "a64", "a65", "a66", "a67", "a68", "a69", "a70", \
|
||||
"a71", "a72", "a73", "a74", "a75", "a76", "a77", "a78", "a79", "a80", \
|
||||
"a81", "a82", "a83", "a84", "a85", "a86", "a87", "a88", "a89", "a90", \
|
||||
"a91", "a92", "a93", "a94", "a95", "a96", "a97", "a98", "a99", "a100", \
|
||||
"a101", "a102", "a103", "a104", "a105", "a106", "a107", "a108", "a109", \
|
||||
"a110", "a111", "a112", "a113", "a114", "a115", "a116", "a117", "a118", \
|
||||
"a119", "a120", "a121", "a122", "a123", "a124", "a125", "a126", "a127", \
|
||||
"a128", "a129", "a130", "a131", "a132", "a133", "a134", "a135", "a136", \
|
||||
"a137", "a138", "a139", "a140", "a141", "a142", "a143", "a144", "a145", \
|
||||
"a146", "a147", "a148", "a149", "a150", "a151", "a152", "a153", "a154", \
|
||||
"a155", "a156", "a157", "a158", "a159", "a160", "a161", "a162", "a163", \
|
||||
"a164", "a165", "a166", "a167", "a168", "a169", "a170", "a171", "a172", \
|
||||
"a173", "a174", "a175", "a176", "a177", "a178", "a179", "a180", "a181", \
|
||||
"a182", "a183", "a184", "a185", "a186", "a187", "a188", "a189", "a190", \
|
||||
"a191", "a192", "a193", "a194", "a195", "a196", "a197", "a198", "a199", \
|
||||
"a200", "a201", "a202", "a203", "a204", "a205", "a206", "a207", "a208", \
|
||||
"a209", "a210", "a211", "a212", "a213", "a214", "a215", "a216", "a217", \
|
||||
"a218", "a219", "a220", "a221", "a222", "a223", "a224", "a225", "a226", \
|
||||
"a227", "a228", "a229", "a230", "a231", "a232", "a233", "a234", "a235", \
|
||||
"a236", "a237", "a238", "a239", "a240", "a241", "a242", "a243", "a244", \
|
||||
"a245", "a246", "a247", "a248", "a249", "a250", "a251", "a252", "a253", \
|
||||
"a254", "a255", \
|
||||
"?ap0", "?ap1", "?fp0", "?fp1", "?dwlr" }
|
||||
|
||||
#define PRINT_OPERAND(FILE, X, CODE) print_operand(FILE, X, CODE)
|
||||
|
|
|
|||
|
|
@ -51,13 +51,15 @@
|
|||
(EXECZ_REG 128)
|
||||
(SCC_REG 129)
|
||||
(FIRST_VGPR_REG 160)
|
||||
(LAST_VGPR_REG 415)])
|
||||
(LAST_VGPR_REG 415)
|
||||
(FIRST_AVGPR_REG 416)
|
||||
(LAST_AVGPR_REG 671)])
|
||||
|
||||
(define_constants
|
||||
[(SP_REGNUM 16)
|
||||
(LR_REGNUM 18)
|
||||
(AP_REGNUM 416)
|
||||
(FP_REGNUM 418)])
|
||||
(AP_REGNUM 672)
|
||||
(FP_REGNUM 674)])
|
||||
|
||||
(define_c_enum "unspecv" [
|
||||
UNSPECV_PROLOGUE_USE
|
||||
|
|
@ -171,6 +173,11 @@
|
|||
; vdst: vgpr0-255
|
||||
; sdst: sgpr0-103/vcc/tba/tma/ttmp0-11
|
||||
;
|
||||
; vop3p_mai - vector, three inputs, one vector output
|
||||
; vsrc0,vsrc1,vsrc2: inline constant -16 to -64, fp inline immediate,
|
||||
; (acc or arch) vgpr0-255
|
||||
; vdst: (acc or arch) vgpr0-255
|
||||
;
|
||||
; vop_sdwa - second dword for vop1/vop2/vopc for specifying sub-dword address
|
||||
; src0: vgpr0-255
|
||||
; dst_sel: BYTE_0-3, WORD_0-1, DWORD
|
||||
|
|
@ -229,7 +236,8 @@
|
|||
|
||||
(define_attr "type"
|
||||
"unknown,sop1,sop2,sopk,sopc,sopp,smem,ds,vop2,vop1,vopc,
|
||||
vop3a,vop3b,vop_sdwa,vop_dpp,mubuf,mtbuf,flat,mult,vmult"
|
||||
vop3a,vop3b,vop3p_mai,vop_sdwa,vop_dpp,mubuf,mtbuf,flat,mult,
|
||||
vmult"
|
||||
(const_string "unknown"))
|
||||
|
||||
; Set if instruction is executed in scalar or vector unit
|
||||
|
|
@ -237,7 +245,7 @@
|
|||
(define_attr "unit" "unknown,scalar,vector"
|
||||
(cond [(eq_attr "type" "sop1,sop2,sopk,sopc,sopp,smem,mult")
|
||||
(const_string "scalar")
|
||||
(eq_attr "type" "vop2,vop1,vopc,vop3a,vop3b,ds,
|
||||
(eq_attr "type" "vop2,vop1,vopc,vop3a,vop3b,ds,vop3p_mai,
|
||||
vop_sdwa,vop_dpp,flat,vmult")
|
||||
(const_string "vector")]
|
||||
(const_string "unknown")))
|
||||
|
|
@ -284,7 +292,7 @@
|
|||
|
||||
; Disable alternatives that only apply to specific ISA variants.
|
||||
|
||||
(define_attr "gcn_version" "gcn3,gcn5" (const_string "gcn3"))
|
||||
(define_attr "gcn_version" "gcn3,gcn5,cdna2" (const_string "gcn3"))
|
||||
(define_attr "rdna" "any,no,yes" (const_string "any"))
|
||||
|
||||
(define_attr "enabled" ""
|
||||
|
|
@ -297,6 +305,9 @@
|
|||
(eq_attr "gcn_version" "gcn3") (const_int 1)
|
||||
(and (eq_attr "gcn_version" "gcn5")
|
||||
(ne (symbol_ref "TARGET_GCN5_PLUS") (const_int 0)))
|
||||
(const_int 1)
|
||||
(and (eq_attr "gcn_version" "cdna2")
|
||||
(ne (symbol_ref "TARGET_CDNA2_PLUS") (const_int 0)))
|
||||
(const_int 1)]
|
||||
(const_int 0)))
|
||||
|
||||
|
|
@ -552,25 +563,32 @@
|
|||
[(set (match_operand:SISF 0 "nonimmediate_operand")
|
||||
(match_operand:SISF 1 "gcn_load_operand"))]
|
||||
""
|
||||
{@ [cons: =0, 1; attrs: type, exec, length]
|
||||
[SD ,SSA ;sop1 ,* ,4 ] s_mov_b32\t%0, %1
|
||||
[SD ,J ;sopk ,* ,4 ] s_movk_i32\t%0, %1
|
||||
[SD ,B ;sop1 ,* ,8 ] s_mov_b32\t%0, %1
|
||||
[SD ,RB ;smem ,* ,12] s_buffer_load%s0\t%0, s[0:3], %1\;s_waitcnt\tlgkmcnt(0)
|
||||
[RB ,Sm ;smem ,* ,12] s_buffer_store%s1\t%1, s[0:3], %0
|
||||
[Sm ,RS ;smem ,* ,12] s_load_dword\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
|
||||
[RS ,Sm ;smem ,* ,12] s_store_dword\t%1, %A0
|
||||
[v ,v ;vop1 ,* ,4 ] v_mov_b32\t%0, %1
|
||||
[Sg ,v ;vop3a,none,8 ] v_readlane_b32\t%0, %1, 0
|
||||
[v ,Sv ;vop3a,none,8 ] v_writelane_b32\t%0, %1, 0
|
||||
[v ,RF ;flat ,* ,12] flat_load_dword\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[RF ,v ;flat ,* ,12] flat_store_dword\t%A0, %1%O0%g0
|
||||
[v ,B ;vop1 ,* ,8 ] v_mov_b32\t%0, %1
|
||||
[RLRG,v ;ds ,* ,12] ds_write_b32\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RLRG;ds ,* ,12] ds_read_b32\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[SD ,Y ;sop1 ,* ,8 ] s_mov_b32\t%0, %1
|
||||
[v ,RM ;flat ,* ,12] global_load_dword\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[RM ,v ;flat ,* ,12] global_store_dword\t%A0, %1%O0%g0
|
||||
{@ [cons: =0, 1; attrs: type, exec, length, gcn_version]
|
||||
[SD ,SSA ;sop1 ,* ,4 ,* ] s_mov_b32\t%0, %1
|
||||
[SD ,J ;sopk ,* ,4 ,* ] s_movk_i32\t%0, %1
|
||||
[SD ,B ;sop1 ,* ,8 ,* ] s_mov_b32\t%0, %1
|
||||
[SD ,RB ;smem ,* ,12,* ] s_buffer_load%s0\t%0, s[0:3], %1\;s_waitcnt\tlgkmcnt(0)
|
||||
[RB ,Sm ;smem ,* ,12,* ] s_buffer_store%s1\t%1, s[0:3], %0
|
||||
[Sm ,RS ;smem ,* ,12,* ] s_load_dword\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
|
||||
[RS ,Sm ;smem ,* ,12,* ] s_store_dword\t%1, %A0
|
||||
[v ,v ;vop1 ,* ,4 ,* ] v_mov_b32\t%0, %1
|
||||
[Sg ,v ;vop3a,none,8 ,* ] v_readlane_b32\t%0, %1, 0
|
||||
[v ,Sv ;vop3a,none,8 ,* ] v_writelane_b32\t%0, %1, 0
|
||||
[v ,^a ;vop3p_mai,*,8,* ] v_accvgpr_read_b32\t%0, %1
|
||||
[a ,v ;vop3p_mai,*,8,* ] v_accvgpr_write_b32\t%0, %1
|
||||
[a ,a ;vop1 ,* ,4,cdna2] v_accvgpr_mov_b32\t%0, %1
|
||||
[v ,RF ;flat ,* ,12,* ] flat_load_dword\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[^a ,RF ;flat ,* ,12,cdna2] ^
|
||||
[RF ,v ;flat ,* ,12,* ] flat_store_dword\t%A0, %1%O0%g0
|
||||
[RF ,a ;flat ,* ,12,cdna2] ^
|
||||
[v ,B ;vop1 ,* ,8 ,* ] v_mov_b32\t%0, %1
|
||||
[RLRG,v ;ds ,* ,12,* ] ds_write_b32\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RLRG;ds ,* ,12,* ] ds_read_b32\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[SD ,Y ;sop1 ,* ,8 ,* ] s_mov_b32\t%0, %1
|
||||
[v ,RM ;flat ,* ,12,* ] global_load_dword\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[^a ,RM ;flat ,* ,12,cdna2] ^
|
||||
[RM ,v ;flat ,* ,12,* ] global_store_dword\t%A0, %1%O0%g0
|
||||
[RM ,a ;flat ,* ,12,cdna2] ^
|
||||
})
|
||||
|
||||
; 8/16bit move pattern
|
||||
|
|
@ -580,20 +598,27 @@
|
|||
[(set (match_operand:QIHI 0 "nonimmediate_operand")
|
||||
(match_operand:QIHI 1 "gcn_load_operand"))]
|
||||
"gcn_valid_move_p (<MODE>mode, operands[0], operands[1])"
|
||||
{@ [cons: =0, 1; attrs: type, exec, length]
|
||||
[SD ,SSA ;sop1 ,* ,4 ] s_mov_b32\t%0, %1
|
||||
[SD ,J ;sopk ,* ,4 ] s_movk_i32\t%0, %1
|
||||
[SD ,B ;sop1 ,* ,8 ] s_mov_b32\t%0, %1
|
||||
[v ,v ;vop1 ,* ,4 ] v_mov_b32\t%0, %1
|
||||
[Sg ,v ;vop3a,none,4 ] v_readlane_b32\t%0, %1, 0
|
||||
[v ,Sv ;vop3a,none,4 ] v_writelane_b32\t%0, %1, 0
|
||||
[v ,RF ;flat ,* ,12] flat_load%o1\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[RF ,v ;flat ,* ,12] flat_store%s0\t%A0, %1%O0%g0
|
||||
[v ,B ;vop1 ,* ,8 ] v_mov_b32\t%0, %1
|
||||
[RLRG,v ;ds ,* ,12] ds_write%b0\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RLRG;ds ,* ,12] ds_read%u1\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RM ;flat ,* ,12] global_load%o1\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[RM ,v ;flat ,* ,12] global_store%s0\t%A0, %1%O0%g0
|
||||
{@ [cons: =0, 1; attrs: type, exec, length, gcn_version]
|
||||
[SD ,SSA ;sop1 ,* ,4 ,* ] s_mov_b32\t%0, %1
|
||||
[SD ,J ;sopk ,* ,4 ,* ] s_movk_i32\t%0, %1
|
||||
[SD ,B ;sop1 ,* ,8 ,* ] s_mov_b32\t%0, %1
|
||||
[v ,v ;vop1 ,* ,4 ,* ] v_mov_b32\t%0, %1
|
||||
[Sg ,v ;vop3a,none,4 ,* ] v_readlane_b32\t%0, %1, 0
|
||||
[v ,Sv ;vop3a,none,4 ,* ] v_writelane_b32\t%0, %1, 0
|
||||
[v ,^a ;vop3p_mai,*,8,* ] v_accvgpr_read_b32\t%0, %1
|
||||
[a ,v ;vop3p_mai,*,8,* ] v_accvgpr_write_b32\t%0, %1
|
||||
[a ,a ;vop1 ,* ,8,cdna2] v_accvgpr_mov_b32\t%0, %1
|
||||
[v ,RF ;flat ,* ,12,* ] flat_load%o1\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[^a ,RF ;flat ,* ,12,cdna2] ^
|
||||
[RF ,v ;flat ,* ,12,* ] flat_store%s0\t%A0, %1%O0%g0
|
||||
[RF ,a ;flat ,* ,12,cdna2] ^
|
||||
[v ,B ;vop1 ,* ,8 ,* ] v_mov_b32\t%0, %1
|
||||
[RLRG,v ;ds ,* ,12,* ] ds_write%b0\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RLRG;ds ,* ,12,* ] ds_read%u1\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RM ;flat ,* ,12,* ] global_load%o1\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[^a ,RM ;flat ,* ,12,cdna2] ^
|
||||
[RM ,v ;flat ,* ,12,* ] global_store%s0\t%A0, %1%O0%g0
|
||||
[RM ,a ;flat ,* ,12,cdna2] ^
|
||||
})
|
||||
|
||||
; 64bit move pattern
|
||||
|
|
@ -602,22 +627,29 @@
|
|||
[(set (match_operand:DIDF 0 "nonimmediate_operand")
|
||||
(match_operand:DIDF 1 "general_operand"))]
|
||||
"GET_CODE(operands[1]) != SYMBOL_REF"
|
||||
{@ [cons: =0, 1; attrs: type, length]
|
||||
[SD ,SSA ;sop1 ,4 ] s_mov_b64\t%0, %1
|
||||
[SD ,C ;sop1 ,8 ] ^
|
||||
[SD ,DB ;mult ,* ] #
|
||||
[RS ,Sm ;smem ,12] s_store_dwordx2\t%1, %A0
|
||||
[Sm ,RS ;smem ,12] s_load_dwordx2\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,v ;vmult,* ] #
|
||||
[v ,DB ;vmult,* ] #
|
||||
[Sg ,v ;vmult,* ] #
|
||||
[v ,Sv ;vmult,* ] #
|
||||
[v ,RF ;flat ,12] flat_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[RF ,v ;flat ,12] flat_store_dwordx2\t%A0, %1%O0%g0
|
||||
[RLRG,v ;ds ,12] ds_write_b64\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RLRG;ds ,12] ds_read_b64\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RM ;flat ,12] global_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[RM ,v ;flat ,12] global_store_dwordx2\t%A0, %1%O0%g0
|
||||
{@ [cons: =0, 1; attrs: type, length, gcn_version]
|
||||
[SD ,SSA ;sop1 ,4 ,* ] s_mov_b64\t%0, %1
|
||||
[SD ,C ;sop1 ,8 ,* ] ^
|
||||
[SD ,DB ;mult ,* ,* ] #
|
||||
[RS ,Sm ;smem ,12,* ] s_store_dwordx2\t%1, %A0
|
||||
[Sm ,RS ;smem ,12,* ] s_load_dwordx2\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,v ;vmult,* ,* ] #
|
||||
[v ,DB ;vmult,* ,* ] #
|
||||
[Sg ,v ;vmult,* ,* ] #
|
||||
[v ,Sv ;vmult,* ,* ] #
|
||||
[v ,^a ;vmult,* ,* ] #
|
||||
[a ,v ;vmult,* ,* ] #
|
||||
[a ,a ;vmult,* ,cdna2] #
|
||||
[v ,RF ;flat ,12,* ] flat_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[^a ,RF ;flat ,12,cdna2] ^
|
||||
[RF ,v ;flat ,12,* ] flat_store_dwordx2\t%A0, %1%O0%g0
|
||||
[RF ,a ;flat ,12,cdna2] ^
|
||||
[RLRG,v ;ds ,12,* ] ds_write_b64\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RLRG;ds ,12,* ] ds_read_b64\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RM ;flat ,12,* ] global_load_dwordx2\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[^a ,RM ;flat ,12,cdna2] ^
|
||||
[RM ,v ;flat ,12,* ] global_store_dwordx2\t%A0, %1%O0%g0
|
||||
[RM ,a ;flat ,12,cdna2] ^
|
||||
}
|
||||
"reload_completed
|
||||
&& ((!MEM_P (operands[0]) && !MEM_P (operands[1])
|
||||
|
|
@ -655,19 +687,26 @@
|
|||
[(set (match_operand:TI 0 "nonimmediate_operand")
|
||||
(match_operand:TI 1 "general_operand" ))]
|
||||
""
|
||||
{@ [cons: =0, 1; attrs: type, delayeduse, length]
|
||||
[SD,SSB;mult ,* ,* ] #
|
||||
[RS,Sm ;smem ,* ,12] s_store_dwordx4\t%1, %A0
|
||||
[Sm,RS ;smem ,yes,12] s_load_dwordx4\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
|
||||
[RF,v ;flat ,* ,12] flat_store_dwordx4\t%A0, %1%O0%g0
|
||||
[v ,RF ;flat ,* ,12] flat_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[v ,v ;vmult,* ,* ] #
|
||||
[v ,Sv ;vmult,* ,* ] #
|
||||
[SD,v ;vmult,* ,* ] #
|
||||
[RM,v ;flat ,yes,12] global_store_dwordx4\t%A0, %1%O0%g0
|
||||
[v ,RM ;flat ,* ,12] global_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[RL,v ;ds ,* ,12] ds_write_b128\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RL ;ds ,* ,12] ds_read_b128\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
{@ [cons: =0, 1; attrs: type, delayeduse, length, gcn_version]
|
||||
[SD,SSB;mult ,* ,* ,* ] #
|
||||
[RS,Sm ;smem ,* ,12,* ] s_store_dwordx4\t%1, %A0
|
||||
[Sm,RS ;smem ,yes,12,* ] s_load_dwordx4\t%0, %A1\;s_waitcnt\tlgkmcnt(0)
|
||||
[RF,v ;flat ,* ,12,* ] flat_store_dwordx4\t%A0, %1%O0%g0
|
||||
[RF,a ;flat ,* ,12,cdna2] ^
|
||||
[v ,RF ;flat ,* ,12,* ] flat_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\t0
|
||||
[^a,RF ;flat ,* ,12,cdna2] ^
|
||||
[v ,v ;vmult,* ,* ,* ] #
|
||||
[v ,Sv ;vmult,* ,* ,* ] #
|
||||
[SD,v ;vmult,* ,* ,* ] #
|
||||
[RM,v ;flat ,yes,12,* ] global_store_dwordx4\t%A0, %1%O0%g0
|
||||
[RM,a ;flat ,yes,12,cdna2] ^
|
||||
[v ,RM ;flat ,* ,12,* ] global_load_dwordx4\t%0, %A1%O1%g1\;s_waitcnt\tvmcnt(0)
|
||||
[^a,RM ;flat ,* ,12,cdna2] ^
|
||||
[RL,v ;ds ,* ,12,* ] ds_write_b128\t%A0, %1%O0\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,RL ;ds ,* ,12,* ] ds_read_b128\t%0, %A1%O1\;s_waitcnt\tlgkmcnt(0)
|
||||
[v ,^a ;vmult,* ,* ,* ] #
|
||||
[a ,v ;vmult,* ,* ,* ] #
|
||||
[a ,a ;vmult,* ,* ,cdna2] #
|
||||
}
|
||||
"reload_completed
|
||||
&& REG_P (operands[0])
|
||||
|
|
|
|||
|
|
@ -471,6 +471,26 @@ copy_early_debug_info (const char *infile, const char *outfile)
|
|||
return true;
|
||||
}
|
||||
|
||||
/* CDNA2 devices have twice as many VGPRs compared to older devices,
|
||||
but the AVGPRS are allocated from the same pool. */
|
||||
|
||||
static int
|
||||
isa_has_combined_avgprs (int isa)
|
||||
{
|
||||
switch (isa)
|
||||
{
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX803:
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX900:
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX906:
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX908:
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX1030:
|
||||
return false;
|
||||
case EF_AMDGPU_MACH_AMDGCN_GFX90a:
|
||||
return true;
|
||||
}
|
||||
fatal_error (input_location, "unhandled ISA in isa_has_combined_avgprs");
|
||||
}
|
||||
|
||||
/* Parse an input assembler file, extract the offload tables etc.,
|
||||
and output (1) the assembler code, minus the tables (which can contain
|
||||
problematic relocations), and (2) a C file with the offload tables
|
||||
|
|
@ -496,6 +516,7 @@ process_asm (FILE *in, FILE *out, FILE *cfile)
|
|||
{
|
||||
int sgpr_count;
|
||||
int vgpr_count;
|
||||
int avgpr_count;
|
||||
char *kernel_name;
|
||||
} regcount = { -1, -1, NULL };
|
||||
|
||||
|
|
@ -543,6 +564,12 @@ process_asm (FILE *in, FILE *out, FILE *cfile)
|
|||
gcc_assert (regcount.kernel_name);
|
||||
break;
|
||||
}
|
||||
else if (sscanf (buf, " .agpr_count: %d\n",
|
||||
®count.avgpr_count) == 1)
|
||||
{
|
||||
gcc_assert (regcount.kernel_name);
|
||||
break;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
|
@ -685,6 +712,8 @@ process_asm (FILE *in, FILE *out, FILE *cfile)
|
|||
{
|
||||
sgpr_count = regcounts[j].sgpr_count;
|
||||
vgpr_count = regcounts[j].vgpr_count;
|
||||
if (isa_has_combined_avgprs (elf_arch))
|
||||
vgpr_count += regcounts[j].avgpr_count;
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -70,6 +70,30 @@
|
|||
return VGPR_REGNO_P (REGNO (op)) || REGNO (op) >= FIRST_PSEUDO_REGISTER;
|
||||
})
|
||||
|
||||
(define_predicate "gcn_avgpr_register_operand"
|
||||
(match_operand 0 "register_operand")
|
||||
{
|
||||
if (GET_CODE (op) == SUBREG)
|
||||
op = SUBREG_REG (op);
|
||||
|
||||
if (!REG_P (op))
|
||||
return false;
|
||||
|
||||
return AVGPR_REGNO_P (REGNO (op)) || REGNO (op) >= FIRST_PSEUDO_REGISTER;
|
||||
})
|
||||
|
||||
(define_predicate "gcn_avgpr_hard_register_operand"
|
||||
(match_operand 0 "register_operand")
|
||||
{
|
||||
if (GET_CODE (op) == SUBREG)
|
||||
op = SUBREG_REG (op);
|
||||
|
||||
if (!REG_P (op))
|
||||
return false;
|
||||
|
||||
return AVGPR_REGNO_P (REGNO (op));
|
||||
})
|
||||
|
||||
(define_predicate "gcn_inline_immediate_operand"
|
||||
(match_code "const_int,const_double,const_vector")
|
||||
{
|
||||
|
|
|
|||
|
|
@ -3335,6 +3335,19 @@
|
|||
(set_attr "mode" "<MODE>")
|
||||
(set_attr "length_immediate" "0")])
|
||||
|
||||
(define_insn "*movstrictqi_ext<mode>_1"
|
||||
[(set (strict_low_part
|
||||
(match_operand:QI 0 "register_operand" "+Q"))
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 2 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"mov{b}\t{%h1, %0|%0, %h1}"
|
||||
[(set_attr "type" "imov")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_expand "extv<mode>"
|
||||
[(set (match_operand:SWI24 0 "register_operand")
|
||||
(sign_extract:SWI24 (match_operand:SWI24 1 "register_operand")
|
||||
|
|
@ -6615,6 +6628,69 @@
|
|||
(const_string "alu")))
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
;; Alternative 1 is needed to work around LRA limitation, see PR82524.
|
||||
(define_insn_and_split "*addqi_ext<mode>_1_slp"
|
||||
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q"))
|
||||
(plus:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q,Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(match_operand:QI 1 "nonimmediate_operand" "0,!qm")))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"@
|
||||
add{b}\t{%h2, %0|%0, %h2}
|
||||
#"
|
||||
"&& reload_completed
|
||||
&& !rtx_equal_p (operands[0], operands[1])"
|
||||
[(set (strict_low_part (match_dup 0)) (match_dup 1))
|
||||
(parallel
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(plus:QI
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0)
|
||||
(match_dup 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn_and_split "*addqi_ext<mode>_2_slp"
|
||||
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q"))
|
||||
(plus:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 4 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(subreg:QI
|
||||
(match_op_dup 4
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0))
|
||||
(parallel
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(plus:QI
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 1) (const_int 8) (const_int 8)]) 0)
|
||||
(match_dup 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
;; Split non destructive adds if we cannot use lea.
|
||||
(define_split
|
||||
[(set (match_operand:SWI48 0 "register_operand")
|
||||
|
|
@ -6993,6 +7069,39 @@
|
|||
(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn_and_split "*addqi_ext2<mode>_0"
|
||||
[(set (match_operand:QI 0 "register_operand" "=&Q")
|
||||
(plus:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 4 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(subreg:QI
|
||||
(match_op_dup 4
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0))
|
||||
(parallel
|
||||
[(set (match_dup 0)
|
||||
(plus:QI
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 1) (const_int 8) (const_int 8)]) 0)
|
||||
(match_dup 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_expand "addqi_ext_1"
|
||||
[(parallel
|
||||
[(set (zero_extract:HI (match_operand:HI 0 "register_operand")
|
||||
|
|
@ -7628,6 +7737,69 @@
|
|||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
;; Alternative 1 is needed to work around LRA limitation, see PR82524.
|
||||
(define_insn_and_split "*subqi_ext<mode>_1_slp"
|
||||
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q"))
|
||||
(minus:QI
|
||||
(match_operand:QI 1 "nonimmediate_operand" "0,!qm")
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q,Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"@
|
||||
sub{b}\t{%h2, %0|%0, %h2}
|
||||
#"
|
||||
"&& reload_completed
|
||||
&& !rtx_equal_p (operands[0], operands[1])"
|
||||
[(set (strict_low_part (match_dup 0)) (match_dup 1))
|
||||
(parallel
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(minus:QI
|
||||
(match_dup 0)
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn_and_split "*subqi_ext<mode>_2_slp"
|
||||
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q"))
|
||||
(minus:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 4 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 1) (const_int 8) (const_int 8)]) 0))
|
||||
(parallel
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(minus:QI
|
||||
(match_dup 0)
|
||||
(subreg:QI
|
||||
(match_op_dup 4
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn "*sub<mode>_2"
|
||||
[(set (reg FLAGS_REG)
|
||||
(compare
|
||||
|
|
@ -7675,6 +7847,39 @@
|
|||
(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn_and_split "*subqi_ext2<mode>_0"
|
||||
[(set (match_operand:QI 0 "register_operand" "=&Q")
|
||||
(minus:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 4 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 1) (const_int 8) (const_int 8)]) 0))
|
||||
(parallel
|
||||
[(set (match_dup 0)
|
||||
(minus:QI
|
||||
(match_dup 0)
|
||||
(subreg:QI
|
||||
(match_op_dup 4
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
;; Alternative 1 is needed to work around LRA limitation, see PR82524.
|
||||
(define_insn_and_split "*subqi_ext<mode>_1"
|
||||
[(set (zero_extract:SWI248
|
||||
|
|
@ -9858,7 +10063,10 @@
|
|||
&& REGNO (operands[0]) != REGNO (operands[3])
|
||||
&& (REGNO (operands[0]) == REGNO (operands[4])
|
||||
|| REGNO (operands[0]) == REGNO (operands[5])
|
||||
|| peep2_reg_dead_p (3, operands[0]))"
|
||||
|| peep2_reg_dead_p (3, operands[0]))
|
||||
&& (REGNO (operands[2]) == REGNO (operands[4])
|
||||
|| REGNO (operands[2]) == REGNO (operands[5])
|
||||
|| peep2_reg_dead_p (3, operands[2]))"
|
||||
[(set (match_dup 2) (match_dup 1))
|
||||
(parallel [(set (match_dup 4)
|
||||
(mult:DWIH (match_dup 2) (match_dup 3)))
|
||||
|
|
@ -11423,6 +11631,69 @@
|
|||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "<MODE>")])
|
||||
|
||||
;; Alternative 1 is needed to work around LRA limitation, see PR82524.
|
||||
(define_insn_and_split "*<code>qi_ext<mode>_1_slp"
|
||||
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+Q,&Q"))
|
||||
(any_logic:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q,Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(match_operand:QI 1 "nonimmediate_operand" "0,!qm")))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"@
|
||||
<logic>{b}\t{%h2, %0|%0, %h2}
|
||||
#"
|
||||
"&& reload_completed
|
||||
&& !rtx_equal_p (operands[0], operands[1])"
|
||||
[(set (strict_low_part (match_dup 0)) (match_dup 1))
|
||||
(parallel
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(any_logic:QI
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0)
|
||||
(match_dup 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn_and_split "*<code>qi_ext<mode>_2_slp"
|
||||
[(set (strict_low_part (match_operand:QI 0 "register_operand" "+&Q"))
|
||||
(any_logic:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 4 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
"!TARGET_PARTIAL_REG_STALL || optimize_function_for_size_p (cfun)"
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(subreg:QI
|
||||
(match_op_dup 4
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0))
|
||||
(parallel
|
||||
[(set (strict_low_part (match_dup 0))
|
||||
(any_logic:QI
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 1) (const_int 8) (const_int 8)]) 0)
|
||||
(match_dup 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:SWI248 0 "register_operand")
|
||||
(and:SWI248 (match_operand:SWI248 1 "nonimmediate_operand")
|
||||
|
|
@ -11610,6 +11881,39 @@
|
|||
(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_insn_and_split "*<code>qi_ext2<mode>_0"
|
||||
[(set (match_operand:QI 0 "register_operand" "=&Q")
|
||||
(any_logic:QI
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 3 "extract_operator"
|
||||
[(match_operand 1 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)
|
||||
(subreg:QI
|
||||
(match_operator:SWI248 4 "extract_operator"
|
||||
[(match_operand 2 "int248_register_operand" "Q")
|
||||
(const_int 8)
|
||||
(const_int 8)]) 0)))
|
||||
(clobber (reg:CC FLAGS_REG))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 0)
|
||||
(subreg:QI
|
||||
(match_op_dup 4
|
||||
[(match_dup 2) (const_int 8) (const_int 8)]) 0))
|
||||
(parallel
|
||||
[(set (match_dup 0)
|
||||
(any_logic:QI
|
||||
(subreg:QI
|
||||
(match_op_dup 3
|
||||
[(match_dup 1) (const_int 8) (const_int 8)]) 0)
|
||||
(match_dup 0)))
|
||||
(clobber (reg:CC FLAGS_REG))])]
|
||||
""
|
||||
[(set_attr "type" "alu")
|
||||
(set_attr "mode" "QI")])
|
||||
|
||||
(define_expand "andqi_ext_1"
|
||||
[(parallel
|
||||
[(set (zero_extract:HI (match_operand:HI 0 "register_operand")
|
||||
|
|
@ -14825,8 +15129,8 @@
|
|||
{
|
||||
split_double_mode (<DWI>mode, &operands[1], 1, &operands[1], &operands[3]);
|
||||
operands[4] = GEN_INT ((<MODE_SIZE> * BITS_PER_UNIT) - INTVAL (operands[2]));
|
||||
if (!rtx_equal_p (operands[0], operands[3]))
|
||||
emit_move_insn (operands[0], operands[3]);
|
||||
if (!rtx_equal_p (operands[0], operands[1]))
|
||||
emit_move_insn (operands[0], operands[1]);
|
||||
})
|
||||
|
||||
(define_insn "x86_64_shrd"
|
||||
|
|
|
|||
|
|
@ -1215,7 +1215,7 @@
|
|||
}
|
||||
}
|
||||
[(set_attr "isa" "noavx,noavx,avx")
|
||||
(set_attr "addr" "*,*,gpr16")
|
||||
(set_attr "addr" "gpr16,gpr16,*")
|
||||
(set_attr "type" "sselog")
|
||||
(set_attr "prefix_data16" "1,1,*")
|
||||
(set_attr "prefix_extra" "1")
|
||||
|
|
@ -5277,8 +5277,8 @@
|
|||
(set_attr "mode" "DI,TI")])
|
||||
|
||||
(define_insn "*vec_dup<mode>"
|
||||
[(set (match_operand:V4F_64 0 "register_operand" "=Yw")
|
||||
(vec_duplicate:V4F_64
|
||||
[(set (match_operand:V4FI_64 0 "register_operand" "=Yw")
|
||||
(vec_duplicate:V4FI_64
|
||||
(match_operand:<mmxscalarmode> 1 "register_operand" "Yw")))]
|
||||
"TARGET_MMX_WITH_SSE"
|
||||
"%vpshuflw\t{$0, %1, %0|%0, %1, 0}"
|
||||
|
|
@ -5869,8 +5869,8 @@
|
|||
(set_attr "mode" "TI")])
|
||||
|
||||
(define_insn "*vec_dup<mode>"
|
||||
[(set (match_operand:V2F_32 0 "register_operand" "=Yw")
|
||||
(vec_duplicate:V2F_32
|
||||
[(set (match_operand:V2FI_32 0 "register_operand" "=Yw")
|
||||
(vec_duplicate:V2FI_32
|
||||
(match_operand:<mmxscalarmode> 1 "register_operand" "Yw")))]
|
||||
"TARGET_SSE2"
|
||||
"%vpshuflw\t{$0, %1, %0|%0, %1, 0}"
|
||||
|
|
|
|||
|
|
@ -12049,9 +12049,9 @@
|
|||
(set_attr "mode" "<sseinsnmode>")])
|
||||
|
||||
(define_insn "vec_extract_hi_<mode>"
|
||||
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=vm")
|
||||
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=xjm,vm")
|
||||
(vec_select:<ssehalfvecmode>
|
||||
(match_operand:VI8F_256 1 "register_operand" "v")
|
||||
(match_operand:VI8F_256 1 "register_operand" "x,v")
|
||||
(parallel [(const_int 2) (const_int 3)])))]
|
||||
"TARGET_AVX"
|
||||
{
|
||||
|
|
@ -12065,7 +12065,9 @@
|
|||
else
|
||||
return "vextract<i128>\t{$0x1, %1, %0|%0, %1, 0x1}";
|
||||
}
|
||||
[(set_attr "type" "sselog1")
|
||||
[(set_attr "isa" "noavx512vl,avx512vl")
|
||||
(set_attr "addr" "gpr16,*")
|
||||
(set_attr "type" "sselog1")
|
||||
(set_attr "prefix_extra" "1")
|
||||
(set_attr "length_immediate" "1")
|
||||
(set_attr "prefix" "vex")
|
||||
|
|
@ -12132,7 +12134,7 @@
|
|||
(set_attr "mode" "<sseinsnmode>")])
|
||||
|
||||
(define_insn "vec_extract_hi_<mode>"
|
||||
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=xm, vm")
|
||||
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=xjm, vm")
|
||||
(vec_select:<ssehalfvecmode>
|
||||
(match_operand:VI4F_256 1 "register_operand" "x, v")
|
||||
(parallel [(const_int 4) (const_int 5)
|
||||
|
|
@ -12141,7 +12143,8 @@
|
|||
"@
|
||||
vextract<i128>\t{$0x1, %1, %0|%0, %1, 0x1}
|
||||
vextract<shuffletype>32x4\t{$0x1, %1, %0|%0, %1, 0x1}"
|
||||
[(set_attr "isa" "*, avx512vl")
|
||||
[(set_attr "isa" "noavx512vl, avx512vl")
|
||||
(set_attr "addr" "gpr16,*")
|
||||
(set_attr "prefix" "vex, evex")
|
||||
(set_attr "type" "sselog1")
|
||||
(set_attr "length_immediate" "1")
|
||||
|
|
@ -12222,7 +12225,7 @@
|
|||
"operands[1] = gen_lowpart (<ssehalfvecmode>mode, operands[1]);")
|
||||
|
||||
(define_insn "@vec_extract_hi_<mode>"
|
||||
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=xm,vm")
|
||||
[(set (match_operand:<ssehalfvecmode> 0 "nonimmediate_operand" "=xjm,vm")
|
||||
(vec_select:<ssehalfvecmode>
|
||||
(match_operand:V16_256 1 "register_operand" "x,v")
|
||||
(parallel [(const_int 8) (const_int 9)
|
||||
|
|
@ -12236,7 +12239,8 @@
|
|||
[(set_attr "type" "sselog1")
|
||||
(set_attr "prefix_extra" "1")
|
||||
(set_attr "length_immediate" "1")
|
||||
(set_attr "isa" "*,avx512vl")
|
||||
(set_attr "isa" "noavx512vl,avx512vl")
|
||||
(set_attr "addr" "gpr16,*")
|
||||
(set_attr "prefix" "vex,evex")
|
||||
(set_attr "mode" "OI")])
|
||||
|
||||
|
|
@ -19235,11 +19239,11 @@
|
|||
})
|
||||
|
||||
(define_insn "<mask_codefor>avx512dq_shuf_<shuffletype>64x2_1<mask_name>"
|
||||
[(set (match_operand:VI8F_256 0 "register_operand" "=v")
|
||||
[(set (match_operand:VI8F_256 0 "register_operand" "=x,v")
|
||||
(vec_select:VI8F_256
|
||||
(vec_concat:<ssedoublemode>
|
||||
(match_operand:VI8F_256 1 "register_operand" "v")
|
||||
(match_operand:VI8F_256 2 "nonimmediate_operand" "vm"))
|
||||
(match_operand:VI8F_256 1 "register_operand" "x,v")
|
||||
(match_operand:VI8F_256 2 "nonimmediate_operand" "xjm,vm"))
|
||||
(parallel [(match_operand 3 "const_0_to_3_operand")
|
||||
(match_operand 4 "const_0_to_3_operand")
|
||||
(match_operand 5 "const_4_to_7_operand")
|
||||
|
|
@ -19254,7 +19258,7 @@
|
|||
mask = INTVAL (operands[3]) / 2;
|
||||
mask |= (INTVAL (operands[5]) - 4) / 2 << 1;
|
||||
operands[3] = GEN_INT (mask);
|
||||
if (INTVAL (operands[3]) == 2 && !<mask_applied>)
|
||||
if (INTVAL (operands[3]) == 2 && !<mask_applied> && which_alternative == 0)
|
||||
return "vblendps\t{$240, %2, %1, %0|%0, %1, %2, 240}";
|
||||
return "vshuf<shuffletype>64x2\t{%3, %2, %1, %0<mask_operand7>|%0<mask_operand7>, %1, %2, %3}";
|
||||
}
|
||||
|
|
@ -19386,11 +19390,11 @@
|
|||
})
|
||||
|
||||
(define_insn "avx512vl_shuf_<shuffletype>32x4_1<mask_name>"
|
||||
[(set (match_operand:VI4F_256 0 "register_operand" "=v")
|
||||
[(set (match_operand:VI4F_256 0 "register_operand" "=x,v")
|
||||
(vec_select:VI4F_256
|
||||
(vec_concat:<ssedoublemode>
|
||||
(match_operand:VI4F_256 1 "register_operand" "v")
|
||||
(match_operand:VI4F_256 2 "nonimmediate_operand" "vm"))
|
||||
(match_operand:VI4F_256 1 "register_operand" "x,v")
|
||||
(match_operand:VI4F_256 2 "nonimmediate_operand" "xjm,vm"))
|
||||
(parallel [(match_operand 3 "const_0_to_7_operand")
|
||||
(match_operand 4 "const_0_to_7_operand")
|
||||
(match_operand 5 "const_0_to_7_operand")
|
||||
|
|
@ -19414,7 +19418,7 @@
|
|||
mask |= (INTVAL (operands[7]) - 8) / 4 << 1;
|
||||
operands[3] = GEN_INT (mask);
|
||||
|
||||
if (INTVAL (operands[3]) == 2 && !<mask_applied>)
|
||||
if (INTVAL (operands[3]) == 2 && !<mask_applied> && which_alternative == 0)
|
||||
return "vblendps\t{$240, %2, %1, %0|%0, %1, %2, 240}";
|
||||
|
||||
return "vshuf<shuffletype>32x4\t{%3, %2, %1, %0<mask_operand11>|%0<mask_operand11>, %1, %2, %3}";
|
||||
|
|
@ -20465,7 +20469,7 @@
|
|||
})
|
||||
|
||||
(define_insn "*vec_extractv2ti"
|
||||
[(set (match_operand:TI 0 "nonimmediate_operand" "=xm,vm")
|
||||
[(set (match_operand:TI 0 "nonimmediate_operand" "=xjm,vm")
|
||||
(vec_select:TI
|
||||
(match_operand:V2TI 1 "register_operand" "x,v")
|
||||
(parallel
|
||||
|
|
@ -20477,6 +20481,8 @@
|
|||
[(set_attr "type" "sselog")
|
||||
(set_attr "prefix_extra" "1")
|
||||
(set_attr "length_immediate" "1")
|
||||
(set_attr "isa" "noavx512vl,avx512vl")
|
||||
(set_attr "addr" "gpr16,*")
|
||||
(set_attr "prefix" "vex,evex")
|
||||
(set_attr "mode" "OI")])
|
||||
|
||||
|
|
@ -27556,12 +27562,12 @@
|
|||
(set_attr "mode" "<sseinsnmode>")])
|
||||
|
||||
(define_insn "vec_set_hi_<mode><mask_name>"
|
||||
[(set (match_operand:VI8F_256 0 "register_operand" "=v")
|
||||
[(set (match_operand:VI8F_256 0 "register_operand" "=x,v")
|
||||
(vec_concat:VI8F_256
|
||||
(vec_select:<ssehalfvecmode>
|
||||
(match_operand:VI8F_256 1 "register_operand" "v")
|
||||
(match_operand:VI8F_256 1 "register_operand" "x,v")
|
||||
(parallel [(const_int 0) (const_int 1)]))
|
||||
(match_operand:<ssehalfvecmode> 2 "nonimmediate_operand" "vm")))]
|
||||
(match_operand:<ssehalfvecmode> 2 "nonimmediate_operand" "xjm,vm")))]
|
||||
"TARGET_AVX && <mask_avx512dq_condition>"
|
||||
{
|
||||
if (TARGET_AVX512DQ)
|
||||
|
|
@ -27571,7 +27577,9 @@
|
|||
else
|
||||
return "vinsert<i128>\t{$0x1, %2, %1, %0|%0, %1, %2, 0x1}";
|
||||
}
|
||||
[(set_attr "type" "sselog")
|
||||
[(set_attr "isa" "noavx512vl,avx512vl")
|
||||
(set_attr "addr" "gpr16,*")
|
||||
(set_attr "type" "sselog")
|
||||
(set_attr "prefix_extra" "1")
|
||||
(set_attr "length_immediate" "1")
|
||||
(set_attr "prefix" "vex")
|
||||
|
|
|
|||
|
|
@ -25,8 +25,8 @@ 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.
|
||||
/* Generated automatically by "genstr" from "loongarch-strings" and
|
||||
"isa-evolution.in". Please do not edit this file directly.
|
||||
|
||||
Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
Contributed by Loongson Ltd.
|
||||
|
|
@ -55,6 +55,15 @@ EOF
|
|||
-e 's@^\([^ \t]\+\)[ \t]*\([^ \t]*\)@#define \1 "\2"@' \
|
||||
loongarch-strings
|
||||
|
||||
echo
|
||||
|
||||
# Generate the strings from isa-evolution.in.
|
||||
awk '{
|
||||
a=$3
|
||||
gsub(/-/, "_", a)
|
||||
print("#define OPTSTR_"toupper(a)"\t\""$3"\"")
|
||||
}' isa-evolution.in
|
||||
|
||||
echo
|
||||
echo "#endif /* LOONGARCH_STR_H */"
|
||||
}
|
||||
|
|
@ -77,11 +86,12 @@ gen_options() {
|
|||
# print a header
|
||||
cat << EOF
|
||||
; Generated by "genstr" from the template "loongarch.opt.in"
|
||||
; and definitions from "loongarch-strings".
|
||||
; and definitions from "loongarch-strings" and "isa-evolution.in".
|
||||
;
|
||||
; 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".
|
||||
; if you change "loongarch.opt.in", "loongarch-strings", or
|
||||
; "isa-evolution.in".
|
||||
;
|
||||
EOF
|
||||
|
||||
|
|
@ -91,13 +101,85 @@ EOF
|
|||
eval "echo \"$line\""
|
||||
done
|
||||
}
|
||||
|
||||
# Generate the strings from isa-evolution.in.
|
||||
awk '{
|
||||
print("")
|
||||
print("m"$3)
|
||||
gsub(/-/, "_", $3)
|
||||
print("Target Mask(ISA_"toupper($3)") Var(isa_evolution)")
|
||||
$1=""; $2=""; $3=""
|
||||
sub(/^ */, "", $0)
|
||||
print($0)
|
||||
}' isa-evolution.in
|
||||
}
|
||||
|
||||
gen_cpucfg_map() {
|
||||
cat <<EOF
|
||||
/* Generated automatically by "genstr" from "isa-evolution.in".
|
||||
Please do not edit this file directly.
|
||||
|
||||
Copyright (C) 2023 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_CPUCFG_MAP_H
|
||||
#define LOONGARCH_CPUCFG_MAP_H
|
||||
|
||||
#include "options.h"
|
||||
|
||||
static constexpr struct {
|
||||
int cpucfg_word;
|
||||
unsigned int cpucfg_bit;
|
||||
HOST_WIDE_INT isa_evolution_bit;
|
||||
} cpucfg_map[] = {
|
||||
EOF
|
||||
|
||||
# Generate the strings from isa-evolution.in.
|
||||
awk '{
|
||||
gsub(/-/, "_", $3)
|
||||
print(" { "$1", 1u << "$2", OPTION_MASK_ISA_"toupper($3)" },")
|
||||
}' isa-evolution.in
|
||||
|
||||
echo "};"
|
||||
echo
|
||||
echo "static constexpr int cpucfg_useful_idx[] = {"
|
||||
|
||||
awk 'BEGIN { print(" 0,\n 1,\n 2,\n 16,\n 17,\n 18,\n 19,") }
|
||||
{if ($1+0 > max+0) max=$1; print(" "$1",")}' \
|
||||
isa-evolution.in | sort -n | uniq
|
||||
|
||||
echo "};"
|
||||
echo ""
|
||||
|
||||
awk 'BEGIN { max=19 }
|
||||
{ if ($1+0 > max+0) max=$1 }
|
||||
END { print "static constexpr int N_CPUCFG_WORDS = "1+max";" }' \
|
||||
isa-evolution.in
|
||||
|
||||
echo "#endif /* LOONGARCH_CPUCFG_MAP_H */"
|
||||
}
|
||||
|
||||
main() {
|
||||
case "$1" in
|
||||
cpucfg-map) gen_cpucfg_map;;
|
||||
header) gen_defines;;
|
||||
opt) gen_options;;
|
||||
*) echo "Unknown Command: \"$1\". Available: header, opt"; exit 1;;
|
||||
*) echo "Unknown Command: \"$1\". Available: cpucfg-map, header, opt"; exit 1;;
|
||||
esac
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,4 @@
|
|||
2 26 div32 Support div.w[u] and mod.w[u] instructions with inputs not sign-extended.
|
||||
2 27 lam-bh Support am{swap/add}[_db].{b/h} instructions.
|
||||
2 28 lamcas Support amcas[_db].{b/h/w/d} instructions.
|
||||
3 23 ld-seq-sa Do not need load-load barriers (dbar 0x700).
|
||||
|
|
@ -26,9 +26,11 @@ STR_CPU_NATIVE native
|
|||
STR_CPU_ABI_DEFAULT abi-default
|
||||
STR_CPU_LOONGARCH64 loongarch64
|
||||
STR_CPU_LA464 la464
|
||||
STR_CPU_LA664 la664
|
||||
|
||||
# Base architecture
|
||||
STR_ISA_BASE_LA64V100 la64
|
||||
STR_ISA_BASE_LA64V110 la64v1.1
|
||||
|
||||
# -mfpu
|
||||
OPTSTR_ISA_EXT_FPU fpu
|
||||
|
|
|
|||
|
|
@ -32,6 +32,9 @@ Basic ISAs of LoongArch:
|
|||
EnumValue
|
||||
Enum(isa_base) String(@@STR_ISA_BASE_LA64V100@@) Value(ISA_BASE_LA64V100)
|
||||
|
||||
EnumValue
|
||||
Enum(isa_base) String(@@STR_ISA_BASE_LA64V110@@) Value(ISA_BASE_LA64V110)
|
||||
|
||||
;; ISA extensions / adjustments
|
||||
Enum
|
||||
Name(isa_ext_fpu) Type(int)
|
||||
|
|
@ -107,6 +110,9 @@ Enum(cpu_type) String(@@STR_CPU_LOONGARCH64@@) Value(CPU_LOONGARCH64)
|
|||
EnumValue
|
||||
Enum(cpu_type) String(@@STR_CPU_LA464@@) Value(CPU_LA464)
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(@@STR_CPU_LA664@@) Value(CPU_LA664)
|
||||
|
||||
m@@OPTSTR_ARCH@@=
|
||||
Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
|
||||
-m@@OPTSTR_ARCH@@=PROCESSOR Generate code for the given PROCESSOR ISA.
|
||||
|
|
@ -223,10 +229,14 @@ Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0)
|
|||
Avoid using the GOT to access external symbols.
|
||||
|
||||
mrelax
|
||||
Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION)
|
||||
Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
|
||||
Take advantage of linker relaxations to reduce the number of instructions
|
||||
required to materialize symbol addresses.
|
||||
|
||||
mpass-mrelax-to-as
|
||||
Target Var(loongarch_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
|
||||
Pass -mrelax or -mno-relax option to the assembler.
|
||||
|
||||
-param=loongarch-vect-unroll-limit=
|
||||
Target Joined UInteger Var(loongarch_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
|
||||
Used to limit unroll factor which indicates how much the autovectorizer may
|
||||
|
|
@ -237,3 +247,10 @@ Target Undocumented Joined UInteger Var(loongarch_vect_issue_info) Init(4) Integ
|
|||
Indicate how many non memory access vector instructions can be issued per
|
||||
cycle, it's used in unroll factor determination for autovectorizer. The
|
||||
default value is 4.
|
||||
|
||||
; Features added during ISA evolution. This concept is different from ISA
|
||||
; extension, read Section 1.5 of LoongArch v1.10 Volume 1 for the
|
||||
; explanation. These features may be implemented and enumerated with
|
||||
; CPUCFG independantly, so we use bit flags to specify them.
|
||||
Variable
|
||||
HOST_WIDE_INT isa_evolution = 0
|
||||
|
|
|
|||
|
|
@ -3136,11 +3136,31 @@
|
|||
(match_operand:FLASX 1 "register_operand")))
|
||||
(set (match_dup 5)
|
||||
(and:FLASX (match_dup 3)
|
||||
(match_operand:FLASX 2 "register_operand")))
|
||||
(match_operand:FLASX 2 "reg_or_vector_same_val_operand")))
|
||||
(set (match_operand:FLASX 0 "register_operand")
|
||||
(ior:FLASX (match_dup 4) (match_dup 5)))]
|
||||
"ISA_HAS_LASX"
|
||||
{
|
||||
/* copysign (x, -1) should instead be expanded as setting the sign
|
||||
bit. */
|
||||
if (!REG_P (operands[2]))
|
||||
{
|
||||
rtx op2_elt = unwrap_const_vec_duplicate (operands[2]);
|
||||
if (GET_CODE (op2_elt) == CONST_DOUBLE
|
||||
&& real_isneg (CONST_DOUBLE_REAL_VALUE (op2_elt)))
|
||||
{
|
||||
rtx n = GEN_INT (8 * GET_MODE_SIZE (<UNITMODE>mode) - 1);
|
||||
operands[0] = lowpart_subreg (<VIMODE256>mode, operands[0],
|
||||
<MODE>mode);
|
||||
operands[1] = lowpart_subreg (<VIMODE256>mode, operands[1],
|
||||
<MODE>mode);
|
||||
emit_insn (gen_lasx_xvbitseti_<lasxfmt> (operands[0],
|
||||
operands[1], n));
|
||||
DONE;
|
||||
}
|
||||
}
|
||||
|
||||
operands[2] = force_reg (<MODE>mode, operands[2]);
|
||||
operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
|
||||
|
||||
operands[4] = gen_reg_rtx (<MODE>mode);
|
||||
|
|
|
|||
|
|
@ -29,12 +29,25 @@ along with GCC; see the file COPYING3. If not see
|
|||
#include "loongarch-def.h"
|
||||
#include "loongarch-opts.h"
|
||||
#include "loongarch-cpu.h"
|
||||
#include "loongarch-cpucfg-map.h"
|
||||
#include "loongarch-str.h"
|
||||
|
||||
/* loongarch_isa_base_features defined here instead of loongarch-def.c
|
||||
because we need to use options.h. Pay attention on the order of elements
|
||||
in the initializer becaue ISO C++ does not allow C99 designated
|
||||
initializers! */
|
||||
|
||||
#define ISA_BASE_LA64V110_FEATURES \
|
||||
(OPTION_MASK_ISA_DIV32 | OPTION_MASK_ISA_LD_SEQ_SA \
|
||||
| OPTION_MASK_ISA_LAM_BH | OPTION_MASK_ISA_LAMCAS)
|
||||
|
||||
int64_t loongarch_isa_base_features[N_ISA_BASE_TYPES] = {
|
||||
/* [ISA_BASE_LA64V100] = */ 0,
|
||||
/* [ISA_BASE_LA64V110] = */ ISA_BASE_LA64V110_FEATURES,
|
||||
};
|
||||
|
||||
/* 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)
|
||||
|
|
@ -56,11 +69,8 @@ read_cpucfg_word (int wordno)
|
|||
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]);
|
||||
}
|
||||
for (int idx: cpucfg_useful_idx)
|
||||
cpucfg_cache[idx] = read_cpucfg_word (idx);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
|
|
@ -106,6 +116,10 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
native_cpu_type = CPU_LA464;
|
||||
break;
|
||||
|
||||
case 0x0014d000: /* LA664 */
|
||||
native_cpu_type = CPU_LA664;
|
||||
break;
|
||||
|
||||
default:
|
||||
/* Unknown PRID. */
|
||||
if (tune_native_p)
|
||||
|
|
@ -121,11 +135,15 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
int tmp;
|
||||
tgt->cpu_arch = native_cpu_type;
|
||||
|
||||
auto &preset = loongarch_cpu_default_isa[tgt->cpu_arch];
|
||||
|
||||
/* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].base
|
||||
With: base architecture (ARCH)
|
||||
At: cpucfg_words[1][1:0] */
|
||||
|
||||
#define PRESET_ARCH (loongarch_cpu_default_isa[tgt->cpu_arch].base)
|
||||
if (native_cpu_type != CPU_NATIVE)
|
||||
tmp = loongarch_cpu_default_isa[native_cpu_type].base;
|
||||
else
|
||||
switch (cpucfg_cache[1] & 0x3)
|
||||
{
|
||||
case 0x02:
|
||||
|
|
@ -135,24 +153,18 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
default:
|
||||
fatal_error (UNKNOWN_LOCATION,
|
||||
"unknown native base architecture %<0x%x%>, "
|
||||
"%qs failed", (unsigned int) (cpucfg_cache[1] & 0x3),
|
||||
"%qs failed",
|
||||
(unsigned int) (cpucfg_cache[1] & 0x3),
|
||||
"-m" OPTSTR_ARCH "=" STR_CPU_NATIVE);
|
||||
}
|
||||
|
||||
/* Check consistency with PRID presets. */
|
||||
if (native_cpu_type != CPU_NATIVE && tmp != PRESET_ARCH)
|
||||
warning (0, "base architecture %qs differs from PRID preset %qs",
|
||||
loongarch_isa_base_strings[tmp],
|
||||
loongarch_isa_base_strings[PRESET_ARCH]);
|
||||
|
||||
/* Use the native value anyways. */
|
||||
PRESET_ARCH = tmp;
|
||||
preset.base = tmp;
|
||||
|
||||
/* Fill: loongarch_cpu_default_isa[tgt->cpu_arch].fpu
|
||||
With: FPU type (FP, FP_SP, FP_DP)
|
||||
At: cpucfg_words[2][2:0] */
|
||||
|
||||
#define PRESET_FPU (loongarch_cpu_default_isa[tgt->cpu_arch].fpu)
|
||||
switch (cpucfg_cache[2] & 0x7)
|
||||
{
|
||||
case 0x07:
|
||||
|
|
@ -175,20 +187,19 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
}
|
||||
|
||||
/* Check consistency with PRID presets. */
|
||||
if (native_cpu_type != CPU_NATIVE && tmp != PRESET_FPU)
|
||||
if (native_cpu_type != CPU_NATIVE && tmp != preset.fpu)
|
||||
warning (0, "floating-point unit %qs differs from PRID preset %qs",
|
||||
loongarch_isa_ext_strings[tmp],
|
||||
loongarch_isa_ext_strings[PRESET_FPU]);
|
||||
loongarch_isa_ext_strings[preset.fpu]);
|
||||
|
||||
/* Use the native value anyways. */
|
||||
PRESET_FPU = tmp;
|
||||
preset.fpu = tmp;
|
||||
|
||||
|
||||
/* Fill: loongarch_cpu_default_isa[CPU_NATIVE].simd
|
||||
With: SIMD extension type (LSX, LASX)
|
||||
At: cpucfg_words[2][7:6] */
|
||||
|
||||
#define PRESET_SIMD (loongarch_cpu_default_isa[tgt->cpu_arch].simd)
|
||||
switch (cpucfg_cache[2] & 0xc0)
|
||||
{
|
||||
case 0xc0:
|
||||
|
|
@ -215,14 +226,34 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
/* Check consistency with PRID presets. */
|
||||
|
||||
/*
|
||||
if (native_cpu_type != CPU_NATIVE && tmp != PRESET_SIMD)
|
||||
if (native_cpu_type != CPU_NATIVE && tmp != preset.simd)
|
||||
warning (0, "SIMD extension %qs differs from PRID preset %qs",
|
||||
loongarch_isa_ext_strings[tmp],
|
||||
loongarch_isa_ext_strings[PRESET_SIMD]);
|
||||
loongarch_isa_ext_strings[preset.simd]);
|
||||
*/
|
||||
|
||||
/* Use the native value anyways. */
|
||||
PRESET_SIMD = tmp;
|
||||
preset.simd = tmp;
|
||||
|
||||
/* Features added during ISA evolution. */
|
||||
for (const auto &entry: cpucfg_map)
|
||||
if (cpucfg_cache[entry.cpucfg_word] & entry.cpucfg_bit)
|
||||
preset.evolution |= entry.isa_evolution_bit;
|
||||
|
||||
if (native_cpu_type != CPU_NATIVE)
|
||||
{
|
||||
/* Check if the local CPU really supports the features of the base
|
||||
ISA of probed native_cpu_type. If any feature is not detected,
|
||||
either GCC or the hardware is buggy. */
|
||||
auto base_isa_feature = loongarch_isa_base_features[preset.base];
|
||||
if ((preset.evolution & base_isa_feature) != base_isa_feature)
|
||||
warning (0,
|
||||
"detected base architecture %qs, but some of its "
|
||||
"features are not detected; the detected base "
|
||||
"architecture may be unreliable, only detected "
|
||||
"features will be enabled",
|
||||
loongarch_isa_base_strings[preset.base]);
|
||||
}
|
||||
}
|
||||
|
||||
if (tune_native_p)
|
||||
|
|
@ -233,7 +264,7 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
With: cache size info
|
||||
At: cpucfg_words[16:20][31:0] */
|
||||
|
||||
#define PRESET_CACHE (loongarch_cpu_cache[tgt->cpu_tune])
|
||||
auto &preset_cache = loongarch_cpu_cache[tgt->cpu_tune];
|
||||
struct loongarch_cache native_cache;
|
||||
int l1d_present = 0, l1u_present = 0;
|
||||
int l2d_present = 0;
|
||||
|
|
@ -264,8 +295,8 @@ fill_native_cpu_config (struct loongarch_target *tgt)
|
|||
>> 10; /* in kibibytes */
|
||||
|
||||
/* Use the native value anyways. */
|
||||
PRESET_CACHE.l1d_line_size = native_cache.l1d_line_size;
|
||||
PRESET_CACHE.l1d_size = native_cache.l1d_size;
|
||||
PRESET_CACHE.l2d_size = native_cache.l2d_size;
|
||||
preset_cache.l1d_line_size = native_cache.l1d_line_size;
|
||||
preset_cache.l1d_size = native_cache.l1d_size;
|
||||
preset_cache.l2d_size = native_cache.l2d_size;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,50 @@
|
|||
/* Generated automatically by "genstr" from "isa-evolution.in".
|
||||
Please do not edit this file directly.
|
||||
|
||||
Copyright (C) 2023 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_CPUCFG_MAP_H
|
||||
#define LOONGARCH_CPUCFG_MAP_H
|
||||
|
||||
#include "options.h"
|
||||
|
||||
static constexpr struct {
|
||||
int cpucfg_word;
|
||||
unsigned int cpucfg_bit;
|
||||
HOST_WIDE_INT isa_evolution_bit;
|
||||
} cpucfg_map[] = {
|
||||
{ 2, 1u << 26, OPTION_MASK_ISA_DIV32 },
|
||||
{ 2, 1u << 27, OPTION_MASK_ISA_LAM_BH },
|
||||
{ 2, 1u << 28, OPTION_MASK_ISA_LAMCAS },
|
||||
{ 3, 1u << 23, OPTION_MASK_ISA_LD_SEQ_SA },
|
||||
};
|
||||
|
||||
static constexpr int cpucfg_useful_idx[] = {
|
||||
0,
|
||||
1,
|
||||
2,
|
||||
3,
|
||||
16,
|
||||
17,
|
||||
18,
|
||||
19,
|
||||
};
|
||||
|
||||
static constexpr int N_CPUCFG_WORDS = 20;
|
||||
#endif /* LOONGARCH_CPUCFG_MAP_H */
|
||||
|
|
@ -28,6 +28,7 @@ loongarch_cpu_strings[N_TUNE_TYPES] = {
|
|||
[CPU_ABI_DEFAULT] = STR_CPU_ABI_DEFAULT,
|
||||
[CPU_LOONGARCH64] = STR_CPU_LOONGARCH64,
|
||||
[CPU_LA464] = STR_CPU_LA464,
|
||||
[CPU_LA664] = STR_CPU_LA664,
|
||||
};
|
||||
|
||||
struct loongarch_isa
|
||||
|
|
@ -42,6 +43,11 @@ loongarch_cpu_default_isa[N_ARCH_TYPES] = {
|
|||
.fpu = ISA_EXT_FPU64,
|
||||
.simd = ISA_EXT_SIMD_LASX,
|
||||
},
|
||||
[CPU_LA664] = {
|
||||
.base = ISA_BASE_LA64V110,
|
||||
.fpu = ISA_EXT_FPU64,
|
||||
.simd = ISA_EXT_SIMD_LASX,
|
||||
},
|
||||
};
|
||||
|
||||
struct loongarch_cache
|
||||
|
|
@ -58,6 +64,12 @@ loongarch_cpu_cache[N_TUNE_TYPES] = {
|
|||
.l2d_size = 256,
|
||||
.simultaneous_prefetches = 4,
|
||||
},
|
||||
[CPU_LA664] = {
|
||||
.l1d_line_size = 64,
|
||||
.l1d_size = 64,
|
||||
.l2d_size = 256,
|
||||
.simultaneous_prefetches = 4,
|
||||
},
|
||||
};
|
||||
|
||||
struct loongarch_align
|
||||
|
|
@ -70,6 +82,10 @@ loongarch_cpu_align[N_TUNE_TYPES] = {
|
|||
.function = "32",
|
||||
.label = "16",
|
||||
},
|
||||
[CPU_LA664] = {
|
||||
.function = "32",
|
||||
.label = "16",
|
||||
},
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -104,6 +120,9 @@ loongarch_cpu_rtx_cost_data[N_TUNE_TYPES] = {
|
|||
[CPU_LA464] = {
|
||||
DEFAULT_COSTS
|
||||
},
|
||||
[CPU_LA664] = {
|
||||
DEFAULT_COSTS
|
||||
},
|
||||
};
|
||||
|
||||
/* RTX costs to use when optimizing for size. */
|
||||
|
|
@ -127,6 +146,7 @@ loongarch_cpu_issue_rate[N_TUNE_TYPES] = {
|
|||
[CPU_NATIVE] = 4,
|
||||
[CPU_LOONGARCH64] = 4,
|
||||
[CPU_LA464] = 4,
|
||||
[CPU_LA664] = 6,
|
||||
};
|
||||
|
||||
int
|
||||
|
|
@ -134,6 +154,7 @@ loongarch_cpu_multipass_dfa_lookahead[N_TUNE_TYPES] = {
|
|||
[CPU_NATIVE] = 4,
|
||||
[CPU_LOONGARCH64] = 4,
|
||||
[CPU_LA464] = 4,
|
||||
[CPU_LA664] = 6,
|
||||
};
|
||||
|
||||
/* Wiring string definitions from loongarch-str.h to global arrays
|
||||
|
|
@ -144,6 +165,7 @@ loongarch_cpu_multipass_dfa_lookahead[N_TUNE_TYPES] = {
|
|||
const char*
|
||||
loongarch_isa_base_strings[N_ISA_BASE_TYPES] = {
|
||||
[ISA_BASE_LA64V100] = STR_ISA_BASE_LA64V100,
|
||||
[ISA_BASE_LA64V110] = STR_ISA_BASE_LA64V110,
|
||||
};
|
||||
|
||||
const char*
|
||||
|
|
|
|||
|
|
@ -46,6 +46,7 @@ along with GCC; see the file COPYING3. If not see
|
|||
#ifndef LOONGARCH_DEF_H
|
||||
#define LOONGARCH_DEF_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include "loongarch-tune.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
|
@ -54,8 +55,16 @@ extern "C" {
|
|||
|
||||
/* enum isa_base */
|
||||
extern const char* loongarch_isa_base_strings[];
|
||||
|
||||
/* LoongArch V1.00. */
|
||||
#define ISA_BASE_LA64V100 0
|
||||
#define N_ISA_BASE_TYPES 1
|
||||
/* LoongArch V1.10. */
|
||||
#define ISA_BASE_LA64V110 1
|
||||
#define N_ISA_BASE_TYPES 2
|
||||
|
||||
/* Unlike other arrays, this is defined in loongarch-cpu.cc. The problem is
|
||||
we cannot use the C++ header options.h in loongarch-def.c. */
|
||||
extern int64_t loongarch_isa_base_features[];
|
||||
|
||||
/* enum isa_ext_* */
|
||||
extern const char* loongarch_isa_ext_strings[];
|
||||
|
|
@ -118,6 +127,12 @@ struct loongarch_isa
|
|||
int base; /* ISA_BASE_ */
|
||||
int fpu; /* ISA_EXT_FPU_ */
|
||||
int simd; /* ISA_EXT_SIMD_ */
|
||||
|
||||
/* ISA evolution features implied by -march=, for -march=native probed
|
||||
via CPUCFG. The features implied by base may be not included here.
|
||||
|
||||
Using int64_t instead of HOST_WIDE_INT for C compatibility. */
|
||||
int64_t evolution;
|
||||
};
|
||||
|
||||
struct loongarch_abi
|
||||
|
|
@ -141,8 +156,9 @@ struct loongarch_target
|
|||
#define CPU_ABI_DEFAULT 1
|
||||
#define CPU_LOONGARCH64 2
|
||||
#define CPU_LA464 3
|
||||
#define N_ARCH_TYPES 4
|
||||
#define N_TUNE_TYPES 4
|
||||
#define CPU_LA664 4
|
||||
#define N_ARCH_TYPES 5
|
||||
#define N_TUNE_TYPES 5
|
||||
|
||||
/* parallel tables. */
|
||||
extern const char* loongarch_cpu_strings[];
|
||||
|
|
|
|||
|
|
@ -51,9 +51,23 @@ along with GCC; see the file COPYING3. If not see
|
|||
"%{G*} %{,ada:-gnatea %{mabi=*} -gnatez} " \
|
||||
"%(subtarget_cc1_spec)"
|
||||
|
||||
#if HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION
|
||||
#define ASM_MRELAX_DEFAULT "%{!mrelax:%{!mno-relax:-mrelax}}"
|
||||
#else
|
||||
#define ASM_MRELAX_DEFAULT "%{!mrelax:%{!mno-relax:-mno-relax}}"
|
||||
#endif
|
||||
|
||||
#if HAVE_AS_MRELAX_OPTION
|
||||
#define ASM_MRELAX_SPEC \
|
||||
"%{!mno-pass-mrelax-to-as:%{mrelax} %{mno-relax} " ASM_MRELAX_DEFAULT "}"
|
||||
#else
|
||||
#define ASM_MRELAX_SPEC \
|
||||
"%{mpass-mrelax-to-as:%{mrelax} %{mno-relax} " ASM_MRELAX_DEFAULT "}"
|
||||
#endif
|
||||
|
||||
#undef ASM_SPEC
|
||||
#define ASM_SPEC \
|
||||
"%{mabi=*} %{mno-relax} %(subtarget_asm_spec)"
|
||||
"%{mabi=*} " ASM_MRELAX_SPEC " %(subtarget_asm_spec)"
|
||||
|
||||
|
||||
extern const char*
|
||||
|
|
|
|||
|
|
@ -284,6 +284,9 @@ config_target_isa:
|
|||
/* Get default ISA from "-march" or its default value. */
|
||||
t.isa = loongarch_cpu_default_isa[t.cpu_arch];
|
||||
|
||||
if (t.cpu_arch != CPU_NATIVE)
|
||||
t.isa.evolution |= loongarch_isa_base_features[t.isa.base];
|
||||
|
||||
/* Apply incremental changes. */
|
||||
/* "-march=native" overrides the default FPU type. */
|
||||
|
||||
|
|
@ -552,17 +555,17 @@ isa_default_abi (const struct loongarch_isa *isa)
|
|||
switch (isa->fpu)
|
||||
{
|
||||
case ISA_EXT_FPU64:
|
||||
if (isa->base == ISA_BASE_LA64V100)
|
||||
if (isa->base >= ISA_BASE_LA64V100)
|
||||
abi.base = ABI_BASE_LP64D;
|
||||
break;
|
||||
|
||||
case ISA_EXT_FPU32:
|
||||
if (isa->base == ISA_BASE_LA64V100)
|
||||
if (isa->base >= ISA_BASE_LA64V100)
|
||||
abi.base = ABI_BASE_LP64F;
|
||||
break;
|
||||
|
||||
case ISA_EXT_NONE:
|
||||
if (isa->base == ISA_BASE_LA64V100)
|
||||
if (isa->base >= ISA_BASE_LA64V100)
|
||||
abi.base = ABI_BASE_LP64S;
|
||||
break;
|
||||
|
||||
|
|
@ -582,7 +585,7 @@ isa_base_compat_p (const struct loongarch_isa *set1,
|
|||
switch (set2->base)
|
||||
{
|
||||
case ISA_BASE_LA64V100:
|
||||
return (set1->base == ISA_BASE_LA64V100);
|
||||
return (set1->base >= ISA_BASE_LA64V100);
|
||||
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
|
|
|
|||
|
|
@ -76,7 +76,8 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target,
|
|||
#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_64BIT (la_target.isa.base == ISA_BASE_LA64V100 \
|
||||
|| la_target.isa.base == ISA_BASE_LA64V110)
|
||||
#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)
|
||||
|
|
@ -85,9 +86,10 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target,
|
|||
|| la_target.isa.simd == ISA_EXT_SIMD_LASX)
|
||||
#define ISA_HAS_LASX (la_target.isa.simd == ISA_EXT_SIMD_LASX)
|
||||
|
||||
|
||||
/* TARGET_ macros for use in *.md template conditionals */
|
||||
#define TARGET_uARCH_LA464 (la_target.cpu_tune == CPU_LA464)
|
||||
#define TARGET_uARCH_LA664 (la_target.cpu_tune == CPU_LA664)
|
||||
#define ISA_BASE_IS_LA64V110 (la_target.isa.base == ISA_BASE_LA64V110)
|
||||
|
||||
/* Note: optimize_size may vary across functions,
|
||||
while -m[no]-memcpy imposes a global constraint. */
|
||||
|
|
@ -97,10 +99,18 @@ loongarch_update_gcc_opt_status (struct loongarch_target *target,
|
|||
#define HAVE_AS_EXPLICIT_RELOCS 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_AS_SUPPORT_CALL36
|
||||
#define HAVE_AS_SUPPORT_CALL36 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_AS_MRELAX_OPTION
|
||||
#define HAVE_AS_MRELAX_OPTION 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_AS_COND_BRANCH_RELAXATION
|
||||
#define HAVE_AS_COND_BRANCH_RELAXATION 0
|
||||
#endif
|
||||
|
||||
#ifndef HAVE_AS_TLS
|
||||
#define HAVE_AS_TLS 0
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/* Generated automatically by "genstr" from "loongarch-strings".
|
||||
Please do not edit this file directly.
|
||||
/* Generated automatically by "genstr" from "loongarch-strings" and
|
||||
"isa-evolution.in". Please do not edit this file directly.
|
||||
|
||||
Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
Contributed by Loongson Ltd.
|
||||
|
|
@ -30,8 +30,10 @@ along with GCC; see the file COPYING3. If not see
|
|||
#define STR_CPU_ABI_DEFAULT "abi-default"
|
||||
#define STR_CPU_LOONGARCH64 "loongarch64"
|
||||
#define STR_CPU_LA464 "la464"
|
||||
#define STR_CPU_LA664 "la664"
|
||||
|
||||
#define STR_ISA_BASE_LA64V100 "la64"
|
||||
#define STR_ISA_BASE_LA64V110 "la64v1.1"
|
||||
|
||||
#define OPTSTR_ISA_EXT_FPU "fpu"
|
||||
#define STR_NONE "none"
|
||||
|
|
@ -67,4 +69,9 @@ along with GCC; see the file COPYING3. If not see
|
|||
#define STR_EXPLICIT_RELOCS_NONE "none"
|
||||
#define STR_EXPLICIT_RELOCS_ALWAYS "always"
|
||||
|
||||
#define OPTSTR_DIV32 "div32"
|
||||
#define OPTSTR_LAM_BH "lam-bh"
|
||||
#define OPTSTR_LAMCAS "lamcas"
|
||||
#define OPTSTR_LD_SEQ_SA "ld-seq-sa"
|
||||
|
||||
#endif /* LOONGARCH_STR_H */
|
||||
|
|
|
|||
|
|
@ -3006,12 +3006,16 @@ loongarch_legitimize_call_address (rtx addr)
|
|||
|
||||
enum loongarch_symbol_type symbol_type = loongarch_classify_symbol (addr);
|
||||
|
||||
/* Split function call insn 'bl sym' or 'bl %plt(sym)' to :
|
||||
/* If add the compilation option '-cmodel=medium', and the assembler does
|
||||
not support call36. The following sequence of instructions will be
|
||||
used for the function call:
|
||||
pcalau12i $rd, %pc_hi20(sym)
|
||||
jr $rd, %pc_lo12(sym). */
|
||||
jr $rd, %pc_lo12(sym)
|
||||
*/
|
||||
|
||||
if (TARGET_CMODEL_MEDIUM
|
||||
&& TARGET_EXPLICIT_RELOCS
|
||||
&& !HAVE_AS_SUPPORT_CALL36
|
||||
&& (la_opt_explicit_relocs != EXPLICIT_RELOCS_NONE)
|
||||
&& (SYMBOL_REF_P (addr) || LABEL_REF_P (addr))
|
||||
&& (symbol_type == SYMBOL_PCREL
|
||||
|| (symbol_type == SYMBOL_GOT_DISP && flag_plt)))
|
||||
|
|
@ -3893,11 +3897,9 @@ loongarch_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
|
|||
case scalar_stmt:
|
||||
case scalar_load:
|
||||
case vector_stmt:
|
||||
case vector_load:
|
||||
case vec_to_scalar:
|
||||
case scalar_to_vec:
|
||||
case scalar_store:
|
||||
case vector_store:
|
||||
return 1;
|
||||
|
||||
case vec_promote_demote:
|
||||
|
|
@ -3905,6 +3907,8 @@ loongarch_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
|
|||
return LASX_SUPPORTED_MODE_P (mode)
|
||||
&& !LSX_SUPPORTED_MODE_P (mode) ? 2 : 1;
|
||||
|
||||
case vector_load:
|
||||
case vector_store:
|
||||
case unaligned_load:
|
||||
case unaligned_store:
|
||||
return 2;
|
||||
|
|
@ -5813,16 +5817,12 @@ loongarch_print_operand_punct_valid_p (unsigned char code)
|
|||
static bool
|
||||
loongarch_memmodel_needs_rel_acq_fence (enum memmodel model)
|
||||
{
|
||||
switch (model)
|
||||
switch (memmodel_base (model))
|
||||
{
|
||||
case MEMMODEL_ACQ_REL:
|
||||
case MEMMODEL_SEQ_CST:
|
||||
case MEMMODEL_SYNC_SEQ_CST:
|
||||
case MEMMODEL_RELEASE:
|
||||
case MEMMODEL_SYNC_RELEASE:
|
||||
case MEMMODEL_ACQUIRE:
|
||||
case MEMMODEL_CONSUME:
|
||||
case MEMMODEL_SYNC_ACQUIRE:
|
||||
return true;
|
||||
|
||||
case MEMMODEL_RELAXED:
|
||||
|
|
@ -5833,27 +5833,27 @@ loongarch_memmodel_needs_rel_acq_fence (enum memmodel model)
|
|||
}
|
||||
}
|
||||
|
||||
/* Return true if a FENCE should be emitted to before a memory access to
|
||||
implement the release portion of memory model MODEL. */
|
||||
/* Return true if a FENCE should be emitted after a failed CAS to
|
||||
implement the acquire semantic of failure_memorder. */
|
||||
|
||||
static bool
|
||||
loongarch_memmodel_needs_release_fence (enum memmodel model)
|
||||
loongarch_cas_failure_memorder_needs_acquire (enum memmodel model)
|
||||
{
|
||||
switch (model)
|
||||
switch (memmodel_base (model))
|
||||
{
|
||||
case MEMMODEL_ACQUIRE:
|
||||
case MEMMODEL_ACQ_REL:
|
||||
case MEMMODEL_SEQ_CST:
|
||||
case MEMMODEL_SYNC_SEQ_CST:
|
||||
case MEMMODEL_RELEASE:
|
||||
case MEMMODEL_SYNC_RELEASE:
|
||||
return true;
|
||||
|
||||
case MEMMODEL_ACQUIRE:
|
||||
case MEMMODEL_CONSUME:
|
||||
case MEMMODEL_SYNC_ACQUIRE:
|
||||
case MEMMODEL_RELAXED:
|
||||
case MEMMODEL_RELEASE:
|
||||
return false;
|
||||
|
||||
/* MEMMODEL_CONSUME is deliberately not handled because it's always
|
||||
replaced by MEMMODEL_ACQUIRE as at now. If you see an ICE caused by
|
||||
MEMMODEL_CONSUME, read the change (re)introducing it carefully and
|
||||
decide what to do. See PR 59448 and get_memmodel in builtins.cc. */
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
|
|
@ -5966,7 +5966,8 @@ loongarch_print_operand_reloc (FILE *file, rtx op, bool hi64_part,
|
|||
'd' Print CONST_INT OP in decimal.
|
||||
'E' Print CONST_INT OP element 0 of a replicated CONST_VECTOR in decimal.
|
||||
'F' Print the FPU branch condition for comparison OP.
|
||||
'G' Print a DBAR insn if the memory model requires a release.
|
||||
'G' Print a DBAR insn for CAS failure (with an acquire semantic if
|
||||
needed, otherwise a simple load-load barrier).
|
||||
'H' Print address 52-61bit relocation associated with OP.
|
||||
'h' Print the high-part relocation associated with OP.
|
||||
'i' Print i if the operand is not a register.
|
||||
|
|
@ -6057,8 +6058,11 @@ loongarch_print_operand (FILE *file, rtx op, int letter)
|
|||
break;
|
||||
|
||||
case 'G':
|
||||
if (loongarch_memmodel_needs_release_fence ((enum memmodel) INTVAL (op)))
|
||||
fputs ("dbar\t0", file);
|
||||
if (loongarch_cas_failure_memorder_needs_acquire (
|
||||
memmodel_from_int (INTVAL (op))))
|
||||
fputs ("dbar\t0b10100", file);
|
||||
else if (!TARGET_LD_SEQ_SA)
|
||||
fputs ("dbar\t0x700", file);
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
|
|
@ -7432,7 +7436,7 @@ loongarch_option_override_internal (struct gcc_options *opts,
|
|||
|
||||
if (la_opt_explicit_relocs == M_OPT_UNSET)
|
||||
la_opt_explicit_relocs = (HAVE_AS_EXPLICIT_RELOCS
|
||||
? (HAVE_AS_MRELAX_OPTION
|
||||
? (loongarch_mrelax
|
||||
? EXPLICIT_RELOCS_AUTO
|
||||
: EXPLICIT_RELOCS_ALWAYS)
|
||||
: EXPLICIT_RELOCS_NONE);
|
||||
|
|
@ -7451,6 +7455,10 @@ loongarch_option_override_internal (struct gcc_options *opts,
|
|||
if (loongarch_branch_cost == 0)
|
||||
loongarch_branch_cost = loongarch_cost->branch_cost;
|
||||
|
||||
/* If the user hasn't disabled a feature added during ISA evolution,
|
||||
use the processor's default. */
|
||||
isa_evolution |= (la_target.isa.evolution &
|
||||
~global_options_set.x_isa_evolution);
|
||||
|
||||
/* Enable sw prefetching at -O3 and higher. */
|
||||
if (opts->x_flag_prefetch_loop_arrays < 0
|
||||
|
|
@ -10169,6 +10177,7 @@ loongarch_cpu_sched_reassociation_width (struct loongarch_target *target,
|
|||
{
|
||||
case CPU_LOONGARCH64:
|
||||
case CPU_LA464:
|
||||
case CPU_LA664:
|
||||
/* Vector part. */
|
||||
if (LSX_SUPPORTED_MODE_P (mode) || LASX_SUPPORTED_MODE_P (mode))
|
||||
{
|
||||
|
|
@ -11429,6 +11438,32 @@ loongarch_builtin_support_vector_misalignment (machine_mode mode,
|
|||
is_packed);
|
||||
}
|
||||
|
||||
/* If -fverbose-asm, dump some info for debugging. */
|
||||
static void
|
||||
loongarch_asm_code_end (void)
|
||||
{
|
||||
#define DUMP_FEATURE(PRED) \
|
||||
fprintf (asm_out_file, "%s %s: %s\n", ASM_COMMENT_START, #PRED, \
|
||||
(PRED) ? "enabled" : "disabled")
|
||||
|
||||
if (flag_verbose_asm)
|
||||
{
|
||||
fprintf (asm_out_file, "\n%s CPU: %s\n", ASM_COMMENT_START,
|
||||
loongarch_cpu_strings [la_target.cpu_arch]);
|
||||
fprintf (asm_out_file, "%s Tune: %s\n", ASM_COMMENT_START,
|
||||
loongarch_cpu_strings [la_target.cpu_tune]);
|
||||
fprintf (asm_out_file, "%s Base ISA: %s\n", ASM_COMMENT_START,
|
||||
loongarch_isa_base_strings [la_target.isa.base]);
|
||||
DUMP_FEATURE (TARGET_DIV32);
|
||||
DUMP_FEATURE (TARGET_LAM_BH);
|
||||
DUMP_FEATURE (TARGET_LAMCAS);
|
||||
DUMP_FEATURE (TARGET_LD_SEQ_SA);
|
||||
}
|
||||
|
||||
fputs ("\n\n", asm_out_file);
|
||||
#undef DUMP_FEATURE
|
||||
}
|
||||
|
||||
/* Initialize the GCC target structure. */
|
||||
#undef TARGET_ASM_ALIGNED_HI_OP
|
||||
#define TARGET_ASM_ALIGNED_HI_OP "\t.half\t"
|
||||
|
|
@ -11448,6 +11483,9 @@ loongarch_builtin_support_vector_misalignment (machine_mode mode,
|
|||
#undef TARGET_ASM_FUNCTION_RODATA_SECTION
|
||||
#define TARGET_ASM_FUNCTION_RODATA_SECTION loongarch_function_rodata_section
|
||||
|
||||
#undef TARGET_ASM_CODE_END
|
||||
#define TARGET_ASM_CODE_END loongarch_asm_code_end
|
||||
|
||||
#undef TARGET_SCHED_INIT
|
||||
#define TARGET_SCHED_INIT loongarch_sched_init
|
||||
#undef TARGET_SCHED_REORDER
|
||||
|
|
|
|||
|
|
@ -1239,3 +1239,8 @@ struct GTY (()) machine_function
|
|||
|
||||
#define TARGET_EXPLICIT_RELOCS \
|
||||
(la_opt_explicit_relocs == EXPLICIT_RELOCS_ALWAYS)
|
||||
|
||||
#define CLZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
|
||||
((VALUE) = GET_MODE_UNIT_BITSIZE (MODE), 2)
|
||||
#define CTZ_DEFINED_VALUE_AT_ZERO(MODE, VALUE) \
|
||||
((VALUE) = GET_MODE_UNIT_BITSIZE (MODE), 2)
|
||||
|
|
|
|||
|
|
@ -408,6 +408,10 @@
|
|||
;; st.w.
|
||||
(define_mode_iterator ST_ANY [QHWD ANYF])
|
||||
|
||||
;; A mode for anything legal as a input of a div or mod instruction.
|
||||
(define_mode_iterator DIV [(DI "TARGET_64BIT")
|
||||
(SI "!TARGET_64BIT || TARGET_DIV32")])
|
||||
|
||||
;; In GPR templates, a string like "mul.<d>" will expand to "mul.w" in the
|
||||
;; 32-bit version and "mul.d" in the 64-bit version.
|
||||
(define_mode_attr d [(SI "w") (DI "d")])
|
||||
|
|
@ -914,7 +918,7 @@
|
|||
(match_operand:GPR 2 "register_operand")))]
|
||||
""
|
||||
{
|
||||
if (GET_MODE (operands[0]) == SImode && TARGET_64BIT)
|
||||
if (GET_MODE (operands[0]) == SImode && TARGET_64BIT && !TARGET_DIV32)
|
||||
{
|
||||
rtx reg1 = gen_reg_rtx (DImode);
|
||||
rtx reg2 = gen_reg_rtx (DImode);
|
||||
|
|
@ -934,9 +938,9 @@
|
|||
})
|
||||
|
||||
(define_insn "*<optab><mode>3"
|
||||
[(set (match_operand:X 0 "register_operand" "=r,&r,&r")
|
||||
(any_div:X (match_operand:X 1 "register_operand" "r,r,0")
|
||||
(match_operand:X 2 "register_operand" "r,r,r")))]
|
||||
[(set (match_operand:DIV 0 "register_operand" "=r,&r,&r")
|
||||
(any_div:DIV (match_operand:DIV 1 "register_operand" "r,r,0")
|
||||
(match_operand:DIV 2 "register_operand" "r,r,r")))]
|
||||
""
|
||||
{
|
||||
return loongarch_output_division ("<insn>.<d><u>\t%0,%1,%2", operands);
|
||||
|
|
@ -949,6 +953,23 @@
|
|||
(const_string "yes")
|
||||
(const_string "no")))])
|
||||
|
||||
(define_insn "<optab>si3_extended"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r,&r,&r")
|
||||
(sign_extend
|
||||
(any_div:SI (match_operand:SI 1 "register_operand" "r,r,0")
|
||||
(match_operand:SI 2 "register_operand" "r,r,r"))))]
|
||||
"TARGET_64BIT && TARGET_DIV32"
|
||||
{
|
||||
return loongarch_output_division ("<insn>.w<u>\t%0,%1,%2", operands);
|
||||
}
|
||||
[(set_attr "type" "idiv")
|
||||
(set_attr "mode" "SI")
|
||||
(set (attr "enabled")
|
||||
(if_then_else
|
||||
(match_test "!!which_alternative == loongarch_check_zero_div_p()")
|
||||
(const_string "yes")
|
||||
(const_string "no")))])
|
||||
|
||||
(define_insn "<optab>di3_fake"
|
||||
[(set (match_operand:DI 0 "register_operand" "=r,&r,&r")
|
||||
(sign_extend:DI
|
||||
|
|
@ -957,7 +978,7 @@
|
|||
(any_div:DI (match_operand:DI 1 "register_operand" "r,r,0")
|
||||
(match_operand:DI 2 "register_operand" "r,r,r")) 0)]
|
||||
UNSPEC_FAKE_ANY_DIV)))]
|
||||
"TARGET_64BIT"
|
||||
"TARGET_64BIT && !TARGET_DIV32"
|
||||
{
|
||||
return loongarch_output_division ("<insn>.w<u>\t%0,%1,%2", operands);
|
||||
}
|
||||
|
|
@ -3274,7 +3295,13 @@
|
|||
XEXP (target, 1),
|
||||
operands[1]));
|
||||
else
|
||||
emit_call_insn (gen_sibcall_internal (target, operands[1]));
|
||||
{
|
||||
rtx call = emit_call_insn (gen_sibcall_internal (target, operands[1]));
|
||||
|
||||
if (TARGET_CMODEL_MEDIUM && !REG_P (target))
|
||||
clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
|
||||
gen_rtx_REG (Pmode, T0_REGNUM));
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
|
|
@ -3282,10 +3309,25 @@
|
|||
[(call (mem:SI (match_operand 0 "call_insn_operand" "j,c,b"))
|
||||
(match_operand 1 "" ""))]
|
||||
"SIBLING_CALL_P (insn)"
|
||||
"@
|
||||
jr\t%0
|
||||
b\t%0
|
||||
b\t%%plt(%0)"
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return "jr\t%0";
|
||||
case 1:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r12,%%call36(%0)\n\tjirl\t$r0,$r12,0";
|
||||
else
|
||||
return "b\t%0";
|
||||
case 2:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r12,%%call36(%0)\n\tjirl\t$r0,$r12,0";
|
||||
else
|
||||
return "b\t%%plt(%0)";
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set_attr "jirl" "indirect,direct,direct")])
|
||||
|
||||
(define_insn "@sibcall_internal_1<mode>"
|
||||
|
|
@ -3318,9 +3360,17 @@
|
|||
operands[2],
|
||||
arg2));
|
||||
else
|
||||
emit_call_insn (gen_sibcall_value_multiple_internal (arg1, target,
|
||||
{
|
||||
rtx call
|
||||
= emit_call_insn (gen_sibcall_value_multiple_internal (arg1,
|
||||
target,
|
||||
operands[2],
|
||||
arg2));
|
||||
|
||||
if (TARGET_CMODEL_MEDIUM && !REG_P (target))
|
||||
clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
|
||||
gen_rtx_REG (Pmode, T0_REGNUM));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -3334,8 +3384,15 @@
|
|||
XEXP (target, 1),
|
||||
operands[2]));
|
||||
else
|
||||
emit_call_insn (gen_sibcall_value_internal (operands[0], target,
|
||||
{
|
||||
rtx call = emit_call_insn (gen_sibcall_value_internal (operands[0],
|
||||
target,
|
||||
operands[2]));
|
||||
|
||||
if (TARGET_CMODEL_MEDIUM && !REG_P (target))
|
||||
clobber_reg (&CALL_INSN_FUNCTION_USAGE (call),
|
||||
gen_rtx_REG (Pmode, T0_REGNUM));
|
||||
}
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
|
@ -3345,10 +3402,25 @@
|
|||
(call (mem:SI (match_operand 1 "call_insn_operand" "j,c,b"))
|
||||
(match_operand 2 "" "")))]
|
||||
"SIBLING_CALL_P (insn)"
|
||||
"@
|
||||
jr\t%1
|
||||
b\t%1
|
||||
b\t%%plt(%1)"
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return "jr\t%1";
|
||||
case 1:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
|
||||
else
|
||||
return "b\t%1";
|
||||
case 2:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
|
||||
else
|
||||
return "b\t%%plt(%1)";
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set_attr "jirl" "indirect,direct,direct")])
|
||||
|
||||
(define_insn "@sibcall_value_internal_1<mode>"
|
||||
|
|
@ -3368,10 +3440,25 @@
|
|||
(call (mem:SI (match_dup 1))
|
||||
(match_dup 2)))]
|
||||
"SIBLING_CALL_P (insn)"
|
||||
"@
|
||||
jr\t%1
|
||||
b\t%1
|
||||
b\t%%plt(%1)"
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return "jr\t%1";
|
||||
case 1:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
|
||||
else
|
||||
return "b\t%1";
|
||||
case 2:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r12,%%call36(%1)\n\tjirl\t$r0,$r12,0";
|
||||
else
|
||||
return "b\t%%plt(%1)";
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set_attr "jirl" "indirect,direct,direct")])
|
||||
|
||||
(define_insn "@sibcall_value_multiple_internal_1<mode>"
|
||||
|
|
@ -3411,10 +3498,25 @@
|
|||
(match_operand 1 "" ""))
|
||||
(clobber (reg:SI RETURN_ADDR_REGNUM))]
|
||||
""
|
||||
"@
|
||||
jirl\t$r1,%0,0
|
||||
bl\t%0
|
||||
bl\t%%plt(%0)"
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return "jirl\t$r1,%0,0";
|
||||
case 1:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r1,%%call36(%0)\n\tjirl\t$r1,$r1,0";
|
||||
else
|
||||
return "bl\t%0";
|
||||
case 2:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r1,%%call36(%0)\n\tjirl\t$r1,$r1,0";
|
||||
else
|
||||
return "bl\t%%plt(%0)";
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set_attr "jirl" "indirect,direct,direct")])
|
||||
|
||||
(define_insn "@call_internal_1<mode>"
|
||||
|
|
@ -3473,10 +3575,25 @@
|
|||
(match_operand 2 "" "")))
|
||||
(clobber (reg:SI RETURN_ADDR_REGNUM))]
|
||||
""
|
||||
"@
|
||||
jirl\t$r1,%1,0
|
||||
bl\t%1
|
||||
bl\t%%plt(%1)"
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return "jirl\t$r1,%1,0";
|
||||
case 1:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
|
||||
else
|
||||
return "bl\t%1";
|
||||
case 2:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
|
||||
else
|
||||
return "bl\t%%plt(%1)";
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set_attr "jirl" "indirect,direct,direct")])
|
||||
|
||||
(define_insn "@call_value_internal_1<mode>"
|
||||
|
|
@ -3498,10 +3615,25 @@
|
|||
(match_dup 2)))
|
||||
(clobber (reg:SI RETURN_ADDR_REGNUM))]
|
||||
""
|
||||
"@
|
||||
jirl\t$r1,%1,0
|
||||
bl\t%1
|
||||
bl\t%%plt(%1)"
|
||||
{
|
||||
switch (which_alternative)
|
||||
{
|
||||
case 0:
|
||||
return "jirl\t$r1,%1,0";
|
||||
case 1:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
|
||||
else
|
||||
return "bl\t%1";
|
||||
case 2:
|
||||
if (TARGET_CMODEL_MEDIUM)
|
||||
return "pcaddu18i\t$r1,%%call36(%1)\n\tjirl\t$r1,$r1,0";
|
||||
else
|
||||
return "bl\t%%plt(%1)";
|
||||
default:
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set_attr "jirl" "indirect,direct,direct")])
|
||||
|
||||
(define_insn "@call_value_multiple_internal_1<mode>"
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
; Generated by "genstr" from the template "loongarch.opt.in"
|
||||
; and definitions from "loongarch-strings".
|
||||
; and definitions from "loongarch-strings" and "isa-evolution.in".
|
||||
;
|
||||
; 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".
|
||||
; if you change "loongarch.opt.in", "loongarch-strings", or
|
||||
; "isa-evolution.in".
|
||||
;
|
||||
; Copyright (C) 2021-2023 Free Software Foundation, Inc.
|
||||
;
|
||||
|
|
@ -39,6 +40,9 @@ Basic ISAs of LoongArch:
|
|||
EnumValue
|
||||
Enum(isa_base) String(la64) Value(ISA_BASE_LA64V100)
|
||||
|
||||
EnumValue
|
||||
Enum(isa_base) String(la64v1.1) Value(ISA_BASE_LA64V110)
|
||||
|
||||
;; ISA extensions / adjustments
|
||||
Enum
|
||||
Name(isa_ext_fpu) Type(int)
|
||||
|
|
@ -114,6 +118,9 @@ Enum(cpu_type) String(loongarch64) Value(CPU_LOONGARCH64)
|
|||
EnumValue
|
||||
Enum(cpu_type) String(la464) Value(CPU_LA464)
|
||||
|
||||
EnumValue
|
||||
Enum(cpu_type) String(la664) Value(CPU_LA664)
|
||||
|
||||
march=
|
||||
Target RejectNegative Joined Enum(cpu_type) Var(la_opt_cpu_arch) Init(M_OPT_UNSET)
|
||||
-march=PROCESSOR Generate code for the given PROCESSOR ISA.
|
||||
|
|
@ -230,10 +237,14 @@ Target Var(TARGET_DIRECT_EXTERN_ACCESS) Init(0)
|
|||
Avoid using the GOT to access external symbols.
|
||||
|
||||
mrelax
|
||||
Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION)
|
||||
Target Var(loongarch_mrelax) Init(HAVE_AS_MRELAX_OPTION && HAVE_AS_COND_BRANCH_RELAXATION)
|
||||
Take advantage of linker relaxations to reduce the number of instructions
|
||||
required to materialize symbol addresses.
|
||||
|
||||
mpass-mrelax-to-as
|
||||
Target Var(loongarch_pass_mrelax_to_as) Init(HAVE_AS_MRELAX_OPTION)
|
||||
Pass -mrelax or -mno-relax option to the assembler.
|
||||
|
||||
-param=loongarch-vect-unroll-limit=
|
||||
Target Joined UInteger Var(loongarch_vect_unroll_limit) Init(6) IntegerRange(1, 64) Param
|
||||
Used to limit unroll factor which indicates how much the autovectorizer may
|
||||
|
|
@ -244,3 +255,26 @@ Target Undocumented Joined UInteger Var(loongarch_vect_issue_info) Init(4) Integ
|
|||
Indicate how many non memory access vector instructions can be issued per
|
||||
cycle, it's used in unroll factor determination for autovectorizer. The
|
||||
default value is 4.
|
||||
|
||||
; Features added during ISA evolution. This concept is different from ISA
|
||||
; extension, read Section 1.5 of LoongArch v1.10 Volume 1 for the
|
||||
; explanation. These features may be implemented and enumerated with
|
||||
; CPUCFG independantly, so we use bit flags to specify them.
|
||||
Variable
|
||||
HOST_WIDE_INT isa_evolution = 0
|
||||
|
||||
mdiv32
|
||||
Target Mask(ISA_DIV32) Var(isa_evolution)
|
||||
Support div.w[u] and mod.w[u] instructions with inputs not sign-extended.
|
||||
|
||||
mlam-bh
|
||||
Target Mask(ISA_LAM_BH) Var(isa_evolution)
|
||||
Support am{swap/add}[_db].{b/h} instructions.
|
||||
|
||||
mlamcas
|
||||
Target Mask(ISA_LAMCAS) Var(isa_evolution)
|
||||
Support amcas[_db].{b/h/w/d} instructions.
|
||||
|
||||
mld-seq-sa
|
||||
Target Mask(ISA_LD_SEQ_SA) Var(isa_evolution)
|
||||
Do not need load-load barriers (dbar 0x700).
|
||||
|
|
|
|||
|
|
@ -2873,11 +2873,31 @@
|
|||
(match_operand:FLSX 1 "register_operand")))
|
||||
(set (match_dup 5)
|
||||
(and:FLSX (match_dup 3)
|
||||
(match_operand:FLSX 2 "register_operand")))
|
||||
(match_operand:FLSX 2 "reg_or_vector_same_val_operand")))
|
||||
(set (match_operand:FLSX 0 "register_operand")
|
||||
(ior:FLSX (match_dup 4) (match_dup 5)))]
|
||||
"ISA_HAS_LSX"
|
||||
{
|
||||
/* copysign (x, -1) should instead be expanded as setting the sign
|
||||
bit. */
|
||||
if (!REG_P (operands[2]))
|
||||
{
|
||||
rtx op2_elt = unwrap_const_vec_duplicate (operands[2]);
|
||||
if (GET_CODE (op2_elt) == CONST_DOUBLE
|
||||
&& real_isneg (CONST_DOUBLE_REAL_VALUE (op2_elt)))
|
||||
{
|
||||
rtx n = GEN_INT (8 * GET_MODE_SIZE (<UNITMODE>mode) - 1);
|
||||
operands[0] = lowpart_subreg (<VIMODE>mode, operands[0],
|
||||
<MODE>mode);
|
||||
operands[1] = lowpart_subreg (<VIMODE>mode, operands[1],
|
||||
<MODE>mode);
|
||||
emit_insn (gen_lsx_vbitseti_<lsxfmt> (operands[0], operands[1],
|
||||
n));
|
||||
DONE;
|
||||
}
|
||||
}
|
||||
|
||||
operands[2] = force_reg (<MODE>mode, operands[2]);
|
||||
operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
|
||||
|
||||
operands[4] = gen_reg_rtx (<MODE>mode);
|
||||
|
|
|
|||
|
|
@ -443,19 +443,20 @@
|
|||
{
|
||||
case SYMBOL_PCREL:
|
||||
if (TARGET_CMODEL_EXTREME
|
||||
|| (TARGET_CMODEL_MEDIUM && !TARGET_EXPLICIT_RELOCS))
|
||||
|| (TARGET_CMODEL_MEDIUM
|
||||
&& (la_opt_explicit_relocs == EXPLICIT_RELOCS_NONE)))
|
||||
return false;
|
||||
else
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
case SYMBOL_GOT_DISP:
|
||||
if (TARGET_CMODEL_EXTREME
|
||||
|| !flag_plt
|
||||
|| (flag_plt && TARGET_CMODEL_MEDIUM
|
||||
&& !TARGET_EXPLICIT_RELOCS))
|
||||
&& (la_opt_explicit_relocs == EXPLICIT_RELOCS_NONE)))
|
||||
return false;
|
||||
else
|
||||
return 1;
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@
|
|||
UNSPEC_SYNC_OLD_OP
|
||||
UNSPEC_SYNC_EXCHANGE
|
||||
UNSPEC_ATOMIC_STORE
|
||||
UNSPEC_ATOMIC_LOAD
|
||||
UNSPEC_MEMORY_BARRIER
|
||||
])
|
||||
|
||||
|
|
@ -38,7 +39,7 @@
|
|||
[(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")])
|
||||
(define_mode_attr amo [(QI "b") (HI "h") (SI "w") (DI "d")])
|
||||
|
||||
;; <amop> expands to the name of the atomic operand that implements a
|
||||
;; particular code.
|
||||
|
|
@ -50,36 +51,129 @@
|
|||
[(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.
|
||||
;; DBAR hint encoding for LA664 and later micro-architectures, paraphrased from
|
||||
;; the Linux patch revealing it [1]:
|
||||
;;
|
||||
;; - Bit 4: kind of constraint (0: completion, 1: ordering)
|
||||
;; - Bit 3: barrier for previous read (0: true, 1: false)
|
||||
;; - Bit 2: barrier for previous write (0: true, 1: false)
|
||||
;; - Bit 1: barrier for succeeding read (0: true, 1: false)
|
||||
;; - Bit 0: barrier for succeeding write (0: true, 1: false)
|
||||
;;
|
||||
;; [1]: https://git.kernel.org/torvalds/c/e031a5f3f1ed
|
||||
;;
|
||||
;; Implementations without support for the finer-granularity hints simply treat
|
||||
;; all as the full barrier (DBAR 0), so we can unconditionally start emiting the
|
||||
;; more precise hints right away.
|
||||
(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")
|
||||
{
|
||||
enum memmodel model = memmodel_base (INTVAL (operands[1]));
|
||||
|
||||
switch (model)
|
||||
{
|
||||
case MEMMODEL_ACQUIRE:
|
||||
return "dbar\t0b10100";
|
||||
case MEMMODEL_RELEASE:
|
||||
return "dbar\t0b10010";
|
||||
case MEMMODEL_ACQ_REL:
|
||||
case MEMMODEL_SEQ_CST:
|
||||
return "dbar\t0b10000";
|
||||
default:
|
||||
/* GCC internal: "For the '__ATOMIC_RELAXED' model no instructions
|
||||
need to be issued and this expansion is not invoked."
|
||||
|
||||
__atomic builtins doc: "Consume is implemented using the
|
||||
stronger acquire memory order because of a deficiency in C++11's
|
||||
semantics." See PR 59448 and get_memmodel in builtins.cc.
|
||||
|
||||
Other values should not be returned by memmodel_base. */
|
||||
gcc_unreachable ();
|
||||
}
|
||||
})
|
||||
|
||||
;; Atomic memory operations.
|
||||
|
||||
(define_insn "atomic_load<mode>"
|
||||
[(set (match_operand:QHWD 0 "register_operand" "=r")
|
||||
(unspec_volatile:QHWD
|
||||
[(match_operand:QHWD 1 "memory_operand" "+m")
|
||||
(match_operand:SI 2 "const_int_operand")] ;; model
|
||||
UNSPEC_ATOMIC_LOAD))]
|
||||
""
|
||||
{
|
||||
enum memmodel model = memmodel_base (INTVAL (operands[2]));
|
||||
|
||||
switch (model)
|
||||
{
|
||||
case MEMMODEL_SEQ_CST:
|
||||
return "dbar\t0x11\\n\\t"
|
||||
"ld.<size>\t%0,%1\\n\\t"
|
||||
"dbar\t0x14";
|
||||
case MEMMODEL_ACQUIRE:
|
||||
return "ld.<size>\t%0,%1\\n\\t"
|
||||
"dbar\t0x14";
|
||||
case MEMMODEL_RELAXED:
|
||||
return TARGET_LD_SEQ_SA ? "ld.<size>\t%0,%1"
|
||||
: "ld.<size>\t%0,%1\\n\\t"
|
||||
"dbar\t0x700";
|
||||
|
||||
default:
|
||||
/* The valid memory order variants are __ATOMIC_RELAXED, __ATOMIC_SEQ_CST,
|
||||
__ATOMIC_CONSUME and __ATOMIC_ACQUIRE.
|
||||
The expand_builtin_atomic_store function converts all invalid memmodels
|
||||
to MEMMODEL_SEQ_CST.
|
||||
|
||||
__atomic builtins doc: "Consume is implemented using the
|
||||
stronger acquire memory order because of a deficiency in C++11's
|
||||
semantics." See PR 59448 and get_memmodel in builtins.cc. */
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set (attr "length") (const_int 12))])
|
||||
|
||||
;; 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")
|
||||
[(set (match_operand:QHWD 0 "memory_operand" "+m")
|
||||
(unspec_volatile:QHWD
|
||||
[(match_operand:QHWD 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))])
|
||||
{
|
||||
enum memmodel model = memmodel_base (INTVAL (operands[2]));
|
||||
|
||||
switch (model)
|
||||
{
|
||||
case MEMMODEL_SEQ_CST:
|
||||
return "dbar\t0x12\\n\\t"
|
||||
"st.<size>\t%z1,%0\\n\\t"
|
||||
"dbar\t0x18\\n\\t";
|
||||
case MEMMODEL_RELEASE:
|
||||
return "dbar\t0x12\\n\\t"
|
||||
"st.<size>\t%z1,%0\\n\\t";
|
||||
case MEMMODEL_RELAXED:
|
||||
return "st.<size>\t%z1,%0";
|
||||
|
||||
default:
|
||||
/* The valid memory order variants are __ATOMIC_RELAXED, __ATOMIC_SEQ_CST,
|
||||
and __ATOMIC_RELEASE.
|
||||
The expand_builtin_atomic_store function converts all invalid memmodels
|
||||
to MEMMODEL_SEQ_CST. */
|
||||
gcc_unreachable ();
|
||||
}
|
||||
}
|
||||
[(set (attr "length") (const_int 12))])
|
||||
|
||||
(define_insn "atomic_<atomic_optab><mode>"
|
||||
[(set (match_operand:GPR 0 "memory_operand" "+ZB")
|
||||
|
|
@ -90,7 +184,18 @@
|
|||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
"am<amop>%A2.<amo>\t$zero,%z1,%0"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
[(set (attr "length") (const_int 4))])
|
||||
|
||||
(define_insn "atomic_add<mode>"
|
||||
[(set (match_operand:SHORT 0 "memory_operand" "+ZB")
|
||||
(unspec_volatile:SHORT
|
||||
[(plus:SHORT (match_dup 0)
|
||||
(match_operand:SHORT 1 "reg_or_0_operand" "rJ"))
|
||||
(match_operand:SI 2 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_OLD_OP))]
|
||||
"TARGET_LAM_BH"
|
||||
"amadd%A2.<amo>\t$zero,%z1,%0"
|
||||
[(set (attr "length") (const_int 4))])
|
||||
|
||||
(define_insn "atomic_fetch_<atomic_optab><mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
|
|
@ -103,7 +208,7 @@
|
|||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
"am<amop>%A3.<amo>\t%0,%z2,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
[(set (attr "length") (const_int 4))])
|
||||
|
||||
(define_insn "atomic_exchange<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
|
|
@ -115,7 +220,19 @@
|
|||
(match_operand:GPR 2 "register_operand" "r"))]
|
||||
""
|
||||
"amswap%A3.<amo>\t%0,%z2,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
[(set (attr "length") (const_int 4))])
|
||||
|
||||
(define_insn "atomic_exchange<mode>_short"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(unspec_volatile:SHORT
|
||||
[(match_operand:SHORT 1 "memory_operand" "+ZB")
|
||||
(match_operand:SI 3 "const_int_operand")] ;; model
|
||||
UNSPEC_SYNC_EXCHANGE))
|
||||
(set (match_dup 1)
|
||||
(match_operand:SHORT 2 "register_operand" "r"))]
|
||||
"TARGET_LAM_BH"
|
||||
"amswap%A3.<amo>\t%0,%z2,%1"
|
||||
[(set (attr "length") (const_int 4))])
|
||||
|
||||
(define_insn "atomic_cas_value_strong<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
|
|
@ -123,25 +240,35 @@
|
|||
(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
|
||||
(match_operand:SI 4 "const_int_operand")] ;; mod_s
|
||||
UNSPEC_COMPARE_AND_SWAP))
|
||||
(clobber (match_scratch:GPR 6 "=&r"))]
|
||||
(clobber (match_scratch:GPR 5 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G5\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "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"
|
||||
"or%i3\\t%5,$zero,%3\\n\\t"
|
||||
"sc.<amo>\\t%5,%1\\n\\t"
|
||||
"beqz\\t%5,1b\\n\\t"
|
||||
"b\\t3f\\n\\t"
|
||||
"2:\\n\\t"
|
||||
"dbar\\t0x700\\n\\t"
|
||||
"%G4\\n\\t"
|
||||
"3:\\n\\t";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_strong<mode>_amcas"
|
||||
[(set (match_operand:QHWD 0 "register_operand" "=&r")
|
||||
(match_operand:QHWD 1 "memory_operand" "+ZB"))
|
||||
(set (match_dup 1)
|
||||
(unspec_volatile:QHWD [(match_operand:QHWD 2 "reg_or_0_operand" "rJ")
|
||||
(match_operand:QHWD 3 "reg_or_0_operand" "rJ")
|
||||
(match_operand:SI 4 "const_int_operand")] ;; mod_s
|
||||
UNSPEC_COMPARE_AND_SWAP))]
|
||||
"TARGET_LAMCAS"
|
||||
"ori\t%0,%z2,0\n\tamcas%A4.<amo>\t%0,%z3,%1"
|
||||
[(set (attr "length") (const_int 8))])
|
||||
|
||||
(define_expand "atomic_compare_and_swap<mode>"
|
||||
[(match_operand:SI 0 "register_operand" "") ;; bool output
|
||||
|
|
@ -154,9 +281,29 @@
|
|||
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
|
||||
""
|
||||
{
|
||||
rtx mod_s, mod_f;
|
||||
|
||||
mod_s = operands[6];
|
||||
mod_f = operands[7];
|
||||
|
||||
/* Normally the succ memory model must be stronger than fail, but in the
|
||||
unlikely event of fail being ACQUIRE and succ being RELEASE we need to
|
||||
promote succ to ACQ_REL so that we don't lose the acquire semantics. */
|
||||
|
||||
if (is_mm_acquire (memmodel_base (INTVAL (mod_f)))
|
||||
&& is_mm_release (memmodel_base (INTVAL (mod_s))))
|
||||
mod_s = GEN_INT (MEMMODEL_ACQ_REL);
|
||||
|
||||
operands[6] = mod_s;
|
||||
|
||||
if (TARGET_LAMCAS)
|
||||
emit_insn (gen_atomic_cas_value_strong<mode>_amcas (operands[1], operands[2],
|
||||
operands[3], operands[4],
|
||||
operands[6]));
|
||||
else
|
||||
emit_insn (gen_atomic_cas_value_strong<mode> (operands[1], operands[2],
|
||||
operands[3], operands[4],
|
||||
operands[6], operands[7]));
|
||||
operands[6]));
|
||||
|
||||
rtx compare = operands[1];
|
||||
if (operands[3] != const0_rtx)
|
||||
|
|
@ -234,8 +381,7 @@
|
|||
(clobber (match_scratch:GPR 7 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%2\\n\\t"
|
||||
"bne\\t%7,%z4,2f\\n\\t"
|
||||
|
|
@ -245,10 +391,10 @@
|
|||
"beq\\t$zero,%7,1b\\n\\t"
|
||||
"b\\t3f\\n\\t"
|
||||
"2:\\n\\t"
|
||||
"dbar\\t0x700\\n\\t"
|
||||
"%G6\\n\\t"
|
||||
"3:\\n\\t";
|
||||
}
|
||||
[(set (attr "length") (const_int 40))])
|
||||
[(set (attr "length") (const_int 36))])
|
||||
|
||||
(define_expand "atomic_compare_and_swap<mode>"
|
||||
[(match_operand:SI 0 "register_operand" "") ;; bool output
|
||||
|
|
@ -261,10 +407,32 @@
|
|||
(match_operand:SI 7 "const_int_operand" "")] ;; mod_f
|
||||
""
|
||||
{
|
||||
rtx mod_s, mod_f;
|
||||
|
||||
mod_s = operands[6];
|
||||
mod_f = operands[7];
|
||||
|
||||
/* Normally the succ memory model must be stronger than fail, but in the
|
||||
unlikely event of fail being ACQUIRE and succ being RELEASE we need to
|
||||
promote succ to ACQ_REL so that we don't lose the acquire semantics. */
|
||||
|
||||
if (is_mm_acquire (memmodel_base (INTVAL (mod_f)))
|
||||
&& is_mm_release (memmodel_base (INTVAL (mod_s))))
|
||||
mod_s = GEN_INT (MEMMODEL_ACQ_REL);
|
||||
|
||||
operands[6] = mod_s;
|
||||
|
||||
if (TARGET_LAMCAS)
|
||||
emit_insn (gen_atomic_cas_value_strong<mode>_amcas (operands[1], operands[2],
|
||||
operands[3], operands[4],
|
||||
operands[6]));
|
||||
else
|
||||
{
|
||||
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]);
|
||||
operands[3], operands[4], operands[6]);
|
||||
}
|
||||
|
||||
rtx compare = operands[1];
|
||||
if (operands[3] != const0_rtx)
|
||||
|
|
@ -303,8 +471,7 @@
|
|||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "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"
|
||||
|
|
@ -314,7 +481,7 @@
|
|||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_sub_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
|
|
@ -330,8 +497,7 @@
|
|||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "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"
|
||||
|
|
@ -340,7 +506,7 @@
|
|||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_and_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
|
|
@ -356,8 +522,7 @@
|
|||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"and\\t%8,%0,%z5\\n\\t"
|
||||
|
|
@ -366,7 +531,7 @@
|
|||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_xor_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
|
|
@ -382,8 +547,7 @@
|
|||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"xor\\t%8,%0,%z5\\n\\t"
|
||||
|
|
@ -393,7 +557,7 @@
|
|||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_or_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
|
|
@ -409,8 +573,7 @@
|
|||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"or\\t%8,%0,%z5\\n\\t"
|
||||
|
|
@ -420,7 +583,7 @@
|
|||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_nand_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r") ;; res
|
||||
|
|
@ -436,8 +599,7 @@
|
|||
(clobber (match_scratch:GPR 8 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%3\\n\\t"
|
||||
"and\\t%8,%0,%z5\\n\\t"
|
||||
|
|
@ -446,7 +608,7 @@
|
|||
"sc.<amo>\\t%7,%1\\n\\t"
|
||||
"beq\\t$zero,%7,1b";
|
||||
}
|
||||
[(set (attr "length") (const_int 32))])
|
||||
[(set (attr "length") (const_int 28))])
|
||||
|
||||
(define_insn "atomic_cas_value_exchange_7_<mode>"
|
||||
[(set (match_operand:GPR 0 "register_operand" "=&r")
|
||||
|
|
@ -461,8 +623,7 @@
|
|||
(clobber (match_scratch:GPR 7 "=&r"))]
|
||||
""
|
||||
{
|
||||
return "%G6\\n\\t"
|
||||
"1:\\n\\t"
|
||||
return "1:\\n\\t"
|
||||
"ll.<amo>\\t%0,%1\\n\\t"
|
||||
"and\\t%7,%0,%z3\\n\\t"
|
||||
"or%i5\\t%7,%7,%5\\n\\t"
|
||||
|
|
@ -481,13 +642,31 @@
|
|||
(match_operand:SHORT 2 "register_operand"))]
|
||||
""
|
||||
{
|
||||
if (TARGET_LAM_BH)
|
||||
emit_insn (gen_atomic_exchange<mode>_short (operands[0], operands[1], operands[2], operands[3]));
|
||||
else
|
||||
{
|
||||
union loongarch_gen_fn_ptrs generator;
|
||||
generator.fn_7 = gen_atomic_cas_value_exchange_7_si;
|
||||
loongarch_expand_atomic_qihi (generator, operands[0], operands[1],
|
||||
const0_rtx, operands[2], operands[3]);
|
||||
}
|
||||
DONE;
|
||||
})
|
||||
|
||||
(define_insn "atomic_fetch_add<mode>_short"
|
||||
[(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))]
|
||||
"TARGET_LAM_BH"
|
||||
"amadd%A3.<amo>\t%0,%z2,%1"
|
||||
[(set (attr "length") (const_int 4))])
|
||||
|
||||
(define_expand "atomic_fetch_add<mode>"
|
||||
[(set (match_operand:SHORT 0 "register_operand" "=&r")
|
||||
(match_operand:SHORT 1 "memory_operand" "+ZB"))
|
||||
|
|
@ -499,10 +678,16 @@
|
|||
UNSPEC_SYNC_OLD_OP))]
|
||||
""
|
||||
{
|
||||
if (TARGET_LAM_BH)
|
||||
emit_insn (gen_atomic_fetch_add<mode>_short (operands[0], operands[1],
|
||||
operands[2], operands[3]));
|
||||
else
|
||||
{
|
||||
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;
|
||||
})
|
||||
|
||||
|
|
|
|||
|
|
@ -19,7 +19,8 @@
|
|||
|
||||
GTM_H += loongarch-multilib.h
|
||||
OPTIONS_H_EXTRA += $(srcdir)/config/loongarch/loongarch-def.h \
|
||||
$(srcdir)/config/loongarch/loongarch-tune.h
|
||||
$(srcdir)/config/loongarch/loongarch-tune.h \
|
||||
$(srcdir)/config/loongarch/loongarch-cpucfg-map.h
|
||||
|
||||
# Canonical target triplet from config.gcc
|
||||
LA_MULTIARCH_TRIPLET = $(patsubst LA_MULTIARCH_TRIPLET=%,%,$\
|
||||
|
|
@ -31,7 +32,8 @@ 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
|
||||
$(srcdir)/config/loongarch/genopts/loongarch-strings \
|
||||
$(srcdir)/config/loongarch/genopts/isa-evolution.in
|
||||
$(SHELL) $(srcdir)/config/loongarch/genopts/genstr.sh header \
|
||||
$(srcdir)/config/loongarch/genopts/loongarch-strings > \
|
||||
tmp-loongarch-str.h
|
||||
|
|
@ -58,7 +60,8 @@ loongarch-driver.o : $(srcdir)/config/loongarch/loongarch-driver.cc $(LA_STR_H)
|
|||
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)
|
||||
loongarch-cpu.o: $(srcdir)/config/loongarch/loongarch-cpu.cc $(LA_STR_H) \
|
||||
$(srcdir)/config/loongarch/loongarch-cpucfg-map.h
|
||||
$(COMPILER) -c $(ALL_COMPILERFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
|
||||
|
||||
loongarch-def.o: $(srcdir)/config/loongarch/loongarch-def.c $(LA_STR_H)
|
||||
|
|
@ -67,6 +70,7 @@ loongarch-def.o: $(srcdir)/config/loongarch/loongarch-def.c $(LA_STR_H)
|
|||
$(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/isa-evolution.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 \
|
||||
|
|
@ -74,3 +78,12 @@ s-loongarch-opt: $(srcdir)/config/loongarch/genopts/genstr.sh \
|
|||
$(SHELL) $(srcdir)/../move-if-change tmp-loongarch.opt \
|
||||
$(srcdir)/config/loongarch/loongarch.opt
|
||||
$(STAMP) s-loongarch-opt
|
||||
|
||||
$(srcdir)/config/loongarch/loongarch-cpucfg-map.h: s-loongarch-cpucfg-map
|
||||
@true
|
||||
s-loongarch-cpucfg-map: $(srcdir)/config/loongarch/genopts/genstr.sh \
|
||||
$(srcdir)/config/loongarch/genopts/isa-evolution.in
|
||||
$(SHELL) $< cpucfg-map > tmp-cpucfg.h
|
||||
$(SHELL) $(srcdir)/../move-if-change tmp-cpucfg.h \
|
||||
$(srcdir)/config/loongarch/loongarch-cpucfg-map.h
|
||||
$(STAMP) $@
|
||||
|
|
|
|||
|
|
@ -34,8 +34,6 @@
|
|||
UNSPEC_FPINT_CEIL
|
||||
UNSPEC_FPINT_NEARBYINT
|
||||
|
||||
UNSPEC_BITREV
|
||||
|
||||
UNSPEC_ALLOCA
|
||||
|
||||
UNSPEC_SET_SOFTSTACK
|
||||
|
|
@ -636,8 +634,7 @@
|
|||
|
||||
(define_insn "bitrev<mode>2"
|
||||
[(set (match_operand:SDIM 0 "nvptx_register_operand" "=R")
|
||||
(unspec:SDIM [(match_operand:SDIM 1 "nvptx_register_operand" "R")]
|
||||
UNSPEC_BITREV))]
|
||||
(bitreverse:SDIM (match_operand:SDIM 1 "nvptx_register_operand" "R")))]
|
||||
""
|
||||
"%.\\tbrev.b%T0\\t%0, %1;")
|
||||
|
||||
|
|
|
|||
|
|
@ -10819,23 +10819,29 @@ pa_legitimate_address_p (machine_mode mode, rtx x, bool strict, code_helper)
|
|||
|
||||
if (GET_CODE (index) == CONST_INT)
|
||||
{
|
||||
/* Short 5-bit displacements always okay. */
|
||||
if (INT_5_BITS (index))
|
||||
return true;
|
||||
|
||||
/* When INT14_OK_STRICT is false, a secondary reload is needed
|
||||
to adjust the displacement of SImode and DImode floating point
|
||||
instructions but this may fail when the register also needs
|
||||
reloading. So, we return false when STRICT is true. We
|
||||
also reject long displacements for float mode addresses since
|
||||
the majority of accesses will use floating point instructions
|
||||
that don't support 14-bit offsets. */
|
||||
if (!INT14_OK_STRICT
|
||||
&& (strict || !(reload_in_progress || reload_completed))
|
||||
&& mode != QImode
|
||||
&& mode != HImode)
|
||||
if (!base14_operand (index, mode))
|
||||
return false;
|
||||
|
||||
return base14_operand (index, mode);
|
||||
/* Long 14-bit displacements always okay for these cases. */
|
||||
if (INT14_OK_STRICT
|
||||
|| mode == QImode
|
||||
|| mode == HImode)
|
||||
return true;
|
||||
|
||||
/* A secondary reload may be needed to adjust the displacement
|
||||
of floating-point accesses when STRICT is nonzero. */
|
||||
if (strict)
|
||||
return false;
|
||||
|
||||
/* We get significantly better code if we allow long displacements
|
||||
before reload for all accesses. Instructions must satisfy their
|
||||
constraints after reload, so we must have an integer access.
|
||||
Return true for both cases. */
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!TARGET_DISABLE_INDEXING
|
||||
|
|
|
|||
|
|
@ -37,6 +37,11 @@ extern unsigned long total_code_bytes;
|
|||
#define TARGET_ELF32 0
|
||||
#endif
|
||||
|
||||
/* Generate code for ELF64 ABI. */
|
||||
#ifndef TARGET_ELF64
|
||||
#define TARGET_ELF64 0
|
||||
#endif
|
||||
|
||||
/* Generate code for SOM 32bit ABI. */
|
||||
#ifndef TARGET_SOM
|
||||
#define TARGET_SOM 0
|
||||
|
|
@ -823,12 +828,11 @@ extern int may_call_alloca;
|
|||
|
||||
/* Nonzero if 14-bit offsets can be used for all loads and stores.
|
||||
This is not possible when generating PA 1.x code as floating point
|
||||
loads and stores only support 5-bit offsets. Note that we do not
|
||||
forbid the use of 14-bit offsets for integer modes. Instead, we
|
||||
use secondary reloads to fix REG+D memory addresses for integer
|
||||
mode floating-point loads and stores.
|
||||
accesses only support 5-bit offsets. Note that we do not forbid
|
||||
the use of 14-bit offsets prior to reload. Instead, we use secondary
|
||||
reloads to fix REG+D memory addresses for floating-point accesses.
|
||||
|
||||
FIXME: the ELF32 linker clobbers the LSB of the FP register number
|
||||
FIXME: the GNU ELF linker clobbers the LSB of the FP register number
|
||||
in PA 2.0 floating-point insns with long displacements. This is
|
||||
because R_PARISC_DPREL14WR and other relocations like it are not
|
||||
yet supported by GNU ld. For now, we reject long displacements
|
||||
|
|
@ -836,7 +840,7 @@ extern int may_call_alloca;
|
|||
|
||||
#define INT14_OK_STRICT \
|
||||
(TARGET_SOFT_FLOAT \
|
||||
|| (TARGET_PA_20 && !TARGET_ELF32))
|
||||
|| (TARGET_PA_20 && !TARGET_ELF32 && !TARGET_ELF64))
|
||||
|
||||
/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
|
||||
and check its validity for a certain class.
|
||||
|
|
|
|||
|
|
@ -17,6 +17,10 @@ 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/>. */
|
||||
|
||||
/* 64-bit ELF target. */
|
||||
#undef TARGET_ELF64
|
||||
#define TARGET_ELF64 1
|
||||
|
||||
#if 0 /* needs some work :-( */
|
||||
/* If defined, this macro specifies a table of register pairs used to
|
||||
eliminate unneeded registers that point into the stack frame. */
|
||||
|
|
|
|||
|
|
@ -267,6 +267,10 @@
|
|||
if (!INT_14_BITS (op))
|
||||
return false;
|
||||
|
||||
/* Short displacement. */
|
||||
if (INT_5_BITS (op))
|
||||
return true;
|
||||
|
||||
/* Although this may not be necessary, we require that the
|
||||
base value is correctly aligned for its mode as this is
|
||||
assumed in the instruction encoding. */
|
||||
|
|
@ -304,15 +308,12 @@
|
|||
|
||||
if (reg_plus_base_memory_operand (op, mode))
|
||||
{
|
||||
if (reload_in_progress)
|
||||
return true;
|
||||
|
||||
/* Extract CONST_INT operand. */
|
||||
if (GET_CODE (op) == SUBREG)
|
||||
op = SUBREG_REG (op);
|
||||
op = XEXP (op, 0);
|
||||
op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0);
|
||||
return base14_operand (op, mode) || INT_5_BITS (op);
|
||||
return base14_operand (op, mode);
|
||||
}
|
||||
|
||||
if (!MEM_P (op))
|
||||
|
|
@ -341,17 +342,12 @@
|
|||
|
||||
if (reg_plus_base_memory_operand (op, mode))
|
||||
{
|
||||
if (reload_in_progress)
|
||||
return true;
|
||||
|
||||
/* Extract CONST_INT operand. */
|
||||
if (GET_CODE (op) == SUBREG)
|
||||
op = SUBREG_REG (op);
|
||||
op = XEXP (op, 0);
|
||||
op = REG_P (XEXP (op, 0)) ? XEXP (op, 1) : XEXP (op, 0);
|
||||
return ((TARGET_PA_20
|
||||
&& !TARGET_ELF32
|
||||
&& base14_operand (op, mode))
|
||||
return ((INT14_OK_STRICT && base14_operand (op, mode))
|
||||
|| INT_5_BITS (op));
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -109,11 +109,11 @@ riscv_cpu_cpp_builtins (cpp_reader *pfile)
|
|||
}
|
||||
|
||||
if (riscv_user_wants_strict_align)
|
||||
builtin_define_with_int_value ("__riscv_unaligned_avoid", 1);
|
||||
builtin_define_with_int_value ("__riscv_misaligned_avoid", 1);
|
||||
else if (riscv_slow_unaligned_access_p)
|
||||
builtin_define_with_int_value ("__riscv_unaligned_slow", 1);
|
||||
builtin_define_with_int_value ("__riscv_misaligned_slow", 1);
|
||||
else
|
||||
builtin_define_with_int_value ("__riscv_unaligned_fast", 1);
|
||||
builtin_define_with_int_value ("__riscv_misaligned_fast", 1);
|
||||
|
||||
if (TARGET_MIN_VLEN != 0)
|
||||
builtin_define_with_int_value ("__riscv_v_min_vlen", TARGET_MIN_VLEN);
|
||||
|
|
|
|||
|
|
@ -124,6 +124,7 @@ extern void riscv_split_doubleword_move (rtx, rtx);
|
|||
extern const char *riscv_output_move (rtx, rtx);
|
||||
extern const char *riscv_output_return ();
|
||||
extern void riscv_declare_function_name (FILE *, const char *, tree);
|
||||
extern void riscv_declare_function_size (FILE *, const char *, tree);
|
||||
extern void riscv_asm_output_alias (FILE *, const tree, const tree);
|
||||
extern void riscv_asm_output_external (FILE *, const tree, const char *);
|
||||
extern bool
|
||||
|
|
@ -647,5 +648,25 @@ extern bool th_print_operand_address (FILE *, machine_mode, rtx);
|
|||
|
||||
extern bool riscv_use_divmod_expander (void);
|
||||
void riscv_init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
|
||||
extern bool
|
||||
riscv_option_valid_attribute_p (tree, tree, tree, int);
|
||||
extern void
|
||||
riscv_override_options_internal (struct gcc_options *);
|
||||
|
||||
struct riscv_tune_param;
|
||||
/* Information about one micro-arch we know about. */
|
||||
struct riscv_tune_info {
|
||||
/* This micro-arch canonical name. */
|
||||
const char *name;
|
||||
|
||||
/* Which automaton to use for tuning. */
|
||||
enum riscv_microarchitecture_type microarchitecture;
|
||||
|
||||
/* Tuning parameters for this micro-arch. */
|
||||
const struct riscv_tune_param *tune_param;
|
||||
};
|
||||
|
||||
const struct riscv_tune_info *
|
||||
riscv_parse_tune (const char *, bool);
|
||||
|
||||
#endif /* ! GCC_RISCV_PROTOS_H */
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue