Patch Detail
get:
Show a patch.
patch:
Update a patch.
put:
Update a patch.
GET /api/1.1/patches/2232038/?format=api
{ "id": 2232038, "url": "http://patchwork.ozlabs.org/api/1.1/patches/2232038/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/patch/20260502101755.308183-1-disservin.social@gmail.com/", "project": { "id": 17, "url": "http://patchwork.ozlabs.org/api/1.1/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 }, "msgid": "<20260502101755.308183-1-disservin.social@gmail.com>", "date": "2026-05-02T10:17:56", "name": "Add __builtin_bitreverse{8,16,32,64} [PR50481]", "commit_ref": null, "pull_url": null, "state": "new", "archived": false, "hash": "2b9568657abec49fec1910cefaa9f76f3a52f671", "submitter": { "id": 93304, "url": "http://patchwork.ozlabs.org/api/1.1/people/93304/?format=api", "name": "Disservin", "email": "disservin.social@gmail.com" }, "delegate": null, "mbox": "http://patchwork.ozlabs.org/project/gcc/patch/20260502101755.308183-1-disservin.social@gmail.com/mbox/", "series": [ { "id": 502525, "url": "http://patchwork.ozlabs.org/api/1.1/series/502525/?format=api", "web_url": "http://patchwork.ozlabs.org/project/gcc/list/?series=502525", "date": "2026-05-02T10:17:56", "name": "Add __builtin_bitreverse{8,16,32,64} [PR50481]", "version": 1, "mbox": "http://patchwork.ozlabs.org/series/502525/mbox/" } ], "comments": "http://patchwork.ozlabs.org/api/patches/2232038/comments/", "check": "pending", "checks": "http://patchwork.ozlabs.org/api/patches/2232038/checks/", "tags": {}, "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=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=PaV1kpZ0;\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=gmail.com header.i=@gmail.com header.a=rsa-sha256\n header.s=20251104 header.b=PaV1kpZ0", "sourceware.org;\n dmarc=pass (p=none dis=none) header.from=gmail.com", "sourceware.org; spf=pass smtp.mailfrom=gmail.com", "server2.sourceware.org;\n arc=none smtp.remote-ip=2a00:1450:4864:20::32f" ], "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 4g73nH3cpbz1yGq\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 02 May 2026 20:20:02 +1000 (AEST)", "from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id 047104A9A8B5\n\tfor <incoming@patchwork.ozlabs.org>; Sat, 2 May 2026 10:20:00 +0000 (GMT)", "from mail-wm1-x32f.google.com (mail-wm1-x32f.google.com\n [IPv6:2a00:1450:4864:20::32f])\n by sourceware.org (Postfix) with ESMTPS id 15F654A99307\n for <gcc-patches@gcc.gnu.org>; Sat, 2 May 2026 10:19:31 +0000 (GMT)", "by mail-wm1-x32f.google.com with SMTP id\n 5b1f17b1804b1-4891e5b9c1fso22667565e9.2\n for <gcc-patches@gcc.gnu.org>; Sat, 02 May 2026 03:19:31 -0700 (PDT)", "from ABC.fritz.box ([95.88.170.219])\n by smtp.gmail.com with ESMTPSA id\n 5b1f17b1804b1-48a8ebc4201sm192159625e9.15.2026.05.02.03.19.28\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Sat, 02 May 2026 03:19:28 -0700 (PDT)" ], "DKIM-Filter": [ "OpenDKIM Filter v2.11.0 sourceware.org 047104A9A8B5", "OpenDKIM Filter v2.11.0 sourceware.org 15F654A99307" ], "DMARC-Filter": "OpenDMARC Filter v1.4.2 sourceware.org 15F654A99307", "ARC-Filter": "OpenARC Filter v1.0.0 sourceware.org 15F654A99307", "ARC-Seal": "i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1777717171; cv=none;\n b=sri9lFFLmE0BrS0DgQLeRvdgkvlI333FXdQpVEXLK0cqacTsAv7yIkzFysPzVKAOBOBPuAM/GD5mOP+a3I7mqFWqhG3dPat7A2YM8PxVzztblZrA+bjyTJH862xmFVRjoMFnMshpsJWc+qSvtHBOpJyeOTKAnohLMS/tLyoWqbM=", "ARC-Message-Signature": "i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1777717171; c=relaxed/simple;\n bh=MwMOH9ad5UxgjWC6+4orafbJcN2NMgZnvF/utoYL8Ak=;\n h=DKIM-Signature:From:To:Subject:Date:Message-Id:MIME-Version;\n b=ESxiN0uFfFnFiDkCDEKam4IKJsWNDVSsePrTpVt2HyTb0CsxGV687JUdHbxdZbgJwBGiNrXfjDoMd1YilE21Vg/YXTad/qLlzODynDyWAUxw4Uj5bbec96z6TsLkm4DQ44LIYeJ5HZW1QameRns1WG+dekgbIPi31JentWg8fvs=", "ARC-Authentication-Results": "i=1; server2.sourceware.org", "DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=gmail.com; s=20251104; t=1777717169; x=1778321969; 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=ECu863mLevfG7k9yt4ujQuNtFirdrG7sZZYXbqCtZt4=;\n b=PaV1kpZ0b1drR++DfV4WziW98S+fMeU8vo4LB+HWiVsBA2YD/cVPtM/HRXjvWDmvme\n k4Oqs5E67b1lE2xEUhRv3zEh+4qeZzAMuWAwM4RMN9iyKN38h2OuK0YzKhrG2DAS42Ec\n gis4YrLv93Ugqq3e31CH9iUz5+6AMO7TLwow5FkcnFT77uU4VIimwPMlzrFGd31+L7vY\n oChEwEwIBmDKsDmmVu+2xz4zwE9b/r29z4JMjQrYS3Tch62X+oEc6ITdFbURdo5V+xv0\n 6pNWUCH96HogRmoxgIeuNkOJeItgX8S9sgYBqTqCZPrO9dYdKDEnFpxlPQHTQbqF4YLB\n yzvQ==", "X-Google-DKIM-Signature": "v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1777717169; x=1778321969;\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=ECu863mLevfG7k9yt4ujQuNtFirdrG7sZZYXbqCtZt4=;\n b=ObZrJnhqtL0n/J15KpTB/2huVlP/inIvwEHTO7lfW+b3jqUUztcRfQfhsJQQo9D+BH\n 5RcIuxOdQhmpSeQX1KS0Q7kAOAcSj7CJqNqmaPTVKQQkrNolgjtTEJQEA+xehjCpYNpt\n fRM5NpyZGmCcvkw1n4IWUHLEZxEadaf9SGKuaxdHPYehB664/KIkfsqYKmrv096Pak/x\n TAlYkM2tRsQFn+vrgiZ10bktvHdRYuHd670lRE63bZEBP4ntiOIa2az7irKI4g74nxil\n 6fxHVYGmDX9vN5ykMnVjgG4LUpozTD2QhlQF2vb4TqC1ZJagVTiQudkNd5FZiPim/5qu\n vK/g==", "X-Gm-Message-State": "AOJu0YzSBAaJed3PfNsJB7nsuPsPuHvz5eBsgo1YUqvkXASqIGPPh19U\n cE1ZNn5UhDd3VYjWLaHiWYeih+dp7oFBBuy5VZaaJElL3if99YsNtTWuzcAaTA==", "X-Gm-Gg": "AeBDietzmrdSktsSwdHQPZzEPiIVK7gl/xYt6Wu6tvXwy5jFZCSB+ELJOnjZLgHAhCk\n NuqL3aIze/DY1PVG3lzmacylimzXauztLP/FLBxRi1iTmf5w8YDf1p/S3lT9pL1WUGa/iS3+cko\n dlaR7YXAC/N92SI2jpzUlh41UcPcoDC7/V6YCW80sQ4wWMT3AkeadhE2If1R2pUQsSrWun1uvLa\n 3dX7OFfeDnUw52ZufUEWryvUvpntK40TDtKyw+1v6k2x5Ctwv0J6om4lfZ9VzplmTGbABxX7Qja\n PTyiIK0Gu7njeiUMeCwjKdwWcHX/b1xAatuQvWS1Ksbrj11CyQr6JcnPDvQS0lOaZ03T/K7nmB6\n 6aXpkRKLm5X7+mi7wXnohnIBuBmnbhNpBq9qIEfFTgMOdIWbc+qilTv18qrz5VP8utNWwrZ4PCY\n hKOERi2G7IFaN6S5yJqlDizFpJCr30/aQGDukxcSAtxVE=", "X-Received": "by 2002:a05:600c:444c:b0:488:a824:fe04 with SMTP id\n 5b1f17b1804b1-48a98671f6fmr36185375e9.26.1777717169344;\n Sat, 02 May 2026 03:19:29 -0700 (PDT)", "From": "Disservin <disservin.social@gmail.com>", "To": "gcc-patches@gcc.gnu.org", "Cc": "Disservin <disservin.social@gmail.com>", "Subject": "[PATCH] Add __builtin_bitreverse{8,16,32,64} [PR50481]", "Date": "Sat, 2 May 2026 12:17:56 +0200", "Message-Id": "<20260502101755.308183-1-disservin.social@gmail.com>", "X-Mailer": "git-send-email 2.34.1", "MIME-Version": "1.0", "Content-Transfer-Encoding": "8bit", "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": "This patch adds a first version of __builtin_bitreverse{8,16,32,64} builtins.\nPR target/50481\nhttps://gcc.gnu.org/bugzilla/show_bug.cgi?id=50481\n\nFuture work could optimize this on specific targets:\n - ARM: lower to RBIT\n - x86 with GFNI: lower to vgf2p8affineqb [1]\n\nThis is my first GCC patch; any feedback on process or style is welcome.\n\n[1] https://wunkolo.github.io/post/2020/11/gf2p8affineqb-bit-reversal/\n---\n gcc/builtin-types.def | 1 +\n gcc/builtins.cc | 14 ++\n gcc/builtins.def | 4 +\n gcc/doc/extend.texi | 19 +++\n gcc/fold-const-call.cc | 8 ++\n gcc/fold-const.cc | 4 +\n gcc/optabs.cc | 133 ++++++++++++++++++\n gcc/optabs.def | 1 +\n .../gcc.dg/builtin-bitreverse-fold.c | 9 ++\n gcc/testsuite/gcc.dg/builtin-bitreverse64.c | 24 ++++\n gcc/tree-ssa-ccp.cc | 4 +\n gcc/tree-ssa-phiopt.cc | 8 ++\n 12 files changed, 229 insertions(+)\n create mode 100644 gcc/testsuite/gcc.dg/builtin-bitreverse-fold.c\n create mode 100644 gcc/testsuite/gcc.dg/builtin-bitreverse64.c", "diff": "diff --git a/gcc/builtin-types.def b/gcc/builtin-types.def\nindex ab0cbc65c..365badca2 100644\n--- a/gcc/builtin-types.def\n+++ b/gcc/builtin-types.def\n@@ -412,6 +412,7 @@ DEF_FUNCTION_TYPE_1 (BT_FN_INT16_FLOAT, BT_INT16, BT_FLOAT)\n DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_FLOAT, BT_UINT32, BT_FLOAT)\n DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_FLOAT, BT_UINT16, BT_FLOAT)\n DEF_FUNCTION_TYPE_1 (BT_FN_UINT8_FLOAT, BT_UINT8, BT_FLOAT)\n+DEF_FUNCTION_TYPE_1 (BT_FN_UINT8_UINT8, BT_UINT8, BT_UINT8)\n DEF_FUNCTION_TYPE_1 (BT_FN_UINT16_UINT16, BT_UINT16, BT_UINT16)\n DEF_FUNCTION_TYPE_1 (BT_FN_UINT32_UINT32, BT_UINT32, BT_UINT32)\n DEF_FUNCTION_TYPE_1 (BT_FN_UINT64_UINT64, BT_UINT64, BT_UINT64)\ndiff --git a/gcc/builtins.cc b/gcc/builtins.cc\nindex 692e20088..0475bb88a 100644\n--- a/gcc/builtins.cc\n+++ b/gcc/builtins.cc\n@@ -8184,6 +8184,16 @@ expand_builtin (tree exp, rtx target, rtx subtarget, machine_mode mode,\n \treturn target;\n break;\n \n+ case BUILT_IN_BITREVERSE8:\n+ case BUILT_IN_BITREVERSE16:\n+ case BUILT_IN_BITREVERSE32:\n+ case BUILT_IN_BITREVERSE64:\n+ target = expand_builtin_unop (target_mode, exp, target, subtarget,\n+\t\t\t\t bitreverse_optab);\n+ if (target)\n+\treturn target;\n+ break;\n+\n CASE_INT_FN (BUILT_IN_FFS):\n target = expand_builtin_unop (target_mode, exp, target,\n \t\t\t\t subtarget, ffs_optab);\n@@ -12343,6 +12353,10 @@ is_inexpensive_builtin (tree decl)\n case BUILT_IN_BSWAP32:\n case BUILT_IN_BSWAP64:\n case BUILT_IN_BSWAP128:\n+ case BUILT_IN_BITREVERSE8:\n+ case BUILT_IN_BITREVERSE16:\n+ case BUILT_IN_BITREVERSE32:\n+ case BUILT_IN_BITREVERSE64:\n case BUILT_IN_CLZ:\n case BUILT_IN_CLZIMAX:\n case BUILT_IN_CLZL:\ndiff --git a/gcc/builtins.def b/gcc/builtins.def\nindex 8ab0599b1..68838de55 100644\n--- a/gcc/builtins.def\n+++ b/gcc/builtins.def\n@@ -1024,6 +1024,10 @@ DEF_GCC_BUILTIN (BUILT_IN_BSWAP16, \"bswap16\", BT_FN_UINT16_UINT16, ATTR_C\n DEF_GCC_BUILTIN (BUILT_IN_BSWAP32, \"bswap32\", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)\n DEF_GCC_BUILTIN (BUILT_IN_BSWAP64, \"bswap64\", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)\n DEF_GCC_BUILTIN (BUILT_IN_BSWAP128, \"bswap128\", BT_FN_UINT128_UINT128, ATTR_CONST_NOTHROW_LEAF_LIST)\n+DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE8, \"bitreverse8\", BT_FN_UINT8_UINT8, ATTR_CONST_NOTHROW_LEAF_LIST)\n+DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE16, \"bitreverse16\", BT_FN_UINT16_UINT16, ATTR_CONST_NOTHROW_LEAF_LIST)\n+DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE32, \"bitreverse32\", BT_FN_UINT32_UINT32, ATTR_CONST_NOTHROW_LEAF_LIST)\n+DEF_GCC_BUILTIN (BUILT_IN_BITREVERSE64, \"bitreverse64\", BT_FN_UINT64_UINT64, ATTR_CONST_NOTHROW_LEAF_LIST)\n \n DEF_EXT_LIB_BUILTIN (BUILT_IN_CLEAR_CACHE, \"__clear_cache\", BT_FN_VOID_PTR_PTR, ATTR_NOTHROW_LEAF_LIST)\n /* [trans-mem]: Adjust BUILT_IN_TM_CALLOC if BUILT_IN_CALLOC is changed. */\ndiff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi\nindex 0faa5323c..aa1f526f7 100644\n--- a/gcc/doc/extend.texi\n+++ b/gcc/doc/extend.texi\n@@ -16064,6 +16064,25 @@ Similar to @code{__builtin_bswap64}, except the argument and return types\n are 128-bit. Only supported on targets when 128-bit types are supported.\n @enddefbuiltin\n \n+@defbuiltin{uint8_t __builtin_bitreverse8 (uint8_t @var{x})}\n+Returns @var{x} with all bits reversed.\n+@enddefbuiltin\n+\n+@defbuiltin{uint16_t __builtin_bitreverse16 (uint16_t @var{x})}\n+Similar to @code{__builtin_bitreverse8}, except the argument and return types\n+are 16-bit.\n+@enddefbuiltin\n+\n+@defbuiltin{uint32_t __builtin_bitreverse32 (uint32_t @var{x})}\n+Similar to @code{__builtin_bitreverse8}, except the argument and return types\n+are 32-bit.\n+@enddefbuiltin\n+\n+@defbuiltin{uint64_t __builtin_bitreverse64 (uint64_t @var{x})}\n+Similar to @code{__builtin_bitreverse8}, except the argument and return types\n+are 64-bit.\n+@enddefbuiltin\n+\n @node CRC Builtins\n @subsection CRC Builtins\n @cindex CRC builtins\ndiff --git a/gcc/fold-const-call.cc b/gcc/fold-const-call.cc\nindex 7dd1b21c3..7e8299513 100644\n--- a/gcc/fold-const-call.cc\n+++ b/gcc/fold-const-call.cc\n@@ -1102,6 +1102,14 @@ fold_const_call_ss (wide_int *result, combined_fn fn, const wide_int_ref &arg,\n \t\t\t\t\t TYPE_SIGN (arg_type)));\n return true;\n \n+ case CFN_BUILT_IN_BITREVERSE8:\n+ case CFN_BUILT_IN_BITREVERSE16:\n+ case CFN_BUILT_IN_BITREVERSE32:\n+ case CFN_BUILT_IN_BITREVERSE64:\n+ *result = wi::bitreverse (wide_int::from (arg, precision,\n+\t\t\t\t\t\t TYPE_SIGN (arg_type)));\n+ return true;\n+\n default:\n return false;\n }\ndiff --git a/gcc/fold-const.cc b/gcc/fold-const.cc\nindex 56503e570..3bc82a108 100644\n--- a/gcc/fold-const.cc\n+++ b/gcc/fold-const.cc\n@@ -14984,6 +14984,10 @@ tree_call_nonnegative_warnv_p (tree type, combined_fn fn, tree arg0, tree arg1,\n case CFN_BUILT_IN_BSWAP32:\n case CFN_BUILT_IN_BSWAP64:\n case CFN_BUILT_IN_BSWAP128:\n+ case CFN_BUILT_IN_BITREVERSE8:\n+ case CFN_BUILT_IN_BITREVERSE16:\n+ case CFN_BUILT_IN_BITREVERSE32:\n+ case CFN_BUILT_IN_BITREVERSE64:\n /* Always true. */\n return true;\n \ndiff --git a/gcc/optabs.cc b/gcc/optabs.cc\nindex 111b9be99..bf9ce8ee7 100644\n--- a/gcc/optabs.cc\n+++ b/gcc/optabs.cc\n@@ -2941,6 +2941,129 @@ expand_doubleword_bswap (machine_mode mode, rtx op, rtx target)\n return target;\n }\n \n+/* Try calculating (bitreverse x) using masks and shifts. */\n+\n+static rtx\n+expand_bitreverse (scalar_int_mode mode, rtx op0, rtx target)\n+{\n+ unsigned int precision = GET_MODE_BITSIZE (mode);\n+ rtx_insn *last;\n+\n+ /* Operation requires at least 4 bits (one nibble swap makes no sense below that) */\n+ if (precision < 4)\n+ return NULL_RTX;\n+\n+ if (target == 0\n+ || target == op0\n+ || reg_overlap_mentioned_p (target, op0))\n+ target = gen_reg_rtx (mode);\n+\n+ last = get_last_insn ();\n+\n+ rtx x, lo, hi;\n+\n+ /* Step 1: byte-swap (only meaningful for >= 16 bits) */\n+ if (precision >= 16)\n+ {\n+ x = expand_unop (mode, bswap_optab, op0, NULL_RTX, true);\n+ if (x == NULL_RTX)\n+ goto fail;\n+ }\n+ else\n+ x = op0;\n+\n+ /* Step 2: swap nibbles within each byte (shift=4, only for >= 8 bits) */\n+ if (precision >= 8)\n+ {\n+ wide_int mask = wi::zero (precision);\n+ for (unsigned int start = 0; start < precision; start += 8)\n+ mask = wi::bit_or (mask, wi::shifted_mask (start, 4, false, precision));\n+\n+ rtx mask_rtx = immed_wide_int_const (mask, mode);\n+\n+ hi = expand_simple_binop (mode, LSHIFTRT, x, GEN_INT (4),\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (hi == NULL_RTX) goto fail;\n+ hi = expand_binop (mode, and_optab, hi, mask_rtx,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (hi == NULL_RTX) goto fail;\n+\n+ lo = expand_binop (mode, and_optab, x, mask_rtx,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (lo == NULL_RTX) goto fail;\n+ lo = expand_simple_binop (mode, ASHIFT, lo, GEN_INT (4),\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (lo == NULL_RTX) goto fail;\n+\n+ x = expand_binop (mode, ior_optab, hi, lo,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (x == NULL_RTX) goto fail;\n+ }\n+\n+ /* Step 3: swap pairs of bits within each nibble (shift=2) */\n+ {\n+ wide_int mask = wi::zero (precision);\n+ for (unsigned int start = 0; start < precision; start += 4)\n+ mask = wi::bit_or (mask, wi::shifted_mask (start, 2, false, precision));\n+\n+ rtx mask_rtx = immed_wide_int_const (mask, mode);\n+\n+ hi = expand_simple_binop (mode, LSHIFTRT, x, GEN_INT (2),\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (hi == NULL_RTX) goto fail;\n+ hi = expand_binop (mode, and_optab, hi, mask_rtx,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (hi == NULL_RTX) goto fail;\n+\n+ lo = expand_binop (mode, and_optab, x, mask_rtx,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (lo == NULL_RTX) goto fail;\n+ lo = expand_simple_binop (mode, ASHIFT, lo, GEN_INT (2),\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (lo == NULL_RTX) goto fail;\n+\n+ x = expand_binop (mode, ior_optab, hi, lo,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (x == NULL_RTX) goto fail;\n+ }\n+\n+ /* Step 4: swap adjacent bits (shift=1) */\n+ {\n+ wide_int mask = wi::zero (precision);\n+ for (unsigned int start = 0; start < precision; start += 2)\n+ mask = wi::bit_or (mask, wi::shifted_mask (start, 1, false, precision));\n+\n+ rtx mask_rtx = immed_wide_int_const (mask, mode);\n+\n+ hi = expand_simple_binop (mode, LSHIFTRT, x, GEN_INT (1),\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (hi == NULL_RTX) goto fail;\n+ hi = expand_binop (mode, and_optab, hi, mask_rtx,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (hi == NULL_RTX) goto fail;\n+\n+ lo = expand_binop (mode, and_optab, x, mask_rtx,\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (lo == NULL_RTX) goto fail;\n+ lo = expand_simple_binop (mode, ASHIFT, lo, GEN_INT (1),\n+ NULL_RTX, true, OPTAB_LIB_WIDEN);\n+ if (lo == NULL_RTX) goto fail;\n+\n+ x = expand_binop (mode, ior_optab, hi, lo,\n+ target, true, OPTAB_LIB_WIDEN);\n+ if (x == NULL_RTX) goto fail;\n+ }\n+\n+ if (x != target)\n+ emit_move_insn (target, x);\n+\n+ return target;\n+\n+ fail:\n+ delete_insns_since (last);\n+ return NULL_RTX;\n+}\n+\n /* Try calculating (parity x) as (and (popcount x) 1), where\n popcount can also be done in a wider mode. */\n static rtx\n@@ -3391,6 +3514,16 @@ expand_unop (machine_mode mode, optab unoptab, rtx op0, rtx target,\n goto try_libcall;\n }\n \n+ if (unoptab == bitreverse_optab)\n+ {\n+ if (is_a <scalar_int_mode> (mode, &int_mode))\n+\t{\n+\t temp = expand_bitreverse (int_mode, op0, target);\n+\t if (temp)\n+\t return temp;\n+\t}\n+ }\n+\n /* Neg should be tried via expand_absneg_bit before widening. */\n if (optab_to_code (unoptab) == NEG)\n {\ndiff --git a/gcc/optabs.def b/gcc/optabs.def\nindex 193f42a72..7ccea1854 100644\n--- a/gcc/optabs.def\n+++ b/gcc/optabs.def\n@@ -184,6 +184,7 @@ OPTAB_VC(absv_optab, \"absv$I$a2\", ABS)\n OPTAB_VX(absv_optab, \"abs$F$a2\")\n OPTAB_NL(one_cmpl_optab, \"one_cmpl$a2\", NOT, \"one_cmpl\", '2', gen_int_libfunc)\n OPTAB_NC(bswap_optab, \"bswap$a2\", BSWAP)\n+OPTAB_NC(bitreverse_optab, \"bitreverse$a2\", BITREVERSE)\n OPTAB_NL(ffs_optab, \"ffs$a2\", FFS, \"ffs\", '2', gen_int_libfunc)\n OPTAB_NL(clz_optab, \"clz$a2\", CLZ, \"clz\", '2', gen_int_libfunc)\n OPTAB_NL(ctz_optab, \"ctz$a2\", CTZ, \"ctz\", '2', gen_int_libfunc)\ndiff --git a/gcc/testsuite/gcc.dg/builtin-bitreverse-fold.c b/gcc/testsuite/gcc.dg/builtin-bitreverse-fold.c\nnew file mode 100644\nindex 000000000..4a8cfb3f1\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/builtin-bitreverse-fold.c\n@@ -0,0 +1,9 @@\n+/* { dg-do compile } */\n+/* { dg-options \"-std=gnu11\" } */\n+\n+_Static_assert (__builtin_bitreverse8 (0x01u) == 0x80u, \"bitreverse8\");\n+_Static_assert (__builtin_bitreverse16 (0x0001u) == 0x8000u, \"bitreverse16\");\n+_Static_assert (__builtin_bitreverse32 (0x12345678u) == 0x1e6a2c48u,\n+\t\t\"bitreverse32\");\n+_Static_assert (__builtin_bitreverse64 (0x0123456789abcdefull)\n+\t\t == 0xf7b3d591e6a2c480ull, \"bitreverse64\");\ndiff --git a/gcc/testsuite/gcc.dg/builtin-bitreverse64.c b/gcc/testsuite/gcc.dg/builtin-bitreverse64.c\nnew file mode 100644\nindex 000000000..8419452ff\n--- /dev/null\n+++ b/gcc/testsuite/gcc.dg/builtin-bitreverse64.c\n@@ -0,0 +1,24 @@\n+/* { dg-do run } */\n+/* { dg-options \"-O2\" } */\n+\n+extern void abort (void);\n+\n+static unsigned long long\n+br64 (unsigned long long x)\n+{\n+ return __builtin_bitreverse64 (x);\n+}\n+\n+int\n+main (void)\n+{\n+ if (br64 (0x0000000000000000ull) != 0x0000000000000000ull)\n+ abort ();\n+ if (br64 (0x0000000000000001ull) != 0x8000000000000000ull)\n+ abort ();\n+ if (br64 (0x0123456789abcdefull) != 0xf7b3d591e6a2c480ull)\n+ abort ();\n+ if (br64 (0xffffffffffffffffull) != 0xffffffffffffffffull)\n+ abort ();\n+ return 0;\n+}\ndiff --git a/gcc/tree-ssa-ccp.cc b/gcc/tree-ssa-ccp.cc\nindex 952ebf17e..974bef178 100644\n--- a/gcc/tree-ssa-ccp.cc\n+++ b/gcc/tree-ssa-ccp.cc\n@@ -2435,6 +2435,10 @@ evaluate_stmt (gimple *stmt)\n \t case BUILT_IN_BSWAP32:\n \t case BUILT_IN_BSWAP64:\n \t case BUILT_IN_BSWAP128:\n+\t case BUILT_IN_BITREVERSE8:\n+\t case BUILT_IN_BITREVERSE16:\n+\t case BUILT_IN_BITREVERSE32:\n+\t case BUILT_IN_BITREVERSE64:\n \t val = get_value_for_expr (gimple_call_arg (stmt, 0), true);\n \t if (val.lattice_val == UNDEFINED)\n \t\tbreak;\ndiff --git a/gcc/tree-ssa-phiopt.cc b/gcc/tree-ssa-phiopt.cc\nindex 0bf7e58b8..50ddeaa67 100644\n--- a/gcc/tree-ssa-phiopt.cc\n+++ b/gcc/tree-ssa-phiopt.cc\n@@ -819,6 +819,10 @@ empty_bb_or_one_feeding_into_p (basic_block bb,\n \tcase CFN_BUILT_IN_BSWAP32:\n \tcase CFN_BUILT_IN_BSWAP64:\n \tcase CFN_BUILT_IN_BSWAP128:\n+\tcase CFN_BUILT_IN_BITREVERSE8:\n+\tcase CFN_BUILT_IN_BITREVERSE16:\n+\tcase CFN_BUILT_IN_BITREVERSE32:\n+\tcase CFN_BUILT_IN_BITREVERSE64:\n \tCASE_CFN_FFS:\n \tCASE_CFN_PARITY:\n \tCASE_CFN_POPCOUNT:\n@@ -2578,6 +2582,10 @@ cond_removal_in_builtin_zero_pattern (basic_block cond_bb,\n case CFN_BUILT_IN_BSWAP32:\n case CFN_BUILT_IN_BSWAP64:\n case CFN_BUILT_IN_BSWAP128:\n+ case CFN_BUILT_IN_BITREVERSE8:\n+ case CFN_BUILT_IN_BITREVERSE16:\n+ case CFN_BUILT_IN_BITREVERSE32:\n+ case CFN_BUILT_IN_BITREVERSE64:\n CASE_CFN_FFS:\n CASE_CFN_PARITY:\n CASE_CFN_POPCOUNT:\n", "prefixes": [] }