Skip to content

[BPF] Add asm support for JSET insn #73161

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 28, 2023
Merged

Conversation

yonghong-song
Copy link
Contributor

BPF upstream reported that JSET insn is not supported in inline asm ([1]). BPF_JSET insn is part of BPF ISA so let us add asm support for it now.

[1] https://lore.kernel.org/bpf/[email protected]/

@llvmbot llvmbot added the mc Machine (object) code label Nov 22, 2023
@llvmbot
Copy link
Member

llvmbot commented Nov 22, 2023

@llvm/pr-subscribers-mc

Author: None (yonghong-song)

Changes

BPF upstream reported that JSET insn is not supported in inline asm ([1]). BPF_JSET insn is part of BPF ISA so let us add asm support for it now.

[1] https://lore.kernel.org/bpf/2e8a1584-a289-4b2e-800c-8b463e734bcb@linux.dev/


Full diff: https://github.com/llvm/llvm-project/pull/73161.diff

4 Files Affected:

  • (modified) llvm/lib/Target/BPF/BPFInstrFormats.td (+1)
  • (modified) llvm/lib/Target/BPF/BPFInstrInfo.td (+68)
  • (modified) llvm/test/MC/BPF/insn-unit-32.s (+5)
  • (modified) llvm/test/MC/BPF/insn-unit.s (+5)
diff --git a/llvm/lib/Target/BPF/BPFInstrFormats.td b/llvm/lib/Target/BPF/BPFInstrFormats.td
index 841d97efc01c5c1..6ed83d877ac0f23 100644
--- a/llvm/lib/Target/BPF/BPFInstrFormats.td
+++ b/llvm/lib/Target/BPF/BPFInstrFormats.td
@@ -63,6 +63,7 @@ def BPF_JA   : BPFJumpOp<0x0>;
 def BPF_JEQ  : BPFJumpOp<0x1>;
 def BPF_JGT  : BPFJumpOp<0x2>;
 def BPF_JGE  : BPFJumpOp<0x3>;
+def BPF_JSET : BPFJumpOp<0x4>;
 def BPF_JNE  : BPFJumpOp<0x5>;
 def BPF_JSGT : BPFJumpOp<0x6>;
 def BPF_JSGE : BPFJumpOp<0x7>;
diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 305cbbd34d2707d..9e75f35efe70cb3 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -246,6 +246,70 @@ class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
   let BPFClass = BPF_JMP32;
 }
 
+class JSET_RR<string OpcodeStr>
+    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value,
+                   (outs),
+                   (ins GPR:$dst, GPR:$src, brtarget:$BrDst),
+                   "if $dst "#OpcodeStr#" $src goto $BrDst",
+                   []> {
+  bits<4> dst;
+  bits<4> src;
+  bits<16> BrDst;
+
+  let Inst{55-52} = src;
+  let Inst{51-48} = dst;
+  let Inst{47-32} = BrDst;
+  let BPFClass = BPF_JMP;
+}
+
+class JSET_RI<string OpcodeStr>
+    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value,
+                   (outs),
+                   (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst),
+                   "if $dst "#OpcodeStr#" $imm goto $BrDst",
+                   []> {
+  bits<4> dst;
+  bits<16> BrDst;
+  bits<32> imm;
+
+  let Inst{51-48} = dst;
+  let Inst{47-32} = BrDst;
+  let Inst{31-0} = imm;
+  let BPFClass = BPF_JMP;
+}
+
+class JSET_RR_32<string OpcodeStr>
+    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value,
+                   (outs),
+                   (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst),
+                   "if $dst "#OpcodeStr#" $src goto $BrDst",
+                   []> {
+  bits<4> dst;
+  bits<4> src;
+  bits<16> BrDst;
+
+  let Inst{55-52} = src;
+  let Inst{51-48} = dst;
+  let Inst{47-32} = BrDst;
+  let BPFClass = BPF_JMP32;
+}
+
+class JSET_RI_32<string OpcodeStr>
+    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value,
+                   (outs),
+                   (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst),
+                   "if $dst "#OpcodeStr#" $imm goto $BrDst",
+                   []> {
+  bits<4> dst;
+  bits<16> BrDst;
+  bits<32> imm;
+
+  let Inst{51-48} = dst;
+  let Inst{47-32} = BrDst;
+  let Inst{31-0} = imm;
+  let BPFClass = BPF_JMP32;
+}
+
 multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> {
   def _rr : JMP_RR<Opc, OpcodeStr, Cond>;
   def _ri : JMP_RI<Opc, OpcodeStr, Cond>;
@@ -265,6 +329,10 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>;
 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>;
+def JSET_RR    : JSET_RR<"&">;
+def JSET_RI    : JSET_RI<"&">;
+def JSET_RR_32 : JSET_RR_32<"&">;
+def JSET_RI_32 : JSET_RI_32<"&">;
 }
 
 // ALU instructions
