On Wed, Jan 17, 2018 at 3:55 PM, Richard Earnshaw <richard.earns...@arm.com> wrote: > > This patch adds generic support for the new builtin > __builtin_speculation_safe_load. It provides the overloading of the > different access sizes and a default fall-back expansion for targets > that do not support a mechanism for inhibiting speculation.
+ if (ignore) + { + warning_at (input_location, 0, + "result of __builtin_speculation_safe_load must be used to " + "ensure correct operation"); + target = NULL; + } This warning cannot be disabled but these kind of cases could appear via path isolation or missed optimizations since memory optimizations do not recognize such speculative loads. So - should it not be emitted way earlier instead, like from the FEs or during some early warning pass? In which case it could be an error as well, no? + set_mem_align (mem, MAX (GET_MODE_ALIGNMENT (mode), + get_pointer_alignment (arg0))); err... so there's no way to do an unaligned speculation safe load? Using just get_pointer_alignment would be safe here. Other builtins/IFNs explicitely pass down the alignment and FEs generate such alignment from their language constraints. + set_mem_alias_set (mem, get_alias_set (TREE_TYPE (TREE_TYPE (arg0)))); sorry, but pointer types are arbitrary in GIMPLE so this is clearly wrong. Without more information you have to use zero. Thus, __builtin_speculation_safe_load ((int *)p, ...); will do the wrong thing if the type of p is not int *. + /* Mark the memory access as volatile. We don't want the optimizers to + move it or otherwise substitue an alternative value. */ + MEM_VOLATILE_P (mem) = 1; how is moving or substituting in any way related to inhibiting speculation? Why's this done for all targets rather than only those that need any such mitigation? I btw miss implementation for x86_64 (at least) where the agreed upon mitigation is to insert 'lfence' before the load. Any reason the builtin expansion is not fully left to the targets? +/* Suppressing speculation. Users are expected to use the first (N) + variant, which will be translated internally into one of the other + types. */ +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_LOAD_N, "speculation_safe_load", + BT_FN_VOID_VAR, ATTR_NULL) + +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_LOAD_1, "speculation_safe_load_1", + BT_FN_I1_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR, ATTR_NULL) +DEF_GCC_BUILTIN (BUILT_IN_SPECULATION_SAFE_LOAD_2, "speculation_safe_load_2", + BT_FN_I2_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR, ATTR_NULL) any reason you are not simply using an internal function for the non-_N variants? Looks like you're closely following the atomic/sync builtins but those predate IFNs I think. They also have more constraints on alignment and use a restrictive alias set. +rtx +default_speculation_safe_load (machine_mode mode ATTRIBUTE_UNUSED, + rtx result, rtx mem, rtx lower_bound, + rtx upper_bound, rtx cmpptr, bool warn) +{ + rtx_code_label *done_label = gen_label_rtx (); + rtx_code_label *inrange_label = gen_label_rtx (); + + if (warn) + warning_at + (input_location, 0, + "this target does not support anti-speculation operations. " + "Your program will still execute correctly, but speculation " + "will not be inhibited"); so there's no way to inhibit this warning than changing all targets? Iff it is correct for a target to expand this to an unconditional load with a preceeding fence why not have the generic target hook implementation do exactly that - emit an unconditional move? Maybe I misunderstand the clear words in the hook docs, but the builtin docs also say the behavior is undefined if the builtin is executed when the condition is false - which means traps are allowed. Richard. > * builtin-types.def (BT_FN_I1_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR): > New builtin type signature. > (BT_FN_I2_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR): Likewise. > (BT_FN_I4_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR): Likewise. > (BT_FN_I8_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR): Likewise. > (BT_FN_I16_CONST_VPTR_CONST_VPTR_CONST_VPTR_VAR): Likewise. > * builtins.def (BUILT_IN_SPECULATION_SAFE_LOAD_N): New builtin. > (BUILT_IN_SPECULATION_SAFE_LOAD_1): Likewise. > (BUILT_IN_SPECULATION_SAFE_LOAD_2): Likewise. > (BUILT_IN_SPECULATION_SAFE_LOAD_4): Likewise. > (BUILT_IN_SPECULATION_SAFE_LOAD_8): Likewise. > (BUILT_IN_SPECULATION_SAFE_LOAD_16): Likewise. > * target.def (speculation_safe_load): New hook. > * doc/tm.texi.in (TARGET_SPECULATION_SAFE_LOAD): Add to > documentation. > * doc/tm.texi: Regenerated. > * doc/cpp.texi: Document __HAVE_SPECULATION_SAFE_LOAD. > * doc/extend.texi: Document __builtin_speculation_safe_load. > * c-family/c-common.c (speculation_safe_load_resolve_size): New > function. > (speculation_safe_load_resolve_params): New function. > (speculation_safe_load_resolve_return): New function. > (resolve_overloaded_builtin): Handle overloading > __builtin_speculation_safe_load. > * builtins.c (expand_speculation_safe_load): New function. > (expand_builtin): Handle new speculation-safe builtins. > * targhooks.h (default_speculation_safe_load): Declare. > * targhooks.c (default_speculation_safe_load): New function. > --- > gcc/builtin-types.def | 16 +++++ > gcc/builtins.c | 81 +++++++++++++++++++++++ > gcc/builtins.def | 17 +++++ > gcc/c-family/c-common.c | 152 > ++++++++++++++++++++++++++++++++++++++++++++ > gcc/c-family/c-cppbuiltin.c | 5 +- > gcc/doc/cpp.texi | 4 ++ > gcc/doc/extend.texi | 68 ++++++++++++++++++++ > gcc/doc/tm.texi | 9 +++ > gcc/doc/tm.texi.in | 2 + > gcc/target.def | 34 ++++++++++ > gcc/targhooks.c | 59 +++++++++++++++++ > gcc/targhooks.h | 3 + > 12 files changed, 449 insertions(+), 1 deletion(-) >