{"id":2227621,"url":"http://patchwork.ozlabs.org/api/patches/2227621/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/patch/20260424025503.2589107-1-kito.cheng@sifive.com/","project":{"id":17,"url":"http://patchwork.ozlabs.org/api/projects/17/?format=json","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":"<20260424025503.2589107-1-kito.cheng@sifive.com>","list_archive_url":null,"date":"2026-04-24T02:55:03","name":"RISC-V: Use long jump for crossing section boundaries","commit_ref":null,"pull_url":null,"state":"new","archived":false,"hash":"f5ce13eecdc4642098f464eb5e0331d125c2640e","submitter":{"id":77002,"url":"http://patchwork.ozlabs.org/api/people/77002/?format=json","name":"Kito Cheng","email":"kito.cheng@sifive.com"},"delegate":null,"mbox":"http://patchwork.ozlabs.org/project/gcc/patch/20260424025503.2589107-1-kito.cheng@sifive.com/mbox/","series":[{"id":501284,"url":"http://patchwork.ozlabs.org/api/series/501284/?format=json","web_url":"http://patchwork.ozlabs.org/project/gcc/list/?series=501284","date":"2026-04-24T02:55:03","name":"RISC-V: Use long jump for crossing section boundaries","version":1,"mbox":"http://patchwork.ozlabs.org/series/501284/mbox/"}],"comments":"http://patchwork.ozlabs.org/api/patches/2227621/comments/","check":"pending","checks":"http://patchwork.ozlabs.org/api/patches/2227621/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=sifive.com header.i=@sifive.com header.a=rsa-sha256\n header.s=google header.b=hU87n1zm;\n\tdkim-atps=neutral","legolas.ozlabs.org;\n spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org\n (client-ip=38.145.34.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=sifive.com header.i=@sifive.com header.a=rsa-sha256\n header.s=google header.b=hU87n1zm","sourceware.org;\n dmarc=pass (p=reject dis=none) header.from=sifive.com","sourceware.org; spf=pass smtp.mailfrom=sifive.com","server2.sourceware.org;\n arc=none smtp.remote-ip=209.85.210.179"],"Received":["from vm01.sourceware.org (vm01.sourceware.org [38.145.34.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 4g1yJJ4jY7z1xvV\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 24 Apr 2026 12:55:43 +1000 (AEST)","from vm01.sourceware.org (localhost [127.0.0.1])\n\tby sourceware.org (Postfix) with ESMTP id A18554BB1C18\n\tfor <incoming@patchwork.ozlabs.org>; Fri, 24 Apr 2026 02:55:40 +0000 (GMT)","from mail-pf1-f179.google.com (mail-pf1-f179.google.com\n [209.85.210.179])\n by sourceware.org (Postfix) with ESMTPS id C790A4B99F7A\n for <gcc-patches@gcc.gnu.org>; Fri, 24 Apr 2026 02:55:10 +0000 (GMT)","by mail-pf1-f179.google.com with SMTP id\n d2e1a72fcca58-82f2766905fso3420103b3a.3\n for <gcc-patches@gcc.gnu.org>; Thu, 23 Apr 2026 19:55:10 -0700 (PDT)","from hsinchu18.internal.sifive.com ([210.176.154.34])\n by smtp.gmail.com with ESMTPSA id\n d2e1a72fcca58-82f8ebb3f31sm26966756b3a.37.2026.04.23.19.55.07\n (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);\n Thu, 23 Apr 2026 19:55:08 -0700 (PDT)"],"DKIM-Filter":["OpenDKIM Filter v2.11.0 sourceware.org A18554BB1C18","OpenDKIM Filter v2.11.0 sourceware.org C790A4B99F7A"],"DMARC-Filter":"OpenDMARC Filter v1.4.2 sourceware.org C790A4B99F7A","ARC-Filter":"OpenARC Filter v1.0.0 sourceware.org C790A4B99F7A","ARC-Seal":"i=1; a=rsa-sha256; d=sourceware.org; s=key; t=1776999311; cv=none;\n b=i/DWBpg7SFwKyErKhHzZE+JRcdsT3v4MnWsxETJGIRyS+E9L/khRw/hbTS5KDuDpHVcHHDtepDIVJIqA2yJQxO+ICFTNhxqa+8eKwj2mwc3SdysYIA7yOTZxRAGWvHJ3d9pH1/XKQhba/WTj2mt8XDjqwUzYyGUw3aO3tvW08r0=","ARC-Message-Signature":"i=1; a=rsa-sha256; d=sourceware.org; s=key;\n t=1776999311; c=relaxed/simple;\n bh=tiiZFvFx8Yle0cRaUNj6lZpep4KZnTZfvmXz7kF+lIE=;\n h=DKIM-Signature:From:To:Subject:Date:Message-ID:MIME-Version;\n b=pnc1hAD0Q6DTDqEMsTeJ/zO3dKhdq4ZnIcID90GWmmqpOPOi4HlFb5rIvvgwm2o6srdqtAhUdQGzckozAdgETS1kNXiKD/WYNMhpFv5HRRcwl7fjkUWmQAXuwx6N6opFS2WplGv20ysd3rJqSk1bxGLOWbwUJRhbZUnxmbCXNRg=","ARC-Authentication-Results":"i=1; server2.sourceware.org","DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=sifive.com; s=google; t=1776999309; x=1777604109; 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=wa7sWEw6S1eoxfzi2SjnKPHGJP4p5qFfIyrR41jhg+g=;\n b=hU87n1zmJZwcmh3+KHQLcqk7ospEfgvw84KG9/YD9TtsrI5vx6+aANT8u7CuYXmXsp\n dOpmvTRa5N6H8SkGkSQhivNt5sMTA+ygE+H9ZputYgQUH8/A0t5yJVl/4hV2Dde7gX0s\n 88Lr4N5GzsxTWGG4DNgpxXTqoxhPpyQ/TPSJXqvRkBW+kGhmNRcEv4a+aRjZh0rW3HU9\n T7A13Ah5YuufgWvOoIR7RkEsNXinaLvn0aw18K3iDmWKdl8S/r/htqx88FJ/yvwrYX57\n kcI674KoFfhObd3Xcndxo10friidVS/Mlbj84t2lWcgUBaJ89hPbiC0boCxKbuJrRfZ+\n Me6Q==","X-Google-DKIM-Signature":"v=1; a=rsa-sha256; c=relaxed/relaxed;\n d=1e100.net; s=20251104; t=1776999309; x=1777604109;\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=wa7sWEw6S1eoxfzi2SjnKPHGJP4p5qFfIyrR41jhg+g=;\n b=QVVzQTWVp3McFN75uyXPtLO3StGIHJq0cK6+ITOo5D50fUJyXSp1K55oi/kOIOYTAW\n EUpZJBoG9h6W0uOnYmtJ3WiDZpj9yT95MRht30q6vTae7C3iwuLicfUGbLI2tCqhu6me\n KTHG7sqIiLTM+jzuWJqU0aSf+CcD0NFPl6mAJjfWgjqLd4BTScTRetAxyrCsoqwIKxmO\n vD6LKNasY8B7Fg6SpfKB6XFELZkBL8U+3c3oJwH6fbBrWKaRwiADu+w6x2/la+e1aidn\n z/EG9hRT4BZ9xFOSmn/NN5Z7i3jDwsFDAYKUMb1KzDOpk+Yak+DRuzhjte0/q4hp2ZTq\n TDzA==","X-Gm-Message-State":"AOJu0YzZN5eVqIAY2rR6SINxXQOOejBU9nFyPwzAebLYdrftAnUZQ7+W\n VEIg1eNnb8V11FAewowPIHQM7fAgBod5/bUylLhhtW7qx4S4GI3zAykjVei6xqACPxAuTVeyNvV\n C3SzA8ka5uxIXHcIGNkY90iqQ4pIUGv1jbngDhN479yzUEUNQ1Q29tqr9WeIVEHL7/Nud+Ca+N6\n v75nKqusCSNbHMUKNfdvFczDlOhLWpijsGhcgDKMEptq/r6sY=","X-Gm-Gg":"AeBDieuEfAR3aIYkgO4dcE91/Eac6yaY/BpqL789GzggWIktRbxjtSizW38Qf8xPCMm\n L+yGhJQFqycUxfiIkC5uIs6q9KmTonurPT/JPly70agHE3Y1TE/pFOYjkaUMsc/T06RChG8nTxd\n PIyXG37/q9RZrqqPc9TVyJXZP9SYkHV9eiycl7Rk82SDZkBCrWsiF8cSTsdrRBEMAomD0cb+td6\n QNXIEOZz0qi84aux7l/d5lnhYW+SQfue2nOQFbwdYnZvxFbQ921sCfu87CHroK+Phw4OwuBPm9M\n 1KKwe7nGbJaBxaZU9RJ37mYMRfGWn+7u0pSBeU2lk8sXjHDBJAINVSW4c0k6TmzfAxO/c+ELtFl\n wk6bmkIsHjFfYrSAaN+jYNePy+YUVvhssH/5KG8ULpO4aDjjRaAs8Ik39E82Tyf9IADSrd/93nx\n rUqKxbpdwmu+pk+LiIBuO4Hg0hEbWU2xwo+8J6zDyj6H3Rb8ajS30ai5Nf9ho=","X-Received":"by 2002:a05:6a00:6c8e:b0:82c:212a:906a with SMTP id\n d2e1a72fcca58-82f8c907fa5mr30879199b3a.36.1776999309117;\n Thu, 23 Apr 2026 19:55:09 -0700 (PDT)","From":"Kito Cheng <kito.cheng@sifive.com>","To":"gcc-patches@gcc.gnu.org,\n\tkito.cheng@gmail.com,\n\tjeffreyalaw@gmail.com","Cc":"Monk Chiang <monk.chiang@sifive.com>","Subject":"[PATCH] RISC-V: Use long jump for crossing section boundaries","Date":"Fri, 24 Apr 2026 10:55:03 +0800","Message-ID":"<20260424025503.2589107-1-kito.cheng@sifive.com>","X-Mailer":"git-send-email 2.52.0","MIME-Version":"1.0","Content-Type":"text/plain; charset=UTF-8","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":"From: Monk Chiang <monk.chiang@sifive.com>\n\nWhen -freorder-blocks-and-partition is used, GCC places cold code in\n.text.unlikely section.  Jumps from hot code (.text) to cold code\n(.text.unlikely) may cross section boundaries.  Since the linker may\nplace these sections more than 1MB apart, the JAL instruction's ±1MB\nrange can be exceeded, causing linker errors like:\n\n  relocation truncated to fit: R_RISCV_JAL against `.text.unlikely'\n\nThis patch fixes the issue by checking CROSSING_JUMP_P in the length\nattribute calculation for jump instructions.  When a jump crosses\nsection boundaries, the length is set to 8 bytes (AUIPC+JALR) instead\nof 4 bytes (JAL), ensuring the long form is used.\n\nThis approach is consistent with other backends (NDS32, SH, ARC) that\nalso use CROSSING_JUMP_P to handle cross-section jumps.\n\ngcc/ChangeLog:\n\n\t* config/riscv/riscv.md (length attribute): Check CROSSING_JUMP_P\n\tfor jump instructions and use length 8 for crossing jumps.\n\t(jump): Update comment to explain when long form is used.\n\ngcc/testsuite/ChangeLog:\n\n\t* gcc.target/riscv/pr-crossing-jump-1.c: New test.\n\t* gcc.target/riscv/pr-crossing-jump-2.c: New test.\n\t* gcc.target/riscv/pr-crossing-jump-3.c: New test.\n---\n gcc/config/riscv/riscv.md                     | 23 ++++++----\n .../gcc.target/riscv/pr-crossing-jump-1.c     | 41 +++++++++++++++++\n .../gcc.target/riscv/pr-crossing-jump-2.c     | 45 +++++++++++++++++++\n .../gcc.target/riscv/pr-crossing-jump-3.c     | 33 ++++++++++++++\n 4 files changed, 134 insertions(+), 8 deletions(-)\n create mode 100644 gcc/testsuite/gcc.target/riscv/pr-crossing-jump-1.c\n create mode 100644 gcc/testsuite/gcc.target/riscv/pr-crossing-jump-2.c\n create mode 100644 gcc/testsuite/gcc.target/riscv/pr-crossing-jump-3.c","diff":"diff --git a/gcc/config/riscv/riscv.md b/gcc/config/riscv/riscv.md\nindex 7ea6ee704c3..8803eec075e 100644\n--- a/gcc/config/riscv/riscv.md\n+++ b/gcc/config/riscv/riscv.md\n@@ -630,13 +630,18 @@ (define_attr \"length\" \"\"\n \t\t\t\t      (const_int 12)))\n \n \t  ;; Jumps further than +/- 1 MiB require two instructions.\n+\t  ;; Also, jumps that cross section boundaries (e.g., from hot to cold\n+\t  ;; section when -freorder-blocks-and-partition is used) require two\n+\t  ;; instructions because the linker may place the sections far apart.\n \t  (eq_attr \"type\" \"jump\")\n-\t  (if_then_else (and (le (minus (match_dup 0) (pc))\n-\t\t\t\t (const_int 1048568))\n-\t\t\t     (le (minus (pc) (match_dup 0))\n-\t\t\t\t (const_int 1048572)))\n-\t\t\t(const_int 4)\n-\t\t\t(const_int 8))\n+\t  (if_then_else (match_test \"CROSSING_JUMP_P (insn)\")\n+\t\t\t(const_int 8)\n+\t\t\t(if_then_else (and (le (minus (match_dup 0) (pc))\n+\t\t\t\t\t       (const_int 1048568))\n+\t\t\t\t\t   (le (minus (pc) (match_dup 0))\n+\t\t\t\t\t       (const_int 1048572)))\n+\t\t\t\t      (const_int 4)\n+\t\t\t\t      (const_int 8)))\n \n \t  ;; Conservatively assume calls take two instructions (AUIPC + JALR).\n \t  ;; The linker will opportunistically relax the sequence to JAL.\n@@ -3822,8 +3827,10 @@ (define_insn \"jump\"\n   [(set (pc) (label_ref (match_operand 0 \"\" \"\")))]\n   \"\"\n {\n-  /* Hopefully this does not happen often as this is going\n-     to clobber $ra and muck up the return stack predictors.  */\n+  /* Use the long form (AUIPC+JALR) if the jump distance exceeds 1 MiB,\n+     or if the jump crosses section boundaries (e.g., from hot to cold\n+     section when -freorder-blocks-and-partition is used).\n+     Note: This clobbers $ra and mucks up the return stack predictors.  */\n   if (get_attr_length (insn) == 8)\n     return \"jump\\t%l0,ra\";\n \ndiff --git a/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-1.c b/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-1.c\nnew file mode 100644\nindex 00000000000..88def7ce545\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-1.c\n@@ -0,0 +1,41 @@\n+/* Test that jumps crossing section boundaries use the long form (AUIPC+JALR).\n+   When -freorder-blocks-and-partition is used, cold code is placed in\n+   .text.unlikely section.  Jumps from hot code (.text) to cold code\n+   (.text.unlikely) must use the long form because the linker may place\n+   these sections more than 1MB apart, exceeding the JAL instruction's range.\n+\n+   This test verifies that CROSSING_JUMP_P is handled correctly in the\n+   RISC-V backend.  */\n+\n+/* { dg-do compile } */\n+/* { dg-require-effective-target freorder } */\n+/* { dg-options \"-O2 -freorder-blocks-and-partition\" } */\n+\n+extern void abort (void);\n+\n+/* Force the error path to be cold.  */\n+static void __attribute__((cold, noinline))\n+handle_error (void)\n+{\n+  abort ();\n+}\n+\n+/* Function with hot and cold paths.  */\n+int\n+check_positive (int x)\n+{\n+  if (__builtin_expect (x > 0, 1))\n+    {\n+      /* Hot path - stays in .text  */\n+      return x;\n+    }\n+  /* Cold path - moved to .text.unlikely  */\n+  handle_error ();\n+  return -1;\n+}\n+\n+/* The jump to the cold section should use \"jump\" (AUIPC+JALR) not \"j\" (JAL).\n+   We check for \"jump\" instruction which is the long form.  */\n+\n+/* { dg-final { scan-assembler \"jump\\\\t\\\\.L\\[0-9\\]+,ra\" } } */\n+\ndiff --git a/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-2.c b/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-2.c\nnew file mode 100644\nindex 00000000000..f2e7c55014d\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-2.c\n@@ -0,0 +1,45 @@\n+/* Test that multiple crossing jumps all use the long form.\n+   This is a more comprehensive test for CROSSING_JUMP_P handling.  */\n+\n+/* { dg-do compile } */\n+/* { dg-require-effective-target freorder } */\n+/* { dg-options \"-O2 -freorder-blocks-and-partition\" } */\n+\n+extern void abort (void);\n+\n+static void __attribute__((cold, noinline))\n+cold_path_1 (void)\n+{\n+  abort ();\n+}\n+\n+static void __attribute__((cold, noinline))\n+cold_path_2 (void)\n+{\n+  abort ();\n+}\n+\n+/* Function with multiple cold paths.  */\n+int\n+validate (int a, int b)\n+{\n+  if (__builtin_expect (a > 0, 1))\n+    {\n+      if (__builtin_expect (b > 0, 1))\n+\t{\n+\t  /* Hot path  */\n+\t  return a + b;\n+\t}\n+      /* Cold path 1  */\n+      cold_path_1 ();\n+    }\n+  /* Cold path 2  */\n+  cold_path_2 ();\n+  return -1;\n+}\n+\n+/* All jumps to cold sections should use \"jump\" (AUIPC+JALR).\n+   We expect at least 2 crossing jumps.  */\n+\n+/* { dg-final { scan-assembler-times \"jump\\\\t\\\\.L\\[0-9\\]+,ra\" 2 } } */\n+\ndiff --git a/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-3.c b/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-3.c\nnew file mode 100644\nindex 00000000000..d594488e222\n--- /dev/null\n+++ b/gcc/testsuite/gcc.target/riscv/pr-crossing-jump-3.c\n@@ -0,0 +1,33 @@\n+/* Test that jumps within the same section still use the short form (JAL).\n+   This ensures that the CROSSING_JUMP_P fix doesn't pessimize normal jumps.  */\n+\n+/* { dg-do compile } */\n+/* { dg-options \"-O2\" } */\n+\n+int global;\n+\n+/* Simple function with a loop - jumps stay within .text section.  */\n+int\n+sum_to_n (int n)\n+{\n+  int sum = 0;\n+  for (int i = 1; i <= n; i++)\n+    sum += i;\n+  return sum;\n+}\n+\n+/* Function with conditional - jumps stay within .text section.  */\n+int\n+abs_value (int x)\n+{\n+  if (x < 0)\n+    return -x;\n+  return x;\n+}\n+\n+/* The backward jump in the loop should use \"j\" (JAL) not \"jump\" (AUIPC+JALR)\n+   since it doesn't cross section boundaries.  We verify that \"jump\" is NOT\n+   used for intra-section jumps.  */\n+\n+/* { dg-final { scan-assembler-not \"jump\\\\t\\\\.L\\[0-9\\]+,ra\" } } */\n+\n","prefixes":[]}