diff --git a/llvm/test/MC/BPF/insn-unit-32.s b/llvm/test/MC/BPF/insn-unit-32.s
index e53c686a4fa3e33..09b89d72e507c0e 100644
--- a/llvm/test/MC/BPF/insn-unit-32.s
+++ b/llvm/test/MC/BPF/insn-unit-32.s
@@ -55,6 +55,11 @@
 // CHECK: b4 09 00 00 ff ff ff ff      w9 = -1
 // CHECK: c4 0a 00 00 40 00 00 00      w10 s>>= 64
 
+  if w1 & w2 goto Llabel0    // BPF_JSET | BPF_X
+  if w1 & 0xff goto Llabel0  // BPF_JSET | BPF_K
+// CHECK: 4e 21 0d 00 00 00 00 00      if w1 & w2 goto +13
+// CHECK: 46 01 0c 00 ff 00 00 00      if w1 & 255 goto +12
+
   if w0 == w1 goto Llabel0   // BPF_JEQ  | BPF_X
   if w3 != w4 goto Llabel0   // BPF_JNE  | BPF_X
 // CHECK: 1e 10 0b 00 00 00 00 00 	if w0 == w1 goto +11
diff --git a/llvm/test/MC/BPF/insn-unit.s b/llvm/test/MC/BPF/insn-unit.s
index 94c46e9013bac78..58342cda7cc0ad0 100644
--- a/llvm/test/MC/BPF/insn-unit.s
+++ b/llvm/test/MC/BPF/insn-unit.s
@@ -62,6 +62,11 @@
 // CHECK: db a3 e2 ff 00 00 00 00 	lock *(u64 *)(r3 - 30) += r10
 
 // ======== BPF_JMP Class ========
+  if r1 & r2 goto Llabel0    // BPF_JSET  | BPF_X
+  if r1 & 0xffff goto Llabel0    // BPF_JSET  | BPF_K
+// 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
+
   goto Llabel0               // BPF_JA
   call 1                     // BPF_CALL
   exit                       // BPF_EXIT

@yonghong-song
Copy link
Contributor Author

cc @4ast @anakryiko @jemarch

@yonghong-song
Copy link
Contributor Author

linux succeeded and windows failed. The windows failure message:

