From patchwork Wed Jun 3 01:03:10 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jim Lin X-Patchwork-Id: 136344 X-Patchwork-Delegate: kito.cheng@gmail.com Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from vm01.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 57CDE4BA2E1C for ; Wed, 3 Jun 2026 01:04:47 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 57CDE4BA2E1C X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from Atcsqr.andestech.com (exmail.andestech.com [60.248.187.195]) by sourceware.org (Postfix) with ESMTPS id 80D234BA2E06 for ; Wed, 3 Jun 2026 01:03:42 +0000 (GMT) Authentication-Results: sourceware.org; dmarc=permerror header.from=andestech.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=andestech.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 80D234BA2E06 Authentication-Results: sourceware.org; arc=none smtp.remote-ip=60.248.187.195 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780448623; cv=none; b=d3TKy99tMmYFsnYXo98a+y9mxutCawWXw83YMKweYdL2Iq3InPaA4ciqQcBialrHAytLPrVWjBOcYyT72wWnabiLLW6DTgY5p0bhsbr8YCeCzuJN8a6uS5wHF423afo91Z4U+fbMUf9UziRv7LORukseDKbWK2nxEAjhU3TOQYo= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1780448623; c=relaxed/simple; bh=XQeBAbIDQD7Nn1iutUNqjyhlNfL0AUFgpKeZEgRJVus=; h=From:To:Subject:Date:Message-ID:MIME-Version; b=peU1FSx8LHJwRxi6gF8vcMwCoZPwOqaUjWxVoLhh6SjEzklEYipxUZM08R5Xvs4VoyTWr8/FbAk4l3sSYp3610z/lVKQaqEXPd4Is6aZB+4VOYtD8auSRePDUGW9QdPyr2vzZuTuGG/oXPA51Yh3woaq2je+oGjd3X7k3E3OAmE= ARC-Authentication-Results: i=1; sourceware.org DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 80D234BA2E06 Received: from mail.andestech.com (ATCPCS34.andestech.com [10.0.1.134]) by Atcsqr.andestech.com with ESMTPS id 65313XDn089536 (version=TLSv1.2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128 verify=OK) for ; Wed, 3 Jun 2026 09:03:33 +0800 (+08) (envelope-from jim@andestech.com) Received: from atccpl01.andestech.com (10.0.15.149) by ATCPCS34.andestech.com (10.0.1.134) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2507.39; Wed, 3 Jun 2026 09:03:33 +0800 From: Jim Lin To: CC: Jim Tsung-Chun Lin Subject: [PATCH 1/1] RISC-V: Run smart multilib match even when generic matcher picked a dir Date: Wed, 3 Jun 2026 09:03:10 +0800 Message-ID: <20260603010310.3070271-1-jim@andestech.com> X-Mailer: git-send-email 2.34.1 MIME-Version: 1.0 X-Originating-IP: [10.0.15.149] X-ClientProxiedBy: ATCPCS33.andestech.com (10.0.1.100) To ATCPCS34.andestech.com (10.0.1.134) X-DKIM-Results: atcpcs34.andestech.com; dkim=none; X-DNSRBL: X-SPAM-SOURCE-CHECK: pass X-MAIL: Atcsqr.andestech.com 65313XDn089536 X-Spam-Status: No, score=-12.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, KAM_SHORT, RCVD_IN_DNSWL_BLOCKED, SPF_HELO_NONE, SPF_PASS, TXREP, URIBL_BLOCKED shortcircuit=no autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.30 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces~patchwork=sourceware.org@gcc.gnu.org From: Jim Tsung-Chun Lin The generic textual matcher in gcc.cc:set_multilib_dir does not understand RISC-V arch supersetting and treats MULTILIB_DEFAULTS entries as if they were on the command line via default_arg(). When the user passes a -march= that is a superset of one of MULTILIB_OPTIONS' arches but does not textually match, default_arg can rescue the wrong entry and pick a multilib that is not the closest match. riscv_compute_multilib used to early-return whenever multilib_dir was already set, accepting that incorrect generic pick. Drop the early return and run the match-score-based selection unconditionally. There is no need to fall back to the generic-matched multilib_dir after the smart matcher runs: the default "." multilib is parsed into multilib_infos with the compiler's default arch/abi, so the smart matcher handles every case the generic matcher can reach. If it still returns NULL the request is genuinely incompatible with all configured multilibs and riscv_multi_lib_check fires the proper "Cannot find suitable multilib" diagnostic instead of silently linking against incompatible default-arch libraries. Reproduce with: ./configure --enable-multilib --with-abi=lp64d --with-arch=rv64gc \ --with-multilib-generator="rv64gc-lp64f--;rv64g_zcmp_zcmt-lp64f--" With the pre-fix driver, "-march=rv64g_zba_zcmp_zcmt -mabi=lp64f" selects the rv64gc multilib (textual default rescue); after the fix the smart matcher correctly picks the rv64g_zcmp_zcmt multilib. gcc/ChangeLog: * common/config/riscv/riscv-common.cc (riscv_select_multilib): Don't set riscv_no_matched_multi_lib here; let the caller own the flag. (riscv_compute_multilib): Drop the early return that accepted the generic-matched multilib_dir; always run the smart matcher and set riscv_no_matched_multi_lib when it finds no candidate. gcc/testsuite/ChangeLog: * gcc.target/riscv/multilib.exp: New test. --- gcc/common/config/riscv/riscv-common.cc | 42 +++++--- gcc/testsuite/gcc.target/riscv/multilib.exp | 109 ++++++++++++++++++++ 2 files changed, 137 insertions(+), 14 deletions(-) create mode 100644 gcc/testsuite/gcc.target/riscv/multilib.exp diff --git a/gcc/common/config/riscv/riscv-common.cc b/gcc/common/config/riscv/riscv-common.cc index 5d3d37c7a7b..f6cac606acd 100644 --- a/gcc/common/config/riscv/riscv-common.cc +++ b/gcc/common/config/riscv/riscv-common.cc @@ -2013,12 +2013,9 @@ riscv_select_multilib ( } if (best_match_multi_lib == -1) - { - riscv_no_matched_multi_lib = true; - return NULL; - } - else - return xstrdup (multilib_infos[best_match_multi_lib].path.c_str ()); + return NULL; + + return xstrdup (multilib_infos[best_match_multi_lib].path.c_str ()); } #ifndef RISCV_USE_CUSTOMISED_MULTI_LIB @@ -2054,9 +2051,17 @@ riscv_compute_multilib ( std::string option_cond; riscv_multi_lib_info_t multilib_info; - /* Already found suitable, multi-lib, just use that. */ - if (multilib_dir != NULL) - return multilib_dir; + /* The generic textual matcher in gcc.cc:set_multilib_dir does not + understand RISC-V arch supersetting and treats MULTILIB_DEFAULTS + entries as if they were on the command line via default_arg (). + That can pick the wrong multilib when the user's -march is a + superset of one of MULTILIB_OPTIONS' arches but does not textually + match. Run our own match-score-based selection regardless. The + default "." multilib is included in multilib_infos with the + compiler's default arch/abi, so the smart matcher handles every + case the generic matcher can reach; if it still returns NULL the + request is genuinely incompatible and riscv_multi_lib_check will + emit the proper diagnostic. */ /* Find march. */ riscv_current_arch_str = @@ -2146,19 +2151,28 @@ riscv_compute_multilib ( p++; } + const char *selected = NULL; switch (select_kind) { case select_by_abi: - return riscv_select_multilib_by_abi (riscv_current_abi_str, - multilib_infos); + selected = riscv_select_multilib_by_abi (riscv_current_abi_str, + multilib_infos); + break; case select_by_abi_arch_cmodel: - return riscv_select_multilib (riscv_current_abi_str, subset_list, - switches, n_switches, multilib_infos); + selected = riscv_select_multilib (riscv_current_abi_str, subset_list, + switches, n_switches, multilib_infos); + break; case select_by_builtin: - gcc_unreachable (); default: gcc_unreachable (); } + + /* Either select function may return NULL when nothing is compatible; + ensure the flag is set so riscv_multi_lib_check fires its + "Cannot find suitable multilib" diagnostic. */ + if (selected == NULL) + riscv_no_matched_multi_lib = true; + return selected; } #undef TARGET_COMPUTE_MULTILIB diff --git a/gcc/testsuite/gcc.target/riscv/multilib.exp b/gcc/testsuite/gcc.target/riscv/multilib.exp new file mode 100644 index 00000000000..1917aea7c43 --- /dev/null +++ b/gcc/testsuite/gcc.target/riscv/multilib.exp @@ -0,0 +1,109 @@ +# Copyright (C) 2026 Free Software Foundation, Inc. + +# This program 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 of the License, or +# (at your option) any later version. +# +# This program 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 +# . +# +# gcc.cc:set_multilib_dir does textual matching of MULTILIB_OPTIONS +# against the command line plus MULTILIB_DEFAULTS, which doesn't +# understand RISC-V arch supersetting. When -march is a superset of +# one of the configured multilibs' arches but does not textually match, +# the textual matcher can pick the wrong (default) multilib. Before +# the fix, riscv_compute_multilib early-returned that wrong pick; +# afterwards it runs the smart, score-based matcher unconditionally +# and selects the closest superset multilib. +# +# To exercise the bug a toolchain must be configured so that both +# rv64gc/lp64f and rv64g_zcmp_zcmt/lp64f are present, e.g.: +# ./configure --enable-multilib --with-abi=lp64d --with-arch=rv64gc \ +# --with-multilib-generator="rv64gc-lp64f--;rv64g_zcmp_zcmt-lp64f--" +# The test only inspects --print-multi-lib output to detect that the +# two relevant multilibs exist, and is a no-op on any toolchain that +# is not configured this way. + +if ![istarget riscv*-*-*] then { + return +} + +load_lib gcc-dg.exp + +dg-init + +if ![gcc_parallel_test_run_p options] { + return +} +gcc_parallel_test_enable 0 + +proc gcc_run_with_flags { flags } { + global tool + set options [list "additional_flags=$flags"] + return [${tool}_target_compile "" "" "none" $options] +} + +proc gcc_print_multi_dir { opts } { + return [string trim [gcc_run_with_flags [concat --print-multi-directory $opts]]] +} + +proc check_multi_dir { gcc_opts multi_dir } { + set got [gcc_print_multi_dir $gcc_opts] + if { $got eq $multi_dir } { + pass "multilibdir $gcc_opts -> $multi_dir" + } else { + fail "multilibdir $gcc_opts -> $multi_dir (got '$got')" + } +} + +# Detect the configured multilibs. Each line of --print-multi-lib is +# ";"; the default multilib appears as ".;". +set zcmp_dir "" +set rv64gc_dir "" +foreach line [split [gcc_run_with_flags --print-multi-lib] "\n"] { + set line [string trim $line] + if { $line eq "" || [string match ".;*" $line] } { + continue + } + set dir [lindex [split $line ";"] 0] + if { [string match "*zcmp_zcmt*/lp64f" $dir] } { + set zcmp_dir $dir + } elseif { [string match "*zcd*/lp64f" $dir] + && ![string match "*zcmp_zcmt*" $dir] } { + set rv64gc_dir $dir + } +} + +if { $zcmp_dir eq "" || $rv64gc_dir eq "" } { + verbose "skipping: rv64gc/lp64f and rv64g_zcmp_zcmt/lp64f multilibs not both configured" 1 + gcc_parallel_test_enable 1 + return +} + +# Sanity: exact arches must each select their own multilib. +check_multi_dir {-march=rv64gc -mabi=lp64f} $rv64gc_dir +check_multi_dir {-march=rv64g_zcmp_zcmt -mabi=lp64f} $zcmp_dir + +# An arch that is a strict superset of rv64g_zcmp_zcmt but not of +# rv64gc (it has Zcmp/Zcmt and lacks Zcd) must select the Zc* multilib. +# Before the fix, the generic textual matcher in gcc.cc rescued the +# rv64gc default and riscv_compute_multilib accepted it; the smart +# matcher now runs unconditionally and overrides that pick. +check_multi_dir {-march=rv64g_zba_zcmp_zcmt -mabi=lp64f} $zcmp_dir +check_multi_dir {-march=rv64g_zicond_zcmp_zcmt -mabi=lp64f} $zcmp_dir + +# Reverse direction: an arch that is a superset of rv64gc but not of +# rv64g_zcmp_zcmt (it has Zcd and lacks Zcmp/Zcmt) must still select +# the rv64gc multilib. Guards against a future change that would +# unconditionally favour the longer Zc*-rich multilib. +check_multi_dir {-march=rv64gc_zba -mabi=lp64f} $rv64gc_dir +check_multi_dir {-march=rv64gc_zicond -mabi=lp64f} $rv64gc_dir + +gcc_parallel_test_enable 1