public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
From: "Kong, Lingling" <lingling.kong@intel.com>
To: Uros Bizjak <ubizjak@gmail.com>
Cc: "gcc-patches@gcc.gnu.org" <gcc-patches@gcc.gnu.org>,
	"Liu, Hongtao" <hongtao.liu@intel.com>,
	"Wang, Hongyu" <hongyu.wang@intel.com>,
	"Kong, Lingling" <lingling.kong@intel.com>
Subject: [PATCH v2 1/8] [APX NF]: Support APX NF add
Date: Wed, 22 May 2024 08:29:41 +0000	[thread overview]
Message-ID: <BN9PR11MB5483892E10834975E862CB8AECEB2@BN9PR11MB5483.namprd11.prod.outlook.com> (raw)
In-Reply-To: <CAFULd4Y=6B8Xci5eirb8Mkg9fC1JfsJd9spTUDoyfGhZV471tg@mail.gmail.com>

> I wonder if we can use "define_subst" to conditionally add flags clobber
> for !TARGET_APX_NF targets. Even the example for "Define Subst" uses the insn
> w/ and w/o the clobber, so I think it is worth considering this approach.
> 
> Uros.

Good Suggestion, I defined new subst for no flags, and Bootstrapped and regtested on x86_64-linux-gnu. Also supported SPEC 2017 run normally on Intel software development emulator.
Ok for trunk?

Thanks,
Lingling

Subject: [PATCH v2 1/8] [APX NF]: Support APX NF add
APX NF(no flags) feature implements suppresses the update of status flags
for arithmetic operations.

For NF add, it is not clear whether nf add can be faster than lea. If so,
the pattern needs to be adjusted to perfer lea generation.

gcc/ChangeLog:

	* config/i386/i386-opts.h (enum apx_features): Add nf
	enumeration.
	* config/i386/i386.h (TARGET_APX_NF): New.
	* config/i386/i386.md (nf_subst): New define_subst.
	(nf_name): New subst_attr.
	(nf_prefix): Ditto.
	(nf_condition): Ditto.
	(nf_mem_constraint): Ditto.
	(nf_applied): Ditto.
	(*add<mode>_1_nf): New define_insn.
	(addhi_1_nf): Ditto.
	(addqi_1_nf): Ditto.
	* config/i386/i386.opt: Add apx_nf enumeration.

gcc/testsuite/ChangeLog:

	* gcc.target/i386/apx-ndd.c: Fixed test.
	* gcc.target/i386/apx-nf.c: New test.

Co-authored-by: Lingling Kong <lingling.kong@intel.com>
---
 gcc/config/i386/i386-opts.h             |   3 +-
 gcc/config/i386/i386.h                  |   1 +
 gcc/config/i386/i386.md                 | 179 +++++++++++++++---------
 gcc/config/i386/i386.opt                |   3 +
 gcc/testsuite/gcc.target/i386/apx-ndd.c |   2 +-
 gcc/testsuite/gcc.target/i386/apx-nf.c  |   6 +
 6 files changed, 126 insertions(+), 68 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/i386/apx-nf.c

diff --git a/gcc/config/i386/i386-opts.h b/gcc/config/i386/i386-opts.h
index ef2825803b3..60176ce609f 100644
--- a/gcc/config/i386/i386-opts.h
+++ b/gcc/config/i386/i386-opts.h
@@ -140,7 +140,8 @@ enum apx_features {
   apx_push2pop2 = 1 << 1,
   apx_ndd = 1 << 2,
   apx_ppx = 1 << 3,
-  apx_all = apx_egpr | apx_push2pop2 | apx_ndd | apx_ppx,
+  apx_nf = 1<< 4,
+  apx_all = apx_egpr | apx_push2pop2 | apx_ndd | apx_ppx | apx_nf,
 };
 
 #endif
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 529edff93a4..f20ae4726da 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -55,6 +55,7 @@ see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_APX_PUSH2POP2 (ix86_apx_features & apx_push2pop2)
 #define TARGET_APX_NDD (ix86_apx_features & apx_ndd)
 #define TARGET_APX_PPX (ix86_apx_features & apx_ppx)
+#define TARGET_APX_NF (ix86_apx_features & apx_nf)
 
 #include "config/vxworks-dummy.h"
 
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 764bfe20ff2..bae344518bd 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -6233,28 +6233,6 @@
     }
 })
 

