[llvm] [RISCV] Emit lpad for function with returns-twice attribute (PR #170520)

Jesse Huang via llvm-commits llvm-commits at lists.llvm.org
Wed Dec 3 10:29:08 PST 2025


https://github.com/jaidTw updated https://github.com/llvm/llvm-project/pull/170520

>From 045314517ee6a694b4261cb377bef67c29bd9932 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jessehuang2222 at gmail.com>
Date: Thu, 4 Dec 2025 01:33:10 +0800
Subject: [PATCH 1/3] [RISCV] Emit lpad for function with returns-twice
 attribute

Insert landing pads after the callsite of attribute "returs-twice" as
these functions could result in a indirect call to land after it.
---
 .../RISCV/RISCVIndirectBranchTracking.cpp     | 28 +++++++-
 llvm/test/CodeGen/RISCV/lpad.ll               | 71 +++++++++++++++++++
 2 files changed, 98 insertions(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
index 9664ab345dcbf..7697b176daffb 100644
--- a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
+++ b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
@@ -20,7 +20,7 @@
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
 
-#define DEBUG_TYPE "riscv-indrect-branch-tracking"
+#define DEBUG_TYPE "riscv-indirect-branch-tracking"
 #define PASS_NAME "RISC-V Indirect Branch Tracking"
 
 using namespace llvm;
@@ -61,6 +61,16 @@ static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII,
       .addImm(Label);
 }
 
+static bool IsCallReturnTwice(llvm::MachineOperand &MOp) {
+  if (!MOp.isGlobal())
+    return false;
+  auto *CalleeFn = dyn_cast<Function>(MOp.getGlobal());
+  if (!CalleeFn)
+    return false;
+  AttributeList Attrs = CalleeFn->getAttributes();
+  return Attrs.hasFnAttr(Attribute::ReturnsTwice);
+}
+
 bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
   const auto &Subtarget = MF.getSubtarget<RISCVSubtarget>();
   const RISCVInstrInfo *TII = Subtarget.getInstrInfo();
@@ -100,5 +110,21 @@ bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
     }
   }
 
+  // Check for calls to functions with ReturnsTwice attribute and insert
+  // LPAD after such calls
+  for (MachineBasicBlock &MBB : MF) {
+    for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
+      if (I->isCall() && I->getNumOperands() > 0) {
+        if (IsCallReturnTwice(I->getOperand(0))) {
+          auto NextI = std::next(I);
+          BuildMI(MBB, NextI, MBB.findDebugLoc(NextI), TII->get(RISCV::AUIPC),
+                  RISCV::X0)
+              .addImm(FixedLabel);
+          Changed = true;
+        }
+      }
+    }
+  }
+
   return Changed;
 }
diff --git a/llvm/test/CodeGen/RISCV/lpad.ll b/llvm/test/CodeGen/RISCV/lpad.ll
index 93eda6f10eedb..28873ab6c49a4 100644
--- a/llvm/test/CodeGen/RISCV/lpad.ll
+++ b/llvm/test/CodeGen/RISCV/lpad.ll
@@ -289,3 +289,74 @@ define void @interrupt() "interrupt"="machine" {
 ; FIXED-ONE-NEXT:    mret
   ret void
 }
+
+declare i32 @setjmp(ptr) returns_twice
+
+define i32 @test_returns_twice() {
+; RV32-LABEL: test_returns_twice:
+; RV32:       # %bb.0:
+; RV32-NEXT:    lpad 0
+; RV32-NEXT:    addi sp, sp, -16
+; RV32-NEXT:    .cfi_def_cfa_offset 16
+; RV32-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; RV32-NEXT:    .cfi_offset ra, -4
+; RV32-NEXT:    addi a0, sp, 8
+; RV32-NEXT:    call setjmp
+; RV32-NEXT:    lpad 0
+; RV32-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; RV32-NEXT:    .cfi_restore ra
+; RV32-NEXT:    addi sp, sp, 16
+; RV32-NEXT:    .cfi_def_cfa_offset 0
+; RV32-NEXT:    ret
+;
+; RV64-LABEL: test_returns_twice:
+; RV64:       # %bb.0:
+; RV64-NEXT:    lpad 0
+; RV64-NEXT:    addi sp, sp, -16
+; RV64-NEXT:    .cfi_def_cfa_offset 16
+; RV64-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; RV64-NEXT:    .cfi_offset ra, -8
+; RV64-NEXT:    addi a0, sp, 4
+; RV64-NEXT:    call setjmp
+; RV64-NEXT:    lpad 0
+; RV64-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; RV64-NEXT:    .cfi_restore ra
+; RV64-NEXT:    addi sp, sp, 16
+; RV64-NEXT:    .cfi_def_cfa_offset 0
+; RV64-NEXT:    ret
+;
+; FIXED-ONE-RV32-LABEL: test_returns_twice:
+; FIXED-ONE-RV32:       # %bb.0:
+; FIXED-ONE-RV32-NEXT:    lpad 1
+; FIXED-ONE-RV32-NEXT:    addi sp, sp, -16
+; FIXED-ONE-RV32-NEXT:    .cfi_def_cfa_offset 16
+; FIXED-ONE-RV32-NEXT:    sw ra, 12(sp) # 4-byte Folded Spill
+; FIXED-ONE-RV32-NEXT:    .cfi_offset ra, -4
+; FIXED-ONE-RV32-NEXT:    addi a0, sp, 8
+; FIXED-ONE-RV32-NEXT:    call setjmp
+; FIXED-ONE-RV32-NEXT:    lpad 1
+; FIXED-ONE-RV32-NEXT:    lw ra, 12(sp) # 4-byte Folded Reload
+; FIXED-ONE-RV32-NEXT:    .cfi_restore ra
+; FIXED-ONE-RV32-NEXT:    addi sp, sp, 16
+; FIXED-ONE-RV32-NEXT:    .cfi_def_cfa_offset 0
+; FIXED-ONE-RV32-NEXT:    ret
+;
+; FIXED-ONE-RV64-LABEL: test_returns_twice:
+; FIXED-ONE-RV64:       # %bb.0:
+; FIXED-ONE-RV64-NEXT:    lpad 1
+; FIXED-ONE-RV64-NEXT:    addi sp, sp, -16
+; FIXED-ONE-RV64-NEXT:    .cfi_def_cfa_offset 16
+; FIXED-ONE-RV64-NEXT:    sd ra, 8(sp) # 8-byte Folded Spill
+; FIXED-ONE-RV64-NEXT:    .cfi_offset ra, -8
+; FIXED-ONE-RV64-NEXT:    addi a0, sp, 4
+; FIXED-ONE-RV64-NEXT:    call setjmp
+; FIXED-ONE-RV64-NEXT:    lpad 1
+; FIXED-ONE-RV64-NEXT:    ld ra, 8(sp) # 8-byte Folded Reload
+; FIXED-ONE-RV64-NEXT:    .cfi_restore ra
+; FIXED-ONE-RV64-NEXT:    addi sp, sp, 16
+; FIXED-ONE-RV64-NEXT:    .cfi_def_cfa_offset 0
+; FIXED-ONE-RV64-NEXT:    ret
+  %buf = alloca [1 x i32], align 4
+  %call = call i32 @setjmp(ptr %buf)
+  ret i32 %call
+}

