From patchwork Tue Mar 29 17:00:46 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Aldy Hernandez X-Patchwork-Id: 88814 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) by ozlabs.org (Postfix) with SMTP id A439CB6EDF for ; Wed, 30 Mar 2011 04:01:09 +1100 (EST) Received: (qmail 3777 invoked by alias); 29 Mar 2011 17:00:59 -0000 Received: (qmail 3725 invoked by uid 22791); 29 Mar 2011 17:00:52 -0000 X-SWARE-Spam-Status: No, hits=-6.5 required=5.0 tests=AWL, BAYES_00, RCVD_IN_DNSWL_HI, SPF_HELO_PASS, T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Tue, 29 Mar 2011 17:00:47 +0000 Received: from int-mx02.intmail.prod.int.phx2.redhat.com (int-mx02.intmail.prod.int.phx2.redhat.com [10.5.11.12]) by mx1.redhat.com (8.14.4/8.14.4) with ESMTP id p2TH0lx3011295 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Tue, 29 Mar 2011 13:00:47 -0400 Received: from houston.quesejoda.com (vpn-231-154.phx2.redhat.com [10.3.231.154]) by int-mx02.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id p2TH0kkk006477; Tue, 29 Mar 2011 13:00:46 -0400 Message-ID: <4D92103E.90100@redhat.com> Date: Tue, 29 Mar 2011 12:00:46 -0500 From: Aldy Hernandez User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.2.15) Gecko/20110307 Fedora/3.1.9-0.39.b3pre.fc14 Lightning/1.0b3pre Thunderbird/3.1.9 MIME-Version: 1.0 To: gcc-patches CC: Jakub Jelinek Subject: [cxx-mem-model] bitfield tests 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 [Language lawyers, please correct me if I have mis-interpreted the upcoming standard in any way.] In the C++ memory model, contiguous bitfields comprise a single memory location, so it's fair game to bit twiddle them when setting them. For example: struct { unsigned int a : 4; unsigned int b : 4; unsigned int c : 4; }; In the above example, you can touch and while setting . No race there. However, non contiguous bitfields are a different story: struct { unsigned int a : 4; char b; unsigned int c : 6; }; Here we have 3 distinct memory locations, so you can't touch or while setting . No bit twiddling allowed. Similarly for bitfields separated by a zero-length bitfield: struct { unsigned int a : 4; int : 0; unsigned int c : 6; }; In the above example, and are distinct memory locations. Also, a structure/union boundary will also separate previously contiguous bit sequences: struct { unsigned int a : 4; struct { unsigned int b : 4 } BBB; unsigned int c : 4; }; Here we have 3 distinct memory locations, so again, we can't clobber or while setting . The patch below adds a non-contiguous bit test (bitfields-2.C) which passes on x86, but upon assembly inspection, fails on PPC64, s390, and Alpha. These 3 architectures bit-twiddle their way out of the problem. There is also a similar test already in the testsuite (bitfields.C) which is similar except one field is a volatile. This test fails on x86-64 as well and is the subject of PR48128 which Jakub is currently tackling. As soon as Jakub finishes with PR48128, I will be working on getting these bitfield tests working in a C++ memory model fashion. Committing to branch. * gcc.dg/memmodel/subfields.c (set_a): Set noinline attribute. * g++.dg/memmodel/bitfields.C (set_a): Same. * g++.dg/memmodel/bitfields-2.C: New. Index: gcc.dg/memmodel/subfields.c =================================================================== --- gcc.dg/memmodel/subfields.c (revision 170937) +++ gcc.dg/memmodel/subfields.c (working copy) @@ -20,6 +20,7 @@ struct test_struct { not affect any of the other fields in the structure. An improper implementation may load an entire word, change the 8 bits for field 'a' and write the entire word back out. */ +__attribute__((noinline)) void set_a(char x) { var.a = x; Index: g++.dg/memmodel/bitfields-2.C =================================================================== --- g++.dg/memmodel/bitfields-2.C (revision 0) +++ g++.dg/memmodel/bitfields-2.C (revision 0) @@ -0,0 +1,71 @@ +/* { dg-do link } */ +/* { dg-options "-O2 --param allow-load-data-races=0 --param allow-store-data-races=0" } */ +/* { dg-final { memmodel-gdb-test } } */ + +/* Test that setting does not touch either or . + In the C++ memory model, non contiguous bitfields ("a" and "c" + here) should be considered as distinct memory locations, so we + can't use bit twiddling to set either one. */ + +#include +#include "memmodel.h" + +#define CONSTA 12 + +static int global; +struct S +{ + unsigned int a : 4; + unsigned char b; + unsigned int c : 6; +} var; + +__attribute__((noinline)) +void set_a() +{ + var.a = CONSTA; +} + +void memmodel_other_threads() +{ + ++global; + var.b = global; + var.c = global; +} + +int memmodel_step_verify() +{ + int ret = 0; + if (var.b != global) + { + printf ("FAIL: Unexpected value: var.b is %d, should be %d\n", + var.b, global); + ret = 1; + } + if (var.c != global) + { + printf ("FAIL: Unexpected value: var.c is %d, should be %d\n", + var.c, global); + ret = 1; + } + return ret; +} + +int memmodel_final_verify() +{ + int ret = memmodel_step_verify(); + if (var.a != CONSTA) + { + printf ("FAIL: Unexpected value: var.a is %d, should be %d\n", + var.a, CONSTA); + ret = 1; + } + return ret; +} + +int main() +{ + set_a(); + memmodel_done(); + return 0; +} Index: g++.dg/memmodel/bitfields.C =================================================================== --- g++.dg/memmodel/bitfields.C (revision 171248) +++ g++.dg/memmodel/bitfields.C (working copy) @@ -23,6 +23,7 @@ struct S unsigned int c : 6; } var; +__attribute__((noinline)) void set_a() { var.a = CONSTA;