-;; Load effective address instructions
-
-(define_insn "*lea<mode>"
-  [(set (match_operand:SWI48 0 "register_operand" "=r")
-	(match_operand:SWI48 1 "address_no_seg_operand" "Ts"))]
-  "ix86_hardreg_mov_ok (operands[0], operands[1])"
-{
-  if (SImode_address_operand (operands[1], VOIDmode))
-    {
-      gcc_assert (TARGET_64BIT);
-      return "lea{l}\t{%E1, %k0|%k0, %E1}";
-    }
-  else
-    return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
-}
-  [(set_attr "type" "lea")
-   (set (attr "mode")
-     (if_then_else
-       (match_operand 1 "SImode_address_operand")
-       (const_string "SI")
-       (const_string "<MODE>")))])
-
 (define_peephole2
   [(set (match_operand:SWI48 0 "register_operand")
 	(match_operand:SWI48 1 "address_no_seg_operand"))]
@@ -6290,6 +6268,13 @@
   [(parallel [(set (match_dup 0) (ashift:SWI48 (match_dup 0) (match_dup 1)))
               (clobber (reg:CC FLAGS_REG))])]
   "operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
+
+(define_split
+  [(set (match_operand:SWI48 0 "general_reg_operand")
+	(mult:SWI48 (match_dup 0) (match_operand:SWI48 1 "const1248_operand")))]
+  "TARGET_APX_NF && reload_completed"
+  [(set (match_dup 0) (ashift:SWI48 (match_dup 0) (match_dup 1)))]
+  "operands[1] = GEN_INT (exact_log2 (INTVAL (operands[1])));")
 

 ;; Add instructions
 
@@ -6437,48 +6422,65 @@
 	      (clobber (reg:CC FLAGS_REG))])]
  "split_double_mode (<DWI>mode, &operands[0], 1, &operands[0], &operands[5]);")
 
