public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: David Faust <david.faust@oracle.com>
To: gcc-patches@gcc.gnu.org
Subject: [PATCH 1/3] bpf: add -mcpu and related feature options
Date: Thu,  9 Sep 2021 14:36:43 -0700	[thread overview]
Message-ID: <20210909213645.11605-2-david.faust@oracle.com> (raw)
In-Reply-To: <20210909213645.11605-1-david.faust@oracle.com>

New instructions have been added over time to the eBPF ISA, but
previously there has been no good method to select which version to
target in GCC.

This patch adds the following options to the BPF backend:

  -mcpu={v1, v2, v3}
    Select which version of the eBPF ISA to target. This enables or
    disables generation of certain instructions. The default is v3.

  -mjmpext
    Enable extra conditional branch instructions.
    Enabled for CPU v2 and above.

  -mjmp32
    Enable 32-bit jump/branch instructions.
    Enabled for CPU v3 and above.

  -malu32
    Enable 32-bit ALU instructions.
    Enabled for CPU v3 and above.

gcc/ChangeLog:
	* config/bpf/bpf-opts.h (bpf_isa_version): New enum.
	* config/bpf/bpf-protos.h (bpf_expand_cbranch): New.
	* config/bpf/bpf.c (bpf_option_override): Handle -mcpu option.
	(bpf_expand_cbranch): New function.
	* config/bpf/bpf.md (AM mode iterator): Conditionalize support for SI
	mode.
	(zero_extendsidi2): Only use mov32 instruction if it is available.
	(SIM mode iterator): Conditionalize support for SI mode.
	(JM mode iterator): New.
	(cbranchdi4): Update name, use new JM iterator. Use bpf_expand_cbranch.
	(*branch_on_di): Update name, use new JM iterator.
	* config/bpf/bpf.opt: (mjmpext): New option.
	(malu32): Likewise.
	(mjmp32): Likewise.
	(mcpu): Likewise.
	(bpf_isa): New enum.
---
 gcc/config/bpf/bpf-opts.h   |  7 ++++++
 gcc/config/bpf/bpf-protos.h |  1 +
 gcc/config/bpf/bpf.c        | 41 ++++++++++++++++++++++++++++++++++
 gcc/config/bpf/bpf.md       | 44 ++++++++++++++++++++-----------------
 gcc/config/bpf/bpf.opt      | 29 ++++++++++++++++++++++++
 5 files changed, 102 insertions(+), 20 deletions(-)

diff --git a/gcc/config/bpf/bpf-opts.h b/gcc/config/bpf/bpf-opts.h
index 1bc930cd194..456e39c2200 100644
--- a/gcc/config/bpf/bpf-opts.h
+++ b/gcc/config/bpf/bpf-opts.h
@@ -53,4 +53,11 @@ enum bpf_kernel_version
   LINUX_NATIVE,
 };
 
+enum bpf_isa_version
+{
+  ISA_V1,
+  ISA_V2,
+  ISA_V3,
+};
+
 #endif /* ! BPF_OPTS_H */
diff --git a/gcc/config/bpf/bpf-protos.h b/gcc/config/bpf/bpf-protos.h
index 7ce3386ffda..e6bb9015449 100644
--- a/gcc/config/bpf/bpf-protos.h
+++ b/gcc/config/bpf/bpf-protos.h
@@ -29,6 +29,7 @@ extern void bpf_print_operand (FILE *, rtx, int);
 extern void bpf_print_operand_address (FILE *, rtx);
 extern void bpf_expand_prologue (void);
 extern void bpf_expand_epilogue (void);
+extern void bpf_expand_cbranch (machine_mode, rtx *);
 
 rtl_opt_pass * make_pass_bpf_core_attr (gcc::context *);
 
diff --git a/gcc/config/bpf/bpf.c b/gcc/config/bpf/bpf.c
index 01d9c03479e..82bb698bd91 100644
--- a/gcc/config/bpf/bpf.c
+++ b/gcc/config/bpf/bpf.c
@@ -242,6 +242,17 @@ bpf_option_override (void)
       target_flags |= MASK_BPF_CORE;
       write_symbols |= BTF_WITH_CORE_DEBUG;
     }
