From patchwork Mon Sep 11 10:26:09 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Eric Botcazou X-Patchwork-Id: 812300 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-461804-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="Ejea1ojS"; dkim-atps=neutral Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3xrPGm704Tz9s7f for ; Mon, 11 Sep 2017 20:26:24 +1000 (AEST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=MxHago27fIvY8hvo 4AIsxx5lcJjngqMyu35y2eRNbK2knhO2+JccHcacVhmfbCP37mchBzuFXlj6J6mp N23au0BRm8nMc51FPDI2AIG9/NrqkgAOHa2zSzSTOdM+UCgtKCjcjjRzf2VZLHOy r2HDcAMphV6iqaBZ9X+niLP+RzA= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=2wwj0ICu5sVUoqWkZe+lQP e+QtI=; b=Ejea1ojSfH2Mek4RUwy7QnHbc0msVq495IRx/Ryl+IQsEtYcBEKGcI Gjn+5a+GpsTHZfG3hzchp5KWdRWrERBalatE2jSahWkC8ofQQ0LhDWWyQpnIYRTo Fx6vB56W6+rHGjUAcVqJkQ2/sgtnsJEh9+BPbS6J+p1/m2alOG/ko= Received: (qmail 46279 invoked by alias); 11 Sep 2017 10:26:17 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 45893 invoked by uid 89); 11 Sep 2017 10:26:16 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.9 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=Hx-languages-length:3140, UD:c2, 036 X-HELO: smtp.eu.adacore.com Received: from mel.act-europe.fr (HELO smtp.eu.adacore.com) (194.98.77.210) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 11 Sep 2017 10:26:13 +0000 Received: from localhost (localhost [127.0.0.1]) by filtered-smtp.eu.adacore.com (Postfix) with ESMTP id 719D282310 for ; Mon, 11 Sep 2017 12:26:10 +0200 (CEST) Received: from smtp.eu.adacore.com ([127.0.0.1]) by localhost (smtp.eu.adacore.com [127.0.0.1]) (amavisd-new, port 10024) with ESMTP id tm9XrW90Mth2 for ; Mon, 11 Sep 2017 12:26:10 +0200 (CEST) Received: from polaris.localnet (bon31-6-88-161-99-133.fbx.proxad.net [88.161.99.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.eu.adacore.com (Postfix) with ESMTPSA id DDCE9822CE for ; Mon, 11 Sep 2017 12:26:09 +0200 (CEST) From: Eric Botcazou To: gcc-patches@gcc.gnu.org Subject: [patch] Fix wrong code with small structure return on PowerPC Date: Mon, 11 Sep 2017 12:26:09 +0200 Message-ID: <14904386.2vhstX5eeo@polaris> User-Agent: KMail/4.14.10 (Linux/3.16.7-53-desktop; KDE/4.14.9; x86_64; ; ) MIME-Version: 1.0 Hi, this is a bug originally reported in Ada on 32-bit PowerPC with the SVR4 ABI (hence not Linux) and reproducible in C with the attached testcase at -O1. The problem lies in function 'foo': struct S ret; char r, s, c1, c2; char *p = &r; s = bar (&p); if (s) c2 = *p; c1 = 0; ret.c1 = c1; ret.c2 = c2; return ret; Since the call to bar returns 0, c2 is uninitialized at run time (but this doesn't matter for correctness since its value is never read). Now both c1 and c2 are represented at the RTL level by unsigned promoted subregs, i.e. SUBREGs verifying SUBREG_PROMOTED_VAR_P and SUBREG_PROMOTED_UNSIGNED_P As a consequence, when store_fixed_bit_field_1 stores the 8-bit values into the 'ret' object, it considers that the underlying 32-bit objects have only 8 bits set and the rest cleared so it doesn't mask the other 24 bits. That's OK for c1 but not for c2, since c2 is uninitialized so the bits are random. This appears to be an inherent weakness of the promoted subregs mechanism, but I don't think that we want to go for an upheaval at this point. So the patch addresses the problem in an ad-hoc manner directly in store_fixed_bit_field_1 and yields the expected 8-bit insertion: @@ -26,7 +26,7 @@ lwz 9,12(1) lbz 31,0(9) .L3: - slwi 3,31,16 + rlwinm 3,31,16,8,15 lwz 0,36(1) mtlr 0 lwz 31,28(1) Tested on x86-64/Linux and PowerPC64/Linux, OK for the mainline? 2017-09-11 Eric Botcazou * expmed.c (store_fixed_bit_field_1): Force the masking if the value is an unsigned promoted SUBREG of a sufficiently large object. 2017-09-11 Eric Botcazou * gcc.c-torture/execute/20170911-1.c: New test. Index: expmed.c =================================================================== --- expmed.c (revision 251906) +++ expmed.c (working copy) @@ -1213,13 +1213,25 @@ store_fixed_bit_field_1 (rtx op0, scalar } else { - int must_and = (GET_MODE_BITSIZE (value_mode) != bitsize - && bitnum + bitsize != GET_MODE_BITSIZE (mode)); + /* Compute whether we must mask the value in order to make sure that the + bits outside the bitfield are all cleared. Note that, even though the + value has the right size, if it has a mode different from MODE, then + converting it to MODE may unmask uninitialized bits in the case where + it is an unsigned promoted SUBREG of a sufficiently large object. */ + const bool must_mask + = (GET_MODE_BITSIZE (value_mode) != bitsize + || (value_mode != mode + && GET_CODE (value) == SUBREG + && SUBREG_PROMOTED_VAR_P (value) + && SUBREG_PROMOTED_UNSIGNED_P (value) + && GET_MODE_SIZE (GET_MODE (SUBREG_REG (value))) + >= GET_MODE_SIZE (mode))) + && bitnum + bitsize != GET_MODE_BITSIZE (mode); if (value_mode != mode) value = convert_to_mode (mode, value, 1); - if (must_and) + if (must_mask) value = expand_binop (mode, and_optab, value, mask_rtx (mode, 0, bitsize, 0), NULL_RTX, 1, OPTAB_LIB_WIDEN);