-(define_insn "*add<mode>_1"
-  [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r,r,r,r,r,r")
+(define_subst_attr "nf_name" "nf_subst" "_nf" "")
+(define_subst_attr "nf_prefix" "nf_subst" "%{nf%} " "")
+(define_subst_attr "nf_condition" "nf_subst" "TARGET_APX_NF" "true")
+(define_subst_attr "nf_mem_constraint" "nf_subst" "je" "m")
+(define_subst_attr "nf_applied" "nf_subst" "true" "false")
+
+(define_subst "nf_subst"
+  [(set (match_operand:SWI 0)
+        (match_operand:SWI 1))]
+  ""
+  [(set (match_dup 0)
+	(match_dup 1))
+	(clobber (reg:CC FLAGS_REG))])
+
+(define_insn "*add<mode>_1<nf_name>"
+  [(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm,r<nf_mem_constraint>,r,r,r,r,r,r")
 	(plus:SWI48
-	  (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,r,r,rje,jM,r")
-	  (match_operand:SWI48 2 "x86_64_general_operand" "re,BM,0,le,r,e,BM")))
-   (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)"
+	  (match_operand:SWI48 1 "nonimmediate_operand" "%0,0,0,r,r,rje,jM,r")
+	  (match_operand:SWI48 2 "x86_64_general_operand" "r,e,BM,0,le,r,e,BM")))]
+  "ix86_binary_operator_ok (PLUS, <MODE>mode, operands, TARGET_APX_NDD)
+  && <nf_condition>"
 {
   bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD;
   switch (get_attr_type (insn))
     {
     case TYPE_LEA:
-      return "#";
+      if (TARGET_APX_NDD && <nf_applied>)
+	return "%{nf%} add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}";
+      else
+	return "#";
 
     case TYPE_INCDEC:
       if (operands[2] == const1_rtx)
-        return use_ndd ? "inc{<imodesuffix>}\t{%1, %0|%0, %1}"
-		      : "inc{<imodesuffix>}\t%0";
+        return use_ndd ? "<nf_prefix>inc{<imodesuffix>}\t{%1, %0|%0, %1}"
+		      : "<nf_prefix>inc{<imodesuffix>}\t%0";
       else
         {
 	  gcc_assert (operands[2] == constm1_rtx);
-	  return use_ndd ? "dec{<imodesuffix>}\t{%1, %0|%0, %1}"
-			: "dec{<imodesuffix>}\t%0";
+	  return use_ndd ? "<nf_prefix>dec{<imodesuffix>}\t{%1, %0|%0, %1}"
+			: "<nf_prefix>dec{<imodesuffix>}\t%0";
 	}
 
     default:
       /* For most processors, ADD is faster than LEA.  This alternative
 	 was added to use ADD as much as possible.  */
-      if (which_alternative == 2)
+      if (which_alternative == 3)
         std::swap (operands[1], operands[2]);
         
       if (x86_maybe_negate_const_int (&operands[2], <MODE>mode))
-        return use_ndd ? "sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
-		      : "sub{<imodesuffix>}\t{%2, %0|%0, %2}";
+        return use_ndd ? "<nf_prefix>sub{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+		      : "<nf_prefix>sub{<imodesuffix>}\t{%2, %0|%0, %2}";
 
-      return use_ndd ? "add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
-		    : "add{<imodesuffix>}\t{%2, %0|%0, %2}";
+      return use_ndd ? "<nf_prefix>add{<imodesuffix>}\t{%2, %1, %0|%0, %1, %2}"
+		    : "<nf_prefix>add{<imodesuffix>}\t{%2, %0|%0, %2}";
     }
 }
-  [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd,apx_ndd")
+  [(set_attr "isa" "*,*,*,*,*,apx_ndd,apx_ndd,apx_ndd")
    (set (attr "type")
-     (cond [(eq_attr "alternative" "3")
+     (cond [(eq_attr "alternative" "4")
               (const_string "lea")
 	    (match_operand:SWI48 2 "incdec_operand")
 	      (const_string "incdec")
@@ -6491,6 +6493,28 @@
 	(const_string "*")))
    (set_attr "mode" "<MODE>")])
 
+;; Load effective address instructions
+
+(define_insn "*lea<mode>"
+  [(set (match_operand:SWI48 0 "register_operand" "=r")
+	(match_operand:SWI48 1 "address_no_seg_operand" "Ts"))]
+  "ix86_hardreg_mov_ok (operands[0], operands[1])"
+{
+  if (SImode_address_operand (operands[1], VOIDmode))
+    {
+      gcc_assert (TARGET_64BIT);
+      return "lea{l}\t{%E1, %k0|%k0, %E1}";
+    }
+  else
+    return "lea{<imodesuffix>}\t{%E1, %0|%0, %E1}";
+}
+  [(set_attr "type" "lea")
+   (set (attr "mode")
+     (if_then_else
+       (match_operand 1 "SImode_address_operand")
+       (const_string "SI")
+       (const_string "<MODE>")))])
+
 ;; It may seem that nonimmediate operand is proper one for operand 1.
 ;; The addsi_1 pattern allows nonimmediate operand at that place and
 ;; we take care in ix86_binary_operator_ok to not allow two memory
@@ -6552,26 +6576,29 @@
 	(const_string "*")))
    (set_attr "mode" "SI")])
 
-(define_insn "*addhi_1"
+(define_insn "*addhi_1<nf_name>"
   [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,r,Yp,r,r")
 	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r,Yp,rm,r")
-		 (match_operand:HI 2 "general_operand" "rn,m,0,ln,rn,m")))
-   (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (PLUS, HImode, operands, TARGET_APX_NDD)"
+		 (match_operand:HI 2 "general_operand" "rn,m,0,ln,rn,m")))]
+  "ix86_binary_operator_ok (PLUS, HImode, operands, TARGET_APX_NDD)
+  && <nf_condition>"
 {
   bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD;
   switch (get_attr_type (insn))
     {
     case TYPE_LEA:
-      return "#";
+      if (TARGET_APX_NDD && <nf_applied>)
+	return "%{nf%} add{w}\t{%2, %1, %0|%0, %1, %2}";
+      else
+	return "#";
 
     case TYPE_INCDEC:
       if (operands[2] == const1_rtx)
-	return use_ndd ? "inc{w}\t{%1, %0|%0, %1}" : "inc{w}\t%0";
+	return use_ndd ? "<nf_prefix>inc{w}\t{%1, %0|%0, %1}" : "<nf_prefix>inc{w}\t%0";
       else
 	{
 	  gcc_assert (operands[2] == constm1_rtx);
-	  return use_ndd ? "dec{w}\t{%1, %0|%0, %1}" : "dec{w}\t%0";
+	  return use_ndd ? "<nf_prefix>dec{w}\t{%1, %0|%0, %1}" : "<nf_prefix>dec{w}\t%0";
 	}
 
     default:
@@ -6581,11 +6608,11 @@
         std::swap (operands[1], operands[2]);
 
       if (x86_maybe_negate_const_int (&operands[2], HImode))
-	return use_ndd ? "sub{w}\t{%2, %1, %0|%0, %1, %2}"
-		       : "sub{w}\t{%2, %0|%0, %2}";
+	return use_ndd ? "<nf_prefix>sub{w}\t{%2, %1, %0|%0, %1, %2}"
+		       : "<nf_prefix>sub{w}\t{%2, %0|%0, %2}";
 
-      return use_ndd ? "add{w}\t{%2, %1, %0|%0, %1, %2}"
-		     : "add{w}\t{%2, %0|%0, %2}";
+      return use_ndd ? "<nf_prefix>add{w}\t{%2, %1, %0|%0, %1, %2}"
+		     : "<nf_prefix>add{w}\t{%2, %0|%0, %2}";
     }
 }
   [(set_attr "isa" "*,*,*,*,apx_ndd,apx_ndd")
@@ -6603,33 +6630,36 @@
 	(const_string "*")))
    (set_attr "mode" "HI,HI,HI,SI,HI,HI")])
 
-(define_insn "*addqi_1"
+(define_insn "*addqi_1<nf_name>"
   [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,q,r,r,Yp,r,r")
 	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q,0,r,Yp,rm,r")
-		 (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln,rn,m")))
-   (clobber (reg:CC FLAGS_REG))]
-  "ix86_binary_operator_ok (PLUS, QImode, operands, TARGET_APX_NDD)"
+		 (match_operand:QI 2 "general_operand" "qn,m,0,rn,0,ln,rn,m")))]
+  "ix86_binary_operator_ok (PLUS, QImode, operands, TARGET_APX_NDD)
+  && <nf_condition>"
 {
   bool widen = (get_attr_mode (insn) != MODE_QI);
   bool use_ndd = get_attr_isa (insn) == ISA_APX_NDD;
   switch (get_attr_type (insn))
     {
     case TYPE_LEA:
-      return "#";
+      if (TARGET_APX_NDD && <nf_applied>)
+	return "%{nf%} add{b}\t{%2, %1, %0|%0, %1, %2}";
+      else
+	return "#";
 
     case TYPE_INCDEC:
       if (operands[2] == const1_rtx)
 	if (use_ndd)
-	  return "inc{b}\t{%1, %0|%0, %1}";
+	  return "<nf_prefix>inc{b}\t{%1, %0|%0, %1}";
 	else
-	  return widen ? "inc{l}\t%k0" : "inc{b}\t%0";
+	  return widen ? "<nf_prefix>inc{l}\t%k0" : "<nf_prefix>inc{b}\t%0";
       else
 	{
 	  gcc_assert (operands[2] == constm1_rtx);
 	  if (use_ndd)
-	    return "dec{b}\t{%1, %0|%0, %1}";
+	    return "<nf_prefix>dec{b}\t{%1, %0|%0, %1}";
 	  else
-	    return widen ? "dec{l}\t%k0" : "dec{b}\t%0";
+	    return widen ? "<nf_prefix>dec{l}\t%k0" : "<nf_prefix>dec{b}\t%0";
 	}
 
     default:
@@ -6641,16 +6671,16 @@
       if (x86_maybe_negate_const_int (&operands[2], QImode))
 	{
 	  if (use_ndd)
-	    return "sub{b}\t{%2, %1, %0|%0, %1, %2}";
+	    return "<nf_prefix>sub{b}\t{%2, %1, %0|%0, %1, %2}";
 	  else
-	    return widen ? "sub{l}\t{%2, %k0|%k0, %2}"
-			 : "sub{b}\t{%2, %0|%0, %2}";
+	    return widen ? "<nf_prefix>sub{l}\t{%2, %k0|%k0, %2}"
+			 : "<nf_prefix>sub{b}\t{%2, %0|%0, %2}";
 	}
       if (use_ndd)
-	return "add{b}\t{%2, %1, %0|%0, %1, %2}";
+	return "<nf_prefix>add{b}\t{%2, %1, %0|%0, %1, %2}";
       else
-	return widen ? "add{l}\t{%k2, %k0|%k0, %k2}"
-		     : "add{b}\t{%2, %0|%0, %2}";
+	return widen ? "<nf_prefix>add{l}\t{%k2, %k0|%k0, %k2}"
+		     : "<nf_prefix>add{b}\t{%2, %0|%0, %2}";
     }
 }
   [(set_attr "isa" "*,*,*,*,*,*,apx_ndd,apx_ndd")
@@ -6824,6 +6854,23 @@
     }
 })
 
+(define_split
+  [(set (match_operand:SWI 0 "register_operand")
+	(plus:SWI (match_operand:SWI 1 "register_operand")
+		  (match_operand:SWI 2 "<nonmemory_operand>")))]
+  "TARGET_APX_NF && reload_completed
+   && ix86_lea_for_add_ok (insn, operands)"
+  [(set (match_dup 0)
+	(plus:<LEAMODE> (match_dup 1) (match_dup 2)))]
+{
+  if (<MODE>mode != <LEAMODE>mode)
+    {
+      operands[0] = gen_lowpart (<LEAMODE>mode, operands[0]);
+      operands[1] = gen_lowpart (<LEAMODE>mode, operands[1]);
+      operands[2] = gen_lowpart (<LEAMODE>mode, operands[2]);
+    }
+})
+
 ;; Convert add to the lea pattern to avoid flags dependency.
 (define_split
   [(set (match_operand:DI 0 "register_operand")
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index d5f793a9e8b..66021d59d4e 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1356,6 +1356,9 @@ Enum(apx_features) String(ndd) Value(apx_ndd) Set(4)
 EnumValue
 Enum(apx_features) String(ppx) Value(apx_ppx) Set(5)
 
+EnumValue
+Enum(apx_features) String(nf) Value(apx_nf) Set(6)
+
 EnumValue
 Enum(apx_features) String(all) Value(apx_all) Set(1)
 
diff --git a/gcc/testsuite/gcc.target/i386/apx-ndd.c b/gcc/testsuite/gcc.target/i386/apx-ndd.c
index 0eb751ad225..0ff4df0780c 100644
--- a/gcc/testsuite/gcc.target/i386/apx-ndd.c
+++ b/gcc/testsuite/gcc.target/i386/apx-ndd.c
@@ -1,5 +1,5 @@
 /* { dg-do compile { target { ! ia32 } } } */
-/* { dg-options "-mapxf -march=x86-64 -O2" } */
+/* { dg-options "-mapx-features=egpr,push2pop2,ndd,ppx -march=x86-64 -O2" } */
 /* { dg-final { scan-assembler-not "movl"} } */
 
 #include <stdint.h>
diff --git a/gcc/testsuite/gcc.target/i386/apx-nf.c b/gcc/testsuite/gcc.target/i386/apx-nf.c
new file mode 100644
index 00000000000..3adc7a27902
--- /dev/null
+++ b/gcc/testsuite/gcc.target/i386/apx-nf.c
@@ -0,0 +1,6 @@
+/* { dg-do compile { target { ! ia32 } } } */
+/* { dg-options "-mapx-features=egpr,push2pop2,ndd,ppx,nf -march=x86-64 -O2" } */
+/* { dg-final { scan-assembler-times "\{nf\} add" 4 } } */
+
+#include "apx-ndd.c"
+
-- 
2.31.1



  reply	other threads:[~2024-05-22  8:29 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
     [not found] <20240515070226.3760873-1-lingling.kong@intel.com>
2024-05-15  7:43 ` [PATCH " Kong, Lingling
2024-05-15  8:14   ` Uros Bizjak
2024-05-15  8:36     ` Kong, Lingling
2024-05-15  8:46   ` Uros Bizjak
2024-05-22  8:29     ` Kong, Lingling [this message]
2024-05-22  8:35       ` [PATCH v2 " Uros Bizjak
     [not found] ` <20240515070226.3760873-2-lingling.kong@intel.com>
2024-05-15  7:44   ` [PATCH 2/8] [APX NF] Support APX NF for {sub/and/or/xor/neg} Kong, Lingling
     [not found] ` <20240515070226.3760873-3-lingling.kong@intel.com>
2024-05-15  7:44   ` [PATCH 3/8] [APX NF] Support APX NF for left shift insns Kong, Lingling
     [not found] ` <20240515070226.3760873-4-lingling.kong@intel.com>
2024-05-15  7:45   ` [PATCH 4/8] [APX NF] Support APX NF for right " Kong, Lingling
     [not found] ` <20240515070226.3760873-5-lingling.kong@intel.com>
2024-05-15  7:45   ` [PATCH 5/8] [APX NF] Support APX NF for rotate insns Kong, Lingling
     [not found] ` <20240515070226.3760873-6-lingling.kong@intel.com>
2024-05-15  7:46   ` [PATCH 6/8] [APX NF] Support APX NF for shld/shrd Kong, Lingling
     [not found] ` <20240515070226.3760873-7-lingling.kong@intel.com>
2024-05-15  7:46   ` [PATCH 7/8] [APX NF] Support APX NF for mul/div Kong, Lingling
     [not found] ` <20240515070226.3760873-8-lingling.kong@intel.com>
2024-05-15  7:47   ` [PATCH 8/8] [APX NF] Support APX NF for lzcnt/tzcnt/popcnt Kong, Lingling

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=BN9PR11MB5483892E10834975E862CB8AECEB2@BN9PR11MB5483.namprd11.prod.outlook.com \
    --to=lingling.kong@intel.com \
    --cc=gcc-patches@gcc.gnu.org \
    --cc=hongtao.liu@intel.com \
    --cc=hongyu.wang@intel.com \
    --cc=ubizjak@gmail.com \
    /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).