From patchwork Thu Apr 18 07:36:36 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 88649 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 3024C3858404 for ; Thu, 18 Apr 2024 07:37:12 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by sourceware.org (Postfix) with ESMTPS id 0575F3858D20 for ; Thu, 18 Apr 2024 07:36:42 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org 0575F3858D20 Authentication-Results: sourceware.org; dmarc=pass (p=none dis=none) header.from=redhat.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=redhat.com ARC-Filter: OpenARC Filter v1.0.0 sourceware.org 0575F3858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=170.10.133.124 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713425803; cv=none; b=RffjRAKShEIalKFqN5O/8jLK/Ezh/QHu1F+ytSNHbn0nSq9Npz4VDQ+ynkLFf/eIsuceZb6iV/mcfXMPCFNLzY714SIhOn/07RduhX5DTYMA5B1tiZ73FxjmJybdeAUb26kSEMMPZFWIJrfzSC+fdd9nYxBXR6Y9poKFM8HlqC0= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1713425803; c=relaxed/simple; bh=JO+CdwF4j46KiI7/Rq6qSS97iN3FQxWFPB5TA65B4T8=; h=DKIM-Signature:Date:From:To:Subject:Message-ID:MIME-Version; b=guQnLSIiRQRMjMykCrqUOLmd7SVegnJH1x6lTsOZBYHtRmXVbH8Bzz1VAYtUAynhM4fU8bQ2Fw40Y8gYcxM5Hi8wckpwGKkXaz6rycr5fetdwtVb1f0BmU6TBpvciebl4OtlX/0aGqdnkKjlMul3HMysIJibX2qq6iNOo84GktU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1713425801; h=from:from:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type; bh=1KjGw+X+T6IT050agCCveJfKDiueR5rSYnoxOp51AFc=; b=MzhDlJHgkIhYt4olF5M2zaXDbjYi3L+ZBbEd3lZgPsOPt7zKNXAYJFOhnYQDzy6JatTVmU jrQqOCcrvsHPCkU/j2LTJ0n7hzOj9h20aPkskhb+kxIGfRXjejFkSPCsHekmKW6cJkdo0D yLWgtTD3YaAUC04MRwR5BTclubYEZTM= Received: from mimecast-mx02.redhat.com (mx-ext.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.3, cipher=TLS_AES_256_GCM_SHA384) id us-mta-214-pTk_rEARMrWnC8nM8mvNHg-1; Thu, 18 Apr 2024 03:36:39 -0400 X-MC-Unique: pTk_rEARMrWnC8nM8mvNHg-1 Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 9462128B698B; Thu, 18 Apr 2024 07:36:38 +0000 (UTC) Received: from tucnak.zalov.cz (unknown [10.45.224.5]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 539BDC2595D; Thu, 18 Apr 2024 07:36:38 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.17.1/8.17.1) with ESMTPS id 43I7aaJh1267908 (version=TLSv1.3 cipher=TLS_AES_256_GCM_SHA384 bits=256 verify=NOT); Thu, 18 Apr 2024 09:36:36 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.17.1/8.17.1/Submit) id 43I7aaaC1267907; Thu, 18 Apr 2024 09:36:36 +0200 Date: Thu, 18 Apr 2024 09:36:36 +0200 From: Jakub Jelinek To: Richard Biener , "Joseph S. Myers" Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] libgcc: Fix up __divmodbitint4 [PR114755] Message-ID: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.4.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Disposition: inline X-Spam-Status: No, score=-4.7 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=ham autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.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: , Reply-To: Jakub Jelinek Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Hi! The following testcase aborts on aarch64-linux but does not on x86_64-linux. In both cases there is UB in the __divmodbitint4 implemenetation. When the divisor is negative with most significant limb (even when partial) all ones, has at least 2 limbs and the second most significant limb has the most significant bit clear, when this number is negated, it will have 0 in the most significant limb. Already in the PR114397 r14-9592 fix I was dealing with such divisors, but thought the problem is only if because of that un < vn doesn't imply the quotient is 0 and remainder u. But as this testcase shows, the problem is with such divisors always. What happens is that we use __builtin_clz* on the most significant limb, and assume it will not be 0 because that is UB for the builtins. Normally the most significant limb of the divisor shouldn't be 0, as guaranteed by the bitint_reduce_prec e.g. for the positive numbers, unless the divisor is just 0 (but for vn == 1 we have special cases). The following patch moves the handling of this corner case a few lines earlier before the un < vn check, because adjusting the vn later is harder. Bootstrapped/regtested on x86_64-linux and i686-linux, plus tested with make check-gcc -j32 -k GCC_TEST_RUN_EXPENSIVE=1 RUNTESTFLAGS="GCC_TEST_RUN_EXPENSIVE=1 dg.exp='*bitint* pr112673.c builtin-stdc-bit-*.c pr112566-2.c pr112511.c' dg-torture.exp=*bitint* dfp.exp=*bitint*" on aarch64-linux, ok for trunk? 2024-04-18 Jakub Jelinek PR libgcc/114755 * libgcc2.c (__divmodbitint4): Perform the decrement on negative v with most significant limb all ones and the second least significant limb with most significant bit clear always, regardless of un < vn. * gcc.dg/torture/bitint-69.c: New test. Jakub --- libgcc/libgcc2.c.jj 2024-03-21 13:07:43.629886730 +0100 +++ libgcc/libgcc2.c 2024-04-17 19:00:55.453691368 +0200 @@ -1705,69 +1705,62 @@ __divmodbitint4 (UBILtype *q, SItype qpr USItype rn = ((USItype) rprec + W_TYPE_SIZE - 1) / W_TYPE_SIZE; USItype up = auprec % W_TYPE_SIZE; USItype vp = avprec % W_TYPE_SIZE; + /* If vprec < 0 and the top limb of v is all ones and the second most + significant limb has most significant bit clear, then just decrease + vn/avprec/vp, because after negation otherwise v2 would have most + significant limb clear. */ + if (vprec < 0 + && ((v[BITINT_END (0, vn - 1)] | (vp ? ((UWtype) -1 << vp) : 0)) + == (UWtype) -1) + && vn > 1 + && (Wtype) v[BITINT_END (1, vn - 2)] >= 0) + { + vp = 0; + --vn; +#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ + ++v; +#endif + } if (__builtin_expect (un < vn, 0)) { - /* If abs(v) > abs(u), then q is 0 and r is u. - Unfortunately un < vn doesn't always mean abs(v) > abs(u). - If uprec > 0 and vprec < 0 and vn == un + 1, if the - top limb of v is all ones and the second most significant - limb has most significant bit clear, then just decrease - vn/avprec/vp and continue, after negation both numbers - will have the same number of limbs. */ - if (un + 1 == vn - && uprec >= 0 - && vprec < 0 - && ((v[BITINT_END (0, vn - 1)] | (vp ? ((UWtype) -1 << vp) : 0)) - == (UWtype) -1) - && (Wtype) v[BITINT_END (1, vn - 2)] >= 0) - { - vp = 0; - --vn; + /* q is 0 and r is u. */ + if (q) + __builtin_memset (q, 0, qn * sizeof (UWtype)); + if (r == NULL) + return; #if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ - ++v; + r += rn - 1; + u += un - 1; #endif + if (up) + --un; + if (rn < un) + un = rn; + for (rn -= un; un; --un) + { + *r = *u; + r += BITINT_INC; + u += BITINT_INC; } - else + if (!rn) + return; + if (up) { - /* q is 0 and r is u. */ - if (q) - __builtin_memset (q, 0, qn * sizeof (UWtype)); - if (r == NULL) + if (uprec > 0) + *r = *u & (((UWtype) 1 << up) - 1); + else + *r = *u | ((UWtype) -1 << up); + r += BITINT_INC; + if (!--rn) return; -#if __LIBGCC_BITINT_ORDER__ == __ORDER_BIG_ENDIAN__ - r += rn - 1; - u += un - 1; -#endif - if (up) - --un; - if (rn < un) - un = rn; - for (rn -= un; un; --un) - { - *r = *u; - r += BITINT_INC; - u += BITINT_INC; - } - if (!rn) - return; - if (up) - { - if (uprec > 0) - *r = *u & (((UWtype) 1 << up) - 1); - else - *r = *u | ((UWtype) -1 << up); - r += BITINT_INC; - if (!--rn) - return; - } - UWtype c = uprec < 0 ? (UWtype) -1 : (UWtype) 0; - for (; rn; --rn) - { - *r = c; - r += BITINT_INC; - } - return; } + UWtype c = uprec < 0 ? (UWtype) -1 : (UWtype) 0; + for (; rn; --rn) + { + *r = c; + r += BITINT_INC; + } + return; } USItype qn2 = un - vn + 1; if (qn >= qn2) --- gcc/testsuite/gcc.dg/torture/bitint-69.c.jj 2024-04-17 19:09:34.165521448 +0200 +++ gcc/testsuite/gcc.dg/torture/bitint-69.c 2024-04-17 19:10:25.343814139 +0200 @@ -0,0 +1,26 @@ +/* PR libgcc/114755 */ +/* { dg-do run { target bitint } } */ +/* { dg-options "-std=c23" } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "*" } { "-O0" "-O2" } } */ +/* { dg-skip-if "" { ! run_expensive_tests } { "-flto" } { "" } } */ + +#if __BITINT_MAXWIDTH__ >= 255 +_BitInt(65) +foo (void) +{ + _BitInt(255) a = 0x040404040404040404040404wb; + _BitInt(65) b = -0xffffffffffffffffwb; + _BitInt(65) r = a % b; + return r; +} +#endif + +int +main () +{ +#if __BITINT_MAXWIDTH__ >= 255 + _BitInt(65) x = foo (); + if (x != 0x0404040408080808wb) + __builtin_abort (); +#endif +}