Merge commit '56ca59a03150cf44cea340f58967c990ed6bf43c^' into HEAD

This commit is contained in:
Thomas Schwinge 2024-03-17 00:10:04 +01:00
commit b3a1373731
1017 changed files with 58021 additions and 22243 deletions

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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 = []

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
20231109
20231119

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -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",
&regcount.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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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