[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-03-15 Thread Lu Weining via Phabricator via cfe-commits
This revision was automatically updated to reflect the committed changes.
Closed by commit rGdb5dfec9d444: [Clang][LoongArch] Implement patchable 
function entry (authored by WANG Xuerui , committed by 
SixWeining).

Changed prior to commit:
  https://reviews.llvm.org/D141785?vs=497598&id=505680#toc

Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/fpatchable-function-entry.c
  clang/test/Sema/patchable-function-entry-attr.cpp
  llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
  llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
  llvm/test/CodeGen/LoongArch/patchable-function-entry.ll

Index: llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
===
--- /dev/null
+++ llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
@@ -0,0 +1,63 @@
+;; Test the function attribute "patchable-function-entry".
+;; Adapted from the RISCV test case.
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @f0() "patchable-function-entry"="0" {
+; CHECK-LABEL: f0:
+; CHECK-NEXT:  .Lfunc_begin0:
+; CHECK-NOT: nop
+; CHECK: ret
+; CHECK-NOT:   .section __patchable_function_entries
+  ret void
+}
+
+define void @f1() "patchable-function-entry"="1" {
+; CHECK-LABEL: f1:
+; CHECK-NEXT: .Lfunc_begin1:
+; CHECK: nop
+; CHECK-NEXT:ret
+; CHECK:   .section __patchable_function_entries,"awo",@progbits,f1{{$}}
+; LA32:.p2align 2
+; LA32-NEXT:   .word .Lfunc_begin1
+; LA64:.p2align 3
+; LA64-NEXT:   .dword .Lfunc_begin1
+  ret void
+}
+
+$f5 = comdat any
+define void @f5() "patchable-function-entry"="5" comdat {
+; CHECK-LABEL:   f5:
+; CHECK-NEXT:.Lfunc_begin2:
+; CHECK-COUNT-5:   nop
+; CHECK-NEXT:  ret
+; CHECK: .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5{{$}}
+; LA32:  .p2align 2
+; LA32-NEXT: .word .Lfunc_begin2
+; LA64:  .p2align 3
+; LA64-NEXT: .dword .Lfunc_begin2
+  ret void
+}
+
+;; -fpatchable-function-entry=3,2
+;; "patchable-function-prefix" emits data before the function entry label.
+define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
+; CHECK-LABEL:   .type f3_2,@function
+; CHECK-NEXT:.Ltmp0: # @f3_2
+; CHECK-COUNT-2:   nop
+; CHECK-NEXT:f3_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT:  nop
+; LA32-NEXT:   addi.w $sp, $sp, -16
+; LA64-NEXT:   addi.d $sp, $sp, -16
+;; .size does not include the prefix.
+; CHECK:  .Lfunc_end3:
+; CHECK-NEXT: .size f3_2, .Lfunc_end3-f3_2
+; CHECK:  .section __patchable_function_entries,"awo",@progbits,f3_2{{$}}
+; LA32:   .p2align 2
+; LA32-NEXT:  .word .Ltmp0
+; LA64:   .p2align 3
+; LA64-NEXT:  .dword .Ltmp0
+  %frame = alloca i8, i32 16
+  ret void
+}
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -27,6 +27,8 @@
 public:
   explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
 
+  MCInst getNop() const override;
+
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
bool KillSrc) const override;
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -17,6 +17,7 @@
 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
 #include "MCTargetDesc/LoongArchMatInt.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCInstBuilder.h"
 
 using namespace llvm;
 
@@ -28,6 +29,13 @@
 LoongArch::ADJCALLSTACKUP),
   STI(STI) {}
 
+MCInst LoongArchInstrInfo::getNop() const {
+  return MCInstBuilder(LoongArch::ANDI)
+  .addReg(LoongArch::R0)
+  .addReg(LoongArch::R0)
+  .addImm(0);
+}
+
 void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
  MachineBasicBlock::iterator MBBI,
  const DebugLoc &DL, MCRegister DstReg,
