]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Clear stack protector scratch with zero/sign-extend instruction
authorUros Bizjak <ubizjak@gmail.com>
Fri, 10 Nov 2023 15:22:44 +0000 (16:22 +0100)
committerUros Bizjak <ubizjak@gmail.com>
Fri, 10 Nov 2023 15:23:52 +0000 (16:23 +0100)
Use unrelated register initializations using zero/sign-extend instructions
to clear stack protector scratch register.

Hanlde only SI -> DImode extensions for 64-bit targets, as this is the
only extension that triggers the peephole in a non-negligible number.

Also use explicit check for word_mode instead of mode iterator in peephole2
patterns to avoid pattern explosion.

gcc/ChangeLog:

* config/i386/i386.md (stack_protect_set_1 peephole2):
Explicitly check operand 2 for word_mode.
(stack_protect_set_1 peephole2 #2): Ditto.
(stack_protect_set_2 peephole2): Ditto.
(stack_protect_set_3 peephole2): Ditto.
(*stack_protect_set_4z_<mode>_di): New insn patter.
(*stack_protect_set_4s_<mode>_di): Ditto.
(stack_protect_set_4 peephole2): New peephole2 pattern to
substitute stack protector scratch register clear with unrelated
register initialization involving zero/sign-extend instruction.

gcc/config/i386/i386.md

index 9dc614c60c0c025fd3aab23965b4cf6354006180..01fc6ecc35187d0c29bc84479de0314e2662e7e4 100644 (file)
   [(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))
+             (set (match_operand 2 "general_reg_operand") (const_int 0))
              (clobber (reg:CC FLAGS_REG))])
    (set (match_operand 3 "general_reg_operand")
        (match_operand 4 "const0_operand"))]
-  "GET_MODE_SIZE (GET_MODE (operands[3])) <= UNITS_PER_WORD
+  "GET_MODE (operands[2]) == word_mode
+   && GET_MODE_SIZE (GET_MODE (operands[3])) <= UNITS_PER_WORD
    && peep2_reg_dead_p (0, operands[3])
    && peep2_reg_dead_p (1, operands[2])"
   [(parallel [(set (match_dup 0)
   [(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))
+             (set (match_operand 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])
+  "GET_MODE (operands[2]) == word_mode
+   && 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))
    (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))
+             (set (match_operand 2 "general_reg_operand") (const_int 0))
              (clobber (reg:CC FLAGS_REG))])]
-  "peep2_reg_dead_p (0, operands[3])
+  "GET_MODE (operands[2]) == word_mode
+   && peep2_reg_dead_p (0, operands[3])
    && peep2_reg_dead_p (2, operands[2])
    && !reg_mentioned_p (operands[3], operands[0])
    && !reg_mentioned_p (operands[3], operands[1])"
   [(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))
+             (set (match_operand 2 "general_reg_operand") (const_int 0))
              (clobber (reg:CC FLAGS_REG))])
    (set (match_operand:SWI48 3 "general_reg_operand")
        (match_operand:SWI48 4 "address_no_seg_operand"))]
-  "peep2_reg_dead_p (0, operands[3])
+  "GET_MODE (operands[2]) == word_mode
+   && 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_insn "*stack_protect_set_4z_<mode>_di"
+  [(set (match_operand:PTR 0 "memory_operand" "=m")
+       (unspec:PTR [(match_operand:PTR 3 "memory_operand" "m")]
+                   UNSPEC_SP_SET))
+   (set (match_operand:DI 1 "register_operand" "=&r")
+       (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))]
+  "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 (ix86_use_lea_for_mov (insn, operands + 1))
+    return "lea{l}\t{%E2, %k1|%k1, %E2}";
+  else
+    return "mov{l}\t{%2, %k1|%k1, %2}";
+}
+  [(set_attr "type" "multi")
+   (set_attr "length" "24")])
+
+(define_insn "*stack_protect_set_4s_<mode>_di"
+  [(set (match_operand:PTR 0 "memory_operand" "=m,m")
+       (unspec:PTR [(match_operand:PTR 3 "memory_operand" "m,m")]
+                   UNSPEC_SP_SET))
+   (set (match_operand:DI 1 "register_operand" "=&a,&r")
+       (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "0,rm")))]
+  "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 (which_alternative)
+    return "movs{lq|x}\t{%2, %1|%1, %2}";
+  else
+    return "{cltq|cdqe}";
+}
+  [(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 2 "general_reg_operand") (const_int 0))
+             (clobber (reg:CC FLAGS_REG))])
+   (set (match_operand:DI 3 "general_reg_operand")
+       (any_extend:DI
+         (match_operand:SI 4 "nonimmediate_gr_operand")))]
+  "TARGET_64BIT
+   && GET_MODE (operands[2]) == word_mode
+   && 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)
+                  (any_extend:DI (match_dup 4)))])])
+
 (define_expand "stack_protect_test"
   [(match_operand 0 "memory_operand")
    (match_operand 1 "memory_operand")