FAILED: bin/llvm-link.exe
cmd.exe /C "cd . && C:\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe -E vs_link_exe --intdir=tools\llvm-link\CMakeFiles\llvm-link.dir --rc="C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\rc.exe" --mt="C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\mt.exe" --manifests  -- C:\BuildTools\VC\Tools\MSVC\14.29.30133\bin\Hostx64\x64\link.exe /nologo tools\llvm-link\CMakeFiles\llvm-link.dir\llvm-link.cpp.obj tools\llvm-link\CMakeFiles\llvm-link.dir\__\__\resources\windows_version_resource.rc.res  /out:bin\llvm-link.exe /implib:lib\llvm-link.lib /pdb:bin\llvm-link.pdb /version:0.0 /machine:x64 /STACK:10000000 /INCREMENTAL:NO /subsystem:console  lib\LLVMBinaryFormat.lib  lib\LLVMBitReader.lib  lib\LLVMBitWriter.lib  lib\LLVMCore.lib  lib\LLVMIRReader.lib  lib\LLVMLinker.lib  lib\LLVMObject.lib  lib\LLVMSupport.lib  lib\LLVMTransformUtils.lib  lib\LLVMipo.lib  lib\LLVMBitWriter.lib  lib\LLVMLinker.lib  lib\LLVMFrontendOpenMP.lib  lib\LLVMFrontendOffloading.lib  lib\LLVMScalarOpts.lib  lib\LLVMAggressiveInstCombine.lib  lib\LLVMInstCombine.lib  lib\LLVMVectorize.lib  lib\LLVMInstrumentation.lib  lib\LLVMTransformUtils.lib  lib\LLVMAnalysis.lib  lib\LLVMProfileData.lib  lib\LLVMSymbolize.lib  lib\LLVMDebugInfoPDB.lib  "C:\BuildTools\DIA SDK\lib\amd64\diaguids.lib"  lib\LLVMDebugInfoMSF.lib  lib\LLVMDebugInfoBTF.lib  lib\LLVMDebugInfoDWARF.lib  lib\LLVMObject.lib  lib\LLVMIRReader.lib  lib\LLVMBitReader.lib  lib\LLVMAsmParser.lib  lib\LLVMCore.lib  lib\LLVMRemarks.lib  lib\LLVMBitstreamReader.lib  lib\LLVMMCParser.lib  lib\LLVMMC.lib  lib\LLVMDebugInfoCodeView.lib  lib\LLVMTextAPI.lib  lib\LLVMBinaryFormat.lib  lib\LLVMTargetParser.lib  lib\LLVMSupport.lib  lib\LLVMDemangle.lib  psapi.lib  shell32.lib  ole32.lib  uuid.lib  advapi32.lib  delayimp.lib  -delayload:shell32.dll  -delayload:ole32.dll  kernel32.lib user32.lib gdi32.lib winspool.lib shell32.lib ole32.lib oleaut32.lib uuid.lib comdlg32.lib advapi32.lib && cd ."
MT: command "C:\Program Files (x86)\Windows Kits\10\bin\10.0.19041.0\x64\mt.exe /nologo /manifest bin\llvm-link.exe.manifest /outputresource:bin\llvm-link.exe;#1" failed (exit code 0x1f) with the following output:
mt.exe : general error c101008d: Failed to write the updated manifest to the resource of file "bin\llvm-link.exe". Operation did not complete successfully because the file contains a virus or potentially unwanted software.

I do not think this is a problem from this patch. Let me rebase and run again.

Copy link
Member

@4ast 4ast left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

lgtm

@eddyz87
Copy link
Contributor

eddyz87 commented Nov 27, 2023

Looks good as is, but I have a suggestion to minimize code duplication, seems to pass all tests.
Feel free to ignore if you think it's too hacky.

diff --git a/llvm/lib/Target/BPF/BPFInstrInfo.td b/llvm/lib/Target/BPF/BPFInstrInfo.td
index 9e75f35efe70..7a440cf94f5d 100644
--- a/llvm/lib/Target/BPF/BPFInstrInfo.td
+++ b/llvm/lib/Target/BPF/BPFInstrInfo.td
@@ -181,13 +181,18 @@ class TYPE_LD_ST<bits<3> mode, bits<2> size,
   let Inst{60-59} = size;
 }
 
+class NoCond : PatLeaf<(vt)> {}
+
 // jump instructions
 class JMP_RR<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
     : TYPE_ALU_JMP<Opc.Value, BPF_X.Value,
                    (outs),
                    (ins GPR:$dst, GPR:$src, brtarget:$BrDst),
                    "if $dst "#OpcodeStr#" $src goto $BrDst",