Index: llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
===
--- llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -41,6 +41,8 @@
   bool Pri

[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-02-15 Thread Lu Weining via Phabricator via cfe-commits
SixWeining accepted this revision.
SixWeining added a comment.
This revision is now accepted and ready to land.

LGTM. Thanks.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-02-15 Thread WÁNG Xuěruì via Phabricator via cfe-commits
xen0n updated this revision to Diff 497598.
xen0n added a comment.

Document the change in Clang release note.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

Files:
  clang/docs/ReleaseNotes.rst
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/fpatchable-function-entry.c
  clang/test/Sema/patchable-function-entry-attr.cpp
  llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
  llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
  llvm/test/CodeGen/LoongArch/patchable-function-entry.ll

Index: llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
===
--- /dev/null
+++ llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
@@ -0,0 +1,63 @@
+;; Test the function attribute "patchable-function-entry".
+;; Adapted from the RISCV test case.
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @f0() "patchable-function-entry"="0" {
+; CHECK-LABEL: f0:
+; CHECK-NEXT:  .Lfunc_begin0:
+; CHECK-NOT: nop
+; CHECK: ret
+; CHECK-NOT:   .section __patchable_function_entries
+  ret void
+}
+
+define void @f1() "patchable-function-entry"="1" {
+; CHECK-LABEL: f1:
+; CHECK-NEXT: .Lfunc_begin1:
+; CHECK: nop
+; CHECK-NEXT:ret
+; CHECK:   .section __patchable_function_entries,"awo",@progbits,f1{{$}}
+; LA32:.p2align 2
+; LA32-NEXT:   .word .Lfunc_begin1
+; LA64:.p2align 3
+; LA64-NEXT:   .dword .Lfunc_begin1
+  ret void
+}
+
+$f5 = comdat any
+define void @f5() "patchable-function-entry"="5" comdat {
+; CHECK-LABEL:   f5:
+; CHECK-NEXT:.Lfunc_begin2:
+; CHECK-COUNT-5:   nop
+; CHECK-NEXT:  ret
+; CHECK: .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5{{$}}
+; LA32:  .p2align 2
+; LA32-NEXT: .word .Lfunc_begin2
+; LA64:  .p2align 3
+; LA64-NEXT: .dword .Lfunc_begin2
+  ret void
+}
+
+;; -fpatchable-function-entry=3,2
+;; "patchable-function-prefix" emits data before the function entry label.
+define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
+; CHECK-LABEL:   .type f3_2,@function
+; CHECK-NEXT:.Ltmp0: # @f3_2
+; CHECK-COUNT-2:   nop
+; CHECK-NEXT:f3_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT:  nop
+; LA32-NEXT:   addi.w $sp, $sp, -16
+; LA64-NEXT:   addi.d $sp, $sp, -16
+;; .size does not include the prefix.
+; CHECK:  .Lfunc_end3:
+; CHECK-NEXT: .size f3_2, .Lfunc_end3-f3_2
+; CHECK:  .section __patchable_function_entries,"awo",@progbits,f3_2{{$}}
+; LA32:   .p2align 2
+; LA32-NEXT:  .word .Ltmp0
+; LA64:   .p2align 3
+; LA64-NEXT:  .dword .Ltmp0
+  %frame = alloca i8, i32 16
+  ret void
+}
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -27,6 +27,8 @@
 public:
   explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
 
+  MCInst getNop() const override;
+
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
bool KillSrc) const override;
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -17,6 +17,7 @@
 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
 #include "MCTargetDesc/LoongArchMatInt.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCInstBuilder.h"
 
 using namespace llvm;
 
@@ -28,6 +29,13 @@
 LoongArch::ADJCALLSTACKUP),
   STI(STI) {}
 
