https://github.com/ADSWT518 updated 
https://github.com/llvm/llvm-project/pull/234076

>From 340931a49dc70032fc540ba550153c3e37273170 Mon Sep 17 00:00:00 2001
From: Tianci Cao <[email protected]>
Date: Sun, 12 Jul 2026 00:51:54 +0800
Subject: [PATCH 1/4] [BPF] Add UHMUL and SHMUL instruction variants

Add assembly, disassembly, and instruction selection support for the
ALU64 high-half multiply variants encoded in the offset field of BPF_MUL:

  uh*=  unsigned high-half multiply (UHMUL, off=1)
  sh*=  signed high-half multiply   (SHMUL, off=2)

Match ISD::MULHU and ISD::MULHS to the new instructions for cpu v4.
Keep ALU32, earlier CPUs, and configurations using -disable-hmul on the
existing expansion path.

Define __BPF_FEATURE_HMUL for cpu v4 so source code can detect compiler
support for the new instructions.

Co-authored-by: Yazhou Tang <[email protected]>
Co-authored-by: Shenghao Yuan <[email protected]>
---
 clang/lib/Basic/Targets/BPF.cpp               |  1 +
 .../test/Preprocessor/bpf-predefined-macros.c |  5 ++
 .../lib/Target/BPF/AsmParser/BPFAsmParser.cpp |  2 +
 llvm/lib/Target/BPF/BPFISelLowering.cpp       |  6 +-
 llvm/lib/Target/BPF/BPFInstrInfo.td           | 15 +++-
 llvm/lib/Target/BPF/BPFSubtarget.cpp          |  5 ++
 llvm/lib/Target/BPF/BPFSubtarget.h            |  3 +-
 .../CodeGen/BPF/assembler-disassembler-v4.s   |  9 ++
 llvm/test/CodeGen/BPF/hmul.ll                 | 83 +++++++++++++++++++
 llvm/test/MC/BPF/bad-hmul.s                   |  5 ++
 10 files changed, 130 insertions(+), 4 deletions(-)
 create mode 100644 llvm/test/CodeGen/BPF/hmul.ll
 create mode 100644 llvm/test/MC/BPF/bad-hmul.s

diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp
index 29e4c86ad88621..6efdd023b32d14 100644
--- a/clang/lib/Basic/Targets/BPF.cpp
+++ b/clang/lib/Basic/Targets/BPF.cpp
@@ -78,6 +78,7 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
     Builder.defineMacro("__BPF_FEATURE_ST");
     Builder.defineMacro("__BPF_FEATURE_LOAD_ACQ_STORE_REL");
     Builder.defineMacro("__BPF_FEATURE_GOTOX");
+    Builder.defineMacro("__BPF_FEATURE_HMUL");
   }
 }
 
diff --git a/clang/test/Preprocessor/bpf-predefined-macros.c 
b/clang/test/Preprocessor/bpf-predefined-macros.c
index d3d59a979e06bf..c81bfa871a440d 100644
--- a/clang/test/Preprocessor/bpf-predefined-macros.c
+++ b/clang/test/Preprocessor/bpf-predefined-macros.c
@@ -82,6 +82,9 @@ int y;
 #ifdef __BPF_FEATURE_UNWIND
 int z;
 #endif
+#ifdef __BPF_FEATURE_HMUL
+int aa;
+#endif
 
 // CHECK: int b;
 // CHECK: int c;
@@ -139,6 +142,8 @@ int z;
 // CPU_V3: int z;
 // CPU_V4: int z;
 
+// CPU_V4: int aa;
+
 // CPU_GENERIC: int g;
 
 // CPU_PROBE: int f;
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp 
b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index ec167a680cdc1b..6483d02aa6f87b 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -268,6 +268,8 @@ struct BPFOperand : public MCParsedAsmOperand {
         .Case("ll", true)
         .Case("skb", true)
         .Case("s", true)
+        .Case("uh", true)
+        .Case("sh", true)
         .Case("atomic_fetch_add", true)
         .Case("atomic_fetch_and", true)
         .Case("atomic_fetch_or", true)
diff --git a/llvm/lib/Target/BPF/BPFISelLowering.cpp 
b/llvm/lib/Target/BPF/BPFISelLowering.cpp
index 435f0e15a25c59..204905a3a1c526 100644
--- a/llvm/lib/Target/BPF/BPFISelLowering.cpp
+++ b/llvm/lib/Target/BPF/BPFISelLowering.cpp
@@ -127,8 +127,10 @@ BPFTargetLowering::BPFTargetLowering(const TargetMachine 
&TM,
       setOperationAction(ISD::SDIV, VT, Custom);
       setOperationAction(ISD::SREM, VT, Custom);
     }
-    setOperationAction(ISD::MULHU, VT, Expand);
-    setOperationAction(ISD::MULHS, VT, Expand);
+    if (VT == MVT::i32 || !STI.hasHmul()) {
+      setOperationAction(ISD::MULHU, VT, Expand);
+      setOperationAction(ISD::MULHS, VT, Expand);
+    }
     setOperationAction(ISD::UMUL_LOHI, VT, Expand);
     setOperationAction(ISD::SMUL_LOHI, VT, Expand);
     setOperationAction(ISD::ROTR, VT, Expand);
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td 
b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 8c3e09009a5e50..0e5d7dce3e4da3 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -71,6 +71,7 @@ def BPFHasLdsx : Predicate<"Subtarget->hasLdsx()">;
 def BPFHasMovsx : Predicate<"Subtarget->hasMovsx()">;
 def BPFHasBswap : Predicate<"Subtarget->hasBswap()">;
 def BPFHasSdivSmod : Predicate<"Subtarget->hasSdivSmod()">;
+def BPFHasHmul : Predicate<"Subtarget->hasHmul()">;
 def BPFNoMovsx : Predicate<"!Subtarget->hasMovsx()">;
 def BPFNoBswap : Predicate<"!Subtarget->hasBswap()">;
 def BPFHasStoreImm : Predicate<"Subtarget->hasStoreImm()">;
@@ -360,7 +361,7 @@ class ALU_RR<BPFOpClass Class, BPFArithOp Opc, int off,
   let BPFClass = Class;
 }
 
