]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
i386: Disable string insn from non-default AS for Pmode != word_mode [PR111657]
authorUros Bizjak <ubizjak@gmail.com>
Tue, 29 Apr 2025 16:08:05 +0000 (18:08 +0200)
committerUros Bizjak <ubizjak@gmail.com>
Tue, 29 Apr 2025 16:15:03 +0000 (18:15 +0200)
0x67 prefix is applied before segment register. That is in

rep movsq %gs:(%esi), (%edi)

the address is %gs + %esi. In case Pmode != word_mode (x32 with a default
-maddress-mode=short) instructions should not allow segment override prefixes.

Also, remove explicit addr32 prefix from asm templates because address
mode can be determined from explicit instruction operands. Also note that
Pmode != word_mode only with TARGET_64BIT, so the check in ix86_print_operand
is not needed.

PR target/111657

gcc/ChangeLog:

* config/i386/i386-expand.cc (alg_usable_p): For Pmode != word_mode
reject rep_prefix_{1,4,8}_byte algorithms with src_as in the
non-default address space.
* config/i386/i386-protos.h (ix86_check_movs): New prototype.
* config/i386/i386.cc (ix86_check_movs): New function.
(ix86_print_operand) [case '^']: Remove excess check for TARGET_64BIT.
* config/i386/i386.md (strmov): For Pmode != word_mode expand with
gen_strmov_single only when operands[3] (source) is in the default
address space.
(*strmovdi_rex_1) Use ix86_check_movs.  Remove %^ from asm template.
(*strmovsi_1): Ditto.
(*strmovhi_1): DItto.
(*strmovqi_1): Ditto.
(*rep_movdi_rex64): Ditto.
(*rep_movsi): Ditto.
(*rep_movqi): Ditto.

gcc/testsuite/ChangeLog:

* gcc.target/i386/pr111657-1.c: Check that segment override is not
generated for "rep movsq" for x32 target.

gcc/config/i386/i386-expand.cc
gcc/config/i386/i386-protos.h
gcc/config/i386/i386.cc
gcc/config/i386/i386.md
gcc/testsuite/gcc.target/i386/pr111657-1.c

index f1cc85b4531c852d586d317e71ca8dc18d895741..7f0fdb6fa9e93701162a9e759bcfc04924dadaeb 100644 (file)
@@ -8933,7 +8933,8 @@ alg_usable_p (enum stringop_alg alg, bool memset,
       if (fixed_regs[CX_REG]
          || fixed_regs[DI_REG]
          || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])
-         || !ADDR_SPACE_GENERIC_P (dst_as))
+         || !ADDR_SPACE_GENERIC_P (dst_as)
+         || !(ADDR_SPACE_GENERIC_P (src_as) || Pmode == word_mode))
        return false;
     }
   return true;
index c59b5a67e3a5b3bce6937633ce8201e3bf4f75d5..e85b925704ba3d2403d4e03db7ba34057212b1f6 100644 (file)
@@ -186,6 +186,7 @@ extern void ix86_expand_v2di_ashiftrt (rtx[]);
 extern rtx ix86_replace_reg_with_reg (rtx, rtx, rtx);
 extern rtx ix86_find_base_term (rtx);
 extern bool ix86_check_movabs (rtx, int);
+extern bool ix86_check_movs (rtx, int);
 extern bool ix86_check_no_addr_space (rtx);
 extern void ix86_split_idivmod (machine_mode, rtx[], bool);
 extern bool ix86_hardreg_mov_ok (rtx, rtx);
index bfd9cac215ad4369f9dfb20290c6d6165ec506fb..2f8403381384bc6c3a224af0b3415770ff917f10 100644 (file)
@@ -5180,6 +5180,27 @@ ix86_check_movabs (rtx insn, int opnum)
   return volatile_ok || !MEM_VOLATILE_P (mem);
 }
 
