[clang] [llvm] [BPF] Add support for may_goto insn (PR #85358)

via cfe-commits cfe-commits at lists.llvm.org
Thu Mar 14 21:03:19 PDT 2024


https://github.com/yonghong-song created https://github.com/llvm/llvm-project/pull/85358

Alexei added may_goto insn in [1]. The asm syntax for may_goto looks like
  may_goto <label>

The instruction represents a conditional branch but the condition is implicit. Later in bpf kernel verifier, the 'may_goto <label>' insn will be rewritten with an explicit condition. The encoding of 'may_goto' insn is enforced in [2] and is also implemented in this patch.

In [3], 'may_goto' insn is encoded with raw bytes. I made the following change
```
  --- a/tools/testing/selftests/bpf/bpf_experimental.h
  +++ b/tools/testing/selftests/bpf/bpf_experimental.h
  @@ -328,10 +328,7 @@ l_true:                                                                                            \

   #define cond_break                                     \
          ({ __label__ l_break, l_continue;               \
  -        asm volatile goto("1:.byte 0xe5;                       \
  -                     .byte 0;                          \
  -                     .long ((%l[l_break] - 1b - 8) / 8) & 0xffff;      \
  -                     .short 0"                         \
  +        asm volatile goto("may_goto %l[l_break]"       \
                        :::: l_break);                    \
          goto l_continue;                                \
          l_break: break;
```
and ran the selftest with the latest llvm with this patch. All tests are passed.

  [1] https://lore.kernel.org/bpf/20240306031929.42666-1-alexei.starovoitov@gmail.com/
  [2] https://lore.kernel.org/bpf/20240306031929.42666-2-alexei.starovoitov@gmail.com/
  [3] https://lore.kernel.org/bpf/20240306031929.42666-4-alexei.starovoitov@gmail.com/

>From 98e0602539ecc28055e55f2f9ce1c3f7f9e8ddb2 Mon Sep 17 00:00:00 2001
From: Yonghong Song <yonghong.song at linux.dev>
Date: Thu, 14 Mar 2024 19:53:35 -0700
Subject: [PATCH] [BPF] Add support for may_goto insn

Alexei added may_goto insn in [1]. The asm syntax for may_goto looks like
  may_goto <label>

The instruction represents a conditional branch but the condition is implicit.
Later in bpf kernel verifier, the 'may_goto <label>' insn will be rewritten
with an explicit condition. The encoding of 'may_goto' insn is enforced
in [2] and is also implemented in this patch.

In [3], 'may_goto' insn is encoded with raw bytes. I made the following change
  --- a/tools/testing/selftests/bpf/bpf_experimental.h
  +++ b/tools/testing/selftests/bpf/bpf_experimental.h
  @@ -328,10 +328,7 @@ l_true:                                                                                            \

   #define cond_break                                     \
          ({ __label__ l_break, l_continue;               \
  -        asm volatile goto("1:.byte 0xe5;                       \
  -                     .byte 0;                          \
  -                     .long ((%l[l_break] - 1b - 8) / 8) & 0xffff;      \
  -                     .short 0"                         \
  +        asm volatile goto("may_goto %l[l_break]"       \
                        :::: l_break);                    \
          goto l_continue;                                \
          l_break: break;
and ran the selftest with the latest llvm with this patch. All tests are passed.

  [1] https://lore.kernel.org/bpf/20240306031929.42666-1-alexei.starovoitov@gmail.com/
  [2] https://lore.kernel.org/bpf/20240306031929.42666-2-alexei.starovoitov@gmail.com/
  [3] https://lore.kernel.org/bpf/20240306031929.42666-4-alexei.starovoitov@gmail.com/

Signed-off-by: Yonghong Song <yonghong.song at linux.dev>
---
 clang/lib/Basic/Targets/BPF.cpp                     |  1 +
 llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp      |  1 +
 llvm/lib/Target/BPF/BPFInstrFormats.td              |  1 +
 llvm/lib/Target/BPF/BPFInstrInfo.td                 | 13 +++++++++++++
 .../lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp |  5 ++++-
 llvm/test/MC/BPF/insn-unit.s                        |  2 ++
 6 files changed, 22 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Basic/Targets/BPF.cpp b/clang/lib/Basic/Targets/BPF.cpp
index a90398a362d10a..b5ba11a3bdca9d 100644
--- a/clang/lib/Basic/Targets/BPF.cpp
+++ b/clang/lib/Basic/Targets/BPF.cpp
@@ -45,6 +45,7 @@ void BPFTargetInfo::getTargetDefines(const LangOptions &Opts,
 
   std::string CpuVerNumStr = CPU.substr(1);
   Builder.defineMacro("__BPF_CPU_VERSION__", CpuVerNumStr);
+  Builder.defineMacro("__BPF_FEATURE_MAY_GOTO");
 
   int CpuVerNum = std::stoi(CpuVerNumStr);
   if (CpuVerNum >= 2)
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
index 3145bc3d19f5dc..1688355f427cc7 100644
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -232,6 +232,7 @@ struct BPFOperand : public MCParsedAsmOperand {
         .Case("callx", true)
         .Case("goto", true)
         .Case("gotol", true)
+        .Case("may_goto", true)
         .Case("*", true)
         .Case("exit", true)
         .Case("lock", true)
diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td
index 6ed83d877ac0f2..feffdbc69465ea 100644
--- a/llvm/lib/Target/BPF/BPFInstrFormats.td
+++ b/llvm/lib/Target/BPF/BPFInstrFormats.td
@@ -73,6 +73,7 @@ def BPF_JLT  : BPFJumpOp<0xa>;
 def BPF_JLE  : BPFJumpOp<0xb>;
 def BPF_JSLT : BPFJumpOp<0xc>;
 def BPF_JSLE : BPFJumpOp<0xd>;
+def BPF_JCOND : BPFJumpOp<0xe>;
 
 class BPFWidthModifer<bits<2> val> {
   bits<2> Value = val;
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 7198e9499bc32a..66c57952a7f10e 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -215,6 +215,18 @@ class JMP_RI<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
   let BPFClass = BPF_JMP;
 }
 
+class JMP_JCOND<BPFJumpOp Opc, string OpcodeStr, list<dag> Pattern>
+    : TYPE_ALU_JMP<Opc.Value, BPF_K.Value,
+                   (outs),
+                   (ins brtarget:$BrDst),
+                   !strconcat(OpcodeStr, " $BrDst"),
+                   Pattern> {
+  bits<16> BrDst;
+
+  let Inst{47-32} = BrDst;
+  let BPFClass = BPF_JMP;
+}
+
 class JMP_RR_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
     : TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
                    (outs),
@@ -267,6 +279,7 @@ defm JULE : J<BPF_JLE, "<=", BPF_CC_LEU, BPF_CC_LEU_32>;
 defm JSLT : J<BPF_JSLT, "s<", BPF_CC_LT, BPF_CC_LT_32>;
 defm JSLE : J<BPF_JSLE, "s<=", BPF_CC_LE, BPF_CC_LE_32>;
 defm JSET : J<BPF_JSET, "&", NoCond, NoCond>;
+def JCOND : JMP_JCOND<BPF_JCOND, "may_goto", []>;
 }
 
 // ALU instructions
diff --git a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
index 7dad40803d4770..44932383fb43e9 100644
--- a/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
+++ b/llvm/lib/Target/BPF/MCTargetDesc/BPFMCTargetDesc.cpp
@@ -81,7 +81,10 @@ class BPFMCInstrAnalysis : public MCInstrAnalysis {
     // The target is the 3rd operand of cond inst and the 1st of uncond inst.
     int32_t Imm;
     if (isConditionalBranch(Inst)) {
-      Imm = (short)Inst.getOperand(2).getImm();
+      if (Inst.getOpcode() == BPF::JCOND)
+        Imm = (short)Inst.getOperand(0).getImm();
+      else
+        Imm = (short)Inst.getOperand(2).getImm();
     } else if (isUnconditionalBranch(Inst)) {
       if (Inst.getOpcode() == BPF::JMP)
         Imm = (short)Inst.getOperand(0).getImm();
diff --git a/llvm/test/MC/BPF/insn-unit.s b/llvm/test/MC/BPF/insn-unit.s
index 224eb7381aa234..84735d196030d6 100644
--- a/llvm/test/MC/BPF/insn-unit.s
+++ b/llvm/test/MC/BPF/insn-unit.s
@@ -65,8 +65,10 @@
 // CHECK: 8d 02 00 00 00 00 00 00 	callx r2
 
 // ======== BPF_JMP Class ========
+  may_goto Llabel0 // BPF_JCOND | BPF_K
   if r1 & r2 goto Llabel0    // BPF_JSET  | BPF_X
   if r1 & 0xffff goto Llabel0    // BPF_JSET  | BPF_K
+// CHECK: e5 00 1e 00 00 00 00 00	may_goto +30
 // CHECK: 4d 21 1d 00 00 00 00 00 	if r1 & r2 goto +29
 // CHECK: 45 01 1c 00 ff ff 00 00 	if r1 & 65535 goto +28
 



More information about the cfe-commits mailing list