+MCInst LoongArchInstrInfo::getNop() const {
+  return MCInstBuilder(LoongArch::ANDI)
+  .addReg(LoongArch::R0)
+  .addReg(LoongArch::R0)
+  .addImm(0);
+}
+
 void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
  MachineBasicBlock::iterator MBBI,
  const DebugLoc &DL, MCRegister DstReg,
Index: llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
===
--- llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -41,6 +41,8 @@
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
  const char *ExtraCode, raw_ostream &OS) override;
 
+  void LowerPATCHABLE_FUNCTION_ENTER(const MachineInstr &MI);
+
 

[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-02-15 Thread WÁNG Xuěruì via Phabricator via cfe-commits
xen0n updated this revision to Diff 497596.
xen0n added a comment.

Rebase and change to lower the op in LoongArchAsmPrinter so as to make people's 
lives easier when they come to rebase D141785 
 on top of this.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/fpatchable-function-entry.c
  clang/test/Sema/patchable-function-entry-attr.cpp
  llvm/lib/Target/LoongArch/LoongArchAsmPrinter.cpp
  llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
  llvm/test/CodeGen/LoongArch/patchable-function-entry.ll

Index: llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
===
--- /dev/null
+++ llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
@@ -0,0 +1,63 @@
+;; Test the function attribute "patchable-function-entry".
+;; Adapted from the RISCV test case.
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @f0() "patchable-function-entry"="0" {
+; CHECK-LABEL: f0:
+; CHECK-NEXT:  .Lfunc_begin0:
+; CHECK-NOT: nop
+; CHECK: ret
+; CHECK-NOT:   .section __patchable_function_entries
+  ret void
+}
+
+define void @f1() "patchable-function-entry"="1" {
+; CHECK-LABEL: f1:
+; CHECK-NEXT: .Lfunc_begin1:
+; CHECK: nop
+; CHECK-NEXT:ret
+; CHECK:   .section __patchable_function_entries,"awo",@progbits,f1{{$}}
+; LA32:.p2align 2
+; LA32-NEXT:   .word .Lfunc_begin1
+; LA64:.p2align 3
+; LA64-NEXT:   .dword .Lfunc_begin1
+  ret void
+}
+
+$f5 = comdat any
+define void @f5() "patchable-function-entry"="5" comdat {
+; CHECK-LABEL:   f5:
+; CHECK-NEXT:.Lfunc_begin2:
+; CHECK-COUNT-5:   nop
+; CHECK-NEXT:  ret
+; CHECK: .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5{{$}}
+; LA32:  .p2align 2
+; LA32-NEXT: .word .Lfunc_begin2
+; LA64:  .p2align 3
+; LA64-NEXT: .dword .Lfunc_begin2
+  ret void
+}
+
+;; -fpatchable-function-entry=3,2
+;; "patchable-function-prefix" emits data before the function entry label.
+define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
+; CHECK-LABEL:   .type f3_2,@function
+; CHECK-NEXT:.Ltmp0: # @f3_2
+; CHECK-COUNT-2:   nop
+; CHECK-NEXT:f3_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT:  nop
+; LA32-NEXT:   addi.w $sp, $sp, -16
+; LA64-NEXT:   addi.d $sp, $sp, -16
+;; .size does not include the prefix.
+; CHECK:  .Lfunc_end3:
+; CHECK-NEXT: .size f3_2, .Lfunc_end3-f3_2
+; CHECK:  .section __patchable_function_entries,"awo",@progbits,f3_2{{$}}
+; LA32:   .p2align 2
+; LA32-NEXT:  .word .Ltmp0
+; LA64:   .p2align 3
+; LA64-NEXT:  .dword .Ltmp0
+  %frame = alloca i8, i32 16
+  ret void
+}
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -27,6 +27,8 @@
 public:
   explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
 
+  MCInst getNop() const override;
+
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
bool KillSrc) const override;
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@@ -17,6 +17,7 @@
 #include "MCTargetDesc/LoongArchMCTargetDesc.h"
 #include "MCTargetDesc/LoongArchMatInt.h"
 #include "llvm/CodeGen/RegisterScavenging.h"