+/* Return true if XVECEXP idx of INSN satisfies MOVS arguments.  */
+bool
+ix86_check_movs (rtx insn, int idx)
+{
+  rtx pat = PATTERN (insn);
+  gcc_assert (GET_CODE (pat) == PARALLEL);
+
+  rtx set = XVECEXP (pat, 0, idx);
+  gcc_assert (GET_CODE (set) == SET);
+
+  rtx dst = SET_DEST (set);
+  gcc_assert (MEM_P (dst));
+
+  rtx src = SET_SRC (set);
+  gcc_assert (MEM_P (src));
+
+  return (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (dst))
+         && (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src))
+             || Pmode == word_mode));
+}
+
 /* Return false if INSN contains a MEM with a non-default address space.  */
 bool
 ix86_check_no_addr_space (rtx insn)
@@ -14296,7 +14317,7 @@ ix86_print_operand (FILE *file, rtx x, int code)
          return;
 
        case '^':
-         if (TARGET_64BIT && Pmode != word_mode)
+         if (Pmode != word_mode)
            fputs ("addr32 ", file);
          return;
 
index 962e7ab92aa835139afd8164faf5b9d5b688abee..44ee94a3e41906ac910a0613ff25bb9b34b35549 100644 (file)
    * since string insns cannot override the destination segment.  */
   if ((TARGET_SINGLE_STRINGOP || optimize_insn_for_size_p ())
       && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])
-      && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[1])))
+      && ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[1]))
+      && (ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[3]))
+         || Pmode == word_mode))
     {
       emit_insn (gen_strmov_singleop (operands[0], operands[1],
                                      operands[2], operands[3],
                (const_int 8)))]
   "TARGET_64BIT
    && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 0))))"
+   && ix86_check_movs (insn, 0)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 0);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^movsq\t{%1, %0|%0, %1}";
+  return "movsq\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
        (plus:P (match_dup 3)
                (const_int 4)))]
   "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 0))))"
+   && ix86_check_movs (insn, 0)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 0);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^movs{l|d}\t{%1, %0|%0, %1}";
+  return "movs{l|d}\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
        (plus:P (match_dup 3)
                (const_int 2)))]
   "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 0))))"
+   && ix86_check_movs (insn, 0)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 0);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^movsw\t{%1, %0|%0, %1}";
+  return "movsw\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
        (plus:P (match_dup 3)
                (const_int 1)))]
   "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 0))))"
+   && ix86_check_movs (insn, 0)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 0);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^movsb\t{%1, %0|%0, %1}";
+  return "movsb\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "memory" "both")
    (use (match_dup 5))]
   "TARGET_64BIT
    && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 3))))"
+   && ix86_check_movs (insn, 3)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 3);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^rep{%;} movsq\t{%1, %0|%0, %1}";
+  return "rep{%;} movsq\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
        (mem:BLK (match_dup 4)))
    (use (match_dup 5))]
   "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 3))))"
+   && ix86_check_movs (insn, 3)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 3);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^rep{%;} movs{l|d}\t{%1, %0|%0, %1}";
+  return "rep{%;} movs{l|d}\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
        (mem:BLK (match_dup 4)))
    (use (match_dup 5))]
   "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])
-   && ADDR_SPACE_GENERIC_P
-       (MEM_ADDR_SPACE (SET_DEST (XVECEXP (PATTERN (insn), 0, 3))))"
+   && ix86_check_movs (insn, 3)"
 {
   rtx exp = XVECEXP (PATTERN (insn), 0, 3);
 
   operands[0] = SET_DEST (exp);
   operands[1] = SET_SRC (exp);
 
-  return "%^rep{%;} movsb\t{%1, %0|%0, %1}";
+  return "rep{%;} movsb\t{%1, %0|%0, %1}";
 }
   [(set_attr "type" "str")
    (set_attr "prefix_rep" "1")
index 69117b72cdf1127e6968341d343ba838d598ac68..99acd1f68393c84a29f74278fc20ee45e2fe29c2 100644 (file)
@@ -8,4 +8,5 @@ struct a { uword arr[30]; };
 __seg_gs struct a m;
 void bar (struct a *dst) { *dst = m; }
 
-/* { dg-final { scan-assembler "rep\[; \t\]+movs(l|q)\[ \t\]+%gs:" } } */
+/* { dg-final { scan-assembler "rep\[; \t\]+movs(l|q)\[ \t\]+%gs:" { target { ! x32 } } } } */
+/* { dg-final { scan-assembler-not "rep\[; \t\]+movs(l|q)\[ \t\]+%gs:" { target x32 } } } */