+
+  /* Determine available features from ISA setting (-mcpu=).  */
+  if (bpf_has_jmpext == -1)
+    bpf_has_jmpext = (bpf_isa >= ISA_V2);
+
+  if (bpf_has_alu32 == -1)
+    bpf_has_alu32 = (bpf_isa >= ISA_V3);
+
+  if (bpf_has_jmp32 == -1)
+    bpf_has_jmp32 = (bpf_isa >= ISA_V3);
+
 }
 
 #undef TARGET_OPTION_OVERRIDE
@@ -540,6 +551,36 @@ bpf_expand_epilogue (void)
   emit_jump_insn (gen_exit ());
 }
 
+/* Expand to the instructions for a conditional branch. This function
+   is called when expanding the 'cbranch<mode>4' pattern in bpf.md.  */
+
+void
+bpf_expand_cbranch (machine_mode mode, rtx *operands)
+{
+  /* If all jump instructions are available, nothing special to do here.  */
+  if (bpf_has_jmpext)
+    return;
+
+  enum rtx_code code = GET_CODE (operands[0]);
+
+  /* Without the conditional branch instructions jslt, jsle, jlt, jle, we need
+     to convert conditional branches that would use them to an available
+     operation instead by reversing the comparison.  */
+  if ((code == LT || code == LE || code == LTU || code == LEU))
+    {
+      /* Reverse the condition.  */
+      PUT_CODE (operands[0], reverse_condition (code));
+
+      /* Swap the operands, and ensure that the first is a register.  */
+      if (!register_operand (operands[2], mode))
+	operands[2] = force_reg (mode, operands[2]);
+
+      rtx tmp = operands[1];
+      operands[1] = operands[2];
+      operands[2] = tmp;
+    }
+}
+
 /* Return the initial difference between the specified pair of
    registers.  The registers that can figure in FROM, and TO, are
    specified by ELIMINABLE_REGS in bpf.h.
diff --git a/gcc/config/bpf/bpf.md b/gcc/config/bpf/bpf.md
index 03830cc250e..c8a85d66d08 100644
--- a/gcc/config/bpf/bpf.md
+++ b/gcc/config/bpf/bpf.md
@@ -100,9 +100,9 @@
 ;; insns, with the proper modes.
 ;;
 ;; 32-bit arithmetic (for SI modes) is implemented using the alu32
-;; instructions.
+;; instructions, if available.
 
-(define_mode_iterator AM [SI DI])
+(define_mode_iterator AM [(SI "bpf_has_alu32") DI])
 
 ;;; Addition
 (define_insn "add<AM:mode>3"
@@ -264,7 +264,7 @@
 	  (match_operand:SI 1 "nonimmediate_operand" "r,m")))]
   ""
   "@
-   mov32\t%0,%1
+   * return bpf_has_alu32 ? \"mov32\t%0,%1\" : \"mov\t%0,%1\;and\t%0,0xffffffff\";
    ldxw\t%0,%1"
   [(set_attr "type" "alu,ldx")])
 
@@ -313,7 +313,7 @@
 
 ;;;; Shifts
 
-(define_mode_iterator SIM [SI DI])
+(define_mode_iterator SIM [(SI "bpf_has_alu32") DI])
 
 (define_insn "ashr<SIM:mode>3"
   [(set (match_operand:SIM 0 "register_operand"                 "=r,r")
@@ -344,24 +344,28 @@
 ;; The eBPF jump instructions use 64-bit arithmetic when evaluating
 ;; the jump conditions.  Therefore we use DI modes below.
 
-(define_expand "cbranchdi4"
+(define_mode_iterator JM [(SI "bpf_has_jmp32") DI])
+
+(define_expand "cbranch<JM:mode>4"
   [(set (pc)
 	(if_then_else (match_operator 0 "comparison_operator"
-			[(match_operand:DI 1 "register_operand")
-			 (match_operand:DI 2 "reg_or_imm_operand")])
+			[(match_operand:JM 1 "register_operand")
+			 (match_operand:JM 2 "reg_or_imm_operand")])
 		      (label_ref (match_operand 3 "" ""))
 		      (pc)))]
   ""
 {
   if (!ordered_comparison_operator (operands[0], VOIDmode))
     FAIL;
+
+  bpf_expand_cbranch (<JM:MODE>mode, operands);
 })
 
-(define_insn "*branch_on_di"
+(define_insn "*branch_on_<JM:mode>"
   [(set (pc)
 	(if_then_else (match_operator 3 "ordered_comparison_operator"
-			 [(match_operand:DI 0 "register_operand" "r")
-			  (match_operand:DI 1 "reg_or_imm_operand" "rI")])
+			 [(match_operand:JM 0 "register_operand" "r")
+			  (match_operand:JM 1 "reg_or_imm_operand" "rI")])
 		      (label_ref (match_operand 2 "" ""))
 		      (pc)))]
   ""
@@ -370,16 +374,16 @@
 
   switch (code)
   {
-  case EQ: return "jeq\t%0,%1,%2"; break;
-  case NE: return "jne\t%0,%1,%2"; break;
-  case LT: return "jslt\t%0,%1,%2"; break;
-  case LE: return "jsle\t%0,%1,%2"; break;
-  case GT: return "jsgt\t%0,%1,%2"; break;
-  case GE: return "jsge\t%0,%1,%2"; break;
-  case LTU: return "jlt\t%0,%1,%2"; break;
-  case LEU: return "jle\t%0,%1,%2"; break;
-  case GTU: return "jgt\t%0,%1,%2"; break;
-  case GEU: return "jge\t%0,%1,%2"; break;
+  case EQ: return "jeq<msuffix>\t%0,%1,%2"; break;
+  case NE: return "jne<msuffix>\t%0,%1,%2"; break;
+  case LT: return "jslt<msuffix>\t%0,%1,%2"; break;
+  case LE: return "jsle<msuffix>\t%0,%1,%2"; break;
+  case GT: return "jsgt<msuffix>\t%0,%1,%2"; break;
+  case GE: return "jsge<msuffix>\t%0,%1,%2"; break;
+  case LTU: return "jlt<msuffix>\t%0,%1,%2"; break;
+  case LEU: return "jle<msuffix>\t%0,%1,%2"; break;
+  case GTU: return "jgt<msuffix>\t%0,%1,%2"; break;
+  case GEU: return "jge<msuffix>\t%0,%1,%2"; break;
   default:
     gcc_unreachable ();
     return "";
diff --git a/gcc/config/bpf/bpf.opt b/gcc/config/bpf/bpf.opt
index 4493067b987..e8b728ca69f 100644
--- a/gcc/config/bpf/bpf.opt
+++ b/gcc/config/bpf/bpf.opt
@@ -131,3 +131,32 @@ Set a hard limit for the size of each stack frame, in bytes.
 mco-re
 Target Mask(BPF_CORE)
 Generate all necessary information for BPF Compile Once - Run Everywhere.
+
+; Selecting BPF ISA features and versions
+
+mjmpext
+Target Var(bpf_has_jmpext) Init(-1)
+Enable extra conditional-branch instructions j(s)lt and j(s)le.
+
+malu32
+Target Var(bpf_has_alu32) Init(-1)
+Enable 32-bit ALU instructions.
+
+mjmp32
+Target Var(bpf_has_jmp32) Init(-1)
+Enable 32-bit jump instructions.
+
+mcpu=
+Target RejectNegative Joined Var(bpf_isa) Enum(bpf_isa) Init(ISA_V3)
+
+Enum
+Name(bpf_isa) Type(enum bpf_isa_version)
+
+EnumValue
+Enum(bpf_isa) String(v1) Value(ISA_V1)
+
+EnumValue
+Enum(bpf_isa) String(v2) Value(ISA_V2)
+
+EnumValue
+Enum(bpf_isa) String(v3) Value(ISA_V3)
-- 
2.33.0


  reply	other threads:[~2021-09-09 21:37 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-09-09 21:36 [PATCH 0/3] " David Faust
2021-09-09 21:36 ` David Faust [this message]
2021-09-09 21:36 ` [PATCH 2/3] bpf testsuite: add tests for new " David Faust
2021-09-09 21:36 ` [PATCH 3/3] doc: document BPF -mcpu and related options David Faust
2021-09-10 14:11 ` [PATCH 0/3] bpf: add -mcpu and related feature options Jose E. Marchesi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210909213645.11605-2-david.faust@oracle.com \
    --to=david.faust@oracle.com \
    --cc=gcc-patches@gcc.gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).