-multiclass ALU<BPFArithOp Opc, int off, string OpcodeStr, SDNode OpNode> {
+multiclass ALU64<BPFArithOp Opc, int off, string OpcodeStr, SDNode OpNode> {
   def _rr : ALU_RR<BPF_ALU64, Opc, off,
                    (outs GPR:$dst),
                    (ins GPR:$src2, GPR:$src),
@@ -371,6 +372,10 @@ multiclass ALU<BPFArithOp Opc, int off, string OpcodeStr, 
SDNode OpNode> {
                    (ins GPR:$src2, i64imm:$imm),
                    "$dst "#OpcodeStr#" $imm",
                    [(set GPR:$dst, (OpNode GPR:$src2, i64immSExt32:$imm))]>;
+}
+
+multiclass ALU<BPFArithOp Opc, int off, string OpcodeStr, SDNode OpNode>
+    : ALU64<Opc, off, OpcodeStr, OpNode> {
   def _rr_32 : ALU_RR<BPF_ALU, Opc, off,
                    (outs GPR32:$dst),
                    (ins GPR32:$src2, GPR32:$src),
@@ -402,6 +407,14 @@ let isAsCheapAsAMove = 1 in {
     defm SDIV : ALU<BPF_DIV, 1, "s/=", sdiv>;
     defm SMOD : ALU<BPF_MOD, 1, "s%=", srem>;
   }
+
+  // High-half multiply variants encoded via insn->off on BPF_MUL:
+  //   off == 1  UHMUL:  dst = ((u128)dst * (u128)src) >> 64
+  //   off == 2  SHMUL:  dst = ((i128)dst * (i128)src) >> 64
+  let Predicates = [BPFHasHmul] in {
+    defm UHMUL : ALU64<BPF_MUL, 1, "uh*=", mulhu>;
+    defm SHMUL : ALU64<BPF_MUL, 2, "sh*=", mulhs>;
+  }
 }
 
 class NEG_RR<BPFOpClass Class, BPFArithOp Opc,
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp 
b/llvm/lib/Target/BPF/BPFSubtarget.cpp
index 726f8f4b39827f..4e9a19a235300a 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -45,6 +45,9 @@ static cl::opt<bool> Disable_load_acq_store_rel(
     cl::desc("Disable load-acquire and store-release insns"));
 static cl::opt<bool> Disable_gotox("disable-gotox", cl::Hidden, 
cl::init(false),
                                    cl::desc("Disable gotox insn"));
+static cl::opt<bool> Disable_hmul(
+    "disable-hmul", cl::Hidden, cl::init(false),
+    cl::desc("Disable high-half multiply (UHMUL/SHMUL) insns"));
 
 void BPFSubtarget::anchor() {}
 
@@ -69,6 +72,7 @@ void BPFSubtarget::initializeEnvironment() {
   HasStoreImm = false;
   HasLoadAcqStoreRel = false;
   HasGotox = false;
+  HasHmul = false;
   AllowsMisalignedMemAccess = false;
 }
 
@@ -101,6 +105,7 @@ void BPFSubtarget::initSubtargetFeatures(StringRef CPU, 
StringRef FS) {
     HasStoreImm = !Disable_StoreImm;
     HasLoadAcqStoreRel = !Disable_load_acq_store_rel;
     HasGotox = !Disable_gotox;
+    HasHmul = !Disable_hmul;
     return;
   }
 }
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.h 
b/llvm/lib/Target/BPF/BPFSubtarget.h
index 24eff862224b04..4be57b424ece15 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.h
+++ b/llvm/lib/Target/BPF/BPFSubtarget.h
@@ -68,7 +68,7 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
 
   // whether cpu v4 insns are enabled.
   bool HasLdsx, HasMovsx, HasBswap, HasSdivSmod, HasGotol, HasStoreImm,
-      HasLoadAcqStoreRel, HasGotox;
+      HasLoadAcqStoreRel, HasGotox, HasHmul;
 
   std::unique_ptr<CallLowering> CallLoweringInfo;
   std::unique_ptr<InstructionSelector> InstSelector;
@@ -101,6 +101,7 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
   bool hasStoreImm() const { return HasStoreImm; }
   bool hasLoadAcqStoreRel() const { return HasLoadAcqStoreRel; }
   bool hasGotox() const { return HasGotox; }
+  bool hasHmul() const { return HasHmul; }
 
   bool isLittleEndian() const { return IsLittleEndian; }
 
diff --git a/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s 
b/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s
index c4949d5d1df5e3..90b709dabe67f9 100644
--- a/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s
+++ b/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s
@@ -38,6 +38,15 @@ w2 = (s16)w4
 r1 s/= r3
 r2 s%= r4
 
+// CHECK: 2f 21 01 00 00 00 00 00     r1 uh*= r2
+// CHECK: 2f 43 02 00 00 00 00 00     r3 sh*= r4
+// CHECK: 27 05 01 00 fe ff ff ff     r5 uh*= -0x2
+// CHECK: 27 06 02 00 fd ff ff ff     r6 sh*= -0x3
+r1 uh*= r2
+r3 sh*= r4
+r5 uh*= -2
+r6 sh*= -3
+
 // CHECK: 3c 31 01 00 00 00 00 00     w1 s/= w3
 // CHECK: 9c 42 01 00 00 00 00 00     w2 s%= w4
 w1 s/= w3
diff --git a/llvm/test/CodeGen/BPF/hmul.ll b/llvm/test/CodeGen/BPF/hmul.ll
new file mode 100644
index 00000000000000..43e5ad0e8b4e23
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/hmul.ll
@@ -0,0 +1,83 @@
+; RUN: llc -mtriple=bpfel -mcpu=v4 -verify-machineinstrs -show-mc-encoding < 
%s | FileCheck %s --check-prefix=V4
+; RUN: llc -mtriple=bpfel -mcpu=v3 -verify-machineinstrs < %s | FileCheck %s 
--check-prefix=NO-HMUL
+; RUN: llc -mtriple=bpfel -mcpu=v4 -disable-hmul -verify-machineinstrs < %s | 
FileCheck %s --check-prefix=NO-HMUL
+
+define i64 @uhmul_rr(i64 %a, i64 %b) {
+; V4-LABEL: uhmul_rr:
+; V4:       r0 = r1
+; V4-NEXT:  r0 uh*= r2                              # encoding: 
[0x2f,0x20,0x01,0x00,0x00,0x00,0x00,0x00]
+; V4-NEXT:  exit
+; NO-HMUL-LABEL: uhmul_rr:
+; NO-HMUL-NOT:   uh*=
+; NO-HMUL-NOT:   sh*=
+; NO-HMUL:       call __multi3
+; NO-HMUL:       exit
+  %awide = zext i64 %a to i128
+  %bwide = zext i64 %b to i128
+  %product = mul i128 %awide, %bwide
+  %high = lshr i128 %product, 64
+  %result = trunc i128 %high to i64
+  ret i64 %result
+}
+
+define i64 @shmul_rr(i64 %a, i64 %b) {
+; V4-LABEL: shmul_rr:
+; V4:       r0 = r1
+; V4-NEXT:  r0 sh*= r2                              # encoding: 
[0x2f,0x20,0x02,0x00,0x00,0x00,0x00,0x00]
+; V4-NEXT:  exit
+; NO-HMUL-LABEL: shmul_rr:
+; NO-HMUL-NOT:   uh*=
+; NO-HMUL-NOT:   sh*=
+; NO-HMUL:       call __multi3
+; NO-HMUL:       exit
+  %awide = sext i64 %a to i128
+  %bwide = sext i64 %b to i128
+  %product = mul i128 %awide, %bwide
+  %high = ashr i128 %product, 64
+  %result = trunc i128 %high to i64
+  ret i64 %result
+}
+
+define i64 @uhmul_ri(i64 %a) {
+; V4-LABEL: uhmul_ri:
+; V4:       r0 = r1
+; V4-NEXT:  r0 uh*= -2                              # encoding: 
[0x27,0x00,0x01,0x00,0xfe,0xff,0xff,0xff]
+; V4-NEXT:  exit
+; NO-HMUL-LABEL: uhmul_ri:
+; NO-HMUL-NOT:   uh*=
+; NO-HMUL-NOT:   sh*=
+; NO-HMUL:       call __multi3
+; NO-HMUL:       exit
+  %awide = zext i64 %a to i128
+  %product = mul i128 %awide, 18446744073709551614
+  %high = lshr i128 %product, 64
+  %result = trunc i128 %high to i64
+  ret i64 %result
+}
+
+define i64 @shmul_ri(i64 %a) {
+; V4-LABEL: shmul_ri:
+; V4:       r0 = r1
+; V4-NEXT:  r0 sh*= -2                              # encoding: 
[0x27,0x00,0x02,0x00,0xfe,0xff,0xff,0xff]
+; V4-NEXT:  exit
+; NO-HMUL-LABEL: shmul_ri:
+; NO-HMUL-NOT:   uh*=
+; NO-HMUL-NOT:   sh*=
+; NO-HMUL:       exit
+  %awide = sext i64 %a to i128
+  %product = mul i128 %awide, -2
+  %high = ashr i128 %product, 64
+  %result = trunc i128 %high to i64
+  ret i64 %result
+}
+
+define i64 @mul_low(i64 %a, i64 %b) {
+; V4-LABEL: mul_low:
+; V4:       r0 = r1
+; V4-NEXT:  r0 *= r2                                # encoding: 
[0x2f,0x20,0x00,0x00,0x00,0x00,0x00,0x00]
+; V4-NEXT:  exit
+; NO-HMUL-LABEL: mul_low:
+; NO-HMUL:       r0 *= r2
+  %product = mul i64 %a, %b
+  ret i64 %product
+}
diff --git a/llvm/test/MC/BPF/bad-hmul.s b/llvm/test/MC/BPF/bad-hmul.s
new file mode 100644
index 00000000000000..e98e30f406c425
--- /dev/null
+++ b/llvm/test/MC/BPF/bad-hmul.s
@@ -0,0 +1,5 @@
+# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \
+# RUN:   | grep 'error: invalid operand for instruction' \
+# RUN:   | count 2
+        w1 uh*= w2
+        w3 sh*= -2

>From bd113192ea18608fce7a1c549c0d3b0295702072 Mon Sep 17 00:00:00 2001
From: Yazhou Tang <[email protected]>
Date: Tue, 20 Oct 2026 22:10:26 +0800
Subject: [PATCH 2/4] [BPF][test] Use implicit negative checks for high-half
 multiply

Replace per-function NO-HMUL-NOT directives with FileCheck implicit negative 
checks for UHMUL and SHMUL. Check all intervals between positive matches in the 
v3 and v4 -disable-hmul runs.
---
 llvm/test/CodeGen/BPF/hmul.ll | 14 ++++----------
 1 file changed, 4 insertions(+), 10 deletions(-)

diff --git a/llvm/test/CodeGen/BPF/hmul.ll b/llvm/test/CodeGen/BPF/hmul.ll
index 43e5ad0e8b4e23..c44f29ced6aff7 100644
--- a/llvm/test/CodeGen/BPF/hmul.ll
+++ b/llvm/test/CodeGen/BPF/hmul.ll
@@ -1,6 +1,8 @@
 ; RUN: llc -mtriple=bpfel -mcpu=v4 -verify-machineinstrs -show-mc-encoding < 
%s | FileCheck %s --check-prefix=V4
-; RUN: llc -mtriple=bpfel -mcpu=v3 -verify-machineinstrs < %s | FileCheck %s 
--check-prefix=NO-HMUL
-; RUN: llc -mtriple=bpfel -mcpu=v4 -disable-hmul -verify-machineinstrs < %s | 
FileCheck %s --check-prefix=NO-HMUL
+; RUN: llc -mtriple=bpfel -mcpu=v3 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=NO-HMUL --implicit-check-not="uh*=" 
--implicit-check-not="sh*="
+; RUN: llc -mtriple=bpfel -mcpu=v4 -disable-hmul -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=NO-HMUL --implicit-check-not="uh*=" 
--implicit-check-not="sh*="
 
 define i64 @uhmul_rr(i64 %a, i64 %b) {
 ; V4-LABEL: uhmul_rr:
@@ -8,8 +10,6 @@ define i64 @uhmul_rr(i64 %a, i64 %b) {
 ; V4-NEXT:  r0 uh*= r2                              # encoding: 
[0x2f,0x20,0x01,0x00,0x00,0x00,0x00,0x00]
 ; V4-NEXT:  exit
 ; NO-HMUL-LABEL: uhmul_rr:
-; NO-HMUL-NOT:   uh*=
-; NO-HMUL-NOT:   sh*=
 ; NO-HMUL:       call __multi3
 ; NO-HMUL:       exit
   %awide = zext i64 %a to i128
@@ -26,8 +26,6 @@ define i64 @shmul_rr(i64 %a, i64 %b) {
 ; V4-NEXT:  r0 sh*= r2                              # encoding: 
[0x2f,0x20,0x02,0x00,0x00,0x00,0x00,0x00]
 ; V4-NEXT:  exit
 ; NO-HMUL-LABEL: shmul_rr:
-; NO-HMUL-NOT:   uh*=
-; NO-HMUL-NOT:   sh*=
 ; NO-HMUL:       call __multi3
 ; NO-HMUL:       exit
   %awide = sext i64 %a to i128
@@ -44,8 +42,6 @@ define i64 @uhmul_ri(i64 %a) {
 ; V4-NEXT:  r0 uh*= -2                              # encoding: 
[0x27,0x00,0x01,0x00,0xfe,0xff,0xff,0xff]
 ; V4-NEXT:  exit
 ; NO-HMUL-LABEL: uhmul_ri:
-; NO-HMUL-NOT:   uh*=
-; NO-HMUL-NOT:   sh*=
 ; NO-HMUL:       call __multi3
 ; NO-HMUL:       exit
   %awide = zext i64 %a to i128
@@ -61,8 +57,6 @@ define i64 @shmul_ri(i64 %a) {
 ; V4-NEXT:  r0 sh*= -2                              # encoding: 
[0x27,0x00,0x02,0x00,0xfe,0xff,0xff,0xff]
 ; V4-NEXT:  exit
 ; NO-HMUL-LABEL: shmul_ri:
-; NO-HMUL-NOT:   uh*=
-; NO-HMUL-NOT:   sh*=
 ; NO-HMUL:       exit
   %awide = sext i64 %a to i128
   %product = mul i128 %awide, -2

>From 550a84f6f59888e34d9b01167aa903a9acb96545 Mon Sep 17 00:00:00 2001
From: Yazhou Tang <[email protected]>
Date: Tue, 20 Oct 2026 19:16:32 +0800
Subject: [PATCH 3/4] [BPF] Introduce cpu v5 for high-half multiply

Introduce -mcpu=v5 for UHMUL/SHMUL while preserving v4 code generation. Update 
Clang CPU support, feature macros, and tests, retaining -disable-hmul.

Suggested by Alexei Starovoitov: 
https://lore.kernel.org/bpf/[email protected]/
---
 clang/docs/ReleaseNotes.md                    |  5 ++
 clang/lib/Basic/Targets/BPF.cpp               |  7 ++-
 clang/lib/Basic/Targets/BPF.h                 |  2 +-
 clang/test/Misc/target-invalid-cpu-note/bpf.c |  1 +
 .../test/Preprocessor/bpf-predefined-macros.c | 29 +++++++++++-
 llvm/docs/ReleaseNotes.md                     |  6 +++
 llvm/lib/Target/BPF/BPF.td                    |  1 +
 llvm/lib/Target/BPF/BPFSubtarget.cpp          |  4 +-
 llvm/lib/Target/BPF/BPFSubtarget.h            |  5 +-
 .../CodeGen/BPF/assembler-disassembler-v4.s   |  9 ----
 .../CodeGen/BPF/assembler-disassembler-v5.s   | 12 +++++
 llvm/test/CodeGen/BPF/hmul.ll                 | 46 ++++++++++---------
 llvm/test/CodeGen/BPF/sdiv_smod.ll            |  1 +
 llvm/test/MC/BPF/bad-hmul.s                   |  2 +-
 14 files changed, 90 insertions(+), 40 deletions(-)
 create mode 100644 llvm/test/CodeGen/BPF/assembler-disassembler-v5.s

diff --git a/clang/docs/ReleaseNotes.md b/clang/docs/ReleaseNotes.md
index 830109b8c4a399..f2105d09f73eef 100644
--- a/clang/docs/ReleaseNotes.md
+++ b/clang/docs/ReleaseNotes.md
@@ -1134,6 +1134,11 @@ features cannot lower the translation-unit ABI level;
   - `__builtin_amdgcn_fcmp`
   - `__builtin_amdgcn_fcmpf`
 
+#### BPF Support
+
+- Added `-mcpu=v5` and the `__BPF_FEATURE_HMUL` predefined macro for unsigned
+  and signed high-half multiply instructions.
+
 #### DirectX Support
 
 - `clang-dxc` and HLSL support are now enabled by default, following the
diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp
index 6efdd023b32d14..2c37d56186ce52 100644
--- a/clang/lib/Basic/Targets/BPF.cpp
+++ b/clang/lib/Basic/Targets/BPF.cpp
@@ -78,12 +78,15 @@ void BPFTargetInfo::getTargetDefines(const LangOptions 
&Opts,
     Builder.defineMacro("__BPF_FEATURE_ST");
     Builder.defineMacro("__BPF_FEATURE_LOAD_ACQ_STORE_REL");
     Builder.defineMacro("__BPF_FEATURE_GOTOX");
+  }
+
+  if (CpuVerNum >= 5) {
     Builder.defineMacro("__BPF_FEATURE_HMUL");
   }
 }
 
-static constexpr llvm::StringLiteral ValidCPUNames[] = {"generic", "v1", "v2",
-                                                        "v3", "v4", "probe"};
+static constexpr llvm::StringLiteral ValidCPUNames[] = {
+    "generic", "v1", "v2", "v3", "v4", "v5", "probe"};
 
 bool BPFTargetInfo::isValidCPUName(StringRef Name) const {
   return llvm::is_contained(ValidCPUNames, Name);
diff --git a/clang/lib/Basic/Targets/BPF.h b/clang/lib/Basic/Targets/BPF.h
index e51f37b851d481..73ab60339a311a 100644
--- a/clang/lib/Basic/Targets/BPF.h
+++ b/clang/lib/Basic/Targets/BPF.h
@@ -100,7 +100,7 @@ class LLVM_LIBRARY_VISIBILITY BPFTargetInfo : public 
TargetInfo {
   void fillValidCPUList(SmallVectorImpl<StringRef> &Values) const override;
 
   bool setCPU(StringRef Name) override {
-    if (Name == "v3" || Name == "v4") {
+    if (Name == "v3" || Name == "v4" || Name == "v5") {
       HasAlu32 = true;
     }
 
diff --git a/clang/test/Misc/target-invalid-cpu-note/bpf.c 
b/clang/test/Misc/target-invalid-cpu-note/bpf.c
index fe925f86cdd137..7f90e64ab16f16 100644
--- a/clang/test/Misc/target-invalid-cpu-note/bpf.c
+++ b/clang/test/Misc/target-invalid-cpu-note/bpf.c
@@ -10,6 +10,7 @@
 // CHECK-SAME: {{^}}, v2
 // CHECK-SAME: {{^}}, v3
 // CHECK-SAME: {{^}}, v4
+// CHECK-SAME: {{^}}, v5
 // CHECK-SAME: {{^}}, probe
 // CHECK-SAME: {{$}}
 
diff --git a/clang/test/Preprocessor/bpf-predefined-macros.c 
b/clang/test/Preprocessor/bpf-predefined-macros.c
index c81bfa871a440d..323c566ffd8f19 100644
--- a/clang/test/Preprocessor/bpf-predefined-macros.c
+++ b/clang/test/Preprocessor/bpf-predefined-macros.c
@@ -4,6 +4,8 @@
 // RUN: %clang -E -target bpfel -mcpu=v2 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V2 %s
 // RUN: %clang -E -target bpfel -mcpu=v3 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V3 %s
 // RUN: %clang -E -target bpfel -mcpu=v4 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V4 %s
+// RUN: %clang -E -target bpfel -mcpu=v5 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V5 %s
+// RUN: %clang -E -target bpfeb -mcpu=v5 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V5 %s
 // RUN: %clang -E -target bpfel -mcpu=generic -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_GENERIC %s
 // RUN: %clang -E -target bpfel -mcpu=probe -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_PROBE %s
 
@@ -34,6 +36,9 @@ int i;
 #if __BPF_CPU_VERSION__ == 4
 int j;
 #endif
+#if __BPF_CPU_VERSION__ == 5
+int aa;
+#endif
 #ifdef __BPF_FEATURE_JMP_EXT
 int k;
 #endif
@@ -83,7 +88,10 @@ int y;
 int z;
 #endif
 #ifdef __BPF_FEATURE_HMUL
-int aa;
+int ab;
+#endif
+#if __BPF_CPU_VERSION__ < 5 && defined(__BPF_FEATURE_HMUL)
+#error HMUL requires CPU v5 or later
 #endif
 
 // CHECK: int b;
@@ -114,35 +122,52 @@ int aa;
 // CPU_V4: int r;
 // CPU_V4: int s;
 
+// CPU_V5: int aa;
+// CPU_V5: int k;
+// CPU_V5: int l;
+// CPU_V5: int m;
+// CPU_V5: int n;
+// CPU_V5: int o;
+// CPU_V5: int p;
+// CPU_V5: int q;
+// CPU_V5: int r;
+// CPU_V5: int s;
+
 // CPU_V1: int t;
 // CPU_V2: int t;
 // CPU_V3: int t;
 // CPU_V4: int t;
+// CPU_V5: int t;
 
 // CPU_V1: int u;
 // CPU_V2: int u;
 // CPU_V3: int u;
 // CPU_V4: int u;
+// CPU_V5: int u;
 
 // CPU_V4: int v;
 // CPU_V4: int w;
+// CPU_V5: int v;
+// CPU_V5: int w;
 
 // CPU_V1: int x;
 // CPU_V2: int x;
 // CPU_V3: int x;
 // CPU_V4: int x;
+// CPU_V5: int x;
 
 // CPU_V1: int y;
 // CPU_V2: int y;
 // CPU_V3: int y;
 // CPU_V4: int y;
+// CPU_V5: int y;
 
 // CPU_V1: int z;
 // CPU_V2: int z;
 // CPU_V3: int z;
 // CPU_V4: int z;
 
-// CPU_V4: int aa;
+// CPU_V5: int ab;
 
 // CPU_GENERIC: int g;
 
diff --git a/llvm/docs/ReleaseNotes.md b/llvm/docs/ReleaseNotes.md
index 77d639d218ef20..9868f7fda4d44e 100644
--- a/llvm/docs/ReleaseNotes.md
+++ b/llvm/docs/ReleaseNotes.md
@@ -296,6 +296,12 @@ Makes programs 10x faster by doing Special New Thing.
 
 ### Changes to the AVR Backend
 
+### Changes to the BPF Backend
+
+* Added `-mcpu=v5`, which includes the v4 instruction set and enables unsigned
+  and signed high-half multiply instructions (`UHMUL` and `SHMUL`). Use
+  `-disable-hmul` to disable their generation.
+
 ### Changes to the DirectX Backend
 
 * The DirectX backend has been promoted from experimental to an official,
diff --git a/llvm/lib/Target/BPF/BPF.td b/llvm/lib/Target/BPF/BPF.td
index 1fc364dad9988f..f52c8eadf60fd2 100644
--- a/llvm/lib/Target/BPF/BPF.td
+++ b/llvm/lib/Target/BPF/BPF.td
@@ -39,6 +39,7 @@ def : Proc<"v1", []>;
 def : Proc<"v2", []>;
 def : Proc<"v3", [ALU32]>;
 def : Proc<"v4", [ALU32]>;
+def : Proc<"v5", [ALU32]>;
 def : Proc<"probe", []>;
 
 def BPFInstPrinter : AsmWriter {
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.cpp 
b/llvm/lib/Target/BPF/BPFSubtarget.cpp
index 4e9a19a235300a..dd8201e3b122b7 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.cpp
+++ b/llvm/lib/Target/BPF/BPFSubtarget.cpp
@@ -93,7 +93,7 @@ void BPFSubtarget::initSubtargetFeatures(StringRef CPU, 
StringRef FS) {
     HasAlu32 = true;
     return;
   }
-  if (CPU == "v4") {
+  if (CPU == "v4" || CPU == "v5") {
     HasJmpExt = true;
     HasJmp32 = true;
     HasAlu32 = true;
@@ -105,7 +105,7 @@ void BPFSubtarget::initSubtargetFeatures(StringRef CPU, 
StringRef FS) {
     HasStoreImm = !Disable_StoreImm;
     HasLoadAcqStoreRel = !Disable_load_acq_store_rel;
     HasGotox = !Disable_gotox;
-    HasHmul = !Disable_hmul;
+    HasHmul = CPU == "v5" && !Disable_hmul;
     return;
   }
 }
diff --git a/llvm/lib/Target/BPF/BPFSubtarget.h 
b/llvm/lib/Target/BPF/BPFSubtarget.h
index 4be57b424ece15..f7808facf0822e 100644
--- a/llvm/lib/Target/BPF/BPFSubtarget.h
+++ b/llvm/lib/Target/BPF/BPFSubtarget.h
@@ -68,7 +68,10 @@ class BPFSubtarget : public BPFGenSubtargetInfo {
 
   // whether cpu v4 insns are enabled.
   bool HasLdsx, HasMovsx, HasBswap, HasSdivSmod, HasGotol, HasStoreImm,
-      HasLoadAcqStoreRel, HasGotox, HasHmul;
+      HasLoadAcqStoreRel, HasGotox;
+
+  // whether cpu v5 insns are enabled.
+  bool HasHmul;
 
   std::unique_ptr<CallLowering> CallLoweringInfo;
   std::unique_ptr<InstructionSelector> InstSelector;
diff --git a/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s 
b/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s
index 90b709dabe67f9..c4949d5d1df5e3 100644
--- a/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s
+++ b/llvm/test/CodeGen/BPF/assembler-disassembler-v4.s
@@ -38,15 +38,6 @@ w2 = (s16)w4
 r1 s/= r3
 r2 s%= r4
 
-// CHECK: 2f 21 01 00 00 00 00 00     r1 uh*= r2
-// CHECK: 2f 43 02 00 00 00 00 00     r3 sh*= r4
-// CHECK: 27 05 01 00 fe ff ff ff     r5 uh*= -0x2
-// CHECK: 27 06 02 00 fd ff ff ff     r6 sh*= -0x3
-r1 uh*= r2
-r3 sh*= r4
-r5 uh*= -2
-r6 sh*= -3
-
 // CHECK: 3c 31 01 00 00 00 00 00     w1 s/= w3
 // CHECK: 9c 42 01 00 00 00 00 00     w2 s%= w4
 w1 s/= w3
diff --git a/llvm/test/CodeGen/BPF/assembler-disassembler-v5.s 
b/llvm/test/CodeGen/BPF/assembler-disassembler-v5.s
new file mode 100644
index 00000000000000..e51e0c7f3f6964
--- /dev/null
+++ b/llvm/test/CodeGen/BPF/assembler-disassembler-v5.s
@@ -0,0 +1,12 @@
+// RUN: llvm-mc -triple bpfel --mcpu=v5 --assemble --filetype=obj %s \
+// RUN:   | llvm-objdump -d --mattr=+alu32 - \
+// RUN:   | FileCheck %s
+
+// CHECK: 2f 21 01 00 00 00 00 00     r1 uh*= r2
+// CHECK: 2f 43 02 00 00 00 00 00     r3 sh*= r4
+// CHECK: 27 05 01 00 fe ff ff ff     r5 uh*= -0x2
+// CHECK: 27 06 02 00 fd ff ff ff     r6 sh*= -0x3
+r1 uh*= r2
+r3 sh*= r4
+r5 uh*= -2
+r6 sh*= -3
diff --git a/llvm/test/CodeGen/BPF/hmul.ll b/llvm/test/CodeGen/BPF/hmul.ll
index c44f29ced6aff7..42d358f9f4df37 100644
--- a/llvm/test/CodeGen/BPF/hmul.ll
+++ b/llvm/test/CodeGen/BPF/hmul.ll
@@ -1,14 +1,16 @@
-; RUN: llc -mtriple=bpfel -mcpu=v4 -verify-machineinstrs -show-mc-encoding < 
%s | FileCheck %s --check-prefix=V4
+; RUN: llc -mtriple=bpfel -mcpu=v5 -verify-machineinstrs -show-mc-encoding < 
%s | FileCheck %s --check-prefix=V5
 ; RUN: llc -mtriple=bpfel -mcpu=v3 -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=NO-HMUL --implicit-check-not="uh*=" 
--implicit-check-not="sh*="
-; RUN: llc -mtriple=bpfel -mcpu=v4 -disable-hmul -verify-machineinstrs < %s \
+; RUN: llc -mtriple=bpfel -mcpu=v4 -verify-machineinstrs < %s \
+; RUN:   | FileCheck %s --check-prefix=NO-HMUL --implicit-check-not="uh*=" 
--implicit-check-not="sh*="
+; RUN: llc -mtriple=bpfel -mcpu=v5 -disable-hmul -verify-machineinstrs < %s \
 ; RUN:   | FileCheck %s --check-prefix=NO-HMUL --implicit-check-not="uh*=" 
--implicit-check-not="sh*="
 
 define i64 @uhmul_rr(i64 %a, i64 %b) {
-; V4-LABEL: uhmul_rr:
-; V4:       r0 = r1
-; V4-NEXT:  r0 uh*= r2                              # encoding: 
[0x2f,0x20,0x01,0x00,0x00,0x00,0x00,0x00]
-; V4-NEXT:  exit
+; V5-LABEL: uhmul_rr:
+; V5:       r0 = r1
+; V5-NEXT:  r0 uh*= r2                              # encoding: 
[0x2f,0x20,0x01,0x00,0x00,0x00,0x00,0x00]
+; V5-NEXT:  exit
 ; NO-HMUL-LABEL: uhmul_rr:
 ; NO-HMUL:       call __multi3
 ; NO-HMUL:       exit
@@ -21,10 +23,10 @@ define i64 @uhmul_rr(i64 %a, i64 %b) {
 }
 
 define i64 @shmul_rr(i64 %a, i64 %b) {
-; V4-LABEL: shmul_rr:
-; V4:       r0 = r1
-; V4-NEXT:  r0 sh*= r2                              # encoding: 
[0x2f,0x20,0x02,0x00,0x00,0x00,0x00,0x00]
-; V4-NEXT:  exit
+; V5-LABEL: shmul_rr:
+; V5:       r0 = r1
+; V5-NEXT:  r0 sh*= r2                              # encoding: 
[0x2f,0x20,0x02,0x00,0x00,0x00,0x00,0x00]
+; V5-NEXT:  exit
 ; NO-HMUL-LABEL: shmul_rr:
 ; NO-HMUL:       call __multi3
 ; NO-HMUL:       exit
@@ -37,10 +39,10 @@ define i64 @shmul_rr(i64 %a, i64 %b) {
 }
 
 define i64 @uhmul_ri(i64 %a) {
-; V4-LABEL: uhmul_ri:
-; V4:       r0 = r1
-; V4-NEXT:  r0 uh*= -2                              # encoding: 
[0x27,0x00,0x01,0x00,0xfe,0xff,0xff,0xff]
-; V4-NEXT:  exit
+; V5-LABEL: uhmul_ri:
+; V5:       r0 = r1
+; V5-NEXT:  r0 uh*= -2                              # encoding: 
[0x27,0x00,0x01,0x00,0xfe,0xff,0xff,0xff]
+; V5-NEXT:  exit
 ; NO-HMUL-LABEL: uhmul_ri:
 ; NO-HMUL:       call __multi3
 ; NO-HMUL:       exit
@@ -52,10 +54,10 @@ define i64 @uhmul_ri(i64 %a) {
 }
 
 define i64 @shmul_ri(i64 %a) {
-; V4-LABEL: shmul_ri:
-; V4:       r0 = r1
-; V4-NEXT:  r0 sh*= -2                              # encoding: 
[0x27,0x00,0x02,0x00,0xfe,0xff,0xff,0xff]
-; V4-NEXT:  exit
+; V5-LABEL: shmul_ri:
+; V5:       r0 = r1
+; V5-NEXT:  r0 sh*= -2                              # encoding: 
[0x27,0x00,0x02,0x00,0xfe,0xff,0xff,0xff]
+; V5-NEXT:  exit
 ; NO-HMUL-LABEL: shmul_ri:
 ; NO-HMUL:       exit
   %awide = sext i64 %a to i128
@@ -66,10 +68,10 @@ define i64 @shmul_ri(i64 %a) {
 }
 
 define i64 @mul_low(i64 %a, i64 %b) {
-; V4-LABEL: mul_low:
-; V4:       r0 = r1
-; V4-NEXT:  r0 *= r2                                # encoding: 
[0x2f,0x20,0x00,0x00,0x00,0x00,0x00,0x00]
-; V4-NEXT:  exit
+; V5-LABEL: mul_low:
+; V5:       r0 = r1
+; V5-NEXT:  r0 *= r2                                # encoding: 
[0x2f,0x20,0x00,0x00,0x00,0x00,0x00,0x00]
+; V5-NEXT:  exit
 ; NO-HMUL-LABEL: mul_low:
 ; NO-HMUL:       r0 *= r2
   %product = mul i64 %a, %b
diff --git a/llvm/test/CodeGen/BPF/sdiv_smod.ll 
b/llvm/test/CodeGen/BPF/sdiv_smod.ll
index 5fb23d03f172db..6d921d683c66c3 100644
--- a/llvm/test/CodeGen/BPF/sdiv_smod.ll
+++ b/llvm/test/CodeGen/BPF/sdiv_smod.ll
@@ -1,4 +1,5 @@
 ; RUN: llc -mtriple=bpfel -mcpu=v4 -verify-machineinstrs -show-mc-encoding < 
%s | FileCheck %s
+; RUN: llc -mtriple=bpfel -mcpu=v5 -verify-machineinstrs -show-mc-encoding < 
%s | FileCheck %s
 ; Source:
 ;  int foo(int a, int b, int c) {
 ;    return a/b + a%c;
diff --git a/llvm/test/MC/BPF/bad-hmul.s b/llvm/test/MC/BPF/bad-hmul.s
index e98e30f406c425..ae163662eefea7 100644
--- a/llvm/test/MC/BPF/bad-hmul.s
+++ b/llvm/test/MC/BPF/bad-hmul.s
@@ -1,4 +1,4 @@
-# RUN: not llvm-mc -mcpu=v4 -triple bpfel < %s 2>&1 \
+# RUN: not llvm-mc -mcpu=v5 -triple bpfel < %s 2>&1 \
 # RUN:   | grep 'error: invalid operand for instruction' \
 # RUN:   | count 2
         w1 uh*= w2

>From 7292bbcb8b60e90707a41d25894c00f7c8666d22 Mon Sep 17 00:00:00 2001
From: Yazhou Tang <[email protected]>
Date: Wed, 21 Oct 2026 16:55:49 +0800
Subject: [PATCH 4/4] [BPF][test] Remove redundant big-endian v5 macro test

---
 clang/test/Preprocessor/bpf-predefined-macros.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/clang/test/Preprocessor/bpf-predefined-macros.c 
b/clang/test/Preprocessor/bpf-predefined-macros.c
index 323c566ffd8f19..f1379de8f7f422 100644
--- a/clang/test/Preprocessor/bpf-predefined-macros.c
+++ b/clang/test/Preprocessor/bpf-predefined-macros.c
@@ -5,7 +5,6 @@
 // RUN: %clang -E -target bpfel -mcpu=v3 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V3 %s
 // RUN: %clang -E -target bpfel -mcpu=v4 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V4 %s
 // RUN: %clang -E -target bpfel -mcpu=v5 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V5 %s
-// RUN: %clang -E -target bpfeb -mcpu=v5 -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_V5 %s
 // RUN: %clang -E -target bpfel -mcpu=generic -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_GENERIC %s
 // RUN: %clang -E -target bpfel -mcpu=probe -x c -o - %s | FileCheck 
-check-prefix=CHECK -check-prefix=CPU_PROBE %s
 

_______________________________________________
cfe-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to