From patchwork Tue Oct 20 21:27:04 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 533191 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4D97D1401DE for ; Wed, 21 Oct 2015 08:29:48 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=GToBWpIs; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; q=dns; s= default; b=pAkNon2TdYZgrBNRNpj3Ib0U50bS4IqFiseXleNqjktQQf5kS3vFS vL4PnraNi6db0morcsynbvMIN1SpLTRt+DY8aRLFeZCsLJlx/4nSTsG6M/QYiewt 6DMDKICxsco8alZv+hUJKN7K+Mbg28tQb4j16XxEm5lQruj/sPpUaY= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:cc:subject:date:message-id:in-reply-to:references; s= default; bh=yiWqL6S0Lw69+U+FE0T8Ty+q+bs=; b=GToBWpIsufXNWrTjA0TS WmaXRyT/H1FNsGhU1moZSZ1gUb09EUoN/R2k9QmIe2NmpXqhsBYZFthGb2v4MlRo Bh4dWQaYcJHjGadqSp9qnhOCKv6KkZOFnQ7M4Kb60KCZry2U030QLKuEfiP4ZPCZ tJAJDelunXPe05ap2V/jMuQ= Received: (qmail 110664 invoked by alias); 20 Oct 2015 21:28:13 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 110554 invoked by uid 89); 20 Oct 2015 21:28:12 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 X-HELO: mail-pa0-f53.google.com Received: from mail-pa0-f53.google.com (HELO mail-pa0-f53.google.com) (209.85.220.53) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-GCM-SHA256 encrypted) ESMTPS; Tue, 20 Oct 2015 21:28:00 +0000 Received: by pabrc13 with SMTP id rc13so32239159pab.0 for ; Tue, 20 Oct 2015 14:27:58 -0700 (PDT) X-Received: by 10.68.161.162 with SMTP id xt2mr6263705pbb.89.1445376477926; Tue, 20 Oct 2015 14:27:57 -0700 (PDT) Received: from bigtime.com (cpe-50-113-10-46.hawaii.res.rr.com. [50.113.10.46]) by smtp.gmail.com with ESMTPSA id de4sm5422136pbb.60.2015.10.20.14.27.56 (version=TLSv1/SSLv3 cipher=OTHER); Tue, 20 Oct 2015 14:27:57 -0700 (PDT) From: Richard Henderson To: gcc-patches@gcc.gnu.org Cc: richard.guenther@gmail.com Subject: [PATCH v2 04/13] i386: Disallow address spaces with string insns Date: Tue, 20 Oct 2015 11:27:04 -1000 Message-Id: <1445376433-14658-5-git-send-email-rth@redhat.com> In-Reply-To: <1445376433-14658-1-git-send-email-rth@redhat.com> References: <1445376433-14658-1-git-send-email-rth@redhat.com> X-IsSubscribed: yes While cmps and movs allow a segment override of the ds:esi source, the es:edi source/destination cannot be overriden. Simplify things in the backend for now by disallowing segments for string insns entirely. --- gcc/config/i386/i386-protos.h | 1 + gcc/config/i386/i386.c | 61 ++++++++++++++++++++++++++++++++----------- gcc/config/i386/i386.md | 59 +++++++++++++++++++++++++++++------------ 3 files changed, 89 insertions(+), 32 deletions(-) diff --git a/gcc/config/i386/i386-protos.h b/gcc/config/i386/i386-protos.h index 6a17ef4..5e46833 100644 --- a/gcc/config/i386/i386-protos.h +++ b/gcc/config/i386/i386-protos.h @@ -141,6 +141,7 @@ extern void ix86_split_ashr (rtx *, rtx, machine_mode); extern void ix86_split_lshr (rtx *, rtx, machine_mode); extern rtx ix86_find_base_term (rtx); extern bool ix86_check_movabs (rtx, int); +extern bool ix86_check_no_addr_space (rtx); extern void ix86_split_idivmod (machine_mode, rtx[], bool); extern rtx assign_386_stack_local (machine_mode, enum ix86_stack_slot); diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c index c800145..8f2c0f2 100644 --- a/gcc/config/i386/i386.c +++ b/gcc/config/i386/i386.c @@ -10537,6 +10537,20 @@ ix86_check_movabs (rtx insn, int opnum) gcc_assert (MEM_P (mem)); return volatile_ok || !MEM_VOLATILE_P (mem); } + +/* Return false if INSN contains a MEM with a non-default address space. */ +bool +ix86_check_no_addr_space (rtx insn) +{ + subrtx_var_iterator::array_type array; + FOR_EACH_SUBRTX_VAR (iter, array, PATTERN (insn), ALL) + { + rtx x = *iter; + if (MEM_P (x) && !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (x))) + return false; + } + return true; +} /* Initialize the table of extra 80387 mathematical constants. */ @@ -25660,7 +25674,7 @@ expand_set_or_movmem_constant_prologue (rtx dst, rtx *srcp, rtx destreg, /* Return true if ALG can be used in current context. Assume we expand memset if MEMSET is true. */ static bool -alg_usable_p (enum stringop_alg alg, bool memset) +alg_usable_p (enum stringop_alg alg, bool memset, bool have_as) { if (alg == no_stringop) return false; @@ -25669,12 +25683,19 @@ alg_usable_p (enum stringop_alg alg, bool memset) /* Algorithms using the rep prefix want at least edi and ecx; additionally, memset wants eax and memcpy wants esi. Don't consider such algorithms if the user has appropriated those - registers for their own purposes. */ + registers for their own purposes, or if we have a non-default + address space, since some string insns cannot override the segment. */ if (alg == rep_prefix_1_byte || alg == rep_prefix_4_byte || alg == rep_prefix_8_byte) - return !(fixed_regs[CX_REG] || fixed_regs[DI_REG] - || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])); + { + if (have_as) + return false; + if (fixed_regs[CX_REG] + || fixed_regs[DI_REG] + || (memset ? fixed_regs[AX_REG] : fixed_regs[SI_REG])) + return false; + } return true; } @@ -25682,7 +25703,8 @@ alg_usable_p (enum stringop_alg alg, bool memset) static enum stringop_alg decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, unsigned HOST_WIDE_INT min_size, unsigned HOST_WIDE_INT max_size, - bool memset, bool zero_memset, int *dynamic_check, bool *noalign) + bool memset, bool zero_memset, bool have_as, + int *dynamic_check, bool *noalign) { const struct stringop_algs * algs; bool optimize_for_speed; @@ -25714,7 +25736,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, for (i = 0; i < MAX_STRINGOP_ALGS; i++) { enum stringop_alg candidate = algs->size[i].alg; - bool usable = alg_usable_p (candidate, memset); + bool usable = alg_usable_p (candidate, memset, have_as); any_alg_usable_p |= usable; if (candidate != libcall && candidate && usable) @@ -25730,17 +25752,17 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, /* If user specified the algorithm, honnor it if possible. */ if (ix86_stringop_alg != no_stringop - && alg_usable_p (ix86_stringop_alg, memset)) + && alg_usable_p (ix86_stringop_alg, memset, have_as)) return ix86_stringop_alg; /* rep; movq or rep; movl is the smallest variant. */ else if (!optimize_for_speed) { *noalign = true; if (!count || (count & 3) || (memset && !zero_memset)) - return alg_usable_p (rep_prefix_1_byte, memset) + return alg_usable_p (rep_prefix_1_byte, memset, have_as) ? rep_prefix_1_byte : loop_1_byte; else - return alg_usable_p (rep_prefix_4_byte, memset) + return alg_usable_p (rep_prefix_4_byte, memset, have_as) ? rep_prefix_4_byte : loop; } /* Very tiny blocks are best handled via the loop, REP is expensive to @@ -25763,7 +25785,8 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, { enum stringop_alg candidate = algs->size[i].alg; - if (candidate != libcall && alg_usable_p (candidate, memset)) + if (candidate != libcall + && alg_usable_p (candidate, memset, have_as)) { alg = candidate; alg_noalign = algs->size[i].noalign; @@ -25783,7 +25806,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, else if (!any_alg_usable_p) break; } - else if (alg_usable_p (candidate, memset)) + else if (alg_usable_p (candidate, memset, have_as)) { *noalign = algs->size[i].noalign; return candidate; @@ -25800,7 +25823,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, choice in ix86_costs. */ if ((TARGET_INLINE_ALL_STRINGOPS || TARGET_INLINE_STRINGOPS_DYNAMICALLY) && (algs->unknown_size == libcall - || !alg_usable_p (algs->unknown_size, memset))) + || !alg_usable_p (algs->unknown_size, memset, have_as))) { enum stringop_alg alg; @@ -25817,7 +25840,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, if (max <= 0) max = 4096; alg = decide_alg (count, max / 2, min_size, max_size, memset, - zero_memset, dynamic_check, noalign); + zero_memset, have_as, dynamic_check, noalign); gcc_assert (*dynamic_check == -1); if (TARGET_INLINE_STRINGOPS_DYNAMICALLY) *dynamic_check = max; @@ -25825,7 +25848,7 @@ decide_alg (HOST_WIDE_INT count, HOST_WIDE_INT expected_size, gcc_assert (alg != libcall); return alg; } - return (alg_usable_p (algs->unknown_size, memset) + return (alg_usable_p (algs->unknown_size, memset, have_as) ? algs->unknown_size : libcall); } @@ -26031,6 +26054,7 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, unsigned HOST_WIDE_INT max_size = -1; unsigned HOST_WIDE_INT probable_max_size = -1; bool misaligned_prologue_used = false; + bool have_as; if (CONST_INT_P (align_exp)) align = INTVAL (align_exp); @@ -26068,11 +26092,15 @@ ix86_expand_set_or_movmem (rtx dst, rtx src, rtx count_exp, rtx val_exp, if (count > (HOST_WIDE_INT_1U << 30)) return false; + have_as = !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (dst)); + if (!issetmem) + have_as |= !ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src)); + /* Step 0: Decide on preferred algorithm, desired alignment and size of chunks to be copied by main loop. */ alg = decide_alg (count, expected_size, min_size, probable_max_size, issetmem, - issetmem && val_exp == const0_rtx, + issetmem && val_exp == const0_rtx, have_as, &dynamic_check, &noalign); if (alg == libcall) return false; @@ -26686,6 +26714,9 @@ ix86_expand_strlen (rtx out, rtx src, rtx eoschar, rtx align) /* Can't use this if the user has appropriated eax, ecx, or edi. */ if (fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) return false; + /* Can't use this for non-default address spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (src))) + return false; scratch2 = gen_reg_rtx (Pmode); scratch3 = gen_reg_rtx (Pmode); diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md index ccb672d..2cb94fe 100644 --- a/gcc/config/i386/i386.md +++ b/gcc/config/i386/i386.md @@ -16159,6 +16159,10 @@ (clobber (reg:CC FLAGS_REG))])] "" { + /* Can't use this for non-default address spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[3]))) + FAIL; + rtx adjust = GEN_INT (GET_MODE_SIZE (GET_MODE (operands[1]))); /* If .md ever supports :P for Pmode, these can be directly @@ -16199,7 +16203,8 @@ (plus:P (match_dup 3) (const_int 8)))] "TARGET_64BIT - && !(fixed_regs[SI_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^movsq" [(set_attr "type" "str") (set_attr "memory" "both") @@ -16214,7 +16219,8 @@ (set (match_operand:P 1 "register_operand" "=S") (plus:P (match_dup 3) (const_int 4)))] - "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^movs{l|d}" [(set_attr "type" "str") (set_attr "memory" "both") @@ -16229,7 +16235,8 @@ (set (match_operand:P 1 "register_operand" "=S") (plus:P (match_dup 3) (const_int 2)))] - "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^movsw" [(set_attr "type" "str") (set_attr "memory" "both") @@ -16245,7 +16252,8 @@ (plus:P (match_dup 3) (const_int 1)))] "!(fixed_regs[SI_REG] || fixed_regs[DI_REG])" - "%^movsb" + "%^movsb + && ix86_check_no_addr_space (insn)" [(set_attr "type" "str") (set_attr "memory" "both") (set (attr "prefix_rex") @@ -16280,7 +16288,8 @@ (mem:BLK (match_dup 4))) (use (match_dup 5))] "TARGET_64BIT - && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} movsq" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16299,7 +16308,8 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} movs{l|d}" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16316,7 +16326,8 @@ (set (mem:BLK (match_dup 3)) (mem:BLK (match_dup 4))) (use (match_dup 5))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} movsb" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16356,6 +16367,10 @@ (clobber (reg:CC FLAGS_REG))])] "" { + /* Can't use this for non-default address spaces. */ + if (!ADDR_SPACE_GENERIC_P (MEM_ADDR_SPACE (operands[1]))) + FAIL; + if (GET_MODE (operands[1]) != GET_MODE (operands[2])) operands[1] = adjust_address_nv (operands[1], GET_MODE (operands[2]), 0); @@ -16391,7 +16406,8 @@ (const_int 8))) (unspec [(const_int 0)] UNSPEC_STOS)] "TARGET_64BIT - && !(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stosq" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16404,7 +16420,8 @@ (plus:P (match_dup 1) (const_int 4))) (unspec [(const_int 0)] UNSPEC_STOS)] - "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stos{l|d}" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16417,7 +16434,8 @@ (plus:P (match_dup 1) (const_int 2))) (unspec [(const_int 0)] UNSPEC_STOS)] - "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stosw" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16430,7 +16448,8 @@ (plus:P (match_dup 1) (const_int 1))) (unspec [(const_int 0)] UNSPEC_STOS)] - "!(fixed_regs[AX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^stosb" [(set_attr "type" "str") (set_attr "memory" "store") @@ -16462,7 +16481,8 @@ (use (match_operand:DI 2 "register_operand" "a")) (use (match_dup 4))] "TARGET_64BIT - && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + && !(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} stosq" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16479,7 +16499,8 @@ (const_int 0)) (use (match_operand:SI 2 "register_operand" "a")) (use (match_dup 4))] - "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} stos{l|d}" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16495,7 +16516,8 @@ (const_int 0)) (use (match_operand:QI 2 "register_operand" "a")) (use (match_dup 4))] - "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^rep{%;} stosb" [(set_attr "type" "str") (set_attr "prefix_rep" "1") @@ -16616,7 +16638,8 @@ (clobber (match_operand:P 0 "register_operand" "=S")) (clobber (match_operand:P 1 "register_operand" "=D")) (clobber (match_operand:P 2 "register_operand" "=c"))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^repz{%;} cmpsb" [(set_attr "type" "str") (set_attr "mode" "QI") @@ -16656,7 +16679,8 @@ (clobber (match_operand:P 0 "register_operand" "=S")) (clobber (match_operand:P 1 "register_operand" "=D")) (clobber (match_operand:P 2 "register_operand" "=c"))] - "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[CX_REG] || fixed_regs[SI_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^repz{%;} cmpsb" [(set_attr "type" "str") (set_attr "mode" "QI") @@ -16697,7 +16721,8 @@ (match_operand:P 4 "register_operand" "0")] UNSPEC_SCAS)) (clobber (match_operand:P 1 "register_operand" "=D")) (clobber (reg:CC FLAGS_REG))] - "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG])" + "!(fixed_regs[AX_REG] || fixed_regs[CX_REG] || fixed_regs[DI_REG]) + && ix86_check_no_addr_space (insn)" "%^repnz{%;} scasb" [(set_attr "type" "str") (set_attr "mode" "QI")