+#include "llvm/MC/MCInstBuilder.h"
 
 using namespace llvm;
 
@@ -28,6 +29,13 @@
 LoongArch::ADJCALLSTACKUP),
   STI(STI) {}
 
+MCInst LoongArchInstrInfo::getNop() const {
+  return MCInstBuilder(LoongArch::ANDI)
+  .addReg(LoongArch::R0)
+  .addReg(LoongArch::R0)
+  .addImm(0);
+}
+
 void LoongArchInstrInfo::copyPhysReg(MachineBasicBlock &MBB,
  MachineBasicBlock::iterator MBBI,
  const DebugLoc &DL, MCRegister DstReg,
Index: llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
===
--- llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
+++ llvm/lib/Target/LoongArch/LoongArchAsmPrinter.h
@@ -41,6 +41,8 @@
   bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo,
  const char *

[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-02-06 Thread WÁNG Xuěruì via Phabricator via cfe-commits
xen0n added inline comments.



Comment at: llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp:150
+  .getAsInteger(10, Num))
+return false;
+  AP.emitNops(Num);

SixWeining wrote:
> Seems should return `true`? Consider when verifier is disabled.
> 
> How about handling `PATCHABLE_FUNCTION_ENTER` in `LoongArchAsmPrinter.cpp` 
> like D140727?
I've checked other targets and indeed implementation in `AsmPrinter` is the 
more widespread approach (RISCV is the outlier here). Let me adjust in one or 
two days.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-01-18 Thread Aaron Ballman via Phabricator via cfe-commits
aaron.ballman added a comment.

The Clang bits LGTM, though you should add a release note about the new 
functionality so users know about it.


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-01-15 Thread Lu Weining via Phabricator via cfe-commits
SixWeining added a comment.

Does anyone know why `patchable-function-entry` is not documented in 
https://llvm.org/docs/LangRef.html#function-attributes?




Comment at: llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp:150
+  .getAsInteger(10, Num))
+return false;
+  AP.emitNops(Num);

Seems should return `true`? Consider when verifier is disabled.

How about handling `PATCHABLE_FUNCTION_ENTER` in `LoongArchAsmPrinter.cpp` like 
D140727?


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D141785/new/

https://reviews.llvm.org/D141785

___
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits


[PATCH] D141785: [Clang][LoongArch] Implement patchable function entry

2023-01-15 Thread WÁNG Xuěruì via Phabricator via cfe-commits
xen0n created this revision.
xen0n added reviewers: SixWeining, wangleiat, gonglingqin, MaskRay, xry111.
Herald added subscribers: luismarques, s.egerton, PkmX, simoncook, hiraditya, 
arichardson.
Herald added a reviewer: aaron.ballman.
Herald added a project: All.
xen0n requested review of this revision.
Herald added subscribers: llvm-commits, cfe-commits, pcwang-thead.
Herald added projects: clang, LLVM.

Similar to D98610  for RISCV.

