+2018-01-16 Bill Schmidt <wschmidt@linux.vnet.ibm.com>
+
+ * config/rs6000/rs6000.c (rs6000_opt_vars): Add entry for
+ -mspeculate-indirect-jumps.
+ * config/rs6000/rs6000.md (*call_indirect_elfv2<mode>): Disable
+ for -mno-speculate-indirect-jumps.
+ (*call_indirect_elfv2<mode>_nospec): New define_insn.
+ (*call_value_indirect_elfv2<mode>): Disable for
+ -mno-speculate-indirect-jumps.
+ (*call_value_indirect_elfv2<mode>_nospec): New define_insn.
+ (indirect_jump): Emit different RTL for
+ -mno-speculate-indirect-jumps.
+ (*indirect_jump<mode>): Disable for
+ -mno-speculate-indirect-jumps.
+ (*indirect_jump<mode>_nospec): New define_insn.
+ (tablejump): Emit different RTL for
+ -mno-speculate-indirect-jumps.
+ (tablejumpsi): Disable for -mno-speculate-indirect-jumps.
+ (tablejumpsi_nospec): New define_expand.
+ (tablejumpdi): Disable for -mno-speculate-indirect-jumps.
+ (tablejumpdi_nospec): New define_expand.
+ (*tablejump<mode>_internal1): Disable for
+ -mno-speculate-indirect-jumps.
+ (*tablejump<mode>_internal1_nospec): New define_insn.
+ * config/rs6000/rs6000.opt (mspeculate-indirect-jumps): New
+ option.
+
2018-01-16 Artyom Skrobov tyomitch@gmail.com
* caller-save.c (insert_save): Drop unnecessary parameter. All
(match_operand 1 "" "g,g"))
(set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
(clobber (reg:P LR_REGNO))]
- "DEFAULT_ABI == ABI_ELFv2"
+ "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps"
"b%T0l\;<ptrload> 2,%2(1)"
[(set_attr "type" "jmpreg")
(set_attr "length" "8")])
+;; Variant with deliberate misprediction.
+(define_insn "*call_indirect_elfv2<mode>_nospec"
+ [(call (mem:SI (match_operand:P 0 "register_operand" "c,*l"))
+ (match_operand 1 "" "g,g"))
+ (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 2 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps"
+ "crset eq\;beq%T0l-\;<ptrload> 2,%2(1)"
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "12")])
+
(define_insn "*call_value_indirect_elfv2<mode>"
[(set (match_operand 0 "" "")
(call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
(match_operand 2 "" "g,g")))
(set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
(clobber (reg:P LR_REGNO))]
- "DEFAULT_ABI == ABI_ELFv2"
+ "DEFAULT_ABI == ABI_ELFv2 && rs6000_speculate_indirect_jumps"
"b%T1l\;<ptrload> 2,%3(1)"
[(set_attr "type" "jmpreg")
(set_attr "length" "8")])
+; Variant with deliberate misprediction.
+(define_insn "*call_value_indirect_elfv2<mode>_nospec"
+ [(set (match_operand 0 "" "")
+ (call (mem:SI (match_operand:P 1 "register_operand" "c,*l"))
+ (match_operand 2 "" "g,g")))
+ (set (reg:P TOC_REGNUM) (unspec:P [(match_operand:P 3 "const_int_operand" "n,n")] UNSPEC_TOCSLOT))
+ (clobber (reg:P LR_REGNO))]
+ "DEFAULT_ABI == ABI_ELFv2 && !rs6000_speculate_indirect_jumps"
+ "crset eq\;beq%T1l-\;<ptrload> 2,%3(1)"
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "12")])
;; Call subroutine returning any type.
(define_expand "untyped_call"
[(set_attr "type" "jmpreg")])
(define_expand "indirect_jump"
- [(set (pc) (match_operand 0 "register_operand"))])
+ [(set (pc) (match_operand 0 "register_operand"))]
+ ""
+{
+ if (!rs6000_speculate_indirect_jumps) {
+ rtx ccreg = gen_reg_rtx (CCmode);
+ if (Pmode == DImode)
+ emit_jump_insn (gen_indirect_jumpdi_nospec (operands[0], ccreg));
+ else
+ emit_jump_insn (gen_indirect_jumpsi_nospec (operands[0], ccreg));
+ DONE;
+ }
+})
(define_insn "*indirect_jump<mode>"
[(set (pc)
(match_operand:P 0 "register_operand" "c,*l"))]
- ""
+ "rs6000_speculate_indirect_jumps"
"b%T0"
[(set_attr "type" "jmpreg")])
+(define_insn "indirect_jump<mode>_nospec"
+ [(set (pc) (match_operand:P 0 "register_operand" "c,*l"))
+ (clobber (match_operand:CC 1 "cc_reg_operand" "=y,y"))]
+ "!rs6000_speculate_indirect_jumps"
+ "crset %E1\;beq%T0- %1\;b ."
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "12")])
+
;; Table jump for switch statements:
(define_expand "tablejump"
[(use (match_operand 0))
(use (label_ref (match_operand 1)))]
""
{
- if (TARGET_32BIT)
- emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+ if (rs6000_speculate_indirect_jumps)
+ {
+ if (TARGET_32BIT)
+ emit_jump_insn (gen_tablejumpsi (operands[0], operands[1]));
+ else
+ emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+ }
else
- emit_jump_insn (gen_tablejumpdi (operands[0], operands[1]));
+ {
+ rtx ccreg = gen_reg_rtx (CCmode);
+ rtx jump;
+ if (TARGET_32BIT)
+ jump = gen_tablejumpsi_nospec (operands[0], operands[1], ccreg);
+ else
+ jump = gen_tablejumpdi_nospec (operands[0], operands[1], ccreg);
+ emit_jump_insn (jump);
+ }
DONE;
})
(parallel [(set (pc)
(match_dup 3))
(use (label_ref (match_operand 1)))])]
- "TARGET_32BIT"
+ "TARGET_32BIT && rs6000_speculate_indirect_jumps"
{
operands[0] = force_reg (SImode, operands[0]);
operands[2] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
operands[3] = gen_reg_rtx (SImode);
})
+(define_expand "tablejumpsi_nospec"
+ [(set (match_dup 4)
+ (plus:SI (match_operand:SI 0)
+ (match_dup 3)))
+ (parallel [(set (pc)
+ (match_dup 4))
+ (use (label_ref (match_operand 1)))
+ (clobber (match_operand 2))])]
+ "TARGET_32BIT && !rs6000_speculate_indirect_jumps"
+{
+ operands[0] = force_reg (SImode, operands[0]);
+ operands[3] = force_reg (SImode, gen_rtx_LABEL_REF (SImode, operands[1]));
+ operands[4] = gen_reg_rtx (SImode);
+})
+
(define_expand "tablejumpdi"
[(set (match_dup 4)
(sign_extend:DI (match_operand:SI 0 "lwa_operand")))
(parallel [(set (pc)
(match_dup 3))
(use (label_ref (match_operand 1)))])]
- "TARGET_64BIT"
+ "TARGET_64BIT && rs6000_speculate_indirect_jumps"
{
operands[2] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
operands[3] = gen_reg_rtx (DImode);
operands[4] = gen_reg_rtx (DImode);
})
+(define_expand "tablejumpdi_nospec"
+ [(set (match_dup 5)
+ (sign_extend:DI (match_operand:SI 0 "lwa_operand")))
+ (set (match_dup 4)
+ (plus:DI (match_dup 5)
+ (match_dup 3)))
+ (parallel [(set (pc)
+ (match_dup 4))
+ (use (label_ref (match_operand 1)))
+ (clobber (match_operand 2))])]
+ "TARGET_64BIT && !rs6000_speculate_indirect_jumps"
+{
+ operands[3] = force_reg (DImode, gen_rtx_LABEL_REF (DImode, operands[1]));
+ operands[4] = gen_reg_rtx (DImode);
+ operands[5] = gen_reg_rtx (DImode);
+})
+
(define_insn "*tablejump<mode>_internal1"
[(set (pc)
(match_operand:P 0 "register_operand" "c,*l"))
(use (label_ref (match_operand 1)))]
- ""
+ "rs6000_speculate_indirect_jumps"
"b%T0"
[(set_attr "type" "jmpreg")])
+(define_insn "*tablejump<mode>_internal1_nospec"
+ [(set (pc)
+ (match_operand:P 0 "register_operand" "c,*l"))
+ (use (label_ref (match_operand 1)))
+ (clobber (match_operand:CC 2 "cc_reg_operand" "=y,y"))]
+ "!rs6000_speculate_indirect_jumps"
+ "crset %E2\;beq%T0- %2\;b ."
+ [(set_attr "type" "jmpreg")
+ (set_attr "length" "12")])
+
(define_insn "nop"
[(unspec [(const_int 0)] UNSPEC_NOP)]
""