From patchwork Tue Nov 2 15:52:24 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 46958 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 19A023858404 for ; Tue, 2 Nov 2021 15:52:58 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mxa.tachyum.com (mxa.tachyum.com [50.229.46.153]) by sourceware.org (Postfix) with ESMTPS id 7FBC03858D39 for ; Tue, 2 Nov 2021 15:52:29 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 7FBC03858D39 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=tachyum.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=tachyum.com X-Virus-Scanned: by SpamTitan at tachyum.com Authentication-Results: mxa.tachyum.com; x-trusted-ip=pass Message-ID: <5bc6c39a-568c-e24b-3a0c-00885b0630f0@tachyum.com> Date: Tue, 2 Nov 2021 09:52:24 -0600 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:91.0) Gecko/20100101 Thunderbird/91.1.2 Content-Language: en-US From: Jeff Law To: GCC Patches Subject: [RFA] Minor optimization of variable bit testing X-ClientProxiedBy: THQ-EX1.tachyum.com (10.7.1.6) To THQ-EX1.tachyum.com (10.7.1.6) X-Spam-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, KAM_DMARC_STATUS, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" I was wandering spec chasing down instances where we should be generating bit-test, bit-set and bit-clear types of instructions for our target when I ran across a generic missed optimization in this space. (((1 << N) & C) != 0)  -> (N == C') (((1 << N) & C) == 0)  -> (N != C') Where C is a constant power of 2 and C' is log2 (C). That obviously avoids the shift by a variable amount and the bit masking which is the primary effect.  I did see cases where we were able to constant propagate into uses of N, but those were only in PHI nodes and never triggered any real secondary effects in the cases I looked at. Anyway, it's a fairly minor optimization, but with the analysis done and patch in hand, it's silly not to take the easy win. Bootstrapped and regression tested on x86_64 and verified that the affected spec benchmark (gcc itself) still passes on our target. OK for the trunk?  Note I added the patterns at the end of match.pd.  Certainly open to moving them elsewhere. Jeff diff --git a/gcc/match.pd b/gcc/match.pd index 4fbba3922e5..b275631555d 100644 --- a/gcc/match.pd +++ b/gcc/match.pd @@ -6835,3 +6835,20 @@ DEFINE_INT_AND_FLOAT_ROUND_FN (RINT) to the number of trailing zeroes. */ (match (ctz_table_index @1 @2 @3) (rshift (mult (bit_and:c (negate @1) @1) INTEGER_CST@2) INTEGER_CST@3)) + +/* ((1 << n) & M) != 0 -> n == log2 (M) */ +(simplify + (ne + (bit_and + (nop_convert? (lshift integer_onep@0 @1)) integer_pow2p@2) integer_zerop@3) + (eq @1 { build_int_cst (integer_type_node, + wi::exact_log2 (wi::to_wide (@2))); })) + +/* ((1 << n) & M) == 0 -> n != log2 (M) */ +(simplify + (eq + (bit_and + (nop_convert? (lshift integer_onep@0 @1)) integer_pow2p@2) integer_zerop@3) + (ne @1 { build_int_cst (integer_type_node, + wi::exact_log2 (wi::to_wide (@2))); })) + diff --git a/gcc/testsuite/gcc.dg/tree-ssa/bittest.c b/gcc/testsuite/gcc.dg/tree-ssa/bittest.c new file mode 100644 index 00000000000..7d712cad1ee --- /dev/null +++ b/gcc/testsuite/gcc.dg/tree-ssa/bittest.c @@ -0,0 +1,27 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + + +void bar (void); + +void +foo(unsigned int abc123) +{ + unsigned int xyzpdq = (1 << abc123); + if ((xyzpdq & 0x800) != 0) + bar(); +} + +void +baz(unsigned int abc123) +{ + unsigned int xyzpdq = (1 << abc123); + if ((xyzpdq & 0x800) == 0) + bar(); +} + +/* What we want to verify is that the bit test against xyzpdq is + replaced with a test against abc123 which avoids the shifting + and bit ops. */ +/* { dg-final { scan-tree-dump-not "xyzpdq" "optimized"} } */ +/* { dg-final { scan-tree-dump-times "if .abc123" 2 "optimized"} } */