This is going to be required by the upcoming Linux/LoongArch
[[ support for dynamic ftrace | https://git.kernel.org/linus/4733f09d88074 ]].


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D141785

Files:
  clang/include/clang/Basic/Attr.td
  clang/include/clang/Basic/AttrDocs.td
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/test/Driver/fpatchable-function-entry.c
  clang/test/Sema/patchable-function-entry-attr.cpp
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
  llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
  llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
  llvm/test/CodeGen/LoongArch/patchable-function-entry.ll

Index: llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
===
--- /dev/null
+++ llvm/test/CodeGen/LoongArch/patchable-function-entry.ll
@@ -0,0 +1,62 @@
+;; Test the function attribute "patchable-function-entry".
+; RUN: llc --mtriple=loongarch32 < %s | FileCheck %s --check-prefixes=CHECK,LA32
+; RUN: llc --mtriple=loongarch64 < %s | FileCheck %s --check-prefixes=CHECK,LA64
+
+define void @f0() "patchable-function-entry"="0" {
+; CHECK-LABEL: f0:
+; CHECK-NEXT:  .Lfunc_begin0:
+; CHECK-NOT: nop
+; CHECK: ret
+; CHECK-NOT:   .section __patchable_function_entries
+  ret void
+}
+
+define void @f1() "patchable-function-entry"="1" {
+; CHECK-LABEL: f1:
+; CHECK-NEXT: .Lfunc_begin1:
+; CHECK: nop
+; CHECK-NEXT:ret
+; CHECK:   .section __patchable_function_entries,"awo",@progbits,f1{{$}}
+; LA32:.p2align 2
+; LA32-NEXT:   .word .Lfunc_begin1
+; LA64:.p2align 3
+; LA64-NEXT:   .dword .Lfunc_begin1
+  ret void
+}
+
+$f5 = comdat any
+define void @f5() "patchable-function-entry"="5" comdat {
+; CHECK-LABEL:   f5:
+; CHECK-NEXT:.Lfunc_begin2:
+; CHECK-COUNT-5:   nop
+; CHECK-NEXT:  ret
+; CHECK: .section __patchable_function_entries,"aGwo",@progbits,f5,comdat,f5{{$}}
+; LA32:  .p2align 2
+; LA32-NEXT: .word .Lfunc_begin2
+; LA64:  .p2align 3
+; LA64-NEXT: .dword .Lfunc_begin2
+  ret void
+}
+
+;; -fpatchable-function-entry=3,2
+;; "patchable-function-prefix" emits data before the function entry label.
+define void @f3_2() "patchable-function-entry"="1" "patchable-function-prefix"="2" {
+; CHECK-LABEL:   .type f3_2,@function
+; CHECK-NEXT:.Ltmp0: # @f3_2
+; CHECK-COUNT-2:   nop
+; CHECK-NEXT:f3_2:
+; CHECK: # %bb.0:
+; CHECK-NEXT:  nop
+; LA32-NEXT:   addi.w $sp, $sp, -16
+; LA64-NEXT:   addi.d $sp, $sp, -16
+;; .size does not include the prefix.
+; CHECK:  .Lfunc_end3:
+; CHECK-NEXT: .size f3_2, .Lfunc_end3-f3_2
+; CHECK:  .section __patchable_function_entries,"awo",@progbits,f3_2{{$}}
+; LA32:   .p2align 2
+; LA32-NEXT:  .word .Ltmp0
+; LA64:   .p2align 3
+; LA64-NEXT:  .dword .Ltmp0
+  %frame = alloca i8, i32 16
+  ret void
+}
Index: llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
===
--- llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
+++ llvm/lib/Target/LoongArch/LoongArchMCInstLower.cpp
@@ -138,5 +138,22 @@
 if (lowerLoongArchMachineOperandToMCOperand(MO, MCOp, AP))
   OutMI.addOperand(MCOp);
   }
+
+  switch (OutMI.getOpcode()) {
+  case TargetOpcode::PATCHABLE_FUNCTION_ENTER: {
+const Function &F = MI->getParent()->getParent()->getFunction();
+if (F.hasFnAttribute("patchable-function-entry")) {
+  unsigned Num;
+  if (F.getFnAttribute("patchable-function-entry")
+  .getValueAsString()
+  .getAsInteger(10, Num))
+return false;
+  AP.emitNops(Num);
+  return true;
+}
+break;
+  }
+  }
+
   return false;
 }
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.h
@@ -27,6 +27,8 @@
 public:
   explicit LoongArchInstrInfo(LoongArchSubtarget &STI);
 
+  MCInst getNop() const override;
+
   void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI,
const DebugLoc &DL, MCRegister DstReg, MCRegister SrcReg,
bool KillSrc) const override;
Index: llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
===
--- llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
+++ llvm/lib/Target/LoongArch/LoongArchInstrInfo.cpp
@