On Thu, Jan 18, 2018 at 1:44 PM, Richard Biener <richard.guent...@gmail.com> wrote: > 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.
Oh, and I think I'd like to see the builtins folded to regular MEMs very early if the target doesn't provide TARGET_SPECULATION_SAFE_LOAD. Ideally directly from where _n is disambiguated in the FE. Richard. > 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(-) >>