From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lf1-x134.google.com (mail-lf1-x134.google.com [IPv6:2a00:1450:4864:20::134]) by sourceware.org (Postfix) with ESMTPS id B853D389EC52 for ; Thu, 11 Aug 2022 00:50:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org B853D389EC52 Received: by mail-lf1-x134.google.com with SMTP id e15so23641640lfs.0 for ; Wed, 10 Aug 2022 17:50:09 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc; bh=x28yA4iat7e1UOiocKEjNzRNDjC+EfYDhqnvLIKgGKo=; b=NyqSctLLXLkZeC88IwxmVsV8nz9B/7JEwJ0jrL/eI18fOBgGZ6MRcTBOdPW9Xqiokz lGLXbGdF5vD3C9dB9LWgG4zU1TUIIctRcH8Gp9aXfIvViJIjrLVkCbU56IPl7jA79CFZ pl5FI0FallCYTnwkubGxdwlh+2SDoGOLiIlc4bcmCRTacMy0Eu/ch2usa/h1fNfRGRs0 M2KqjhlDEanX04OcYC4Fm5xS/U4VqOOA/vWKjkIg2M/7iDUL+XhlzSAVyio2u3Ko8NX5 tiaJY7T8+nQRkJhc4qN4jbEp9UuL/cLstvLu12ft3zcN1MlFYnOAowYF/1zyAbI2Zbfj ii/A== X-Gm-Message-State: ACgBeo3L3gWavWnu9dVSQbxBjKd6NindViBz+dDOMjB1aLSu5K8NQIRh SOC+vb6sNOM9Pkf0ljUAAOcDkyriPUC9aoX8ATE2Bg== X-Google-Smtp-Source: AA6agR4L0qOFnLlGVCiU64YoX/spr6P2izIC3HakHQkeKd+310xj+UF9AanbyBXfTdFFMM+khIZVcTQQqcBseVIPiDg= X-Received: by 2002:a05:6512:4010:b0:48a:f3df:e9af with SMTP id br16-20020a056512401000b0048af3dfe9afmr10698564lfb.131.1660179007854; Wed, 10 Aug 2022 17:50:07 -0700 (PDT) MIME-Version: 1.0 References: <4ba7b262-ee0b-905f-ba0a-611ee6749184@lambda.is> In-Reply-To: <4ba7b262-ee0b-905f-ba0a-611ee6749184@lambda.is> From: Ian Lance Taylor Date: Wed, 10 Aug 2022 17:49:55 -0700 Message-ID: Subject: Re: gccgo emits GIMPLE with temporaries for boolean expressions unlike gcc, gdc To: j Cc: gcc@gcc.gnu.org Content-Type: text/plain; charset="UTF-8" X-Spam-Status: No, score=-16.3 required=5.0 tests=BAYES_00, DKIMWL_WL_MED, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, ENV_AND_HDR_SPF_MATCH, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP, T_SCC_BODY_TEXT_LINE, USER_IN_DEF_DKIM_WL, USER_IN_DEF_SPF_WL 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@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 11 Aug 2022 00:50:15 -0000 On Wed, Aug 3, 2022 at 6:26 AM j wrote: > > I've proposed a patch [1] for condition coverage profiling in gcc, > implemented in the middle-end alongside the branch coverage. I've > written most of the tests for C and a few for C++ and finally got around > to try it with a toy example for D and go and noticed something odd > about Go's CFG construction. > > abc.c: > int fn (int a, int b, int c) { > if (a && (b || c)) > return a; > else > return b * c; > } > > abc.d: > int fn (int a, int b, int c) { > if (a && (b || c)) > return a; > else > return b * c; > } > > abc.go: > func fn (a int, b int, c int) int { > a_ := a != 0; > b_ := b != 0; > c_ := c != 0; > > if a_ && (b_ || c_) { > return 1; > } else { > return 0; > } > } > > All were built with gcc --coverage -fprofile-conditions (my patch, but > it does not affect this) and no optimization. The C and D programs > behaved as expected: > > gcov --conditions abc.d: > > 3: 3:int fn (int a, int b, int c) { > 3*: 4: if (a && (b || c)) > conditions outcomes covered 3/6 > condition 1 not covered (false) > condition 2 not covered (true) > condition 2 not covered (false) > 1: 5: return a; > -: 6: else > 2: 7: return b * c; > > > gcov --conditions abc.go: > 3: 5:func fn (a int, b int, c int) int { > 3: 6: a_ := a != 0; > 3: 7: b_ := b != 0; > 3: 8: c_ := c != 0; > -: 9: > 3*: 10: if a_ && (b_ || c_) { > condition outcomes covered 2/2 > condition outcomes covered 1/2 > condition 0 not covered (true) > condition outcomes covered 2/2 > 1: 11: return 1; > -: 12: } else { > 2: 13: return 0; > -: 14: } > -: 15:} > > So I dumped the gimple gcc -fdump-tree-gimple abc.go: > > int main.fn (int a, int b, int c) > { > int D.2725; > int $ret0; > > $ret0 = 0; > { > bool a_; > bool b_; > bool c_; > > a_ = a != 0; > b_ = b != 0; > c_ = c != 0; > { > { > GOTMP.0 = a_; > if (GOTMP.0 != 0) goto ; else goto ; > : > { > { > GOTMP.1 = b_; > _1 = ~GOTMP.1; > if (_1 != 0) goto ; else goto ; > : > { > GOTMP.1 = c_; > } > : > } > GOTMP.2 = GOTMP.1; > GOTMP.0 = GOTMP.2; > } > : > } > if (GOTMP.0 != 0) goto ; else goto ; > : > > > > { > { > $ret0 = 1; > D.2725 = $ret0; > // predicted unlikely by early return (on trees) predictor. > return D.2725; > } > } > : > { > { > $ret0 = 0; > D.2725 = $ret0; > // predicted unlikely by early return (on trees) predictor. > return D.2725; > } > } > } > } > } > > Where as D (and C) is more-or-less as you would expect: > > int fn (int a, int b, int c) > > > > { > int D.7895; > > if (a != 0) goto ; else goto ; > : > if (b != 0) goto ; else goto ; > : > if (c != 0) goto ; else goto ; > : > D.7895 = a; > // predicted unlikely by early return (on trees) predictor. > return D.7895; > : > D.7895 = b * c; > // predicted unlikely by early return (on trees) predictor. > return D.7895; > } > > Clearly the decision inference algorithm is unable to properly > instrument to Go program for condition coverage because of the use of > temporaries in the emitted GIMPLE. The question is: is this intentional > and/or required from Go's semantics or could it be considered a defect? > Is emitting the GIMPLE without the use of temporaries feasible at all? The Go frontend converts && and || expressions into code that uses explicit if statements. This is done largely as an internal simplification. Go has rules about the order in which function calls and certain other kinds of expressions must be evaluated. Separating out the order of evaluation imposed by && and || simplifies the implementation of the other order of evaluation rules. Ian