UNSPEC_CALL_NEEDS_VZEROUPPER
UNSPEC_PAUSE
UNSPEC_LEA_ADDR
+ UNSPEC_STOS
;; For SSE/MMX support:
UNSPEC_FIX_NOTRUNC
;; For RDRAND support
UNSPECV_RDRAND
-])
+
+ ;; Non-local goto.
+ UNSPECV_NLGR
+ ])
;; Constants to represent rounding modes in the ROUND instruction
(define_constants
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (4)));
})
split_double_mode (DImode, &operands[1], 1, &operands[2], &operands[3]);
operands[1] = gen_lowpart (DImode, operands[2]);
- operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (DImode, stack_pointer_rtx,
+ operands[2] = gen_rtx_MEM (SImode, gen_rtx_PLUS (Pmode, stack_pointer_rtx,
GEN_INT (4)));
})
[(set_attr "type" "*,*,sselog1,ssemov,ssemov")
(set_attr "prefix" "*,*,maybe_vex,maybe_vex,maybe_vex")
(set (attr "mode")
- (cond [(eq_attr "alternative" "2,3")
- (if_then_else
- (match_test "optimize_function_for_size_p (cfun)")
- (const_string "V4SF")
- (const_string "TI"))
- (eq_attr "alternative" "4")
- (if_then_else
- (ior (match_test "TARGET_SSE_TYPELESS_STORES")
- (match_test "optimize_function_for_size_p (cfun)"))
- (const_string "V4SF")
- (const_string "TI"))]
- (const_string "DI")))])
+ (cond [(eq_attr "alternative" "0,1")
+ (const_string "DI")
+ (ior (not (match_test "TARGET_SSE2"))
+ (match_test "optimize_function_for_size_p (cfun)"))
+ (const_string "V4SF")
+ (and (eq_attr "alternative" "4")
+ (match_test "TARGET_SSE_TYPELESS_STORES"))
+ (const_string "V4SF")
+ ]
+ (const_string "TI")))])
(define_split
[(set (match_operand:TI 0 "nonimmediate_operand" "")
"TARGET_LP64 && ix86_check_movabs (insn, 0)"
"@
movabs{<imodesuffix>}\t{%1, %P0|[%P0], %1}
- mov{<imodesuffix>}\t{%1, %a0|%a0, %1}"
+ mov{<imodesuffix>}\t{%1, %a0|<iptrsize> PTR %a0, %1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
"TARGET_LP64 && ix86_check_movabs (insn, 1)"
"@
movabs{<imodesuffix>}\t{%P1, %0|%0, [%P1]}
- mov{<imodesuffix>}\t{%a1, %0|%0, %a1}"
+ mov{<imodesuffix>}\t{%a1, %0|%0, <iptrsize> PTR %a1}"
[(set_attr "type" "imov")
(set_attr "modrm" "0,*")
(set_attr "length_address" "8,0")
})
(define_insn "*zero_extendsidi2_rex64"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,?*y,?*Yi,*x")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,o,?*Ym,?!*y,?*Yi,*x")
(zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "rm,0,r ,m ,r ,m")))]
+ (match_operand:SI 1 "nonimmediate_operand" "rm,0,r ,m ,r ,m")))]
"TARGET_64BIT"
"@
mov{l}\t{%1, %k0|%k0, %1}
;; %%% Kill me once multi-word ops are sane.
(define_insn "zero_extendsidi2_1"
- [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?o,?*Ym,?*y,?*Yi,*x")
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?o,?*Ym,?!*y,?*Yi,*x")
(zero_extend:DI
- (match_operand:SI 1 "nonimmediate_operand" "0,rm,r ,r ,m ,r ,m")))
+ (match_operand:SI 1 "nonimmediate_operand" "0,rm,r ,r ,m ,r ,m")))
(clobber (reg:CC FLAGS_REG))]
"!TARGET_64BIT"
"@
(set_attr "pent_pair" "pu")
(set_attr "mode" "SI")])
\f
-;; Overflow setting add and subtract instructions
+;; Overflow setting add instructions
(define_insn "*add<mode>3_cconly_overflow"
[(set (reg:CCC FLAGS_REG)
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*sub<mode>3_cconly_overflow"
- [(set (reg:CCC FLAGS_REG)
- (compare:CCC
- (minus:SWI
- (match_operand:SWI 0 "nonimmediate_operand" "<r>m,<r>")
- (match_operand:SWI 1 "<general_operand>" "<r><i>,<r>m"))
- (match_dup 0)))]
- ""
- "cmp{<imodesuffix>}\t{%1, %0|%0, %1}"
- [(set_attr "type" "icmp")
- (set_attr "mode" "<MODE>")])
-
-(define_insn "*<plusminus_insn><mode>3_cc_overflow"
+(define_insn "*add<mode>3_cc_overflow"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (plusminus:SWI
- (match_operand:SWI 1 "nonimmediate_operand" "<comm>0,0")
+ (plus:SWI
+ (match_operand:SWI 1 "nonimmediate_operand" "%0,0")
(match_operand:SWI 2 "<general_operand>" "<r><i>,<r>m"))
(match_dup 1)))
(set (match_operand:SWI 0 "nonimmediate_operand" "=<r>m,<r>")
- (plusminus:SWI (match_dup 1) (match_dup 2)))]
- "ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)"
- "<plusminus_mnemonic>{<imodesuffix>}\t{%2, %0|%0, %2}"
+ (plus:SWI (match_dup 1) (match_dup 2)))]
+ "ix86_binary_operator_ok (PLUS, <MODE>mode, operands)"
+ "add{<imodesuffix>}\t{%2, %0|%0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "<MODE>")])
-(define_insn "*<plusminus_insn>si3_zext_cc_overflow"
+(define_insn "*addsi3_zext_cc_overflow"
[(set (reg:CCC FLAGS_REG)
(compare:CCC
- (plusminus:SI
- (match_operand:SI 1 "nonimmediate_operand" "<comm>0")
+ (plus:SI
+ (match_operand:SI 1 "nonimmediate_operand" "%0")
(match_operand:SI 2 "x86_64_general_operand" "rme"))
(match_dup 1)))
(set (match_operand:DI 0 "register_operand" "=r")
- (zero_extend:DI (plusminus:SI (match_dup 1) (match_dup 2))))]
- "TARGET_64BIT && ix86_binary_operator_ok (<CODE>, SImode, operands)"
- "<plusminus_mnemonic>{l}\t{%2, %k0|%k0, %2}"
+ (zero_extend:DI (plus:SI (match_dup 1) (match_dup 2))))]
+ "TARGET_64BIT && ix86_binary_operator_ok (PLUS, SImode, operands)"
+ "add{l}\t{%2, %k0|%k0, %2}"
[(set_attr "type" "alu")
(set_attr "mode" "SI")])
(const_int 0)))
(set (match_operand:DI 0 "nonimmediate_operand" "=r,r,rm")
(and:DI (match_dup 1) (match_dup 2)))]
- "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode)
+ "TARGET_64BIT
+ && ix86_match_ccmode
+ (insn,
+ /* If we are going to emit andl instead of andq, and the operands[2]
+ constant might have the SImode sign bit set, make sure the sign
+ flag isn't tested, because the instruction will set the sign flag
+ based on bit 31 rather than bit 63. If it isn't CONST_INT,
+ conservatively assume it might have bit 31 set. */
+ (satisfies_constraint_Z (operands[2])
+ && (!CONST_INT_P (operands[2])
+ || val_signbit_known_set_p (SImode, INTVAL (operands[2]))))
+ ? CCZmode : CCNOmode)
&& ix86_binary_operator_ok (AND, DImode, operands)"
"@
and{l}\t{%k2, %k0|%k0, %k2}
})
;; Avoid useless masking of count operand.
-(define_insn_and_split "*ashl<mode>3_mask"
+(define_insn "*ashl<mode>3_mask"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
(ashift:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "0")
(subreg:QI
(and:SI
- (match_operand:SI 2 "nonimmediate_operand" "c")
+ (match_operand:SI 2 "register_operand" "c")
(match_operand:SI 3 "const_int_operand" "n")) 0)))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (ASHIFT, <MODE>mode, operands)
&& (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
== GET_MODE_BITSIZE (<MODE>mode)-1"
- "#"
- "&& 1"
- [(parallel [(set (match_dup 0)
- (ashift:SWI48 (match_dup 1) (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
{
- if (can_create_pseudo_p ())
- operands [2] = force_reg (SImode, operands[2]);
-
- operands[2] = simplify_gen_subreg (QImode, operands[2], SImode, 0);
+ return "sal{<imodesuffix>}\t{%b2, %0|%0, %b2}";
}
[(set_attr "type" "ishift")
(set_attr "mode" "<MODE>")])
"ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;")
;; Avoid useless masking of count operand.
-(define_insn_and_split "*<shift_insn><mode>3_mask"
+(define_insn "*<shift_insn><mode>3_mask"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
(any_shiftrt:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "0")
(subreg:QI
(and:SI
- (match_operand:SI 2 "nonimmediate_operand" "c")
+ (match_operand:SI 2 "register_operand" "c")
(match_operand:SI 3 "const_int_operand" "n")) 0)))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
&& (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
== GET_MODE_BITSIZE (<MODE>mode)-1"
- "#"
- "&& 1"
- [(parallel [(set (match_dup 0)
- (any_shiftrt:SWI48 (match_dup 1) (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
{
- if (can_create_pseudo_p ())
- operands [2] = force_reg (SImode, operands[2]);
-
- operands[2] = simplify_gen_subreg (QImode, operands[2], SImode, 0);
+ return "<shift>{<imodesuffix>}\t{%b2, %0|%0, %b2}";
}
[(set_attr "type" "ishift")
(set_attr "mode" "<MODE>")])
"ix86_expand_binary_operator (<CODE>, <MODE>mode, operands); DONE;")
;; Avoid useless masking of count operand.
-(define_insn_and_split "*<rotate_insn><mode>3_mask"
+(define_insn "*<rotate_insn><mode>3_mask"
[(set (match_operand:SWI48 0 "nonimmediate_operand" "=rm")
(any_rotate:SWI48
(match_operand:SWI48 1 "nonimmediate_operand" "0")
(subreg:QI
(and:SI
- (match_operand:SI 2 "nonimmediate_operand" "c")
+ (match_operand:SI 2 "register_operand" "c")
(match_operand:SI 3 "const_int_operand" "n")) 0)))
(clobber (reg:CC FLAGS_REG))]
"ix86_binary_operator_ok (<CODE>, <MODE>mode, operands)
&& (INTVAL (operands[3]) & (GET_MODE_BITSIZE (<MODE>mode)-1))
== GET_MODE_BITSIZE (<MODE>mode)-1"
- "#"
- "&& 1"
- [(parallel [(set (match_dup 0)
- (any_rotate:SWI48 (match_dup 1) (match_dup 2)))
- (clobber (reg:CC FLAGS_REG))])]
{
- if (can_create_pseudo_p ())
- operands [2] = force_reg (SImode, operands[2]);
-
- operands[2] = simplify_gen_subreg (QImode, operands[2], SImode, 0);
+ return "<rotate>{<imodesuffix>}\t{%b2, %0|%0, %b2}";
}
[(set_attr "type" "rotate")
(set_attr "mode" "<MODE>")])
(define_insn "bmi_bextr_<mode>"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (unspec:SWI48 [(match_operand:SWI48 1 "register_operand" "r")
- (match_operand:SWI48 2 "nonimmediate_operand" "rm")]
+ (unspec:SWI48 [(match_operand:SWI48 1 "nonimmediate_operand" "rm")
+ (match_operand:SWI48 2 "register_operand" "r")]
UNSPEC_BEXTR))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI"
;; BMI2 instructions.
(define_insn "bmi2_bzhi_<mode>3"
[(set (match_operand:SWI48 0 "register_operand" "=r")
- (and:SWI48 (match_operand:SWI48 1 "register_operand" "r")
- (lshiftrt:SWI48 (const_int -1)
- (match_operand:SWI48 2 "nonimmediate_operand" "rm"))))
+ (and:SWI48 (lshiftrt:SWI48 (const_int -1)
+ (match_operand:SWI48 2 "register_operand" "r"))
+ (match_operand:SWI48 1 "nonimmediate_operand" "rm")))
(clobber (reg:CC FLAGS_REG))]
"TARGET_BMI2"
"bzhi\t{%2, %1, %0|%0, %1, %2}"
[(parallel [(set (match_operand 1 "memory_operand" "")
(match_operand 2 "register_operand" ""))
(set (match_operand 0 "register_operand" "")
- (match_operand 3 "" ""))])]
+ (match_operand 3 "" ""))
+ (unspec [(const_int 0)] UNSPEC_STOS)])]
""
"ix86_current_function_needs_cld = 1;")
(match_operand:DI 2 "register_operand" "a"))
(set (match_operand:DI 0 "register_operand" "=D")
(plus:DI (match_dup 1)
- (const_int 8)))]
+ (const_int 8)))
+ (unspec [(const_int 0)] UNSPEC_STOS)]
"TARGET_64BIT
&& !(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
"stosq"
(match_operand:SI 2 "register_operand" "a"))
(set (match_operand:P 0 "register_operand" "=D")
(plus:P (match_dup 1)
- (const_int 4)))]
+ (const_int 4)))
+ (unspec [(const_int 0)] UNSPEC_STOS)]
"!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
"stos{l|d}"
[(set_attr "type" "str")
(match_operand:HI 2 "register_operand" "a"))
(set (match_operand:P 0 "register_operand" "=D")
(plus:P (match_dup 1)
- (const_int 2)))]
+ (const_int 2)))
+ (unspec [(const_int 0)] UNSPEC_STOS)]
"!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
"stosw"
[(set_attr "type" "str")
(match_operand:QI 2 "register_operand" "a"))
(set (match_operand:P 0 "register_operand" "=D")
(plus:P (match_dup 1)
- (const_int 1)))]
+ (const_int 1)))
+ (unspec [(const_int 0)] UNSPEC_STOS)]
"!(fixed_regs[AX_REG] || fixed_regs[DI_REG])"
"stosb"
[(set_attr "type" "str")
emit_insn (gen_set_got (pic_offset_table_rtx));
DONE;
})
-\f
+
+(define_insn_and_split "nonlocal_goto_receiver"
+ [(unspec_volatile [(const_int 0)] UNSPECV_NLGR)]
+ "TARGET_MACHO && !TARGET_64BIT && flag_pic"
+ "#"
+ "&& reload_completed"
+ [(const_int 0)]
+{
+ if (crtl->uses_pic_offset_table)
+ {
+ rtx xops[3];
+ rtx label_rtx = gen_label_rtx ();
+ rtx tmp;
+
+ /* Get a new pic base. */
+ emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx));
+ /* Correct this with the offset from the new to the old. */
+ xops[0] = xops[1] = pic_offset_table_rtx;
+ label_rtx = gen_rtx_LABEL_REF (SImode, label_rtx);
+ tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, label_rtx),
+ UNSPEC_MACHOPIC_OFFSET);
+ xops[2] = gen_rtx_CONST (Pmode, tmp);
+ ix86_expand_binary_operator (MINUS, SImode, xops);
+ }
+ else
+ /* No pic reg restore needed. */
+ emit_note (NOTE_INSN_DELETED);
+
+ DONE;
+})
+
;; Avoid redundant prefixes by splitting HImode arithmetic to SImode.
(define_split
"(TARGET_READ_MODIFY_WRITE || optimize_insn_for_size_p ())
&& peep2_reg_dead_p (4, operands[0])
&& !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
&& (<MODE>mode != QImode
|| immediate_operand (operands[2], QImode)
|| q_regs_operand (operands[2], QImode))
|| immediate_operand (operands[2], SImode)
|| q_regs_operand (operands[2], SImode))
&& !reg_overlap_mentioned_p (operands[0], operands[1])
+ && !reg_overlap_mentioned_p (operands[0], operands[2])
&& ix86_match_ccmode (peep2_next_insn (3),
(GET_CODE (operands[3]) == PLUS
|| GET_CODE (operands[3]) == MINUS)