get:
Show a patch.

patch:
Update a patch.

put:
Update a patch.

GET /api/patches/2218124/?format=api
HTTP 200 OK
Allow: GET, PUT, PATCH, HEAD, OPTIONS
Content-Type: application/json
Vary: Accept

{
    "id": 2218124,
    "url": "http://patchwork.ozlabs.org/api/patches/2218124/?format=api",
    "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260331131256.3499627-1-daniel.barboza@oss.qualcomm.com/",
    "project": {
        "id": 17,
        "url": "http://patchwork.ozlabs.org/api/projects/17/?format=api",
        "name": "GNU Compiler Collection",
        "link_name": "gcc",
        "list_id": "gcc-patches.gcc.gnu.org",
        "list_email": "gcc-patches@gcc.gnu.org",
        "web_url": null,
        "scm_url": null,
        "webscm_url": null,
        "list_archive_url": "",
        "list_archive_url_format": "",
        "commit_url_format": ""
    },
    "msgid": "<20260331131256.3499627-1-daniel.barboza@oss.qualcomm.com>",
    "list_archive_url": null,
    "date": "2026-03-31T13:12:56",
    "name": "tree-ssa-phiopt.cc: add cond_removal_mispredict_memop [PR124667]",
    "commit_ref": null,
    "pull_url": null,
    "state": "new",
    "archived": false,
    "hash": "edf2b27f17d7081b02394eeb391ca5b664691993",
    "submitter": {
        "id": 92288,
        "url": "http://patchwork.ozlabs.org/api/people/92288/?format=api",
        "name": "Daniel Henrique Barboza",
        "email": "daniel.barboza@oss.qualcomm.com"
    },
    "delegate": null,
    "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260331131256.3499627-1-daniel.barboza@oss.qualcomm.com/mbox/",
    "series": [
        {
            "id": 498196,
            "url": "http://patchwork.ozlabs.org/api/series/498196/?format=api",
            "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=498196",
            "date": "2026-03-31T13:12:56",
            "name": "tree-ssa-phiopt.cc: add cond_removal_mispredict_memop [PR124667]",
            "version": 1,
            "mbox": "http://patchwork.ozlabs.org/series/498196/mbox/"
        }
    ],
    "comments": "http://patchwork.ozlabs.org/api/patches/2218124/comments/",
    "check": "pending",
    "checks": "http://patchwork.ozlabs.org/api/patches/2218124/checks/",
    "tags": {},
    "related": [],
    "headers": {
        "Return-Path": "<gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org>",
        "X-Original-To": [
            "incoming@patchwork.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Delivered-To": [
            "patchwork-incoming@legolas.ozlabs.org",
            "gcc-patches@gcc.gnu.org"
        ],
        "Authentication-Results": [
            "legolas.ozlabs.org;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.a=rsa-sha256\n header.s=qcppdkim1 header.b=k71eyvsO;\n\tdkim=pass (2048-bit key;\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.a=rsa-sha256 header.s=google header.b=FKC7U2Dn;\n\tdkim-atps=neutral",
            "legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=2620:52:6:3111::32; helo=vm01.sourceware.org;\n envelope-from=gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org;\n receiver=patchwork.ozlabs.org)",
            "sourceware.org;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=qualcomm.com header.i=@qualcomm.com header.a=rsa-sha256\n header.s=qcppdkim1 header.b=k71eyvsO;\n\tdkim=pass (2048-bit key,\n unprotected) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com\n header.a=rsa-sha256 header.s=google header.b=FKC7U2Dn",
            "sourceware.org; dmarc=none (p=none dis=none)\n header.from=oss.qualcomm.com",
            "sourceware.org;\n spf=pass smtp.mailfrom=oss.qualcomm.com",
            "server2.sourceware.org;\n arc=none smtp.remote-ip=205.220.168.131"
        ],
        "Received": [
            "from vm01.sourceware.org (vm01.sourceware.org\n [IPv6:2620:52:6:3111::32])\n\t(using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)\n\t key-exchange x25519 server-signature ECDSA (secp384r1) server-digest SHA384)\n\t(No client certificate requested)\n\tby legolas.ozlabs.org (Postfix) with ESMTPS id 4flT8P34XFz1yCp\n\tfor <incoming@patchwork.ozlabs.org>; Wed, 01 Apr 2026 00:13:41 +1100 (AEDT)",
            "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 5C09A4BB58CA\n\tfor <incoming@patchwork.ozlabs.org>; Tue, 31 Mar 2026 13:13:39 +0000 (GMT)",
            "from mx0a-0031df01.pphosted.com (mx0a-0031df01.pphosted.com\n [205.220.168.131])\n by sourceware.org (Postfix) with ESMTPS id 5E5B04BA2E2A\n for <gcc-patches@gcc.gnu.org>; Tue, 31 Mar 2026 13:13:04 +0000 (GMT)",
            "from pps.filterd (m0279862.ppops.net [127.0.0.1])\n by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id\n 62VB4q9O1091985\n for <gcc-patches@gcc.gnu.org>; Tue, 31 Mar 2026 13:13:03 GMT",
            "from mail-qt1-f197.google.com (mail-qt1-f197.google.com\n [209.85.160.197])\n by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4d7trd4vrn-1\n (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT)\n for <gcc-patches@gcc.gnu.org>; Tue, 31 Mar 2026 13:13:03 +0000 (GMT)",
            "by mail-qt1-f197.google.com with SMTP id\n d75a77b69052e-50b2cbe7223so185616251cf.2\n for <gcc-patches@gcc.gnu.org>; Tue, 31 Mar 2026 06:13:02 -0700 (PDT)",
            "from QCOM-UWl2o8bcGT.qualcomm.com ([177.18.66.130])\n by smtp.gmail.com with ESMTPSA id\n d75a77b69052e-50bb2a80ef0sm91094171cf.0.2026.03.31.06.12.59\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Tue, 31 Mar 2026 06:13:00 -0700 (PDT)"
        ],
        "DKIM-Filter": [
            "OpenDKIM Filter v2.11.0 sourceware.org 5C09A4BB58CA",
            "OpenDKIM Filter v2.11.0 sourceware.org 5E5B04BA2E2A"
        ],
        "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 5E5B04BA2E2A",
        "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 5E5B04BA2E2A",
        "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1774962784; cv=none;\n b=GfS3d5zOQzlpuFggNeXC89dQtUWT6wxXbrRApcHDWq5i6lQHEvb7faARB6oOFvJSDFK424zOegsxnPuOkAj2/bZuDk6kQDaU+x5krzu97BVZWdRljPrBjWn8mptrxUMBz28SYv36xRO1NxakUIqJmFn1Bu9xYH63EvQnaxMfeBQ=",
        "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1774962784; c=relaxed/simple;\n bh=oeicOUmSpdQo+08fA8emVxJarKMAo8pg4IkyM5u2NzI=;\n h=DKIM-Signature:DKIM-Signature:From:To:Subject:Date:Message-ID:\n MIME-Version;\n b=RF7xbL3zTzJFiNsDDVSidYbopZe4winCqZaU+EUnw15YL8EBwihhZc49wRVMbZXJKvmOxcJoP3bXu2KI6tDrMP8lbO2hJoaP/U9OgQGGyoFVxaPYseDR6q93H10dcFY0cVWoPjOZT25XKM4yvR4j2oXSSiAe+n1WQ+69idO18A0=",
        "ARC-Authentication-Results": "i=1; server2.sourceware.org",
        "DKIM-Signature": [
            "v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h=\n cc:content-transfer-encoding:date:from:message-id:mime-version\n :subject:to; s=qcppdkim1; bh=tozLdFv6gbWjIxobALvZx5oEf1a1oIJY9/w\n MAa17W+8=; b=k71eyvsOHEiTEoLTIi4fYkUCG7X3pV4r/SaFCXlQn7P4Vhzr/sx\n 8tosyihh9xGmMv3yBnZn3usPbEqYcTgs0whEX0sJbuYkxGU0/uXBxcdQaLtGvSn/\n 702PXvf4NOtS3DGQ+qqn3qEcj1aTDiznymqcH2qjhJAb28yPIPaE5FSIvx7lhfsW\n RIYYUphyQj38wmp/hCCjLHe+01YXpFLhUWGHiQBM6D9HmAZ9Krr/WP3d5nGxNnsn\n fNjJdAVStPgc5RtGe9ENrJn1ZWHbtFetCiSMFGoIuwGn9ZBtluVT0pLy3HwFsVsq\n Y2dAG9xAAzBBWUW486Ulj416nIB0gIT7ZwA==",
            "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=oss.qualcomm.com; s=google; t=1774962782; x=1775567582; darn=gcc.gnu.org;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:from:to:cc:subject:date:message-id:reply-to;\n bh=tozLdFv6gbWjIxobALvZx5oEf1a1oIJY9/wMAa17W+8=;\n b=FKC7U2Dn0aNj97y2B1uL+lxWDR1aqIOOnqHUs07FxxQetgUkOWhJT2uhGLGTQPYxLK\n c1apm+UdbTH35oxWtfIAuQy7Aor4HzKRyh6AS0vw6j4VBumlM4nO6v6VOO5Sd1C+5rda\n mx7NfORK+O1kywt0YeUTDxiV/Kdy38Eqls0UOmY58fygZOnXeZO5aYpFjuIp9nRG4Wh7\n 4d6UihKgSjlnoaj5ah76BGEE51TnMYY7AHyvWJRZiOVFTBMjBp+2esNCnmVrKQZKAaWZ\n /toRRpyfcCLpxCQ60VlVcKmwLv8FNgyml7ltPgn5gUncslXx1XO43SCICU/knfj84rZ+\n ndCA=="
        ],
        "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1774962782; x=1775567582;\n h=content-transfer-encoding:mime-version:message-id:date:subject:cc\n :to:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date\n :message-id:reply-to;\n bh=tozLdFv6gbWjIxobALvZx5oEf1a1oIJY9/wMAa17W+8=;\n b=S2n/Zr/OH63OcFqKXiRh74xxj27iYE+jsOn5RVTV8LDb9ZIo4uOXytfa6W2MsdI3sl\n bHHFT+pz7FpOiiPfC4suh2fpGcifnUdIU9Oz+XdzJBwo+E/rpWEvYyrrGglKTXuJOx5f\n jrxrQO8V5y2RK1zM+vaZgO/oly4WOTBTq0/6rpX+Xr5seoDHXPkfM5idRwk6Hwz62A7i\n jBh9ObDa8EbSVOoyMcqYCHJo31V92SCFx/sKfIE/dqgIATSKaWLpMVTubYua4jz6T5VX\n kDaiOzrlJCSLxP0VsBCr0QVMaaS8Qh+tfOUI3j4yfmBK0omrsuqZwXYzY2LuH/5qtHQ2\n UVrg==",
        "X-Gm-Message-State": "AOJu0Yw1uNxtKtxbFGLVodiMjLTwyelYJDoAxmpt6sRKmtNczbyRr6Nb\n yYlOG/P6ZCzASk/KywKvqzX2rm/aB15axwMHyPcyoCPTj18DScGA8Hpf5ejTyXdoYqL+6wzpwkP\n JZtFfUCJpVM7Zc4qp2HWlqWSvzz5lR9dit6UuhUcF/GQTF2uTnJFQytWM2of0DjwRnwNX",
        "X-Gm-Gg": "ATEYQzzN37Ts0Mq/WYbWyY7Qz2WQ+Ok15NyahEhvrPs+Pn+bskvE4RdnjjmBU/i7VLd\n 5zNpr9L4af+6Exrr0iAQPS2C4nC09TK7xct3et1OxO2JUsJ9wM26j4BpLumcpdYToxGqkBDHvVE\n MDnV2pR0h2DUqL5y9FYIInO2fZxaU75xylxJNFmswwrP+hZq/6j5INy7WmgDt805dx18ZIIfOgm\n QjWbNZ3w1sOLI5YVWRrZk6vvleSRlFgMxlcOooQVacc8b+AtwSW3JcraCWs9/G9qQpvRDKAO0MK\n t+QA1fRwNu4mwkaV+koHp2eNBnuntphbO4u71NnOUlNI9W0jDty4cgezY2L7AeoDkSKOo8tkl2M\n 0aq+gKnBwfxIXcRlKCzGUZd+aZ1Yk4SlM2T17BXDtxaGD4I4NiSmmLMilIg==",
        "X-Received": [
            "by 2002:a05:622a:24f:b0:50b:4f75:c925 with SMTP id\n d75a77b69052e-50ba3833141mr231505361cf.24.1774962781542;\n Tue, 31 Mar 2026 06:13:01 -0700 (PDT)",
            "by 2002:a05:622a:24f:b0:50b:4f75:c925 with SMTP id\n d75a77b69052e-50ba3833141mr231504601cf.24.1774962780879;\n Tue, 31 Mar 2026 06:13:00 -0700 (PDT)"
        ],
        "From": "Daniel Henrique Barboza <daniel.barboza@oss.qualcomm.com>",
        "To": "gcc-patches@gcc.gnu.org",
        "Cc": "jeffrey.law@oss.qualcomm.com, andrew.pinski@oss.qualcomm.com,\n Daniel Barboza <daniel.barboza@oss.qualcomm.com>",
        "Subject": "[PATCH] tree-ssa-phiopt.cc: add cond_removal_mispredict_memop\n [PR124667]",
        "Date": "Tue, 31 Mar 2026 10:12:56 -0300",
        "Message-ID": "<20260331131256.3499627-1-daniel.barboza@oss.qualcomm.com>",
        "X-Mailer": "git-send-email 2.43.0",
        "MIME-Version": "1.0",
        "Content-Transfer-Encoding": "8bit",
        "X-Proofpoint-GUID": "33v06RKNUQGYK5EEhRsFoVjrVlZVpNYD",
        "X-Proofpoint-Spam-Details-Enc": "AW1haW4tMjYwMzMxMDEyNyBTYWx0ZWRfXwbMsp52AfY7p\n dAlpwvR+OJryWulZfmo1HTnOMyrXw7xBLQJEjS6N6vnGxyy7bZiJ95sLDgwvbdzj9Jd+GWoO856\n c7jwIP9qcRyuKVZkGf2nerEkRGLhrxJELnsd5Jd4J0xPuhlt8lItVFCQ2u+GaI1NTaU9tE9ESUz\n rLcsgXLHwDcn/LE8qG+F/7Kxejcm6rNBbhRGtiXY9FBpo0+6RjkTQmNTIKb0l1k5P+0o2xWqWJ9\n Cmq1WVmLOvQWRfzj02Rhbj9gZ0wpM93cocJo0SoLHIh1hhqaa1gYw5lD8y90CeFTavhQhkyaDMe\n FMu1v8w6f18OP3ofBfnYv320HYlUNqrQJ4Aw/6yZUx55Fmm7gJU5qO9EI4jZXAlQHil2l85p/+H\n cVaaYJU2I6AZYbxFcwjBvq3Y+HyFpl2DYVeza318VQiZnze3ofDdDc+exXyNsuDlF9RcMf0mqw3\n IvNi+m+86feYfEwZJig==",
        "X-Proofpoint-ORIG-GUID": "33v06RKNUQGYK5EEhRsFoVjrVlZVpNYD",
        "X-Authority-Analysis": "v=2.4 cv=H8/WAuYi c=1 sm=1 tr=0 ts=69cbc85f cx=c_pps\n a=EVbN6Ke/fEF3bsl7X48z0g==:117 a=Wg2i10Q8swPuJs8jTFC2sw==:17\n a=Yq5XynenixoA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22\n a=u7WPNUs3qKkmUXheDGA7:22 a=_K5XuSEh1TEqbUxoQ0s3:22 a=EUspDBNiAAAA:8\n a=X-xWsWjqart143jDsn4A:9 a=a_PwQJl-kcHnX1M80qC6:22",
        "X-Proofpoint-Virus-Version": "vendor=baseguard\n engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49\n definitions=2026-03-31_02,2026-03-31_01,2025-10-01_01",
        "X-Proofpoint-Spam-Details": "rule=outbound_notspam policy=outbound score=0\n adultscore=0 priorityscore=1501 bulkscore=0 spamscore=0 lowpriorityscore=0\n clxscore=1015 impostorscore=0 phishscore=0 suspectscore=0 malwarescore=0\n classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0\n reason=mlx scancount=1 engine=8.22.0-2603050001 definitions=main-2603310127",
        "X-BeenThere": "gcc-patches@gcc.gnu.org",
        "X-Mailman-Version": "2.1.30",
        "Precedence": "list",
        "List-Id": "Gcc-patches mailing list <gcc-patches.gcc.gnu.org>",
        "List-Unsubscribe": "<https://gcc.gnu.org/mailman/options/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=unsubscribe>",
        "List-Archive": "<https://gcc.gnu.org/pipermail/gcc-patches/>",
        "List-Post": "<mailto:gcc-patches@gcc.gnu.org>",
        "List-Help": "<mailto:gcc-patches-request@gcc.gnu.org?subject=help>",
        "List-Subscribe": "<https://gcc.gnu.org/mailman/listinfo/gcc-patches>,\n <mailto:gcc-patches-request@gcc.gnu.org?subject=subscribe>",
        "Errors-To": "gcc-patches-bounces~incoming=patchwork.ozlabs.org@gcc.gnu.org"
    },
    "content": "From: Daniel Barboza <daniel.barboza@oss.qualcomm.com>\n\nConsider the following code that checks if a given bit is set, setting\nit in case it isn't:\n\nbit_val = 1 << num;\nif ((ptr[x] & bit_val) == 0)\n  {\n    ptr[x] |= bit_val;\n  }\nreturn ptr[x];\n\nThe generated gimple is something similar to:\n\n  ;; basic block 2\n  bitshift_6 = 1 << bit_5(D);\n  # VUSE <.MEM_7(D)>\n  _1 = arrD.4593[n_8(D)];\n  _2 = _1 & bitshift_6;\n  if (_2 == 0) goto <bb 3>; else goto <bb 4>;\n\n  ;; basic block 3\n  _3 = _1 | bitshift_6;\n  # .MEM_9 = VDEF <.MEM_7(D)>\n  arrD.4593[n_8(D)] = _3;\n  ;;    succ:       4 [always]  (FALLTHRU,EXECUTABLE)\n\n  ;;   basic block 4,\n  ;;    prev block 3\n  # .MEM_4 = PHI <.MEM_7(D)(2), .MEM_9(3)>\n  # VUSE <.MEM_4>\n  _10 = arrD.4593[n_8(D)];\n  # .MEM_11 = VDEF <.MEM_4>\n  arrD.4593 ={v} {CLOBBER(eos)};\n  # VUSE <.MEM_11>\n  return _10;\n\nIf we have the right conditions (e.g. we don't have store data races to\nworry about, we're not dealing with read-only memory) we can move the\nbitset operation to the cond_bb (block 2 in the example), removing the\npotential branch mispredict, as long as we're able to identify this \"bit\nN is either already set or will end up being set\" scenario:\n\n  bitshift_6 = 1 << bit_5(D);\n  # VUSE <.MEM_7(D)>\n  _1 = arrD.4593[n_8(D)];\n  _2 = _1 & bitshift_6;\n  _3 = _1 | bitshift_6;\n  # .MEM_9 = VDEF <.MEM_7(D)>\n  arrD.4593[n_8(D)] = _3;\n  if (_2 == 0) goto <bb 3>; else goto <bb 4>;\n\n  ;; basic block 3\n  ;;    succ:       4 [always]  (FALLTHRU,EXECUTABLE)\n  (...)\n\nIf the bitcheck result isn't being used as a PHI result there's a good\nchance that this optimization will get rid of both the bitcheck and the\ngcond.  The 'optimized' dump for the example above looks like this:\n\n  ;;   basic block 2\n  ;;    prev block 0\n  bitshift_6 = 1 << bit_5(D);\n  # VUSE <.MEM_7(D)>\n  _1 = arrD.4593[n_8(D)];\n  _3 = _1 | bitshift_6;\n  # .MEM_11 = VDEF <.MEM_7(D)>\n  arrD.4593 ={v} {CLOBBER(eos)};\n  # VUSE <.MEM_11>\n  return _3;\n\nThis optimization was motivated by GCC's bitmap_set_bit() before\nPR119482.  We're also covering the bitclear equivalent of this opt\n(check if a bit is set, if positive clear it).  The bitset\ntransformation only works for single bits.  The bitclear variation\ncan handle single or multiple bit masks.\n\nBootstrapped and regression tested in x86, aarch64 and RISC-V.\n\n\tPR tree-optimization/124667\n\ngcc/ChangeLog:\n\n\t* tree-ssa-phiopt.cc (stmt_is_memory_load_assignment): helper to\n\tcheck if a gimple stmt is a memory load.\n\t(stmt_is_memory_store_assignment): helper to check if a gimple\n\tstmt is a memory store.\n\t(cond_removal_mispredict_validate_memregs): helper to check if a\n\tmemory load and a memory store are using the same memory address.\n\t(cond_removal_mispredict_valid_bitmask): helper to validate if\n\tthe bit/bitmask is valid for the current optimization.\n\t(cond_removal_mispredict_check_cond): helper to validate the\n\tgcond and cond_stmt format.\n\t(cond_removal_mispredict_memop): new cselim optimization that,\n\tafter doing checks and validations, move a bitset/bitclear\n\toperation to the end of cond_bb, making it unconditional.\n\t(pass_cselim::execute): call cond_removal_mispredict_memop.\n\ngcc/testsuite/ChangeLog:\n\n\t* gcc.dg/tree-ssa/pr124667.c: New test.\n---\n gcc/testsuite/gcc.dg/tree-ssa/pr124667.c |  77 ++++\n gcc/tree-ssa-phiopt.cc                   | 443 ++++++++++++++++++++++-\n 2 files changed, 515 insertions(+), 5 deletions(-)\n create mode 100644 gcc/testsuite/gcc.dg/tree-ssa/pr124667.c",
    "diff": "diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr124667.c b/gcc/testsuite/gcc.dg/tree-ssa/pr124667.c\nnew file mode 100644\nindex 00000000000..1074169ac20\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/tree-ssa/pr124667.c\n@@ -0,0 +1,77 @@\n+/* { dg-additional-options -O2 } */\n+/* { dg-additional-options -fdump-tree-cselim } */\n+\n+int bitset1 (int n, int bit)\n+{\n+  int arr[16];\n+\n+  int bitshift = 1 << bit;\n+\n+  if ((arr[n] & bitshift) == 0)\n+    arr[n] |= bitshift;\n+\n+  return arr[n];\n+}\n+\n+int bitset2 (int n)\n+{\n+  int arr[16];\n+\n+  int bit = 0x4;\n+\n+  if ((arr[n] & bit) == 0)\n+    arr[n] |= bit;\n+\n+  return arr[n];\n+}\n+\n+int bitset3 (int n)\n+{\n+  int arr[16];\n+\n+  int bits = 0xF;\n+\n+  if ((arr[n] & bits) == 0)\n+    arr[n] |= bits;\n+\n+  return arr[n];\n+}\n+\n+int bitclear1 (int n, int bit)\n+{\n+  int arr[16];\n+\n+  int bitshift = 1 << bit;\n+\n+  if ((arr[n] & bitshift) != 0)\n+    arr[n] &= ~bitshift;\n+\n+  return arr[n];\n+}\n+\n+int bitclear2 (int n)\n+{\n+  int arr[16];\n+\n+  int bit = 0x4;\n+\n+  if ((arr[n] & bit) != 0)\n+    arr[n] &= ~bit;\n+\n+  return arr[n];\n+}\n+\n+int bitclear3 (int n)\n+{\n+  int arr[16];\n+\n+  int bits = 0xF;\n+\n+  if ((arr[n] & bits) != 0)\n+    arr[n] &= ~bits;\n+\n+  return arr[n];\n+}\n+\n+/* bitset3 won't be optimized all willl kept its branch.  */\n+/* { dg-final { scan-tree-dump-times \"goto\" 2 cselim } } */\ndiff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc\nindex 0bf7e58b8f0..32b577ae4cf 100644\n--- a/gcc/tree-ssa-phiopt.cc\n+++ b/gcc/tree-ssa-phiopt.cc\n@@ -3115,6 +3115,436 @@ cond_store_replacement (basic_block middle_bb, basic_block join_bb,\n   return true;\n }\n \n+/* Return TRUE if STMT is a memory load, FALSE otherwise.  */\n+\n+static bool\n+stmt_is_memory_load_assignment (gimple *stmt)\n+{\n+  if (!stmt\n+      || !gimple_assign_single_p (stmt)\n+      || gimple_has_volatile_ops (stmt)\n+      || !gimple_references_memory_p (stmt))\n+    return false;\n+\n+  tree rhs1 = gimple_assign_rhs1 (stmt);\n+  if ((!REFERENCE_CLASS_P (rhs1)\n+       && !DECL_P (rhs1))\n+      || !is_gimple_reg_type (TREE_TYPE (rhs1)))\n+    return false;\n+\n+  return true;\n+}\n+\n+/* Return TRUE if STMT is a memory store, FALSE otherwise.  */\n+\n+static bool\n+stmt_is_memory_store_assignment (gimple *stmt)\n+{\n+  /* Check if middle_bb contains of only one store.  */\n+  if (!stmt\n+      || !gimple_assign_single_p (stmt)\n+      || gimple_has_volatile_ops (stmt)\n+      || !gimple_references_memory_p (stmt))\n+    return false;\n+\n+  tree lhs = gimple_assign_lhs (stmt);\n+  if ((!REFERENCE_CLASS_P (lhs)\n+       && !DECL_P (lhs))\n+      || !is_gimple_reg_type (TREE_TYPE (lhs)))\n+    return false;\n+\n+  return true;\n+}\n+\n+/* cond_removal_mispredict_memop helper that checks if a\n+   given memreg operand of a bitop_stmt is a memory load,\n+   and it loads the same mem addr that is later stored\n+   in store_stmt:\n+\n+   # VUSE <.MEM_11>\n+   _1 = ptr_10->bits[word_num_12]; (load_stmt)\n+   (...)\n+   _3 = _1 OP bitmask;\t\t   (bitop_stmt)\n+   # .MEM_14 = VDEF <.MEM_11>\n+   ptr_10->bits[word_num_12] = _3; (store_stmt)\n+\n+   For the case above \"_1\" matches the criteria.\n+\n+   We're also validating whether store_stmt supports the\n+   transformation by testing its LHS for read-only memory\n+   and store data races.  */\n+\n+static bool\n+cond_removal_mispredict_validate_memregs (gimple *store_stmt,\n+\t\t\t\t\t  tree memreg)\n+{\n+  gimple *load_stmt = SSA_NAME_DEF_STMT (memreg);\n+  tree vuse = gimple_vuse (load_stmt);\n+\n+  if (!vuse || TREE_CODE (vuse) != SSA_NAME)\n+    return false;\n+\n+  vuse = SSA_NAME_VAR (vuse);\n+  tree vdef = gimple_vdef (store_stmt);\n+  if (!vdef || TREE_CODE (vdef) != SSA_NAME)\n+    return false;\n+\n+  vdef = SSA_NAME_VAR (vdef);\n+  if (vuse != vdef)\n+    return false;\n+\n+  tree lhs = gimple_assign_lhs (store_stmt);\n+  if (ref_can_have_store_data_races (lhs) && !flag_store_data_races)\n+    return false;\n+\n+  tree base = get_base_address (lhs);\n+  if (DECL_P (base) && TREE_READONLY (base))\n+    return false;\n+\n+  return true;\n+}\n+\n+/* Check if a given node represents a valid bitmask for\n+   the cond_removal_mispredict_memop transformation:\n+   single bit mask for unconditional bit set, multiple\n+   bits mask for unconditional bit clear.  */\n+\n+static bool\n+cond_removal_mispredict_valid_bitmask (tree bitmask, bool only_single_bit)\n+{\n+  if (TREE_CODE (bitmask) == INTEGER_CST)\n+    {\n+      if (!only_single_bit)\n+\treturn true;\n+      return wi::popcount (wi::to_wide (bitmask)) == 1;\n+    }\n+\n+  /* There are several ops that can generate any bitmask, but in this\n+     case we want to detect \"SSA_NAME = 1 << X\" that represents a\n+     single bit mask.  */\n+  if (TREE_CODE (bitmask) == SSA_NAME)\n+    {\n+      gimple *def_stmt = SSA_NAME_DEF_STMT (bitmask);\n+      return def_stmt\n+\t     && gimple_assign_rhs_code (def_stmt) == LSHIFT_EXPR\n+\t     && integer_onep (gimple_assign_rhs1 (def_stmt));\n+    }\n+  return false;\n+}\n+\n+/* cond_removal_mispredict helper that checks if the 'cond'\n+   stamement is on the expected format for the possible\n+   transformation we can have:\n+   - a \"bitcheck EQ 0\" comparison that follows a bitset\n+   - a \"bitcheck NE 0\" comparison that follows a bitclear\n+\n+   This also includes checking if the bitmasks involved are\n+   compatible with each other.  E.g. if we're checking for\n+   bit N and then clearing a bit other than N, we can't do\n+   the transformation.  */\n+\n+static bool\n+cond_removal_mispredict_check_cond (gcond *cond, tree_code bitop_code,\n+\t\t\t\t    tree memreg, tree bitop_bitmask,\n+\t\t\t\t    bool has_not_stmt)\n+{\n+  /* First check if the conditional has the following format:\n+\n+     # VUSE <.MEM_11>\n+     _1 = ptr_10->bits[word_num_12];\n+     _2 = _1 & bitmask;\n+     if (_2 ==/!= 0)\n+       goto <bb 4>; [50.00%]\n+     else\n+       goto <bb 5>; [50.00%]\n+\n+    I.e. there is a check for an absent bitmask (_2 == 0) that follows\n+    a bit set or a check for an existing bitmask (_2 != 0) that follows\n+    a bit clear.  */\n+  if (TREE_CODE (gimple_cond_lhs (cond)) != SSA_NAME)\n+    return false;\n+\n+  if (!integer_zerop (gimple_cond_rhs (cond)))\n+    return false;\n+\n+  gimple *cond_stmt = SSA_NAME_DEF_STMT (gimple_cond_lhs (cond));\n+  tree_code cond_code = gimple_cond_code (cond);\n+\n+  if (cond_code != EQ_EXPR && cond_code != NE_EXPR)\n+    return false;\n+\n+  if (gimple_cond_code (cond) == EQ_EXPR && bitop_code != BIT_IOR_EXPR)\n+    return false;\n+  else if (gimple_cond_code (cond) == NE_EXPR && bitop_code != BIT_AND_EXPR)\n+    return false;\n+\n+  tree cond_rhs1 = gimple_assign_rhs1 (cond_stmt);\n+  tree cond_rhs2 = gimple_assign_rhs2 (cond_stmt);\n+  tree cond_bitmask = NULL_TREE;\n+\n+  /* cond_stmt must use the same memreg as bitop_stmt.  */\n+  if (cond_rhs1 == memreg)\n+    cond_bitmask = cond_rhs2;\n+  else if (cond_rhs2 == memreg)\n+    cond_bitmask = cond_rhs1;\n+  else\n+    return false;\n+\n+  /* If \"bitop_stmt == bit_ior\" 'bitmask' must also match.\n+\n+     (cond_bb)\n+     _1 = ptr_10->bits[word_num_12];\n+     _2 = _1 & bit_val_9; <====== cond_stmt\n+\n+     (middle_bb)\n+     _3 = _1 | bit_val_9; <====== bit_ior\n+     # .MEM_14 = VDEF <.MEM_11>\n+     ptr_10->bits[word_num_12] = _3;\n+\n+     Same thing for bit_and with a 'not':\n+\n+     (cond_bb)\n+     _1 = ptr_10->bits[word_num_12];\n+     _2 = _1 & bit_val_9; <==== cond_stmt\n+\n+     (middle_bb)\n+     _3 = ~bit_val_9;  <==== not_stmt\n+     _4 = _1 & _3;     <==== bit_and\n+     # .MEM_14 = VDEF <.MEM_11>\n+     ptr_10->bits[word_num_12] = _4;  */\n+  if (bitop_code == BIT_IOR_EXPR || has_not_stmt)\n+    return cond_bitmask == bitop_bitmask;\n+\n+  /* Finally, for \"bitop_stmt == bit_and\" with an INTEGER_CST\n+     bitop_bitmask, check if we're clearing exactly what we're\n+     checking in cond_bitmask:\n+\n+     (cond_bb)\n+     # VUSE <.MEM_11>\n+     _1 = ptr_10->bits[word_num_12];\n+     _2 = _1 & 15; <==== cond_stmt\n+     if (_2 ==/!= 0)\n+\n+     (middle_bb)\n+     _4 = _1 & 18446744073709551600; <==== ~15\n+     # .MEM_11 = VDEF <.MEM_8>\n+     ptr_10->bits[word_num_12] = _4;  */\n+  if (TREE_CODE (bitop_bitmask) == INTEGER_CST\n+      && TREE_CODE (cond_bitmask) == INTEGER_CST\n+      && wi::to_wide (bitop_bitmask) == ~wi::to_wide (cond_bitmask))\n+    return true;\n+\n+  return false;\n+}\n+\n+\n+/* This transformation aims to optimize cases where conditional\n+   bit clear and bit set operations can be made unconditional\n+   if the end result in memory is the same.  A conditional\n+   bitset that can be optimized would be:\n+\n+   ;; bb 2\n+   bitshift_6 = 1 << bit_5;\n+   # VUSE <.MEM_7>\n+   _1 = arrD.4593[n_8];    (load_stmt)\n+   _2 = _1 & bitshift_6;   (cond_stmt)\n+   if (_2 == 0) goto <bb 3>; else goto <bb 4>;\n+\n+   ;; bb 3\n+    _3 = _1 | bitshift_6;  (bitop_stmt)\n+   # .MEM_9 = VDEF <.MEM_7>\n+   arrD.4593[n_8] = _3;    (store_stmt)\n+   ;;    succ:  4 (FALLTHRU,EXECUTABLE)\n+\n+   As far as the memory pointed by MEM_7 goes the end result at the\n+   start of bb4 is \"bitshift_6 is set\", either because it was already\n+   set before or because it is set it in bb3.\n+\n+   In this case, depending on constraints like store data races and\n+   read only memory, we want to move the stms from bb3 to the end of\n+   bb2, i.e. always do the bitset:\n+\n+   ;; bb 2\n+   bitshift_6 = 1 << bit_5;\n+   # VUSE <.MEM_7>\n+   _1 = arrD.4593[n_8];    (load_stmt)\n+   _2 = _1 & bitshift_6;   (cond_stmt)\n+   _3 = _1 | bitshift_6;   (bitop_stmt)\n+   # .MEM_9 = VDEF <.MEM_7>\n+   arrD.4593[n_8] = _3;    (store_stmt)\n+   if (_2 == 0) goto <bb 3>; else goto <bb 4>;\n+\n+   This will not just remove the gcond but it can also get rid of\n+   'cond_stmt' in case it's not used anywhere else.  */\n+\n+static bool\n+cond_removal_mispredict_memop (basic_block cond_bb,\n+\t\t\t       basic_block middle_bb,\n+\t\t\t       basic_block join_bb)\n+{\n+  /* 'middle_bb' must have no PHI nodes, it must come via a\n+     TRUE_VALUE edge, and it must have a store preceeding\n+     a bitop:\n+\n+     _3 = _1 BITOP bitmask;\n+     # .MEM_14 = VDEF <.MEM_11>\n+     ptr_10->bits[word_num_12] = _3;  */\n+  if (!gimple_seq_empty_p (phi_nodes (middle_bb)))\n+    return false;\n+\n+  edge e_cond_middle = single_pred_edge (middle_bb);\n+  if (!(e_cond_middle->flags & EDGE_TRUE_VALUE))\n+    return false;\n+\n+  gimple_stmt_iterator gsi = gsi_last_nondebug_bb (middle_bb);\n+  gimple *store_stmt = gsi_stmt (gsi);\n+  if (!store_stmt)\n+    return false;\n+\n+  if (!stmt_is_memory_store_assignment (store_stmt))\n+    return false;\n+\n+  gsi = gsi_start_nondebug_after_labels_bb (middle_bb);\n+  gimple *bitop_stmt = gsi_stmt (gsi);\n+\n+  if (!is_gimple_assign (bitop_stmt))\n+    return false;\n+\n+  tree_code bitop_code = gimple_assign_rhs_code (bitop_stmt);\n+  gimple *not_stmt = NULL;\n+\n+  if (bitop_code != BIT_IOR_EXPR && bitop_code != BIT_AND_EXPR)\n+    {\n+      /* For a bit clear case we can also expect a pattern like this:\n+\t if (_2 != 0)\n+\t   goto <bb 4>; [50.00%]\n+\t else\n+\t   goto <bb 5>; [50.00%]\n+\n+\t ;;   basic block 4,\n+\t _3 = ~bit_val_9;\n+\t _4 = _1 & _3;\n+\t # .MEM_14 = VDEF <.MEM_11>\n+\t ptr_10->bitsD.4594[word_num_12] = _4;  */\n+      if (bitop_code != BIT_NOT_EXPR)\n+\treturn false;\n+\n+      not_stmt = bitop_stmt;\n+      gsi_next (&gsi);\n+      bitop_stmt = gsi_stmt (gsi);\n+\n+      if (!is_gimple_assign (bitop_stmt))\n+\treturn false;\n+\n+      bitop_code = gimple_assign_rhs_code (bitop_stmt);\n+      if (bitop_code != BIT_AND_EXPR)\n+\treturn false;\n+    }\n+\n+  /* Verify that after bitop_stmt we only have store_stmt.  */\n+  gsi_next (&gsi);\n+  if (gsi_stmt (gsi) != store_stmt)\n+    return false;\n+\n+  /* Check if the register being stored by 'store_stmt'\n+     is the result of the previous bitop_stmt.  */\n+  tree store_rhs1 = gimple_assign_rhs1 (store_stmt);\n+  if (TREE_CODE (store_rhs1) != SSA_NAME\n+      || SSA_NAME_DEF_STMT (store_rhs1) != bitop_stmt)\n+    return false;\n+\n+  /* One of the BITOP operands must be a memory load.  Assume for\n+     now that the other operand will be a valid bitmask.  */\n+  tree memreg = NULL_TREE, bitmask = NULL_TREE;\n+\n+  if (TREE_CODE (gimple_assign_rhs1 (bitop_stmt)) == SSA_NAME\n+      && stmt_is_memory_load_assignment (\n+\t\tSSA_NAME_DEF_STMT (gimple_assign_rhs1 (bitop_stmt))))\n+    {\n+      memreg = gimple_assign_rhs1 (bitop_stmt);\n+      bitmask = gimple_assign_rhs2 (bitop_stmt);\n+    }\n+  else if (TREE_CODE (gimple_assign_rhs2 (bitop_stmt)) == SSA_NAME\n+\t   && stmt_is_memory_load_assignment (\n+\t\tSSA_NAME_DEF_STMT (gimple_assign_rhs2 (bitop_stmt))))\n+    {\n+      memreg = gimple_assign_rhs2 (bitop_stmt);\n+      bitmask = gimple_assign_rhs1 (bitop_stmt);\n+    }\n+\n+  if (!memreg)\n+    return false;\n+\n+  /* For the conditional bitclear case with a not_stmt,\n+     'bitmask' would be pointing to the LHS of not_stmt,\n+     and the actual bitmask we want to verify is its RHS1.  */\n+  if (not_stmt)\n+    {\n+      if (gimple_assign_lhs (not_stmt) == bitmask)\n+\tbitmask = gimple_assign_rhs1 (not_stmt);\n+      else\n+\treturn false;\n+    }\n+\n+  /* Validate 'bitmask' before proceeding.  Only single bit masks\n+     are supported for the bit_ior pattern.  */\n+  if (!cond_removal_mispredict_valid_bitmask (bitmask,\n+\t\t\t\t\t      bitop_code == BIT_IOR_EXPR))\n+    return false;\n+\n+  /* Validate store_stmt LHS and memreg.  */\n+  if (!cond_removal_mispredict_validate_memregs (store_stmt, memreg))\n+    return false;\n+\n+  gcond *cond = safe_dyn_cast <gcond *> (*gsi_last_bb (cond_bb));\n+  if (!cond)\n+    return false;\n+\n+  if (!cond_removal_mispredict_check_cond (cond, bitop_code,\n+\t\t\t\t\t   memreg, bitmask,\n+\t\t\t\t\t   not_stmt != NULL))\n+    return false;\n+\n+  /* At this point we're certain we can always execute\n+     the store.  We could make more analysis to determine\n+     if the gcond result is being used as a PHI result,\n+     or we can just move things to cond_bb, right before\n+     the gcond, and trust that cfg_cleanup will do\n+     the right thing.  */\n+  gimple_stmt_iterator gsi_from;\n+  gsi = gsi_for_stmt (cond);\n+\n+  if (not_stmt)\n+    {\n+      gsi_from = gsi_for_stmt (not_stmt);\n+      gsi_move_before (&gsi_from, &gsi);\n+      update_stmt (not_stmt);\n+    }\n+\n+  gsi_from = gsi_for_stmt (bitop_stmt);\n+  gsi_move_before (&gsi_from, &gsi);\n+  update_stmt (bitop_stmt);\n+\n+  gsi_from = gsi_for_stmt (store_stmt);\n+  gsi_move_before (&gsi_from, &gsi);\n+  update_stmt (store_stmt);\n+\n+  gphi *vphi = get_virtual_phi (join_bb);\n+  edge e_cond_join = find_edge (cond_bb, join_bb);\n+  SET_PHI_ARG_DEF (vphi, e_cond_join->dest_idx, gimple_vdef (store_stmt));\n+  update_stmt (vphi);\n+\n+  if (dump_file && (dump_flags & TDF_DETAILS))\n+    {\n+      fprintf (dump_file, \"\\n Conditional store turned unconditional.\");\n+      print_gimple_stmt (dump_file, store_stmt, 0, TDF_VOPS|TDF_MEMSYMS);\n+    }\n+  statistics_counter_event (cfun,\n+\t\t\t    \"conditional store turned unconditional\", 1);\n+\n+  return true;\n+}\n+\n /* Do the main work of conditional store replacement.  */\n \n static bool\n@@ -4255,11 +4685,14 @@ pass_cselim::execute (function *)\n \treturn;\n \n       /* bb1 is the middle block, bb2 the join block, bb the split block,\n-\t e1 the fallthrough edge from bb1 to bb2.  We can't do the\n-\t optimization if the join block has more than two predecessors.  */\n-      if (EDGE_COUNT (bb2->preds) > 2)\n-\treturn;\n-      if (cond_store_replacement (bb1, bb2, e1, e2, nontrap))\n+\t e1 the fallthrough edge from bb1 to bb2.  */\n+\n+      /* We can't do cond_store_replacement if the join block has more\n+\t than two predecessors.  */\n+      if (EDGE_COUNT (bb2->preds) <= 2\n+\t  && cond_store_replacement (bb1, bb2, e1, e2, nontrap))\n+\tcfgchanged = true;\n+      else if (cond_removal_mispredict_memop (bb, bb1, bb2))\n \tcfgchanged = true;\n     };\n \n",
    "prefixes": []
}