This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH v2, rs6000] Add -msafe-indirect-jumps option and implement safe bctr / bctrl


Hi!

On Sat, Jan 13, 2018 at 10:53:57PM -0600, Bill Schmidt wrote:
> This patch adds a new option for the compiler to produce only "safe" indirect
> jumps, in the sense that these jumps are deliberately mispredicted to inhibit
> speculative execution.  For now, this option is undocumented; this may change
> at some future date.  It is intended eventually for the linker to also honor
> this flag when creating PLT stubs, for example.

I think we settled on calling the option -mmispredict-indirect-jumps;
please let me know if you still agree with that.  Or have thought of a
better name :-)

> In addition to the new option, I've included changes to indirect calls for
> the ELFv2 ABI when the option is specified.  In place of bctrl, we generate
> a "crset eq" followed by a beqctrl-.  Using the CR0.eq bit is safe since CR0
> is volatile over the call.

And CR0 is unused by the call; compare to CR1 (on older ABIs) for example.

> I've also added code to replace uses of bctr when the new option is specified,
> with the sequence
> 
> 	crset 4x[CRb]+2
> 	beqctr- CRb
> 	b .
> 
> where CRb is an available condition register field.  This applies to all
> subtargets, and in particular is not restricted to ELFv2.  The use cases
> covered here are computed gotos and switch statements.
> 
> NOT yet covered by this patch: indirect calls for ELFv1.  That will come later.

Would be nice to have it for all ABIs, even.

> Please let me know if there is a better way to represent the crset without
> an unspec.

See the various patterns using cr%q.  I'm not sure they can generate creqv
(i.e. crset) currently, but that could be added (like crnot is there already,
for example).  If you don't use unspec (or maybe unspec_volatile) it can be
optimised away though.

Maybe it is best not to put the crset into its own insn, just make it part
of the bigger pattern, with an appropriate clobber?

> For the indirect jump, I don't see a way around it due to the
> expected form of indirect jumps in cfganal.c.

I'm not sure what you are getting at here, could you explain a bit?

>  (define_expand "indirect_jump"
> -  [(set (pc) (match_operand 0 "register_operand"))])
> +  [(set (pc) (match_operand 0 "register_operand"))]
> + ""
> +{
> +  /* We need to reserve a CR when forcing a mispredicted jump.  */
> +  if (rs6000_safe_indirect_jumps) {
> +    rtx ccreg = gen_reg_rtx (CCmode);
> +    emit_insn (gen_rtx_SET (ccreg,
> +			    gen_rtx_UNSPEC (CCmode,
> +					    gen_rtvec (1, const0_rtx),
> +					    UNSPEC_CRSET_EQ)));
> +    rtvec v = rtvec_alloc (2);
> +    RTVEC_ELT (v, 0) = operands[0];
> +    RTVEC_ELT (v, 1) = ccreg;
> +    emit_jump_insn (gen_rtx_SET (pc_rtx,
> +				 gen_rtx_UNSPEC (Pmode, v,
> +						 UNSPEC_COMP_GOTO_CR)));
> +    DONE;
> +  }
> +})
>  
>  (define_insn "*indirect_jump<mode>"
>    [(set (pc)
>  	(match_operand:P 0 "register_operand" "c,*l"))]
> -  ""
> +  "!rs6000_safe_indirect_jumps"
>    "b%T0"
>    [(set_attr "type" "jmpreg")])
>  
> +(define_insn "*indirect_jump<mode>_safe"
> +  [(set (pc)
> +	(unspec:P [(match_operand:P 0 "register_operand" "c,*l")
> +		   (match_operand:CC 1 "cc_reg_operand" "y,y")]
> +		   UNSPEC_COMP_GOTO_CR))]
> +  "rs6000_safe_indirect_jumps"
> +  "beq%T0- %1\;b ."
> +  [(set_attr "type" "jmpreg")
> +   (set_attr "length" "8")])
> +
> +(define_insn "*set_cr_eq"
> +  [(set (match_operand:CC 0 "cc_reg_operand" "=y")
> +	(unspec:CC [(const_int 0)] UNSPEC_CRSET_EQ))]
> +  "rs6000_safe_indirect_jumps"
> +  "crset %E0"
> +  [(set_attr "type" "cr_logical")])

So merge this latter insn into the previous, making the CC a clobber?
Like (not tested):

+(define_insn "indirect_jump<mode>_mispredict"
+  [(set (pc)
+	(match_operand:P 0 "register_operand" "c,*l")
+   (clobber (match_operand:CC 1 "cc_reg_operand" "y,y"))]
+  "rs6000_safe_indirect_jumps"
+  "crset %E1\;beq%T0- %1\;b ."
+  [(set_attr "type" "jmpreg")
+   (set_attr "length" "12")])

and then change the indirect_jump pattern to simply select between the normal
and mispredict patterns?

> +(define_expand "tablejumpsi_safe"

And then similar for tablejump.


Segher


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]