>From 31390f4e665b18c50f5c8d1e1e253a44317f8bca Mon Sep 17 00:00:00 2001
From: Jesse Huang <jessehuang2222 at gmail.com>
Date: Thu, 4 Dec 2025 02:28:04 +0800
Subject: [PATCH 2/3] Address comments

---
 .../RISCV/RISCVIndirectBranchTracking.cpp     | 24 +++++++++----------
 1 file changed, 12 insertions(+), 12 deletions(-)

diff --git a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
index 7697b176daffb..2f0b13b7e932b 100644
--- a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
+++ b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
@@ -16,6 +16,7 @@
 #include "RISCVInstrInfo.h"
 #include "RISCVSubtarget.h"
 #include "llvm/ADT/Statistic.h"
+#include "llvm/CodeGen/MachineBasicBlock.h"
 #include "llvm/CodeGen/MachineFunctionPass.h"
 #include "llvm/CodeGen/MachineInstrBuilder.h"
 #include "llvm/CodeGen/MachineModuleInfo.h"
@@ -54,14 +55,16 @@ FunctionPass *llvm::createRISCVIndirectBranchTrackingPass() {
   return new RISCVIndirectBranchTracking();
 }
 
-static void emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII,
-                     uint32_t Label) {
-  auto I = MBB.begin();
+static void
+emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII, uint32_t Label,
+         MachineBasicBlock::iterator I = MachineBasicBlock::iterator{}) {
+  if (!I.isValid())
+    I = MBB.begin();
   BuildMI(MBB, I, MBB.findDebugLoc(I), TII->get(RISCV::AUIPC), RISCV::X0)
       .addImm(Label);
 }
 
-static bool IsCallReturnTwice(llvm::MachineOperand &MOp) {
+static bool isCallReturnTwice(MachineOperand &MOp) {
   if (!MOp.isGlobal())
     return false;
   auto *CalleeFn = dyn_cast<Function>(MOp.getGlobal());
@@ -114,14 +117,11 @@ bool RISCVIndirectBranchTracking::runOnMachineFunction(MachineFunction &MF) {
   // LPAD after such calls
   for (MachineBasicBlock &MBB : MF) {
     for (MachineBasicBlock::iterator I = MBB.begin(); I != MBB.end(); ++I) {
-      if (I->isCall() && I->getNumOperands() > 0) {
-        if (IsCallReturnTwice(I->getOperand(0))) {
-          auto NextI = std::next(I);
-          BuildMI(MBB, NextI, MBB.findDebugLoc(NextI), TII->get(RISCV::AUIPC),
-                  RISCV::X0)
-              .addImm(FixedLabel);
-          Changed = true;
-        }
+      if (I->isCall() && I->getNumOperands() > 0 &&
+          isCallReturnTwice(I->getOperand(0))) {
+        auto NextI = std::next(I);
+        emitLpad(MBB, TII, FixedLabel, NextI);
+        Changed = true;
       }
     }
   }

>From ae3de94b8afecc4649a5bd4981ef2372f70a6339 Mon Sep 17 00:00:00 2001
From: Jesse Huang <jessehuang2222 at gmail.com>
Date: Thu, 4 Dec 2025 02:28:50 +0800
Subject: [PATCH 3/3] Add const for isCallReturnTwice

---
 llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
index 2f0b13b7e932b..0fc139a30ae76 100644
--- a/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
+++ b/llvm/lib/Target/RISCV/RISCVIndirectBranchTracking.cpp
@@ -64,7 +64,7 @@ emitLpad(MachineBasicBlock &MBB, const RISCVInstrInfo *TII, uint32_t Label,
       .addImm(Label);
 }
 
-static bool isCallReturnTwice(MachineOperand &MOp) {
+static bool isCallReturnTwice(const MachineOperand &MOp) {
   if (!MOp.isGlobal())
     return false;
   auto *CalleeFn = dyn_cast<Function>(MOp.getGlobal());



More information about the llvm-commits mailing list