https://gcc.gnu.org/g:69669180d29cc420b1b1ac86530a4f9573748d81
commit r16-285-g69669180d29cc420b1b1ac86530a4f9573748d81 Author: Uros Bizjak <ubiz...@gmail.com> Date: Tue Apr 29 18:08:05 2025 +0200 i386: Disable string insn from non-default AS for Pmode != word_mode [PR111657] 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. Diff: --- gcc/config/i386/i386-expand.cc | 3 ++- gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.cc | 23 +++++++++++++++++- gcc/config/i386/i386.md | 39 +++++++++++++----------------- gcc/testsuite/gcc.target/i386/pr111657-1.c | 3 ++- 5 files changed, 44 insertions(+), 25 deletions(-) diff --git a/gcc/config/i386/i386-expand.cc b/gcc/config/i386/i386-expand.cc index f1cc85b4531c..7f0fdb6fa9e9 100644 --- a/gcc/config/i386/i386-expand.cc +++ b/gcc/config/i386/i386-expand.cc @@ -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; diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index c59b5a67e3a5..e85b925704ba 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -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); diff --git a/gcc/config/i386/i386.cc b/gcc/config/i386/i386.cc index bfd9cac215ad..2f8403381384 100644 --- a/gcc/config/i386/i386.cc +++ b/gcc/config/i386/i386.cc @@ -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; diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index 962e7ab92aa8..44ee94a3e419 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -25599,7 +25599,9 @@ * 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], @@ -25634,15 +25636,14 @@ (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") @@ -25658,15 +25659,14 @@ (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") @@ -25682,15 +25682,14 @@ (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") @@ -25706,15 +25705,14 @@ (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") @@ -25754,15 +25752,14 @@ (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") @@ -25782,15 +25779,14 @@ (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") @@ -25808,15 +25804,14 @@ (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") diff --git a/gcc/testsuite/gcc.target/i386/pr111657-1.c b/gcc/testsuite/gcc.target/i386/pr111657-1.c index 69117b72cdf1..99acd1f68393 100644 --- a/gcc/testsuite/gcc.target/i386/pr111657-1.c +++ b/gcc/testsuite/gcc.target/i386/pr111657-1.c @@ -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 } } } */