Move stack protector patterns above mov $0,%reg -> xor %reg,%reg so the latter won't interfere with stack protector peephole2s.
gcc/ChangeLog: * config/i386/i386.md: Move stack protector patterns above mov $0,%reg -> xor %reg,%reg peephole2 pattern. Bootstrapped and regression tested on x86_64-linux-gnu {,-m32}. Uros.
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 75c75f610c2..0528b8379bf 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -24281,6 +24281,141 @@ (define_expand "restore_stack_nonlocal" DONE; }) +(define_expand "stack_protect_set" + [(match_operand 0 "memory_operand") + (match_operand 1 "memory_operand")] + "" +{ + rtx scratch = gen_reg_rtx (word_mode); + + emit_insn (gen_stack_protect_set_1 + (ptr_mode, word_mode, operands[0], operands[1], scratch)); + DONE; +}) + +(define_insn "@stack_protect_set_1_<PTR:mode>_<SWI48:mode>" + [(set (match_operand:PTR 0 "memory_operand" "=m") + (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")] + UNSPEC_SP_SET)) + (set (match_operand:SWI48 2 "register_operand" "=&r") (const_int 0)) + (clobber (reg:CC FLAGS_REG))] + "" +{ + output_asm_insn ("mov{<PTR:imodesuffix>}\t{%1, %<PTR:k>2|%<PTR:k>2, %1}", + operands); + output_asm_insn ("mov{<PTR:imodesuffix>}\t{%<PTR:k>2, %0|%0, %<PTR:k>2}", + operands); + return "xor{l}\t%k2, %k2"; +} + [(set_attr "type" "multi")]) + +;; Patterns and peephole2s to optimize stack_protect_set_1_<mode> +;; immediately followed by *mov{s,d}i_internal, where we can avoid +;; the xor{l} above. We don't split this, so that scheduling or +;; anything else doesn't separate the *stack_protect_set* pattern from +;; the set of the register that overwrites the register with a new value. + +(define_peephole2 + [(parallel [(set (match_operand:PTR 0 "memory_operand") + (unspec:PTR [(match_operand:PTR 1 "memory_operand")] + UNSPEC_SP_SET)) + (set (match_operand:W 2 "general_reg_operand") (const_int 0)) + (clobber (reg:CC FLAGS_REG))]) + (parallel [(set (match_operand:SWI48 3 "general_reg_operand") + (match_operand:SWI48 4 "const0_operand")) + (clobber (reg:CC FLAGS_REG))])] + "peep2_reg_dead_p (0, operands[3]) + && peep2_reg_dead_p (1, operands[2])" + [(parallel [(set (match_dup 0) + (unspec:PTR [(match_dup 1)] UNSPEC_SP_SET)) + (set (match_dup 3) (const_int 0)) + (clobber (reg:CC FLAGS_REG))])]) + +(define_insn "*stack_protect_set_2_<mode>_si" + [(set (match_operand:PTR 0 "memory_operand" "=m") + (unspec:PTR [(match_operand:PTR 3 "memory_operand" "m")] + UNSPEC_SP_SET)) + (set (match_operand:SI 1 "register_operand" "=&r") + (match_operand:SI 2 "general_operand" "g"))] + "reload_completed" +{ + output_asm_insn ("mov{<imodesuffix>}\t{%3, %<k>1|%<k>1, %3}", operands); + output_asm_insn ("mov{<imodesuffix>}\t{%<k>1, %0|%0, %<k>1}", operands); + if (pic_32bit_operand (operands[2], SImode) + || ix86_use_lea_for_mov (insn, operands + 1)) + return "lea{l}\t{%E2, %1|%1, %E2}"; + else + return "mov{l}\t{%2, %1|%1, %2}"; +} + [(set_attr "type" "multi") + (set_attr "length" "24")]) + +(define_insn "*stack_protect_set_2_<mode>_di" + [(set (match_operand:PTR 0 "memory_operand" "=m,m,m") + (unspec:PTR [(match_operand:PTR 3 "memory_operand" "m,m,m")] + UNSPEC_SP_SET)) + (set (match_operand:DI 1 "register_operand" "=&r,&r,&r") + (match_operand:DI 2 "general_operand" "Z,rem,i"))] + "TARGET_64BIT && reload_completed" +{ + output_asm_insn ("mov{<imodesuffix>}\t{%3, %<k>1|%<k>1, %3}", operands); + output_asm_insn ("mov{<imodesuffix>}\t{%<k>1, %0|%0, %<k>1}", operands); + if (pic_32bit_operand (operands[2], DImode)) + return "lea{q}\t{%E2, %1|%1, %E2}"; + else if (which_alternative == 0) + return "mov{l}\t{%k2, %k1|%k1, %k2}"; + else if (which_alternative == 2) + return "movabs{q}\t{%2, %1|%1, %2}"; + else if (ix86_use_lea_for_mov (insn, operands + 1)) + return "lea{q}\t{%E2, %1|%1, %E2}"; + else + return "mov{q}\t{%2, %1|%1, %2}"; +} + [(set_attr "type" "multi") + (set_attr "length" "24")]) + +(define_peephole2 + [(parallel [(set (match_operand:PTR 0 "memory_operand") + (unspec:PTR [(match_operand:PTR 1 "memory_operand")] + UNSPEC_SP_SET)) + (set (match_operand:W 2 "general_reg_operand") (const_int 0)) + (clobber (reg:CC FLAGS_REG))]) + (set (match_operand:SWI48 3 "general_reg_operand") + (match_operand:SWI48 4 "general_gr_operand"))] + "peep2_reg_dead_p (0, operands[3]) + && peep2_reg_dead_p (1, operands[2])" + [(parallel [(set (match_dup 0) + (unspec:PTR [(match_dup 1)] UNSPEC_SP_SET)) + (set (match_dup 3) (match_dup 4))])]) + +(define_expand "stack_protect_test" + [(match_operand 0 "memory_operand") + (match_operand 1 "memory_operand") + (match_operand 2)] + "" +{ + rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG); + + emit_insn (gen_stack_protect_test_1 + (ptr_mode, flags, operands[0], operands[1])); + + emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), + flags, const0_rtx, operands[2])); + DONE; +}) + +(define_insn "@stack_protect_test_1_<mode>" + [(set (match_operand:CCZ 0 "flags_reg_operand") + (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m") + (match_operand:PTR 2 "memory_operand" "m")] + UNSPEC_SP_TEST)) + (clobber (match_scratch:PTR 3 "=&r"))] + "" +{ + output_asm_insn ("mov{<imodesuffix>}\t{%1, %3|%3, %1}", operands); + return "sub{<imodesuffix>}\t{%2, %3|%3, %2}"; +} + [(set_attr "type" "multi")]) ;; Avoid redundant prefixes by splitting HImode arithmetic to SImode. ;; Do not split instructions with mask registers. @@ -25648,142 +25783,6 @@ (define_insn "prefetchi" (symbol_ref "memory_address_length (operands[0], false)")) (set_attr "memory" "none")]) -(define_expand "stack_protect_set" - [(match_operand 0 "memory_operand") - (match_operand 1 "memory_operand")] - "" -{ - rtx scratch = gen_reg_rtx (word_mode); - - emit_insn (gen_stack_protect_set_1 - (ptr_mode, word_mode, operands[0], operands[1], scratch)); - DONE; -}) - -(define_insn "@stack_protect_set_1_<PTR:mode>_<SWI48:mode>" - [(set (match_operand:PTR 0 "memory_operand" "=m") - (unspec:PTR [(match_operand:PTR 1 "memory_operand" "m")] - UNSPEC_SP_SET)) - (set (match_operand:SWI48 2 "register_operand" "=&r") (const_int 0)) - (clobber (reg:CC FLAGS_REG))] - "" -{ - output_asm_insn ("mov{<PTR:imodesuffix>}\t{%1, %<PTR:k>2|%<PTR:k>2, %1}", - operands); - output_asm_insn ("mov{<PTR:imodesuffix>}\t{%<PTR:k>2, %0|%0, %<PTR:k>2}", - operands); - return "xor{l}\t%k2, %k2"; -} - [(set_attr "type" "multi")]) - -;; Patterns and peephole2s to optimize stack_protect_set_1_<mode> -;; immediately followed by *mov{s,d}i_internal, where we can avoid -;; the xor{l} above. We don't split this, so that scheduling or -;; anything else doesn't separate the *stack_protect_set* pattern from -;; the set of the register that overwrites the register with a new value. - -(define_peephole2 - [(parallel [(set (match_operand:PTR 0 "memory_operand") - (unspec:PTR [(match_operand:PTR 1 "memory_operand")] - UNSPEC_SP_SET)) - (set (match_operand:W 2 "general_reg_operand") (const_int 0)) - (clobber (reg:CC FLAGS_REG))]) - (parallel [(set (match_operand:SWI48 3 "general_reg_operand") - (match_operand:SWI48 4 "const0_operand")) - (clobber (reg:CC FLAGS_REG))])] - "peep2_reg_dead_p (0, operands[3]) - && peep2_reg_dead_p (1, operands[2])" - [(parallel [(set (match_dup 0) - (unspec:PTR [(match_dup 1)] UNSPEC_SP_SET)) - (set (match_dup 3) (const_int 0)) - (clobber (reg:CC FLAGS_REG))])]) - -(define_insn "*stack_protect_set_2_<mode>_si" - [(set (match_operand:PTR 0 "memory_operand" "=m") - (unspec:PTR [(match_operand:PTR 3 "memory_operand" "m")] - UNSPEC_SP_SET)) - (set (match_operand:SI 1 "register_operand" "=&r") - (match_operand:SI 2 "general_operand" "g"))] - "reload_completed" -{ - output_asm_insn ("mov{<imodesuffix>}\t{%3, %<k>1|%<k>1, %3}", operands); - output_asm_insn ("mov{<imodesuffix>}\t{%<k>1, %0|%0, %<k>1}", operands); - if (pic_32bit_operand (operands[2], SImode) - || ix86_use_lea_for_mov (insn, operands + 1)) - return "lea{l}\t{%E2, %1|%1, %E2}"; - else - return "mov{l}\t{%2, %1|%1, %2}"; -} - [(set_attr "type" "multi") - (set_attr "length" "24")]) - -(define_insn "*stack_protect_set_2_<mode>_di" - [(set (match_operand:PTR 0 "memory_operand" "=m,m,m") - (unspec:PTR [(match_operand:PTR 3 "memory_operand" "m,m,m")] - UNSPEC_SP_SET)) - (set (match_operand:DI 1 "register_operand" "=&r,&r,&r") - (match_operand:DI 2 "general_operand" "Z,rem,i"))] - "TARGET_64BIT && reload_completed" -{ - output_asm_insn ("mov{<imodesuffix>}\t{%3, %<k>1|%<k>1, %3}", operands); - output_asm_insn ("mov{<imodesuffix>}\t{%<k>1, %0|%0, %<k>1}", operands); - if (pic_32bit_operand (operands[2], DImode)) - return "lea{q}\t{%E2, %1|%1, %E2}"; - else if (which_alternative == 0) - return "mov{l}\t{%k2, %k1|%k1, %k2}"; - else if (which_alternative == 2) - return "movabs{q}\t{%2, %1|%1, %2}"; - else if (ix86_use_lea_for_mov (insn, operands + 1)) - return "lea{q}\t{%E2, %1|%1, %E2}"; - else - return "mov{q}\t{%2, %1|%1, %2}"; -} - [(set_attr "type" "multi") - (set_attr "length" "24")]) - -(define_peephole2 - [(parallel [(set (match_operand:PTR 0 "memory_operand") - (unspec:PTR [(match_operand:PTR 1 "memory_operand")] - UNSPEC_SP_SET)) - (set (match_operand:W 2 "general_reg_operand") (const_int 0)) - (clobber (reg:CC FLAGS_REG))]) - (set (match_operand:SWI48 3 "general_reg_operand") - (match_operand:SWI48 4 "general_gr_operand"))] - "peep2_reg_dead_p (0, operands[3]) - && peep2_reg_dead_p (1, operands[2])" - [(parallel [(set (match_dup 0) - (unspec:PTR [(match_dup 1)] UNSPEC_SP_SET)) - (set (match_dup 3) (match_dup 4))])]) - -(define_expand "stack_protect_test" - [(match_operand 0 "memory_operand") - (match_operand 1 "memory_operand") - (match_operand 2)] - "" -{ - rtx flags = gen_rtx_REG (CCZmode, FLAGS_REG); - - emit_insn (gen_stack_protect_test_1 - (ptr_mode, flags, operands[0], operands[1])); - - emit_jump_insn (gen_cbranchcc4 (gen_rtx_EQ (VOIDmode, flags, const0_rtx), - flags, const0_rtx, operands[2])); - DONE; -}) - -(define_insn "@stack_protect_test_1_<mode>" - [(set (match_operand:CCZ 0 "flags_reg_operand") - (unspec:CCZ [(match_operand:PTR 1 "memory_operand" "m") - (match_operand:PTR 2 "memory_operand" "m")] - UNSPEC_SP_TEST)) - (clobber (match_scratch:PTR 3 "=&r"))] - "" -{ - output_asm_insn ("mov{<imodesuffix>}\t{%1, %3|%3, %1}", operands); - return "sub{<imodesuffix>}\t{%2, %3|%3, %2}"; -} - [(set_attr "type" "multi")]) - (define_insn "sse4_2_crc32<mode>" [(set (match_operand:SI 0 "register_operand" "=r") (unspec:SI