From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from xry111.site (xry111.site [89.208.246.23]) by sourceware.org (Postfix) with ESMTPS id E91C33858D20 for ; Wed, 10 Apr 2024 09:19:58 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.2 sourceware.org E91C33858D20 Authentication-Results: sourceware.org; dmarc=pass (p=reject dis=none) header.from=xry111.site Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=xry111.site ARC-Filter: OpenARC Filter v1.0.0 sourceware.org E91C33858D20 Authentication-Results: server2.sourceware.org; arc=none smtp.remote-ip=89.208.246.23 ARC-Seal: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712740801; cv=none; b=etRhMPyyfu08u7B1uTReI9Q5P81duszX9eUEA4AnUs8bnoJGGciyUaWkqZcklCOshfILSc669G/aAzxsZeZv2KE9li6NtLvjuHJRxDMajIm7pkyEWWRZNdUEi09mRWRz8+CALkHLqf+xddv3G0/ON2OkFwFs0RFpLeZQe18kvNQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1712740801; c=relaxed/simple; bh=kg7cIPbC8Aj9ChGgu7vQlo0RxBacQ5RjwrSzHEz1JHc=; h=DKIM-Signature:Message-ID:Subject:From:To:Date:MIME-Version; b=NoTaQhHrG9pivP3ujXj7/fcCE1Hrasi9dldnZyd8BoMMi+LJSSfEcSfP+uGIGeA+so++7idWzsnW5QbnYmd7rFv1troeLzB1rRcdofhUbS9hRB4BCHBZ0pwEdeYcLv6/WheVtHST2Zn51XT7+Tox1nyfMxJ72Pwsgx6X7aPnjZU= ARC-Authentication-Results: i=1; server2.sourceware.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=xry111.site; s=default; t=1712740797; bh=kg7cIPbC8Aj9ChGgu7vQlo0RxBacQ5RjwrSzHEz1JHc=; h=Subject:From:To:Cc:Date:In-Reply-To:References:From; b=PTNXkBAoGz1v4BpvjZnhTTiV3kkfc0EA7z5Vzo3neZFh/USqEi4Hvmm3RRoK3cEcO KBrn5OQkRce8dH1Nnne+Mv8/vFSYqcv/WxCUczR7+dnfhFNLNsQvXTQL0vLn9Dqd/8 cRpecZzjIAzG4OlniRCQI6b7BzOi64iF8SUMrLME= Received: from [127.0.0.1] (unknown [IPv6:2001:470:683e::1]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (P-256) server-signature ECDSA (P-384) server-digest SHA384) (Client did not present a certificate) (Authenticated sender: xry111@xry111.site) by xry111.site (Postfix) with ESMTPSA id 7F8FF66C01; Wed, 10 Apr 2024 05:19:56 -0400 (EDT) Message-ID: <5379650ad2582ae97c40ef1a78ded354033d2f71.camel@xry111.site> Subject: Re: optimizer discards sign information From: Xi Ruoyao To: Alexander Monakov , stefan@franke.ms Cc: gcc-help@gcc.gnu.org Date: Wed, 10 Apr 2024 17:19:54 +0800 In-Reply-To: References: <016501da8b24$735d5170$5a17f450$@franke.ms> Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable User-Agent: Evolution 3.52.0 MIME-Version: 1.0 X-Spam-Status: No, score=-1.8 required=5.0 tests=BAYES_00,DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,LIKELY_SPAM_FROM,SPF_HELO_PASS,SPF_PASS,TXREP autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on server2.sourceware.org List-Id: On Wed, 2024-04-10 at 12:16 +0300, Alexander Monakov wrote: >=20 > On Wed, 10 Apr 2024, stefan@franke.ms=C2=A0wrote: >=20 > > Hi all, > >=20 > > I just stumbled over an issue, which is present in almost all gcc versi= ons. > > I worked around using inline assembly=E2=80=A6 > > Maybe gcc behaves correct and I am wrong? Here is the code: > >=20 > > https://godbolt.org/z/cW8jcdh56 > >=20 > > typedef unsigned long long int u64; > > typedef unsigned int u32; > > typedef unsigned short u16; > >=20 > > u64 foo(u16 a, u16 b) { > > =C2=A0 =C2=A0 u32 x =3D a * b; > > =C2=A0 =C2=A0 u64 r =3D x; > > =C2=A0 =C2=A0 return r; > > } > >=20 > > And on gcc 13.2 x86.64 you get > >=20 > > foo: > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 movzx =C2=A0 esi, si > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 movzx =C2=A0 edi, di > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 imul =C2=A0 =C2=A0edi, esi > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 movsx =C2=A0 rax, edi > > =C2=A0 =C2=A0 =C2=A0 =C2=A0 ret > >=20 > >=20 > > There is a sign extension! The optimizer step discards the information > >=20 > > =C2=A0x_6 =3D (u32) _3; > >=20 > > and uses _3 directly instead, which is signed. > >=20 > > Am I wrong or is it gcc? >=20 > GCC is not wrong. When your code computes x: >=20 > =C2=A0=C2=A0=C2=A0 u32 x =3D a * b; >=20 > 'a' and 'b' are first promoted to int according to C language rules, and > the multiplication happens in the signed int type, with UB on overflow. > The compiler deduces the range of signed int temporary holding the result > of the multiplication is [0, 0x7fffffff], which allows to propagate it > to the assignment of 'r' (which in the end produces a sign extension, > as you observed, so the propagation did not turn out to be useful). >=20 > u16 * u16 is a famous footgun for sure. I'd suggest 'x =3D 1u * a * b' > as a fix for the code. Also note that -fsanitize=3Dundefined detects the issue properly: $ cat t.c typedef unsigned long long int u64; typedef unsigned int u32; typedef unsigned short u16; __attribute__((noipa)) u64 foo(u16 a, u16 b) { u32 x =3D a * b; u64 r =3D x; return r; } int main() { __builtin_printf("%llx\n", foo(65535, 65535)); } $ cc t.c -O2 -fsanitize=3Dundefined $ ./a.out t.c:7:15: runtime error: signed integer overflow: 65535 * 65535 cannot be r= epresented in type 'int' fffe0001 --=20 Xi Ruoyao School of Aerospace Science and Technology, Xidian University