re PR target/92841 (Optimize -fstack-protector-strong code generation a bit)
authorJakub Jelinek <jakub@redhat.com>
Tue, 17 Dec 2019 20:40:01 +0000 (21:40 +0100)
committerJakub Jelinek <jakub@gcc.gnu.org>
Tue, 17 Dec 2019 20:40:01 +0000 (21:40 +0100)
PR target/92841
* config/i386/i386.md (@stack_protect_set_1_<mode>,
@stack_protect_test_1_<mode>): Use output_asm_insn.
(*stack_protect_set_2_<mode>, *stack_protect_set_3): New define_insns
and corresponding define_peephole2s.

* gcc.target/i386/pr92841.c: New test.

From-SVN: r279468

gcc/ChangeLog
gcc/config/i386/i386.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.target/i386/pr92841.c [new file with mode: 0644]

index e5702ae06124a6ed5da7d3b057d9c7a6d0d8d0fa..6267594928576aa92f5e12d94bad24571a7f399a 100644 (file)
@@ -1,3 +1,11 @@
+2019-12-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/92841
+       * config/i386/i386.md (@stack_protect_set_1_<mode>,
+       @stack_protect_test_1_<mode>): Use output_asm_insn.
+       (*stack_protect_set_2_<mode>, *stack_protect_set_3): New define_insns
+       and corresponding define_peephole2s.
+
 2019-12-17  Jan Hubicka  <hubicka@ucw.cz>
 
        * symtab.c (symtab_node::get_partitioning_class): Aliases of external
index cf4a0ccb0aaba635e4e61fbce3108c6e7825018c..672fd1c2749b59871f755fb12b1593d819fa6d1f 100644 (file)
    (set (match_scratch:PTR 2 "=&r") (const_int 0))
    (clobber (reg:CC FLAGS_REG))]
   ""
-  "mov{<imodesuffix>}\t{%1, %2|%2, %1}\;mov{<imodesuffix>}\t{%2, %0|%0, %2}\;xor{l}\t%k2, %k2"
+{
+  output_asm_insn ("mov{<imodesuffix>}\t{%1, %2|%2, %1}", operands);
+  output_asm_insn ("mov{<imodesuffix>}\t{%2, %0|%0, %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 to the same register,
+;; 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_insn "*stack_protect_set_2_<mode>"
+  [(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"))
+   (clobber (reg:CC FLAGS_REG))]
+  "reload_completed
+   && !reg_overlap_mentioned_p (operands[1], operands[2])"
+{
+  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_peephole2
+ [(parallel [(set (match_operand:PTR 0 "memory_operand")
+                 (unspec:PTR [(match_operand:PTR 1 "memory_operand")]
+                             UNSPEC_SP_SET))
+            (set (match_operand:PTR 2 "general_reg_operand") (const_int 0))
+            (clobber (reg:CC FLAGS_REG))])
+  (set (match_operand:SI 3 "general_reg_operand")
+       (match_operand:SI 4))]
+ "REGNO (operands[2]) == REGNO (operands[3])
+  && (general_reg_operand (operands[4], SImode)
+      || memory_operand (operands[4], SImode)
+      || immediate_operand (operands[4], SImode))
+  && !reg_overlap_mentioned_p (operands[3], operands[4])"
+ [(parallel [(set (match_dup 0)
+                 (unspec:PTR [(match_dup 1)] UNSPEC_SP_SET))
+            (set (match_dup 3) (match_dup 4))
+            (clobber (reg:CC FLAGS_REG))])])
+
+(define_insn "*stack_protect_set_3"
+  [(set (match_operand:DI 0 "memory_operand" "=m,m,m")
+       (unspec:DI [(match_operand:DI 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"))
+   (clobber (reg:CC FLAGS_REG))]
+  "TARGET_64BIT
+   && reload_completed
+   && !reg_overlap_mentioned_p (operands[1], operands[2])"
+{
+  output_asm_insn ("mov{q}\t{%3, %1|%1, %3}", operands);
+  output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", operands);
+  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 (pic_32bit_operand (operands[2], DImode)
+          || 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:DI 0 "memory_operand")
+                 (unspec:DI [(match_operand:DI 1 "memory_operand")]
+                            UNSPEC_SP_SET))
+            (set (match_operand:DI 2 "general_reg_operand") (const_int 0))
+            (clobber (reg:CC FLAGS_REG))])
+  (set (match_dup 2) (match_operand:DI 3))]
+ "TARGET_64BIT
+  && (general_reg_operand (operands[3], DImode)
+      || memory_operand (operands[3], DImode)
+      || x86_64_zext_immediate_operand (operands[3], DImode)
+      || x86_64_immediate_operand (operands[3], DImode)
+      || (CONSTANT_P (operands[3])
+         && (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[3]))))
+  && !reg_overlap_mentioned_p (operands[2], operands[3])"
+ [(parallel [(set (match_dup 0)
+                 (unspec:PTR [(match_dup 1)] UNSPEC_SP_SET))
+            (set (match_dup 2) (match_dup 3))
+            (clobber (reg:CC FLAGS_REG))])])
+
 (define_expand "stack_protect_test"
   [(match_operand 0 "memory_operand")
    (match_operand 1 "memory_operand")
                    UNSPEC_SP_TEST))
    (clobber (match_scratch:PTR 3 "=&r"))]
   ""
-  "mov{<imodesuffix>}\t{%1, %3|%3, %1}\;sub{<imodesuffix>}\t{%2, %3|%3, %2}"
+{
+  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>"
index 3794eba80ee45db46892b4ee28404d335673e1c3..0ba27eba78b6c8247267561fe70c711361317183 100644 (file)
@@ -1,3 +1,8 @@
+2019-12-17  Jakub Jelinek  <jakub@redhat.com>
+
+       PR target/92841
+       * gcc.target/i386/pr92841.c: New test.
+
 2019-12-17  Christophe Lyon  <christophe.lyon@linaro.org>
 
        * gcc.target/arm/pr45701-1.c: Adjust for -mpure-code.
diff --git a/gcc/testsuite/gcc.target/i386/pr92841.c b/gcc/testsuite/gcc.target/i386/pr92841.c
new file mode 100644 (file)
index 0000000..30be2b6
--- /dev/null
@@ -0,0 +1,17 @@
+/* PR target/92841 */
+/* { dg-do compile { target fstack_protector } } */
+/* { dg-options "-O2 -fstack-protector-strong -masm=att" } */
+/* { dg-final { scan-assembler-not "xor\[lq]\t%(\[re]\[a-z0-9]*), %\\1\[\n\r]*\tmov\[lq]\t\[^\n\r]*, %\\1" } } */
+
+const struct S { int b; } c[] = {30, 12, 20, 0, 11};
+void bar (int *);
+
+void
+foo (void)
+{
+  int e[4];
+  const struct S *a;
+  for (a = c; a < c + sizeof (c) / sizeof (c[0]); a++)
+    if (a->b)
+      bar (e);
+}