X-Git-Url: http://git.sourceforge.jp/view?a=blobdiff_plain;f=gcc%2Fconfig%2Fi386%2Fi386.md;h=639f0b44f744a814de9a770c92e42930349d66f5;hb=bb75867163b3c8d204e3032d971fb114017e6e47;hp=44983193650a5df83d43e5e7c588036127214ba4;hpb=3cb7a12915b19dc2f21263f46764df080e75aab8;p=pf3gnuchains%2Fgcc-fork.git diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 44983193650..639f0b44f74 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -1,6 +1,6 @@ ;; GCC machine description for IA-32 and x86-64. ;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, -;; 2001, 2002, 2003, 2004, 2005 +;; 2001, 2002, 2003, 2004, 2005, 2006 ;; Free Software Foundation, Inc. ;; Mostly by William Schelter. ;; x86_64 support added by Jan Hubicka @@ -73,6 +73,7 @@ (UNSPEC_TP 16) (UNSPEC_TLS_GD 17) (UNSPEC_TLS_LD_BASE 18) + (UNSPEC_TLSDESC 19) ; Other random patterns (UNSPEC_SCAS 20) @@ -83,6 +84,7 @@ (UNSPEC_FLDCW 25) (UNSPEC_REP 26) (UNSPEC_EH_RETURN 27) + (UNSPEC_LD_MPIC 28) ; load_macho_picbase ; For SSE/MMX support: (UNSPEC_FIX_NOTRUNC 30) @@ -185,7 +187,7 @@ ;; Processor type. This attribute must exactly match the processor_type ;; enumeration in i386.h. -(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona" +(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6,athlon,pentium4,k8,nocona,generic32,generic64" (const (symbol_ref "ix86_tune"))) ;; A basic instruction type. Refinements due to arguments to be @@ -473,9 +475,10 @@ (include "athlon.md") -;; Operand and operator predicates +;; Operand and operator predicates and constraints (include "predicates.md") +(include "constraints.md") ;; Compare instructions. @@ -965,8 +968,8 @@ (define_insn "*cmpfp_i_mixed" [(set (reg:CCFP FLAGS_REG) - (compare:CCFP (match_operand 0 "register_operand" "f#x,x#f") - (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))] + (compare:CCFP (match_operand 0 "register_operand" "f,x") + (match_operand 1 "nonimmediate_operand" "f,xm")))] "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" @@ -1014,8 +1017,8 @@ (define_insn "*cmpfp_iu_mixed" [(set (reg:CCFPU FLAGS_REG) - (compare:CCFPU (match_operand 0 "register_operand" "f#x,x#f") - (match_operand 1 "nonimmediate_operand" "f#x,xm#f")))] + (compare:CCFPU (match_operand 0 "register_operand" "f,x") + (match_operand 1 "nonimmediate_operand" "f,xm")))] "TARGET_MIX_SSE_I387 && SSE_FLOAT_MODE_P (GET_MODE (operands[0])) && GET_MODE (operands[0]) == GET_MODE (operands[1])" @@ -1509,8 +1512,12 @@ (const_string "SI") (and (eq_attr "type" "imov") (and (eq_attr "alternative" "0,1") - (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY") - (const_int 0)))) + (and (ne (symbol_ref "TARGET_PARTIAL_REG_DEPENDENCY") + (const_int 0)) + (and (eq (symbol_ref "optimize_size") + (const_int 0)) + (eq (symbol_ref "TARGET_PARTIAL_REG_STALL") + (const_int 0)))))) (const_string "SI") ;; Avoid partial register stalls when not using QImode arithmetic (and (eq_attr "type" "imov") @@ -2215,7 +2222,7 @@ (define_insn "*pushsf" [(set (match_operand:SF 0 "push_operand" "=<,<,<") - (match_operand:SF 1 "general_no_elim_operand" "f#rx,rFm#fx,x#rf"))] + (match_operand:SF 1 "general_no_elim_operand" "f,rFm,x"))] "!TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -2228,7 +2235,7 @@ (define_insn "*pushsf_rex64" [(set (match_operand:SF 0 "push_operand" "=X,X,X") - (match_operand:SF 1 "nonmemory_no_elim_operand" "f#rx,rF#fx,x#rf"))] + (match_operand:SF 1 "nonmemory_no_elim_operand" "f,rF,x"))] "TARGET_64BIT" { /* Anything else should be already split before reg-stack. */ @@ -2267,9 +2274,9 @@ (define_insn "*movsf_1" [(set (match_operand:SF 0 "nonimmediate_operand" - "=f#xr,m ,f#xr,r#xf ,m ,x#rf,x#rf,x#rf ,m ,!*y,!rm,!*y") + "=f,m ,f,r ,m ,x,x,x ,m ,!*y,!rm,!*y") (match_operand:SF 1 "general_operand" - "fm#rx,f#rx,G ,rmF#fx,Fr#fx,C ,x ,xm#rf,x#rf,rm ,*y ,*y"))] + "fm,f,G ,rmF,Fr,C ,x ,xm,x,rm ,*y ,*y"))] "!(MEM_P (operands[0]) && MEM_P (operands[1])) && (reload_in_progress || reload_completed || (ix86_cmodel == CM_MEDIUM || ix86_cmodel == CM_LARGE) @@ -2382,7 +2389,7 @@ (define_insn "*pushdf_nointeger" [(set (match_operand:DF 0 "push_operand" "=<,<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f#Y,Fo#fY,*r#fY,Y#f"))] + (match_operand:DF 1 "general_no_elim_operand" "f,Fo,*r,Y"))] "!TARGET_64BIT && !TARGET_INTEGER_DFMODE_MOVES" { /* This insn should be already split before reg-stack. */ @@ -2394,7 +2401,7 @@ (define_insn "*pushdf_integer" [(set (match_operand:DF 0 "push_operand" "=<,<,<") - (match_operand:DF 1 "general_no_elim_operand" "f#rY,rFo#fY,Y#rf"))] + (match_operand:DF 1 "general_no_elim_operand" "f,rFo,Y"))] "TARGET_64BIT || TARGET_INTEGER_DFMODE_MOVES" { /* This insn should be already split before reg-stack. */ @@ -2434,9 +2441,9 @@ (define_insn "*movdf_nointeger" [(set (match_operand:DF 0 "nonimmediate_operand" - "=f#Y,m ,f#Y,*r ,o ,Y*x#f,Y*x#f,Y*x#f ,m ") + "=f,m,f,*r ,o ,Y*x,Y*x,Y*x ,m ") (match_operand:DF 1 "general_operand" - "fm#Y,f#Y,G ,*roF,F*r,C ,Y*x#f,HmY*x#f,Y*x#f"))] + "fm,f,G,*roF,F*r,C ,Y*x,mY*x,Y*x"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && ((optimize_size || !TARGET_INTEGER_DFMODE_MOVES) && !TARGET_64BIT) && (reload_in_progress || reload_completed @@ -2554,9 +2561,9 @@ (define_insn "*movdf_integer" [(set (match_operand:DF 0 "nonimmediate_operand" - "=f#Yr,m ,f#Yr,r#Yf ,o ,Y*x#rf,Y*x#rf,Y*x#rf,m") + "=f,m,f,r ,o ,Y*x,Y*x,Y*x,m ") (match_operand:DF 1 "general_operand" - "fm#Yr,f#Yr,G ,roF#Yf,Fr#Yf,C ,Y*x#rf,m ,Y*x#rf"))] + "fm,f,G,roF,Fr,C ,Y*x,m ,Y*x"))] "(GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && ((!optimize_size && TARGET_INTEGER_DFMODE_MOVES) || TARGET_64BIT) && (reload_in_progress || reload_completed @@ -2729,7 +2736,7 @@ (define_insn "*pushxf_integer" [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_no_elim_operand" "f#r,ro#f"))] + (match_operand:XF 1 "general_no_elim_operand" "f,ro"))] "!optimize_size" { /* This insn should be already split before reg-stack. */ @@ -2801,8 +2808,8 @@ (set_attr "mode" "XF,XF,XF,SI,SI")]) (define_insn "*movxf_integer" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f#r,m,f#r,r#f,o") - (match_operand:XF 1 "general_operand" "fm#r,f#r,G,roF#f,Fr#f"))] + [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,r,o") + (match_operand:XF 1 "general_operand" "fm,f,G,roF,Fr"))] "!optimize_size && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) && (reload_in_progress || reload_completed @@ -3515,14 +3522,24 @@ /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + { + if ((!TARGET_SSE2 || TARGET_MIX_SSE_I387) + && standard_80387_constant_p (operands[1]) > 0) + { + operands[1] = simplify_const_unary_operation + (FLOAT_EXTEND, DFmode, operands[1], SFmode); + emit_move_insn_1 (operands[0], operands[1]); + DONE; + } + operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + } if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) (define_insn "*extendsfdf2_mixed" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f#Y,m#fY,Y#f") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm#Y,f#Y,mY#f")))] + [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,Y") + (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f,mY")))] "TARGET_SSE2 && TARGET_MIX_SSE_I387 && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" { @@ -3588,7 +3605,16 @@ /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + { + if (standard_80387_constant_p (operands[1]) > 0) + { + operands[1] = simplify_const_unary_operation + (FLOAT_EXTEND, XFmode, operands[1], SFmode); + emit_move_insn_1 (operands[0], operands[1]); + DONE; + } + operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); + } if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (SFmode, operands[1]); }) @@ -3627,7 +3653,16 @@ /* ??? Needed for compress_float_constant since all fp constants are LEGITIMATE_CONSTANT_P. */ if (GET_CODE (operands[1]) == CONST_DOUBLE) - operands[1] = validize_mem (force_const_mem (DFmode, operands[1])); + { + if (standard_80387_constant_p (operands[1]) > 0) + { + operands[1] = simplify_const_unary_operation + (FLOAT_EXTEND, XFmode, operands[1], DFmode); + emit_move_insn_1 (operands[0], operands[1]); + DONE; + } + operands[1] = validize_mem (force_const_mem (DFmode, operands[1])); + } if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) operands[1] = force_reg (DFmode, operands[1]); }) @@ -3837,7 +3872,7 @@ }) (define_insn "*truncxfsf2_mixed" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#rx,?r#fx,?x#rf") + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r,?x") (float_truncate:SF (match_operand:XF 1 "register_operand" "f,f,f,f"))) (clobber (match_operand:SF 2 "memory_operand" "=X,m,m,m"))] @@ -3864,7 +3899,7 @@ (set_attr "mode" "SF")]) (define_insn "*truncxfsf2_i387" - [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f#r,?r#f") + [(set (match_operand:SF 0 "nonimmediate_operand" "=m,?f,?r") (float_truncate:SF (match_operand:XF 1 "register_operand" "f,f,f"))) (clobber (match_operand:SF 2 "memory_operand" "=X,m,m"))] @@ -3935,7 +3970,7 @@ }) (define_insn "*truncxfdf2_mixed" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#rY,?r#fY,?Y#rf") + [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r,?Y") (float_truncate:DF (match_operand:XF 1 "register_operand" "f,f,f,f"))) (clobber (match_operand:DF 2 "memory_operand" "=X,m,m,m"))] @@ -3962,7 +3997,7 @@ (set_attr "mode" "DF")]) (define_insn "*truncxfdf2_i387" - [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f#r,?r#f") + [(set (match_operand:DF 0 "nonimmediate_operand" "=m,?f,?r") (float_truncate:DF (match_operand:XF 1 "register_operand" "f,f,f"))) (clobber (match_operand:DF 2 "memory_operand" "=X,m,m"))] @@ -4143,7 +4178,7 @@ [(match_scratch:DF 2 "Y") (set (match_operand:SSEMODEI24 0 "register_operand" "") (fix:SSEMODEI24 (match_operand:DF 1 "memory_operand" "")))] - "TARGET_K8 && !optimize_size" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))] "") @@ -4152,7 +4187,7 @@ [(match_scratch:SF 2 "x") (set (match_operand:SSEMODEI24 0 "register_operand" "") (fix:SSEMODEI24 (match_operand:SF 1 "memory_operand" "")))] - "TARGET_K8 && !optimize_size" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size" [(set (match_dup 2) (match_dup 1)) (set (match_dup 0) (fix:SSEMODEI24 (match_dup 2)))] "") @@ -4436,7 +4471,7 @@ "") (define_insn "*floatsisf2_mixed" - [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f") + [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x") (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_MIX_SSE_I387" "@ @@ -4479,7 +4514,7 @@ "") (define_insn "*floatdisf2_mixed" - [(set (match_operand:SF 0 "register_operand" "=f#x,?f#x,x#f,x#f") + [(set (match_operand:SF 0 "register_operand" "=f,?f,x,x") (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_64BIT && TARGET_MIX_SSE_I387" "@ @@ -4547,7 +4582,7 @@ "") (define_insn "*floatsidf2_mixed" - [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f") + [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y") (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_SSE2 && TARGET_MIX_SSE_I387" "@ @@ -4590,7 +4625,7 @@ "") (define_insn "*floatdidf2_mixed" - [(set (match_operand:DF 0 "register_operand" "=f#Y,?f#Y,Y#f,Y#f") + [(set (match_operand:DF 0 "register_operand" "=f,?f,Y,Y") (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,r,r,mr")))] "TARGET_64BIT && TARGET_SSE2 && TARGET_MIX_SSE_I387" "@ @@ -6683,7 +6718,7 @@ (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCmode) && ix86_binary_operator_ok (MINUS, SImode, operands)" - "sub{q}\t{%2, %0|%0, %2}" + "sub{l}\t{%2, %1|%1, %2}" [(set_attr "type" "alu") (set_attr "mode" "DI")]) @@ -7865,6 +7900,9 @@ (match_operand:SI 2 "const_int_operand" "")) (const_int 0)))] "ix86_match_ccmode (insn, CCNOmode) + && INTVAL (operands[1]) > 0 + && INTVAL (operands[2]) >= 0 + && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 && (GET_MODE (operands[0]) == SImode || (TARGET_64BIT && GET_MODE (operands[0]) == DImode) || GET_MODE (operands[0]) == HImode @@ -7880,8 +7918,8 @@ (const_int 0)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCNOmode) - /* The code below cannot deal with constants outside HOST_WIDE_INT. */ - && INTVAL (operands[1]) + INTVAL (operands[2]) < HOST_BITS_PER_WIDE_INT + && INTVAL (operands[1]) > 0 + && INTVAL (operands[2]) >= 0 /* Ensure that resulting mask is zero or sign extended operand. */ && (INTVAL (operands[1]) + INTVAL (operands[2]) <= 32 || (INTVAL (operands[1]) + INTVAL (operands[2]) == 64 @@ -7936,8 +7974,11 @@ val = gen_lowpart (QImode, val); } - mask = ((HOST_WIDE_INT)1 << (pos + len)) - 1; - mask &= ~(((HOST_WIDE_INT)1 << pos) - 1); + if (len == HOST_BITS_PER_WIDE_INT) + mask = -1; + else + mask = ((HOST_WIDE_INT)1 << len) - 1; + mask <<= pos; operands[2] = gen_rtx_AND (mode, val, gen_int_mode (mask, mode)); }) @@ -9504,10 +9545,10 @@ "ix86_expand_fp_absneg_operator (ABS, SFmode, operands); DONE;") (define_insn "*absnegsf2_mixed" - [(set (match_operand:SF 0 "nonimmediate_operand" "=x#f,x#f,f#x,rm") + [(set (match_operand:SF 0 "nonimmediate_operand" "=x ,x,f,rm") (match_operator:SF 3 "absneg_operator" - [(match_operand:SF 1 "nonimmediate_operand" "0 ,x#f,0 ,0")])) - (use (match_operand:V4SF 2 "nonimmediate_operand" "xm ,0 ,X ,X")) + [(match_operand:SF 1 "nonimmediate_operand" "0 ,x,0,0 ")])) + (use (match_operand:V4SF 2 "nonimmediate_operand" "xm ,0,X,X ")) (clobber (reg:CC FLAGS_REG))] "TARGET_SSE_MATH && TARGET_MIX_SSE_I387 && ix86_unary_operator_ok (GET_CODE (operands[3]), SFmode, operands)" @@ -9600,10 +9641,10 @@ "ix86_expand_fp_absneg_operator (ABS, DFmode, operands); DONE;") (define_insn "*absnegdf2_mixed" - [(set (match_operand:DF 0 "nonimmediate_operand" "=Y#f,Y#f,f#Y,rm") + [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,f,rm") (match_operator:DF 3 "absneg_operator" - [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y#f,0 ,0")])) - (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym ,0 ,X ,X")) + [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0,0")])) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X,X")) (clobber (reg:CC FLAGS_REG))] "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)" @@ -9612,8 +9653,8 @@ (define_insn "*absnegdf2_sse" [(set (match_operand:DF 0 "nonimmediate_operand" "=Y,Y,rm") (match_operator:DF 3 "absneg_operator" - [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0")])) - (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X")) + [(match_operand:DF 1 "nonimmediate_operand" "0 ,Y,0 ")])) + (use (match_operand:V2DF 2 "nonimmediate_operand" "Ym,0,X ")) (clobber (reg:CC FLAGS_REG))] "TARGET_SSE2 && TARGET_SSE_MATH && ix86_unary_operator_ok (GET_CODE (operands[3]), DFmode, operands)" @@ -9864,7 +9905,7 @@ (define_insn "*negsf2_1" [(set (match_operand:SF 0 "register_operand" "=f") (neg:SF (match_operand:SF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)" "fchs" [(set_attr "type" "fsgn") (set_attr "mode" "SF")]) @@ -9872,7 +9913,7 @@ (define_insn "*negdf2_1" [(set (match_operand:DF 0 "register_operand" "=f") (neg:DF (match_operand:DF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))" "fchs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) @@ -9880,7 +9921,7 @@ (define_insn "*negxf2_1" [(set (match_operand:XF 0 "register_operand" "=f") (neg:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387" "fchs" [(set_attr "type" "fsgn") (set_attr "mode" "XF")]) @@ -9888,7 +9929,7 @@ (define_insn "*abssf2_1" [(set (match_operand:SF 0 "register_operand" "=f") (abs:SF (match_operand:SF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387 && (reload_completed || !TARGET_SSE_MATH)" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "SF")]) @@ -9896,7 +9937,7 @@ (define_insn "*absdf2_1" [(set (match_operand:DF 0 "register_operand" "=f") (abs:DF (match_operand:DF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387 && (reload_completed || !(TARGET_SSE2 && TARGET_SSE_MATH))" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) @@ -9904,7 +9945,7 @@ (define_insn "*absxf2_1" [(set (match_operand:XF 0 "register_operand" "=f") (abs:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387 && reload_completed" + "TARGET_80387" "fabs" [(set_attr "type" "fsgn") (set_attr "mode" "DF")]) @@ -10355,7 +10396,53 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashift:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, DImode, operands)" + && ix86_binary_operator_ok (ASHIFT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{q}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{q}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{q}\t%0"; + else + return "sal{q}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "DI")]) + +(define_insn "*ashldi3_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "immediate_operand" "e")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { @@ -10562,7 +10649,7 @@ [(const_int 0)] { rtx pat, clob; - emit_move_insn (operands[1], operands[0]); + emit_move_insn (operands[0], operands[1]); pat = gen_rtx_SET (VOIDmode, operands[0], gen_rtx_ASHIFT (GET_MODE (operands[0]), operands[0], operands[2])); @@ -10636,7 +10723,53 @@ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashift:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{l}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{l}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{l}\t%0"; + else + return "sal{l}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "SI")]) + +(define_insn "*ashlsi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { @@ -10673,7 +10806,12 @@ (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashift:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { @@ -10792,7 +10930,53 @@ (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashift:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, HImode, operands)" + && ix86_binary_operator_ok (ASHIFT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{w}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{w}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{w}\t%0"; + else + return "sal{w}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "HI")]) + +(define_insn "*ashlhi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { @@ -10950,7 +11134,53 @@ (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashift:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFT, QImode, operands)" + && ix86_binary_operator_ok (ASHIFT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || (TARGET_DOUBLE_WITH_ADD && REG_P (operands[0])))))" +{ + switch (get_attr_type (insn)) + { + case TYPE_ALU: + gcc_assert (operands[2] == const1_rtx); + return "add{b}\t{%0, %0|%0, %0}"; + + default: + if (REG_P (operands[2])) + return "sal{b}\t{%b2, %0|%0, %b2}"; + else if (operands[2] == const1_rtx + && (TARGET_SHIFT1 || optimize_size)) + return "sal{b}\t%0"; + else + return "sal{b}\t{%2, %0|%0, %2}"; + } +} + [(set (attr "type") + (cond [(and (and (ne (symbol_ref "TARGET_DOUBLE_WITH_ADD") + (const_int 0)) + (match_operand 0 "register_operand" "")) + (match_operand 2 "const1_operand" "")) + (const_string "alu") + ] + (const_string "ishift"))) + (set_attr "mode" "QI")]) + +(define_insn "*ashlqi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL + || (operands[2] == const1_rtx + && (TARGET_SHIFT1 + || TARGET_DOUBLE_WITH_ADD)))" { switch (get_attr_type (insn)) { @@ -11121,6 +11351,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrdi3_one_bit_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" + "sar{q}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. @@ -11133,7 +11377,24 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (ashiftrt:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, DImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{q}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "DI")]) + +(define_insn "*ashrdi3_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_int_operand" "n")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, DImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{q}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "DI")]) @@ -11326,6 +11587,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrsi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" + "sar{l}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + (define_insn "*ashrsi3_one_bit_cmp_zext" [(set (reg FLAGS_REG) (compare @@ -11353,7 +11628,24 @@ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (ashiftrt:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{l}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "SI")]) + +(define_insn "*ashrsi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{l}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) @@ -11367,7 +11659,9 @@ (set (match_operand:DI 0 "register_operand" "=r") (zero_extend:DI (ashiftrt:SI (match_dup 1) (match_dup 2))))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, SImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, SImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) @@ -11427,6 +11721,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrhi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" + "sar{w}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. @@ -11439,7 +11747,24 @@ (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (ashiftrt:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{w}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "HI")]) + +(define_insn "*ashrhi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{w}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "HI")]) @@ -11527,6 +11852,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*ashrqi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" + "sar{b}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. @@ -11539,10 +11878,28 @@ (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (ashiftrt:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (ASHIFTRT, QImode, operands)" + && ix86_binary_operator_ok (ASHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "sar{b}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "QI")]) + +(define_insn "*ashrqi3_cconly" + [(set (reg FLAGS_REG) + (compare + (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (ASHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "sar{b}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "QI")]) + ;; Logical shift instructions @@ -11656,6 +12013,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrdi3_cconly_one_bit_rex64" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "shr{q}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. @@ -11668,7 +12039,24 @@ (set (match_operand:DI 0 "nonimmediate_operand" "=rm") (lshiftrt:DI (match_dup 1) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{q}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "DI")]) + +(define_insn "*lshrdi3_cconly_rex64" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_int_operand" "e")) + (const_int 0))) + (clobber (match_scratch:DI 0 "=r"))] + "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{q}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "DI")]) @@ -11785,6 +12173,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrsi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "shr{l}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + (define_insn "*lshrsi3_cmp_one_bit_zext" [(set (reg FLAGS_REG) (compare @@ -11812,7 +12214,24 @@ (set (match_operand:SI 0 "nonimmediate_operand" "=rm") (lshiftrt:SI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{l}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "SI")]) + +(define_insn "*lshrsi3_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:SI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{l}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) @@ -11826,7 +12245,9 @@ (set (match_operand:DI 0 "register_operand" "=r") (lshiftrt:DI (zero_extend:DI (match_dup 1)) (match_dup 2)))] "TARGET_64BIT && ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{l}\t{%2, %k0|%k0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "SI")]) @@ -11886,6 +12307,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrhi3_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + "shr{w}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. @@ -11898,7 +12333,24 @@ (set (match_operand:HI 0 "nonimmediate_operand" "=rm") (lshiftrt:HI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, HImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{w}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "HI")]) + +(define_insn "*lshrhi3_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:HI 0 "=r"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, HImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{w}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "HI")]) @@ -11985,6 +12437,20 @@ (const_string "2") (const_string "*")))]) +(define_insn "*lshrqi2_one_bit_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const1_operand" "")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && (TARGET_SHIFT1 || optimize_size) + && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" + "shr{b}\t%0" + [(set_attr "type" "ishift") + (set_attr "length" "2")]) + ;; This pattern can't accept a variable shift count, since shifts by ;; zero don't affect the flags. We assume that shifts by constant ;; zero are optimized away. @@ -11997,7 +12463,24 @@ (set (match_operand:QI 0 "nonimmediate_operand" "=qm") (lshiftrt:QI (match_dup 1) (match_dup 2)))] "ix86_match_ccmode (insn, CCGOCmode) - && ix86_binary_operator_ok (LSHIFTRT, QImode, operands)" + && ix86_binary_operator_ok (LSHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" + "shr{b}\t{%2, %0|%0, %2}" + [(set_attr "type" "ishift") + (set_attr "mode" "QI")]) + +(define_insn "*lshrqi2_cconly" + [(set (reg FLAGS_REG) + (compare + (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") + (match_operand:QI 2 "const_1_to_31_operand" "I")) + (const_int 0))) + (clobber (match_scratch:QI 0 "=q"))] + "ix86_match_ccmode (insn, CCGOCmode) + && ix86_binary_operator_ok (LSHIFTRT, QImode, operands) + && (optimize_size + || !TARGET_PARTIAL_FLAG_REG_STALL)" "shr{b}\t{%2, %0|%0, %2}" [(set_attr "type" "ishift") (set_attr "mode" "QI")]) @@ -12460,8 +12943,8 @@ (define_expand "extv" [(set (match_operand:SI 0 "register_operand" "") (sign_extract:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + (match_operand:SI 2 "const8_operand" "") + (match_operand:SI 3 "const8_operand" "")))] "" { /* Handle extractions from %ah et al. */ @@ -12477,8 +12960,8 @@ (define_expand "extzv" [(set (match_operand:SI 0 "register_operand" "") (zero_extract:SI (match_operand 1 "ext_register_operand" "") - (match_operand:SI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")))] + (match_operand:SI 2 "const8_operand" "") + (match_operand:SI 3 "const8_operand" "")))] "" { /* Handle extractions from %ah et al. */ @@ -12493,12 +12976,12 @@ (define_expand "insv" [(set (zero_extract (match_operand 0 "ext_register_operand" "") - (match_operand 1 "immediate_operand" "") - (match_operand 2 "immediate_operand" "")) + (match_operand 1 "const8_operand" "") + (match_operand 2 "const8_operand" "")) (match_operand 3 "register_operand" ""))] "" { - /* Handle extractions from %ah et al. */ + /* Handle insertions to %ah et al. */ if (INTVAL (operands[1]) != 8 || INTVAL (operands[2]) != 8) FAIL; @@ -13129,8 +13612,8 @@ (define_insn "*fp_jcc_1_mixed" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f#x,x#f") - (match_operand 2 "nonimmediate_operand" "f#x,xm#f")]) + [(match_operand 1 "register_operand" "f,x") + (match_operand 2 "nonimmediate_operand" "f,xm")]) (label_ref (match_operand 3 "" "")) (pc))) (clobber (reg:CCFP FPSR_REG)) @@ -13174,8 +13657,8 @@ (define_insn "*fp_jcc_2_mixed" [(set (pc) (if_then_else (match_operator 0 "comparison_operator" - [(match_operand 1 "register_operand" "f#x,x#f") - (match_operand 2 "nonimmediate_operand" "f#x,xm#f")]) + [(match_operand 1 "register_operand" "f,x") + (match_operand 2 "nonimmediate_operand" "f,xm")]) (pc) (label_ref (match_operand 3 "" "")))) (clobber (reg:CCFP FPSR_REG)) @@ -13836,7 +14319,7 @@ #else /* It is tempting to use ASM_OUTPUT_ALIGN here, but we don't want to do that. The align insn is used to avoid 3 jump instructions in the row to improve - branch prediction and the benefits hardly outweight the cost of extra 8 + branch prediction and the benefits hardly outweigh the cost of extra 8 nops on the average inserted by full alignment pseudo operation. */ #endif return ""; @@ -13853,7 +14336,17 @@ (unspec:SI [(const_int 0)] UNSPEC_SET_GOT)) (clobber (reg:CC FLAGS_REG))] "!TARGET_64BIT" - { return output_set_got (operands[0]); } + { return output_set_got (operands[0], NULL_RTX); } + [(set_attr "type" "multi") + (set_attr "length" "12")]) + +(define_insn "set_got_labelled" + [(set (match_operand:SI 0 "register_operand" "=r") + (unspec:SI [(label_ref (match_operand 1 "" ""))] + UNSPEC_SET_GOT)) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT" + { return output_set_got (operands[0], operands[1]); } [(set_attr "type" "multi") (set_attr "length" "12")]) @@ -14144,6 +14637,12 @@ operands[2] = gen_reg_rtx (Pmode); emit_insn (gen_set_got (operands[2])); } + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_32 + (operands[0], operands[1], operands[2])); + DONE; + } operands[3] = ix86_tls_get_addr (); }) @@ -14165,6 +14664,12 @@ UNSPEC_TLS_GD)])] "" { + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_64 + (operands[0], operands[1])); + DONE; + } operands[2] = ix86_tls_get_addr (); }) @@ -14211,6 +14716,12 @@ operands[1] = gen_reg_rtx (Pmode); emit_insn (gen_set_got (operands[1])); } + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_32 + (operands[0], ix86_tls_module_base (), operands[1])); + DONE; + } operands[2] = ix86_tls_get_addr (); }) @@ -14230,6 +14741,12 @@ (unspec:DI [(const_int 0)] UNSPEC_TLS_LD_BASE)])] "" { + if (TARGET_GNU2_TLS) + { + emit_insn (gen_tls_dynamic_gnu2_64 + (operands[0], ix86_tls_module_base ())); + DONE; + } operands[1] = ix86_tls_get_addr (); }) @@ -14307,6 +14824,136 @@ (set_attr "length" "7") (set_attr "memory" "load") (set_attr "imm_disp" "false")]) + +;; GNU2 TLS patterns can be split. + +(define_expand "tls_dynamic_gnu2_32" + [(set (match_dup 3) + (plus:SI (match_operand:SI 2 "register_operand" "") + (const:SI + (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC)))) + (parallel + [(set (match_operand:SI 0 "register_operand" "") + (unspec:SI [(match_dup 1) (match_dup 3) + (match_dup 2) (reg:SI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))])] + "!TARGET_64BIT && TARGET_GNU2_TLS" +{ + operands[3] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + ix86_tls_descriptor_calls_expanded_in_cfun = true; +}) + +(define_insn "*tls_dynamic_lea_32" + [(set (match_operand:SI 0 "register_operand" "=r") + (plus:SI (match_operand:SI 1 "register_operand" "b") + (const:SI + (unspec:SI [(match_operand:SI 2 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC))))] + "!TARGET_64BIT && TARGET_GNU2_TLS" + "lea{l}\t{%a2@TLSDESC(%1), %0|%0, %a2@TLSDESC[%1]}" + [(set_attr "type" "lea") + (set_attr "mode" "SI") + (set_attr "length" "6") + (set_attr "length_address" "4")]) + +(define_insn "*tls_dynamic_call_32" + [(set (match_operand:SI 0 "register_operand" "=a") + (unspec:SI [(match_operand:SI 1 "tls_symbolic_operand" "") + (match_operand:SI 2 "register_operand" "0") + ;; we have to make sure %ebx still points to the GOT + (match_operand:SI 3 "register_operand" "b") + (reg:SI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && TARGET_GNU2_TLS" + "call\t{*%a1@TLSCALL(%2)|[DWORD PTR [%2+%a1@TLSCALL]]}" + [(set_attr "type" "call") + (set_attr "length" "2") + (set_attr "length_address" "0")]) + +(define_insn_and_split "*tls_dynamic_gnu2_combine_32" + [(set (match_operand:SI 0 "register_operand" "=&a") + (plus:SI + (unspec:SI [(match_operand:SI 3 "tls_modbase_operand" "") + (match_operand:SI 4 "" "") + (match_operand:SI 2 "register_operand" "b") + (reg:SI SP_REG)] + UNSPEC_TLSDESC) + (const:SI (unspec:SI + [(match_operand:SI 1 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) + (clobber (reg:CC FLAGS_REG))] + "!TARGET_64BIT && TARGET_GNU2_TLS" + "#" + "" + [(set (match_dup 0) (match_dup 5))] +{ + operands[5] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + emit_insn (gen_tls_dynamic_gnu2_32 (operands[5], operands[1], operands[2])); +}) + +(define_expand "tls_dynamic_gnu2_64" + [(set (match_dup 2) + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC)) + (parallel + [(set (match_operand:DI 0 "register_operand" "") + (unspec:DI [(match_dup 1) (match_dup 2) (reg:DI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))])] + "TARGET_64BIT && TARGET_GNU2_TLS" +{ + operands[2] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + ix86_tls_descriptor_calls_expanded_in_cfun = true; +}) + +(define_insn "*tls_dynamic_lea_64" + [(set (match_operand:DI 0 "register_operand" "=r") + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_TLSDESC))] + "TARGET_64BIT && TARGET_GNU2_TLS" + "lea{q}\t{%a1@TLSDESC(%%rip), %0|%0, %a1@TLSDESC[%%rip]}" + [(set_attr "type" "lea") + (set_attr "mode" "DI") + (set_attr "length" "7") + (set_attr "length_address" "4")]) + +(define_insn "*tls_dynamic_call_64" + [(set (match_operand:DI 0 "register_operand" "=a") + (unspec:DI [(match_operand:DI 1 "tls_symbolic_operand" "") + (match_operand:DI 2 "register_operand" "0") + (reg:DI SP_REG)] + UNSPEC_TLSDESC)) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_GNU2_TLS" + "call\t{*%a1@TLSCALL(%2)|[QWORD PTR [%2+%a1@TLSCALL]]}" + [(set_attr "type" "call") + (set_attr "length" "2") + (set_attr "length_address" "0")]) + +(define_insn_and_split "*tls_dynamic_gnu2_combine_64" + [(set (match_operand:DI 0 "register_operand" "=&a") + (plus:DI + (unspec:DI [(match_operand:DI 2 "tls_modbase_operand" "") + (match_operand:DI 3 "" "") + (reg:DI SP_REG)] + UNSPEC_TLSDESC) + (const:DI (unspec:DI + [(match_operand:DI 1 "tls_symbolic_operand" "")] + UNSPEC_DTPOFF)))) + (clobber (reg:CC FLAGS_REG))] + "TARGET_64BIT && TARGET_GNU2_TLS" + "#" + "" + [(set (match_dup 0) (match_dup 4))] +{ + operands[4] = no_new_pseudos ? operands[0] : gen_reg_rtx (Pmode); + emit_insn (gen_tls_dynamic_gnu2_64 (operands[4], operands[1])); +}) + +;; ;; These patterns match the binary 387 instructions for addM3, subM3, ;; mulM3 and divM3. There are three patterns for each of DFmode and @@ -14320,10 +14967,10 @@ ;; so use special patterns for add and mull. (define_insn "*fop_sf_comm_mixed" - [(set (match_operand:SF 0 "register_operand" "=f#x,x#f") + [(set (match_operand:SF 0 "register_operand" "=f,x") (match_operator:SF 3 "binary_fp_operator" [(match_operand:SF 1 "nonimmediate_operand" "%0,0") - (match_operand:SF 2 "nonimmediate_operand" "fm#x,xm#f")]))] + (match_operand:SF 2 "nonimmediate_operand" "fm,xm")]))] "TARGET_MIX_SSE_I387 && COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" @@ -14372,7 +15019,7 @@ [(set (match_operand:SF 0 "register_operand" "=f,f,x") (match_operator:SF 3 "binary_fp_operator" [(match_operand:SF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm#f")]))] + (match_operand:SF 2 "nonimmediate_operand" "fm,0,xm")]))] "TARGET_MIX_SSE_I387 && !COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" @@ -14466,20 +15113,20 @@ (set_attr "mode" "")]) (define_insn "*fop_df_comm_mixed" - [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f") + [(set (match_operand:DF 0 "register_operand" "=f,Y") (match_operator:DF 3 "binary_fp_operator" [(match_operand:DF 1 "nonimmediate_operand" "%0,0") - (match_operand:DF 2 "nonimmediate_operand" "fm#Y,Ym#f")]))] + (match_operand:DF 2 "nonimmediate_operand" "fm,Ym")]))] "TARGET_SSE2 && TARGET_MIX_SSE_I387 && COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (if_then_else (eq_attr "alternative" "1") - (if_then_else (match_operand:SF 3 "mult_operator" "") + (if_then_else (match_operand:DF 3 "mult_operator" "") (const_string "ssemul") (const_string "sseadd")) - (if_then_else (match_operand:SF 3 "mult_operator" "") + (if_then_else (match_operand:DF 3 "mult_operator" "") (const_string "fmul") (const_string "fop")))) (set_attr "mode" "DF")]) @@ -14494,7 +15141,7 @@ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (if_then_else (match_operand:SF 3 "mult_operator" "") + (if_then_else (match_operand:DF 3 "mult_operator" "") (const_string "ssemul") (const_string "sseadd"))) (set_attr "mode" "DF")]) @@ -14509,26 +15156,26 @@ && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") - (if_then_else (match_operand:SF 3 "mult_operator" "") + (if_then_else (match_operand:DF 3 "mult_operator" "") (const_string "fmul") (const_string "fop"))) (set_attr "mode" "DF")]) (define_insn "*fop_df_1_mixed" - [(set (match_operand:DF 0 "register_operand" "=f#Y,f#Y,Y#f") + [(set (match_operand:DF 0 "register_operand" "=f,f,Y") (match_operator:DF 3 "binary_fp_operator" [(match_operand:DF 1 "nonimmediate_operand" "0,fm,0") - (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym#f")]))] + (match_operand:DF 2 "nonimmediate_operand" "fm,0,Ym")]))] "TARGET_SSE2 && TARGET_SSE_MATH && TARGET_MIX_SSE_I387 && !COMMUTATIVE_ARITH_P (operands[3]) && (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != MEM)" "* return output_387_binary_op (insn, operands);" [(set (attr "type") (cond [(and (eq_attr "alternative" "2") - (match_operand:SF 3 "mult_operator" "")) + (match_operand:DF 3 "mult_operator" "")) (const_string "ssemul") (and (eq_attr "alternative" "2") - (match_operand:SF 3 "div_operator" "")) + (match_operand:DF 3 "div_operator" "")) (const_string "ssediv") (eq_attr "alternative" "2") (const_string "sseadd") @@ -14550,9 +15197,9 @@ "* return output_387_binary_op (insn, operands);" [(set_attr "mode" "DF") (set (attr "type") - (cond [(match_operand:SF 3 "mult_operator" "") + (cond [(match_operand:DF 3 "mult_operator" "") (const_string "ssemul") - (match_operand:SF 3 "div_operator" "") + (match_operand:DF 3 "div_operator" "") (const_string "ssediv") ] (const_string "sseadd")))]) @@ -14833,8 +15480,8 @@ }) (define_insn "*sqrtsf2_mixed" - [(set (match_operand:SF 0 "register_operand" "=f#x,x#f") - (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0#x,xm#f")))] + [(set (match_operand:SF 0 "register_operand" "=f,x") + (sqrt:SF (match_operand:SF 1 "nonimmediate_operand" "0,xm")))] "TARGET_USE_FANCY_MATH_387 && TARGET_MIX_SSE_I387" "@ fsqrt @@ -14871,8 +15518,8 @@ }) (define_insn "*sqrtdf2_mixed" - [(set (match_operand:DF 0 "register_operand" "=f#Y,Y#f") - (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0#Y,Ym#f")))] + [(set (match_operand:DF 0 "register_operand" "=f,Y") + (sqrt:DF (match_operand:DF 1 "nonimmediate_operand" "0,Ym")))] "TARGET_USE_FANCY_MATH_387 && TARGET_SSE2 && TARGET_MIX_SSE_I387" "@ fsqrt @@ -18369,11 +19016,11 @@ "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") (define_insn "*movsfcc_1_387" - [(set (match_operand:SF 0 "register_operand" "=f#r,f#r,r#f,r#f") + [(set (match_operand:SF 0 "register_operand" "=f,f,r,r") (if_then_else:SF (match_operator 1 "fcmov_comparison_operator" [(reg FLAGS_REG) (const_int 0)]) - (match_operand:SF 2 "nonimmediate_operand" "f#r,0,rm#f,0") - (match_operand:SF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] + (match_operand:SF 2 "nonimmediate_operand" "f,0,rm,0") + (match_operand:SF 3 "nonimmediate_operand" "0,f,0,rm")))] "TARGET_80387 && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ @@ -18393,11 +19040,11 @@ "if (! ix86_expand_fp_movcc (operands)) FAIL; DONE;") (define_insn "*movdfcc_1" - [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,&r#f,&r#f") + [(set (match_operand:DF 0 "register_operand" "=f,f,&r,&r") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" [(reg FLAGS_REG) (const_int 0)]) - (match_operand:DF 2 "nonimmediate_operand" "f#r,0,rm#f,0") - (match_operand:DF 3 "nonimmediate_operand" "0,f#r,0,rm#f")))] + (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0") + (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))] "!TARGET_64BIT && TARGET_80387 && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ @@ -18409,11 +19056,11 @@ (set_attr "mode" "DF")]) (define_insn "*movdfcc_1_rex64" - [(set (match_operand:DF 0 "register_operand" "=f#r,f#r,r#f,r#f") + [(set (match_operand:DF 0 "register_operand" "=f,f,r,r") (if_then_else:DF (match_operator 1 "fcmov_comparison_operator" [(reg FLAGS_REG) (const_int 0)]) - (match_operand:DF 2 "nonimmediate_operand" "f#r,0#r,rm#f,0#f") - (match_operand:DF 3 "nonimmediate_operand" "0#r,f#r,0#f,rm#f")))] + (match_operand:DF 2 "nonimmediate_operand" "f,0,rm,0") + (match_operand:DF 3 "nonimmediate_operand" "0,f,0,rm")))] "TARGET_64BIT && TARGET_80387 && TARGET_CMOVE && (GET_CODE (operands[2]) != MEM || GET_CODE (operands[3]) != MEM)" "@ @@ -18552,6 +19199,32 @@ [(set_attr "type" "sseadd") (set_attr "mode" "DF")]) +;; Make two stack loads independent: +;; fld aa fld aa +;; fld %st(0) -> fld bb +;; fmul bb fmul %st(1), %st +;; +;; Actually we only match the last two instructions for simplicity. +(define_peephole2 + [(set (match_operand 0 "fp_register_operand" "") + (match_operand 1 "fp_register_operand" "")) + (set (match_dup 0) + (match_operator 2 "binary_fp_operator" + [(match_dup 0) + (match_operand 3 "memory_operand" "")]))] + "REGNO (operands[0]) != REGNO (operands[1])" + [(set (match_dup 0) (match_dup 3)) + (set (match_dup 0) (match_dup 4))] + + ;; The % modifier is not operational anymore in peephole2's, so we have to + ;; swap the operands manually in the case of addition and multiplication. + "if (COMMUTATIVE_ARITH_P (operands[2])) + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]), + operands[0], operands[1]); + else + operands[4] = gen_rtx_fmt_ee (GET_CODE (operands[2]), GET_MODE (operands[2]), + operands[1], operands[0]);") + ;; Conditional addition patterns (define_expand "addqicc" [(match_operand:QI 0 "register_operand" "") @@ -18795,7 +19468,21 @@ [(label_ref (match_operand 0 "" ""))] "!TARGET_64BIT && flag_pic" { - emit_insn (gen_set_got (pic_offset_table_rtx)); + if (TARGET_MACHO) + { + rtx xops[3]; + rtx picreg = gen_rtx_REG (Pmode, PIC_OFFSET_TABLE_REGNUM); + rtx label_rtx = gen_label_rtx (); + emit_insn (gen_set_got_labelled (pic_offset_table_rtx, label_rtx)); + xops[0] = xops[1] = picreg; + xops[2] = gen_rtx_CONST (SImode, + gen_rtx_MINUS (SImode, + gen_rtx_LABEL_REF (SImode, label_rtx), + gen_rtx_SYMBOL_REF (SImode, GOT_SYMBOL_NAME))); + ix86_expand_binary_operator (MINUS, SImode, xops); + } + else + emit_insn (gen_set_got (pic_offset_table_rtx)); DONE; }) @@ -18810,8 +19497,9 @@ "! TARGET_PARTIAL_REG_STALL && reload_completed && ((GET_MODE (operands[0]) == HImode && ((!optimize_size && !TARGET_FAST_PREFIX) + /* ??? next two lines just !satisfies_constraint_K (...) */ || GET_CODE (operands[2]) != CONST_INT - || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))) + || satisfies_constraint_K (operands[2]))) || (GET_MODE (operands[0]) == QImode && (TARGET_PROMOTE_QImode || optimize_size)))" [(parallel [(set (match_dup 0) @@ -19133,8 +19821,7 @@ (const_int 0)]))] "ix86_match_ccmode (insn, CCNOmode) && (true_regnum (operands[2]) != 0 - || (GET_CODE (operands[3]) == CONST_INT - && CONST_OK_FOR_LETTER_P (INTVAL (operands[3]), 'K'))) + || satisfies_constraint_K (operands[3])) && peep2_reg_dead_p (1, operands[2])" [(parallel [(set (match_dup 0) @@ -19699,9 +20386,8 @@ (mult:DI (match_operand:DI 1 "memory_operand" "") (match_operand:DI 2 "immediate_operand" ""))) (clobber (reg:CC FLAGS_REG))])] - "TARGET_K8 && !optimize_size - && (GET_CODE (operands[2]) != CONST_INT - || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && !satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 0) (mult:DI (match_dup 3) (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] @@ -19713,9 +20399,8 @@ (mult:SI (match_operand:SI 1 "memory_operand" "") (match_operand:SI 2 "immediate_operand" ""))) (clobber (reg:CC FLAGS_REG))])] - "TARGET_K8 && !optimize_size - && (GET_CODE (operands[2]) != CONST_INT - || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && !satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 0) (mult:SI (match_dup 3) (match_dup 2))) (clobber (reg:CC FLAGS_REG))])] @@ -19728,9 +20413,8 @@ (mult:SI (match_operand:SI 1 "memory_operand" "") (match_operand:SI 2 "immediate_operand" "")))) (clobber (reg:CC FLAGS_REG))])] - "TARGET_K8 && !optimize_size - && (GET_CODE (operands[2]) != CONST_INT - || !CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && !satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 1)) (parallel [(set (match_dup 0) (zero_extend:DI (mult:SI (match_dup 3) (match_dup 2)))) (clobber (reg:CC FLAGS_REG))])] @@ -19746,8 +20430,8 @@ (match_operand:DI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (match_scratch:DI 3 "r")] - "TARGET_K8 && !optimize_size - && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 2)) (parallel [(set (match_dup 0) (mult:DI (match_dup 0) (match_dup 3))) (clobber (reg:CC FLAGS_REG))])] @@ -19762,8 +20446,8 @@ (match_operand:SI 2 "const_int_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (match_scratch:SI 3 "r")] - "TARGET_K8 && !optimize_size - && CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K')" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size + && satisfies_constraint_K (operands[2])" [(set (match_dup 3) (match_dup 2)) (parallel [(set (match_dup 0) (mult:SI (match_dup 0) (match_dup 3))) (clobber (reg:CC FLAGS_REG))])] @@ -19778,7 +20462,7 @@ (match_operand:HI 2 "immediate_operand" ""))) (clobber (reg:CC FLAGS_REG))]) (match_scratch:HI 3 "r")] - "TARGET_K8 && !optimize_size" + "(TARGET_K8 || TARGET_GENERIC64) && !optimize_size" [(set (match_dup 3) (match_dup 2)) (parallel [(set (match_dup 0) (mult:HI (match_dup 0) (match_dup 3))) (clobber (reg:CC FLAGS_REG))])] @@ -19971,7 +20655,7 @@ (define_insn "trap" [(trap_if (const_int 1) (const_int 6))] "" - ".word\t0x0b0f" + { return ASM_SHORT "0x0b0f"; } [(set_attr "length" "2")]) (define_expand "sse_prologue_save" @@ -20177,7 +20861,15 @@ (set (match_scratch:DI 2 "=&r") (const_int 0)) (clobber (reg:CC FLAGS_REG))] "TARGET_64BIT" - "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2" + { + /* The kernel uses a different segment register for performance reasons; a + system call would not have to trash the userspace segment register, + which would be expensive */ + if (ix86_cmodel != CM_KERNEL) + return "mov{q}\t{%%fs:%P1, %2|%2, QWORD PTR %%fs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"; + else + return "mov{q}\t{%%gs:%P1, %2|%2, QWORD PTR %%gs:%P1}\;mov{q}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"; + } [(set_attr "type" "multi")]) (define_expand "stack_protect_test" @@ -20245,7 +20937,15 @@ UNSPEC_SP_TLS_TEST)) (clobber (match_scratch:DI 3 "=r"))] "TARGET_64BIT" - "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}" + { + /* The kernel uses a different segment register for performance reasons; a + system call would not have to trash the userspace segment register, + which would be expensive */ + if (ix86_cmodel != CM_KERNEL) + return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%fs:%P2, %3|%3, QWORD PTR %%fs:%P2}"; + else + return "mov{q}\t{%1, %3|%3, %1}\;xor{q}\t{%%gs:%P2, %3|%3, QWORD PTR %%gs:%P2}"; + } [(set_attr "type" "multi")]) (include "sse.md")