-                   [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)]> {
+                   !if(!isa<NoCond>(Cond),
+                       [],
+                       [(BPFbrcc i64:$dst, i64:$src, Cond, bb:$BrDst)])>
+{
   bits<4> dst;
   bits<4> src;
   bits<16> BrDst;
@@ -246,70 +251,6 @@ class JMP_RI_32<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond>
   let BPFClass = BPF_JMP32;
 }
 
-class JSET_RR<string OpcodeStr>
-    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value,
-                   (outs),
-                   (ins GPR:$dst, GPR:$src, brtarget:$BrDst),
-                   "if $dst "#OpcodeStr#" $src goto $BrDst",
-                   []> {
-  bits<4> dst;
-  bits<4> src;
-  bits<16> BrDst;
-
-  let Inst{55-52} = src;
-  let Inst{51-48} = dst;
-  let Inst{47-32} = BrDst;
-  let BPFClass = BPF_JMP;
-}
-
-class JSET_RI<string OpcodeStr>
-    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value,
-                   (outs),
-                   (ins GPR:$dst, i64imm:$imm, brtarget:$BrDst),
-                   "if $dst "#OpcodeStr#" $imm goto $BrDst",
-                   []> {
-  bits<4> dst;
-  bits<16> BrDst;
-  bits<32> imm;
-
-  let Inst{51-48} = dst;
-  let Inst{47-32} = BrDst;
-  let Inst{31-0} = imm;
-  let BPFClass = BPF_JMP;
-}
-
-class JSET_RR_32<string OpcodeStr>
-    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_X.Value,
-                   (outs),
-                   (ins GPR32:$dst, GPR32:$src, brtarget:$BrDst),
-                   "if $dst "#OpcodeStr#" $src goto $BrDst",
-                   []> {
-  bits<4> dst;
-  bits<4> src;
-  bits<16> BrDst;
-
-  let Inst{55-52} = src;
-  let Inst{51-48} = dst;
-  let Inst{47-32} = BrDst;
-  let BPFClass = BPF_JMP32;
-}
-
-class JSET_RI_32<string OpcodeStr>
-    : TYPE_ALU_JMP<BPF_JSET.Value, BPF_K.Value,
-                   (outs),
-                   (ins GPR32:$dst, i32imm:$imm, brtarget:$BrDst),
-                   "if $dst "#OpcodeStr#" $imm goto $BrDst",
-                   []> {
-  bits<4> dst;
-  bits<16> BrDst;
-  bits<32> imm;
-
-  let Inst{51-48} = dst;
-  let Inst{47-32} = BrDst;
-  let Inst{31-0} = imm;
-  let BPFClass = BPF_JMP32;
-}
-
 multiclass J<BPFJumpOp Opc, string OpcodeStr, PatLeaf Cond, PatLeaf Cond32> {
   def _rr : JMP_RR<Opc, OpcodeStr, Cond>;
   def _ri : JMP_RI<Opc, OpcodeStr, Cond>;
@@ -329,10 +270,7 @@ defm JULT : J<BPF_JLT, "<", BPF_CC_LTU, BPF_CC_LTU_32>;
 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>;
-def JSET_RR    : JSET_RR<"&">;
-def JSET_RI    : JSET_RI<"&">;
-def JSET_RR_32 : JSET_RR_32<"&">;
-def JSET_RI_32 : JSET_RI_32<"&">;
+defm JSET : J<BPF_JSET, "&", NoCond<>, NoCond<>>;
 }
 
 // ALU instructions

BPF upstream reported that JSET insn is not supported in inline asm ([1]).
BPF_JSET insn is part of BPF ISA so let us add asm support for it now.

  [1] https://lore.kernel.org/bpf/[email protected]/
@yonghong-song
Copy link
Contributor Author

Thanks @eddyz87 Your suggestion looks good. I made the change (slightly different from yours) and the patch is much smaller now. In your original suggestion, JMP_RR specialization is not really needed. Thanks!

@yonghong-song yonghong-song merged commit e247e6f into llvm:main Nov 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
mc Machine (object) code
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants