summaryrefslogtreecommitdiff
path: root/gcc/config/i386
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386')
-rw-r--r--gcc/config/i386/cpuid.h1
-rw-r--r--gcc/config/i386/i386-builtin-types.def4
-rw-r--r--gcc/config/i386/i386-builtin.def4
-rw-r--r--gcc/config/i386/i386-c.cc2
-rw-r--r--gcc/config/i386/i386-expand.cc77
-rw-r--r--gcc/config/i386/i386-isa.def1
-rw-r--r--gcc/config/i386/i386-options.cc4
-rw-r--r--gcc/config/i386/i386.md23
-rw-r--r--gcc/config/i386/i386.opt4
-rw-r--r--gcc/config/i386/predicates.md15
-rw-r--r--gcc/config/i386/prfchiintrin.h49
-rw-r--r--gcc/config/i386/x86gprintrin.h2
-rw-r--r--gcc/config/i386/xmmintrin.h7
13 files changed, 190 insertions, 3 deletions
diff --git a/gcc/config/i386/cpuid.h b/gcc/config/i386/cpuid.h
index 229c15c5950..92583261883 100644
--- a/gcc/config/i386/cpuid.h
+++ b/gcc/config/i386/cpuid.h
@@ -54,6 +54,7 @@
#define bit_AVXVNNIINT8 (1 << 4)
#define bit_AVXNECONVERT (1 << 5)
#define bit_CMPXCHG8B (1 << 8)
+#define bit_PREFETCHI (1 << 14)
#define bit_CMOV (1 << 15)
#define bit_MMX (1 << 23)
#define bit_FXSAVE (1 << 24)
diff --git a/gcc/config/i386/i386-builtin-types.def b/gcc/config/i386/i386-builtin-types.def
index 2af66145d4b..d10de32643f 100644
--- a/gcc/config/i386/i386-builtin-types.def
+++ b/gcc/config/i386/i386-builtin-types.def
@@ -1411,3 +1411,7 @@ DEF_FUNCTION_TYPE (V8SF, PCV16BF)
# CMPccXADD builtins
DEF_FUNCTION_TYPE (INT, PINT, INT, INT, INT)
DEF_FUNCTION_TYPE (LONGLONG, PLONGLONG, LONGLONG, LONGLONG, INT)
+
+# PREFETCHI builtins
+DEF_FUNCTION_TYPE (VOID, PCVOID, INT)
+DEF_FUNCTION_TYPE (VOID, PCVOID, INT, INT, INT)
diff --git a/gcc/config/i386/i386-builtin.def b/gcc/config/i386/i386-builtin.def
index c272c392d03..837007ada8e 100644
--- a/gcc/config/i386/i386-builtin.def
+++ b/gcc/config/i386/i386-builtin.def
@@ -487,6 +487,10 @@ BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesdecwide2
BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesencwide128kl_u8", IX86_BUILTIN_AESENCWIDE128KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
BDESC (0, OPTION_MASK_ISA2_WIDEKL, CODE_FOR_nothing, "__builtin_ia32_aesencwide256kl_u8", IX86_BUILTIN_AESENCWIDE256KLU8, UNKNOWN, (int) UINT8_FTYPE_PV2DI_PCV2DI_PCVOID)
+/* PREFETCHI */
+BDESC (0, 0, CODE_FOR_prefetchi, "__builtin_ia32_prefetchi", IX86_BUILTIN_PREFETCHI, UNKNOWN, (int) VOID_FTYPE_PCVOID_INT)
+BDESC (0, 0, CODE_FOR_nothing, "__builtin_ia32_prefetch", IX86_BUILTIN_PREFETCH, UNKNOWN, (int) VOID_FTYPE_PCVOID_INT_INT_INT)
+
BDESC_END (SPECIAL_ARGS, PURE_ARGS)
/* AVX */
diff --git a/gcc/config/i386/i386-c.cc b/gcc/config/i386/i386-c.cc
index ac0087a4653..07ce0f8a5a7 100644
--- a/gcc/config/i386/i386-c.cc
+++ b/gcc/config/i386/i386-c.cc
@@ -657,6 +657,8 @@ ix86_target_macros_internal (HOST_WIDE_INT isa_flag,
def_or_undef (parse_in, "__CMPCCXADD__");
if (isa_flag2 & OPTION_MASK_ISA2_AMX_FP16)
def_or_undef (parse_in, "__AMX_FP16__");
+ if (isa_flag2 & OPTION_MASK_ISA2_PREFETCHI)
+ def_or_undef (parse_in, "__PREFETCHI__");
if (TARGET_IAMCU)
{
def_or_undef (parse_in, "__iamcu");
diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc
index a37fde307d1..2e0d12c0108 100644
--- a/gcc/config/i386/i386-expand.cc
+++ b/gcc/config/i386/i386-expand.cc
@@ -13035,6 +13035,83 @@ ix86_expand_builtin (tree exp, rtx target, rtx subtarget,
return target;
}
+ case IX86_BUILTIN_PREFETCH:
+ {
+ arg0 = CALL_EXPR_ARG (exp, 0); // const void *
+ arg1 = CALL_EXPR_ARG (exp, 1); // const int
+ arg2 = CALL_EXPR_ARG (exp, 2); // const int
+ arg3 = CALL_EXPR_ARG (exp, 3); // const int
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+ op2 = expand_normal (arg2);
+ op3 = expand_normal (arg3);
+
+ if (!CONST_INT_P (op1) || !CONST_INT_P (op2) || !CONST_INT_P (op3))
+ {
+ error ("second, third and fourth argument must be a const");
+ return const0_rtx;
+ }
+
+ if (INTVAL (op3) == 1)
+ {
+ if (TARGET_64BIT
+ && local_func_symbolic_operand (op0, GET_MODE (op0)))
+ emit_insn (gen_prefetchi (op0, op2));
+ else
+ {
+ warning (0, "instruction prefetch applies when in 64-bit mode"
+ " with RIP-relative addressing and"
+ " option %<-mprefetchi%>;"
+ " they stay NOPs otherwise");
+ emit_insn (gen_nop ());
+ }
+ }
+ else
+ {
+ if (!address_operand (op0, VOIDmode))
+ {
+ op0 = convert_memory_address (Pmode, op0);
+ op0 = copy_addr_to_reg (op0);
+ }
+ emit_insn (gen_prefetch (op0, op1, op2));
+ }
+
+ return 0;
+ }
+
+ case IX86_BUILTIN_PREFETCHI:
+ {
+ arg0 = CALL_EXPR_ARG (exp, 0); // const void *
+ arg1 = CALL_EXPR_ARG (exp, 1); // const int
+
+ op0 = expand_normal (arg0);
+ op1 = expand_normal (arg1);
+
+ if (!CONST_INT_P (op1))
+ {
+ error ("second argument must be a const");
+ return const0_rtx;
+ }
+
+ /* GOT/PLT_PIC should not be available for instruction prefetch.
+ It must be real instruction address. */
+ if (TARGET_64BIT
+ && local_func_symbolic_operand (op0, GET_MODE (op0)))
+ emit_insn (gen_prefetchi (op0, op1));
+ else
+ {
+ /* Ignore the hint. */
+ warning (0, "instruction prefetch applies when in 64-bit mode"
+ " with RIP-relative addressing and"
+ " option %<-mprefetchi%>;"
+ " they stay NOPs otherwise");
+ emit_insn (gen_nop ());
+ }
+
+ return 0;
+ }
+
case IX86_BUILTIN_VEC_INIT_V2SI:
case IX86_BUILTIN_VEC_INIT_V4HI:
case IX86_BUILTIN_VEC_INIT_V8QI:
diff --git a/gcc/config/i386/i386-isa.def b/gcc/config/i386/i386-isa.def
index 55b25763957..f234dcc37d7 100644
--- a/gcc/config/i386/i386-isa.def
+++ b/gcc/config/i386/i386-isa.def
@@ -114,3 +114,4 @@ DEF_PTA(AVXVNNIINT8)
DEF_PTA(AVXNECONVERT)
DEF_PTA(CMPCCXADD)
DEF_PTA(AMX_FP16)
+DEF_PTA(PREFETCHI)
diff --git a/gcc/config/i386/i386-options.cc b/gcc/config/i386/i386-options.cc
index 2c16dc0cf96..e04b8407b62 100644
--- a/gcc/config/i386/i386-options.cc
+++ b/gcc/config/i386/i386-options.cc
@@ -233,7 +233,8 @@ static struct ix86_target_opts isa2_opts[] =
{ "-mavxvnniint8", OPTION_MASK_ISA2_AVXVNNIINT8 },
{ "-mavxneconvert", OPTION_MASK_ISA2_AVXNECONVERT },
{ "-mcmpccxadd", OPTION_MASK_ISA2_CMPCCXADD },
- { "-mamx-fp16", OPTION_MASK_ISA2_AMX_FP16 }
+ { "-mamx-fp16", OPTION_MASK_ISA2_AMX_FP16 },
+ { "-mprefetchi", OPTION_MASK_ISA2_PREFETCHI }
};
static struct ix86_target_opts isa_opts[] =
{
@@ -1082,6 +1083,7 @@ ix86_valid_target_attribute_inner_p (tree fndecl, tree args, char *p_strings[],
IX86_ATTR_ISA ("avxneconvert", OPT_mavxneconvert),
IX86_ATTR_ISA ("cmpccxadd", OPT_mcmpccxadd),
IX86_ATTR_ISA ("amx-fp16", OPT_mamx_fp16),
+ IX86_ATTR_ISA ("prefetchi", OPT_mprefetchi),
/* enum options */
IX86_ATTR_ENUM ("fpmath=", OPT_mfpmath_),
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index 436eabb691a..a2b8f26714a 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -330,6 +330,9 @@
;; For HRESET support
UNSPECV_HRESET
+
+ ;; For PREFETCHI support
+ UNSPECV_PREFETCHI
])
;; Constants to represent rounding modes in the ROUND instruction
@@ -23961,6 +23964,26 @@
(symbol_ref "memory_address_length (operands[0], false)"))
(set_attr "memory" "none")])
+(define_insn "prefetchi"
+ [(unspec_volatile [(match_operand 0 "local_func_symbolic_operand" "p")
+ (match_operand:SI 1 "const_int_operand")]
+ UNSPECV_PREFETCHI)]
+ "TARGET_PREFETCHI && TARGET_64BIT"
+{
+ static const char * const patterns[2] = {
+ "prefetchit1\t%0", "prefetchit0\t%0"
+ };
+
+ int locality = INTVAL (operands[1]);
+ gcc_assert (IN_RANGE (locality, 2, 3));
+
+ return patterns[locality - 2];
+}
+ [(set_attr "type" "sse")
+ (set (attr "length_address")
+ (symbol_ref "memory_address_length (operands[0], false)"))
+ (set_attr "memory" "none")])
+
(define_expand "stack_protect_set"
[(match_operand 0 "memory_operand")
(match_operand 1 "memory_operand")]
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index eaa43946341..1d91103cd54 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -1238,3 +1238,7 @@ CMPCCXADD build-in functions and code generation.
mamx-fp16
Target Mask(ISA2_AMX_FP16) Var(ix86_isa_flags2) Save
Support AMX-FP16 built-in functions and code generation.
+
+mprefetchi
+Target Mask(ISA2_PREFETCHI) Var(ix86_isa_flags2) Save
+Support PREFETCHI built-in functions and code generation.
diff --git a/gcc/config/i386/predicates.md b/gcc/config/i386/predicates.md
index c4141a96735..2a3f07224cc 100644
--- a/gcc/config/i386/predicates.md
+++ b/gcc/config/i386/predicates.md
@@ -610,6 +610,21 @@
return false;
})
+(define_predicate "local_func_symbolic_operand"
+ (match_operand 0 "local_symbolic_operand")
+{
+ if (GET_CODE (op) == CONST
+ && GET_CODE (XEXP (op, 0)) == PLUS
+ && CONST_INT_P (XEXP (XEXP (op, 0), 1)))
+ op = XEXP (XEXP (op, 0), 0);
+
+ if (GET_CODE (op) == SYMBOL_REF
+ && !SYMBOL_REF_FUNCTION_P (op))
+ return false;
+
+ return true;
+})
+
;; Test for a legitimate @GOTOFF operand.
;;
;; VxWorks does not impose a fixed gap between segments; the run-time
diff --git a/gcc/config/i386/prfchiintrin.h b/gcc/config/i386/prfchiintrin.h
new file mode 100644
index 00000000000..06deef488ba
--- /dev/null
+++ b/gcc/config/i386/prfchiintrin.h
@@ -0,0 +1,49 @@
+/* Copyright (C) 2022 Free Software Foundation, Inc.
+
+ This file is part of GCC.
+
+ GCC is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3, or (at your option)
+ any later version.
+
+ GCC is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ Under Section 7 of GPL version 3, you are granted additional
+ permissions described in the GCC Runtime Library Exception, version
+ 3.1, as published by the Free Software Foundation.
+
+ You should have received a copy of the GNU General Public License and
+ a copy of the GCC Runtime Library Exception along with this program;
+ see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
+ <http://www.gnu.org/licenses/>. */
+
+#if !defined _X86GPRINTRIN_H_INCLUDED
+# error "Never use <prfchiintrin.h> directly; include <x86gprintrin.h> instead."
+#endif
+
+#ifndef _PRFCHIINTRIN_H_INCLUDED
+#define _PRFCHIINTRIN_H_INCLUDED
+
+#ifdef __x86_64__
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_prefetchit0 (void* __P)
+{
+ __builtin_ia32_prefetchi (__P, 3);
+}
+
+extern __inline void
+__attribute__((__gnu_inline__, __always_inline__, __artificial__))
+_m_prefetchit1 (void* __P)
+{
+ __builtin_ia32_prefetchi (__P, 2);
+}
+
+#endif
+
+#endif /* _PRFCHIINTRIN_H_INCLUDED */
diff --git a/gcc/config/i386/x86gprintrin.h b/gcc/config/i386/x86gprintrin.h
index a84fbe9137d..abe8f487f03 100644
--- a/gcc/config/i386/x86gprintrin.h
+++ b/gcc/config/i386/x86gprintrin.h
@@ -74,6 +74,8 @@
#include <pkuintrin.h>
+#include <prfchiintrin.h>
+
#include <rdseedintrin.h>
#include <rtmintrin.h>
diff --git a/gcc/config/i386/xmmintrin.h b/gcc/config/i386/xmmintrin.h
index 62659080601..ab65c430a97 100644
--- a/gcc/config/i386/xmmintrin.h
+++ b/gcc/config/i386/xmmintrin.h
@@ -36,6 +36,8 @@
/* Constants for use with _mm_prefetch. */
enum _mm_hint
{
+ _MM_HINT_IT0 = 19,
+ _MM_HINT_IT1 = 18,
/* _MM_HINT_ET is _MM_HINT_T with set 3rd bit. */
_MM_HINT_ET0 = 7,
_MM_HINT_ET1 = 6,
@@ -51,11 +53,12 @@ enum _mm_hint
extern __inline void __attribute__((__gnu_inline__, __always_inline__, __artificial__))
_mm_prefetch (const void *__P, enum _mm_hint __I)
{
- __builtin_prefetch (__P, (__I & 0x4) >> 2, __I & 0x3);
+ __builtin_ia32_prefetch (__P, (__I & 0x4) >> 2,
+ __I & 0x3, (__I & 0x10) >> 4);
}
#else
#define _mm_prefetch(P, I) \
- __builtin_prefetch ((P), ((I & 0x4) >> 2), (I & 0x3))
+ __builtin_ia32_prefetch ((P), ((I) & 0x4) >> 2, ((I) & 0x3), ((I) & 0x10) >> 4)
#endif
#ifndef __SSE__