From patchwork Wed Jan 27 21:01:23 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Makarov X-Patchwork-Id: 574430 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 649661402CD for ; Thu, 28 Jan 2016 08:02:04 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=H5FybqCI; 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 :subject:to:cc:message-id:date:mime-version:content-type; q=dns; s=default; b=GighltrX0aaxJcOngYBScuf5AIY5Zic2v8iTnR2Te3kWvHCzDb cJIALFId6a2fjbnhhQsost+QUvie+BEkfl3NJz65dfN9wzd0sabhqQzbQOj0s9II xOHD0XzYLefQW7CzBSJt4V+K5Y/du9U/U+PjUt0kQuHPCgJKckDwYw/xk= 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 :subject:to:cc:message-id:date:mime-version:content-type; s= default; bh=b5A8J125AEvGwdWqumqFxha4ors=; b=H5FybqCIzYvO/Q0ovvay C6nly3sLQp7RmpnHqZgXSfFQyGZJUDLZTnq5XqKtePfbAOUywJByajdb/ZojFyyr 8SVfgnBOhK7lczYHi53vamw9MHz0j9OjZRGIDJMZXtMUrrdDCW4nBqm29ZCWitWU MFtJ7kVfZiDfxQlBQsURckc= Received: (qmail 35182 invoked by alias); 27 Jan 2016 21:01:40 -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 35122 invoked by uid 89); 27 Jan 2016 21:01:40 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=0.8 required=5.0 tests=BAYES_20, KAM_ASCII_DIVIDERS, RP_MATCHES_RCVD, SPF_HELO_PASS autolearn=no version=3.3.2 spammy=5217, hongjiu.lu@intel.com, hongjiuluintelcom, 1617 X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Wed, 27 Jan 2016 21:01:27 +0000 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) by mx1.redhat.com (Postfix) with ESMTPS id 8AA1291EA3 for ; Wed, 27 Jan 2016 21:01:25 +0000 (UTC) Received: from [10.3.112.111] (ovpn-112-111.phx2.redhat.com [10.3.112.111]) by int-mx09.intmail.prod.int.phx2.redhat.com (8.14.4/8.14.4) with ESMTP id u0RL1N7x011523; Wed, 27 Jan 2016 16:01:24 -0500 From: Vladimir Makarov Subject: RFA: patch to fix PR69299 To: gcc-patches Cc: Jeff Law Message-ID: <56A93023.8020201@redhat.com> Date: Wed, 27 Jan 2016 16:01:23 -0500 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.1.0 MIME-Version: 1.0 X-IsSubscribed: yes The following patch fixes PR69299. The details of the problem is described on https://gcc.gnu.org/bugzilla/show_bug.cgi?id=69299 The patch was successfully bootstrapped and tested on x86/x86-64. The patch introduces a new type of constraints define_special_memory_constraint for memory constraints whose address reload can not make memory to satisfy the constraint. It is useful when specifically aligned memory is necessary or desirable. I don't know what is the best name for this constraint. I use special_memory_constraint but it could be more specific, e.g. aligned_memory_constraint. Please let me know what is the best name for you. Is the patch ok to commit? Index: ChangeLog =================================================================== --- ChangeLog (revision 232903) +++ ChangeLog (working copy) @@ -1,3 +1,37 @@ +2016-01-27 Vladimir Makarov + + PR target/68990 + * config/i386/constraints.md (Bm): Describe as special memory + constraint. + * doc/md.texi (DEFINE_SPECIAL_MEMORY_CONSTRAINT): Describe it. + * genoutput.c (main): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. + * genpreds.c (struct constraint_data): Add is_special_memory. + (have_special_memory_constraints, special_memory_start): New + static vars. + (special_memory_end): Ditto. + (add_constraint): Add new arg is_special_memory. Add code to + process its true value. Update have_special_memory_constraints. + (process_define_constraint): Pass the new arg. + (process_define_register_constraint): Ditto. + (choose_enum_order): Process special memory. + (write_tm_preds_h): Generate enum const CT_SPECIAL_MEMORY and + function insn_extra_special_memory_constraint. + (main): Process DEFINE_SPECIAL_MEMORY_CONSTRAINT. + * gensupport.c (process_rtx): Process + DEFINE_SPECIAL_MEMORY_CONSTRAINT. + * ira-costs.c (record_reg_classes): Process CT_SPECIAL_MEMORY. + * ira-lives.c (single_reg_class): Use + insn_extra_special_memory_constraint. + * ira.c (ira_setup_alts): Process CT_SPECIAL_MEMORY. + * lra-constraints.c (process_alt_operands): Ditto. + (curr_insn_transform): Use insn_extra_special_memory_constraint. + * recog.c (asm_operand_ok, preprocess_constraints): Process + CT_SPECIAL_MEMORY. + * reload.c (find_reloads): Ditto. + * rtl.def (DEFINE_SPECIFAL_MEMORY_CONSTRAINT): New. + * stmt.c (parse_input_constraint): Use + insn_extra_special_memory_constraint. + 2016-01-27 H.J. Lu PR target/68986 Index: config/i386/constraints.md =================================================================== --- config/i386/constraints.md (revision 232571) +++ config/i386/constraints.md (working copy) @@ -161,7 +161,7 @@ "@internal GOT memory operand." (match_operand 0 "GOT_memory_operand")) -(define_constraint "Bm" +(define_special_memory_constraint "Bm" "@internal Vector memory operand." (match_operand 0 "vector_memory_operand")) Index: doc/md.texi =================================================================== --- doc/md.texi (revision 232571) +++ doc/md.texi (working copy) @@ -4424,6 +4424,20 @@ The syntax and semantics are otherwise i @code{define_constraint}. @end deffn +@deffn {MD Expression} define_special_memory_constraint name docstring exp +Use this expression for constraints that match a subset of all memory +operands: that is, @code{reload} can not make them match by reloading +the address as it is described for @code{define_memory_constraint} or +such address reload is undesirable with the performance point of view. + +For example, @code{define_special_memory_constraint} can be useful if +specifically aligned memory is necessary or desirable for some insn +operand. + +The syntax and semantics are otherwise identical to +@code{define_constraint}. +@end deffn + @deffn {MD Expression} define_address_constraint name docstring exp Use this expression for constraints that match a subset of all address operands: that is, @code{reload} can make the constraint match by Index: genoutput.c =================================================================== --- genoutput.c (revision 232571) +++ genoutput.c (working copy) @@ -1019,6 +1019,7 @@ main (int argc, char **argv) case DEFINE_REGISTER_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: + case DEFINE_SPECIAL_MEMORY_CONSTRAINT: note_constraint (&info); break; Index: genpreds.c =================================================================== --- genpreds.c (revision 232571) +++ genpreds.c (working copy) @@ -659,11 +659,11 @@ write_one_predicate_function (struct pre /* Constraints fall into two categories: register constraints (define_register_constraint), and others (define_constraint, - define_memory_constraint, define_address_constraint). We - work out automatically which of the various old-style macros - they correspond to, and produce appropriate code. They all - go in the same hash table so we can verify that there are no - duplicate names. */ + define_memory_constraint, define_special_memory_constraint, + define_address_constraint). We work out automatically which of the + various old-style macros they correspond to, and produce + appropriate code. They all go in the same hash table so we can + verify that there are no duplicate names. */ /* All data from one constraint definition. */ struct constraint_data @@ -681,6 +681,7 @@ struct constraint_data unsigned int is_const_dbl : 1; unsigned int is_extra : 1; unsigned int is_memory : 1; + unsigned int is_special_memory: 1; unsigned int is_address : 1; unsigned int maybe_allows_reg : 1; unsigned int maybe_allows_mem : 1; @@ -718,6 +719,7 @@ static const char const_dbl_constraints[ static unsigned int constraint_max_namelen; static bool have_register_constraints; static bool have_memory_constraints; +static bool have_special_memory_constraints; static bool have_address_constraints; static bool have_extra_constraints; static bool have_const_int_constraints; @@ -728,6 +730,7 @@ static unsigned int register_start, regi static unsigned int satisfied_start; static unsigned int const_int_start, const_int_end; static unsigned int memory_start, memory_end; +static unsigned int special_memory_start, special_memory_end; static unsigned int address_start, address_end; static unsigned int maybe_allows_none_start, maybe_allows_none_end; static unsigned int maybe_allows_reg_start, maybe_allows_reg_end; @@ -754,20 +757,22 @@ mangle (const char *name) /* Add one constraint, of any sort, to the tables. NAME is its name; REGCLASS is the register class, if any; EXP is the expression to - test, if any; IS_MEMORY and IS_ADDRESS indicate memory and address - constraints, respectively; LOC is the .md file location. - - Not all combinations of arguments are valid; most importantly, REGCLASS - is mutually exclusive with EXP, and IS_MEMORY/IS_ADDRESS are only - meaningful for constraints with EXP. + test, if any; IS_MEMORY, IS_SPECIAL_MEMORY and IS_ADDRESS indicate + memory, special memory, and address constraints, respectively; LOC + is the .md file location. + + Not all combinations of arguments are valid; most importantly, + REGCLASS is mutually exclusive with EXP, and + IS_MEMORY/IS_SPECIAL_MEMORY/IS_ADDRESS are only meaningful for + constraints with EXP. This function enforces all syntactic and semantic rules about what constraints can be defined. */ static void add_constraint (const char *name, const char *regclass, - rtx exp, bool is_memory, bool is_address, - file_location loc) + rtx exp, bool is_memory, bool is_special_memory, + bool is_address, file_location loc) { struct constraint_data *c, **iter, **slot; const char *p; @@ -878,6 +883,17 @@ add_constraint (const char *name, const name, name[0]); return; } + else if (is_special_memory) + { + if (name[1] == '\0') + error_at (loc, "constraint letter '%c' cannot be a " + "special memory constraint", name[0]); + else + error_at (loc, "constraint name '%s' begins with '%c', " + "and therefore cannot be a special memory constraint", + name, name[0]); + return; + } else if (is_address) { if (name[1] == '\0') @@ -904,6 +920,7 @@ add_constraint (const char *name, const c->is_const_dbl = is_const_dbl; c->is_extra = !(regclass || is_const_int || is_const_dbl); c->is_memory = is_memory; + c->is_special_memory = is_special_memory; c->is_address = is_address; c->maybe_allows_reg = true; c->maybe_allows_mem = true; @@ -930,17 +947,20 @@ add_constraint (const char *name, const have_const_int_constraints |= c->is_const_int; have_extra_constraints |= c->is_extra; have_memory_constraints |= c->is_memory; + have_special_memory_constraints |= c->is_special_memory; have_address_constraints |= c->is_address; num_constraints += 1; } -/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, or - DEFINE_ADDRESS_CONSTRAINT expression, C. */ +/* Process a DEFINE_CONSTRAINT, DEFINE_MEMORY_CONSTRAINT, + DEFINE_SPECIAL_MEMORY_CONSTRAINT, or DEFINE_ADDRESS_CONSTRAINT + expression, C. */ static void process_define_constraint (md_rtx_info *info) { add_constraint (XSTR (info->def, 0), 0, XEXP (info->def, 2), GET_CODE (info->def) == DEFINE_MEMORY_CONSTRAINT, + GET_CODE (info->def) == DEFINE_SPECIAL_MEMORY_CONSTRAINT, GET_CODE (info->def) == DEFINE_ADDRESS_CONSTRAINT, info->loc); } @@ -950,7 +970,7 @@ static void process_define_register_constraint (md_rtx_info *info) { add_constraint (XSTR (info->def, 0), XSTR (info->def, 1), - 0, false, false, info->loc); + 0, false, false, false, info->loc); } /* Put the constraints into enum order. We want to keep constraints @@ -984,6 +1004,12 @@ choose_enum_order (void) enum_order[next++] = c; memory_end = next; + special_memory_start = next; + FOR_ALL_CONSTRAINTS (c) + if (c->is_special_memory) + enum_order[next++] = c; + special_memory_end = next; + address_start = next; FOR_ALL_CONSTRAINTS (c) if (c->is_address) @@ -992,27 +1018,31 @@ choose_enum_order (void) maybe_allows_none_start = next; FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && !c->maybe_allows_reg && !c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_none_end = next; maybe_allows_reg_start = next; FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && c->maybe_allows_reg && !c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_reg_end = next; maybe_allows_mem_start = next; FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && !c->maybe_allows_reg && c->maybe_allows_mem) enum_order[next++] = c; maybe_allows_mem_end = next; FOR_ALL_CONSTRAINTS (c) - if (!c->is_register && !c->is_const_int && !c->is_memory && !c->is_address + if (!c->is_register && !c->is_const_int && !c->is_memory + && !c->is_special_memory && !c->is_address && c->maybe_allows_reg && c->maybe_allows_mem) enum_order[next++] = c; gcc_assert (next == num_constraints); @@ -1431,6 +1461,8 @@ write_tm_preds_h (void) register_start, register_end); write_range_function ("insn_extra_memory_constraint", memory_start, memory_end); + write_range_function ("insn_extra_special_memory_constraint", + special_memory_start, special_memory_end); write_range_function ("insn_extra_address_constraint", address_start, address_end); write_allows_reg_mem_function (); @@ -1479,6 +1511,7 @@ write_tm_preds_h (void) " CT_REGISTER,\n" " CT_CONST_INT,\n" " CT_MEMORY,\n" + " CT_SPECIAL_MEMORY,\n" " CT_ADDRESS,\n" " CT_FIXED_FORM\n" "};\n" @@ -1491,6 +1524,8 @@ write_tm_preds_h (void) values.safe_push (std::make_pair (const_int_start, "CT_CONST_INT")); if (memory_start != memory_end) values.safe_push (std::make_pair (memory_start, "CT_MEMORY")); + if (special_memory_start != special_memory_end) + values.safe_push (std::make_pair (special_memory_start, "CT_SPECIAL_MEMORY")); if (address_start != address_end) values.safe_push (std::make_pair (address_start, "CT_ADDRESS")); if (address_end != num_constraints) @@ -1602,6 +1637,7 @@ main (int argc, char **argv) case DEFINE_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: + case DEFINE_SPECIAL_MEMORY_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: process_define_constraint (&info); break; Index: gensupport.c =================================================================== --- gensupport.c (revision 232571) +++ gensupport.c (working copy) @@ -521,6 +521,7 @@ process_rtx (rtx desc, file_location loc case DEFINE_CONSTRAINT: case DEFINE_REGISTER_CONSTRAINT: case DEFINE_MEMORY_CONSTRAINT: + case DEFINE_SPECIAL_MEMORY_CONSTRAINT: case DEFINE_ADDRESS_CONSTRAINT: queue_pattern (desc, &define_pred_tail, loc); break; Index: ira-costs.c =================================================================== --- ira-costs.c (revision 232571) +++ ira-costs.c (working copy) @@ -777,6 +777,7 @@ record_reg_classes (int n_alts, int n_op break; case CT_MEMORY: + case CT_SPECIAL_MEMORY: /* Every MEM can be reloaded to fit. */ insn_allows_mem[i] = allows_mem[i] = 1; if (MEM_P (op)) Index: ira-lives.c =================================================================== --- ira-lives.c (revision 232571) +++ ira-lives.c (working copy) @@ -774,6 +774,7 @@ single_reg_class (const char *constraint /* ??? Is this the best way to handle memory constraints? */ cn = lookup_constraint (constraints); if (insn_extra_memory_constraint (cn) + || insn_extra_special_memory_constraint (cn) || insn_extra_address_constraint (cn)) return NO_REGS; if (constraint_satisfied_p (op, cn) Index: ira.c =================================================================== --- ira.c (revision 232571) +++ ira.c (working copy) @@ -1868,6 +1868,7 @@ ira_setup_alts (rtx_insn *insn, HARD_REG case CT_ADDRESS: case CT_MEMORY: + case CT_SPECIAL_MEMORY: goto op_success; case CT_FIXED_FORM: Index: lra-constraints.c =================================================================== --- lra-constraints.c (revision 232571) +++ lra-constraints.c (working copy) @@ -400,7 +400,7 @@ valid_address_p (struct address_info *ad } /* Return true if the eliminated form of memory reference OP satisfies - extra memory constraint CONSTRAINT. */ + extra (special) memory constraint CONSTRAINT. */ static bool satisfies_memory_constraint_p (rtx op, enum constraint_num constraint) { @@ -2038,6 +2038,14 @@ process_alt_operands (int only_alternati if (constraint_satisfied_p (op, cn)) win = true; break; + + case CT_SPECIAL_MEMORY: + if (MEM_P (op) + && satisfies_memory_constraint_p (op, cn)) + win = true; + else if (spilled_pseudo_p (op)) + win = true; + break; } break; @@ -3701,7 +3709,8 @@ curr_insn_transform (bool check_only_p) constraint += CONSTRAINT_LEN (c, constraint)) { enum constraint_num cn = lookup_constraint (constraint); - if (insn_extra_memory_constraint (cn) + if ((insn_extra_memory_constraint (cn) + || insn_extra_special_memory_constraint (cn)) && satisfies_memory_constraint_p (tem, cn)) break; } Index: recog.c =================================================================== --- recog.c (revision 232571) +++ recog.c (working copy) @@ -1791,6 +1791,7 @@ asm_operand_ok (rtx op, const char *cons break; case CT_MEMORY: + case CT_SPECIAL_MEMORY: /* Every memory operand can be reloaded to fit. */ result = result || memory_operand (op, VOIDmode); break; @@ -2403,6 +2404,7 @@ preprocess_constraints (int n_operands, break; case CT_MEMORY: + case CT_SPECIAL_MEMORY: op_alt[i].memory_ok = 1; break; Index: reload.c =================================================================== --- reload.c (revision 232571) +++ reload.c (working copy) @@ -3471,6 +3471,23 @@ find_reloads (rtx_insn *insn, int replac offmemok = 1; break; + case CT_SPECIAL_MEMORY: + if (force_reload) + break; + if (constraint_satisfied_p (operand, cn)) + win = 1; + /* Likewise if the address will be reloaded because + reg_equiv_address is nonzero. For reg_equiv_mem + we have to check. */ + else if (REG_P (operand) + && REGNO (operand) >= FIRST_PSEUDO_REGISTER + && reg_renumber[REGNO (operand)] < 0 + && reg_equiv_mem (REGNO (operand)) != 0 + && (constraint_satisfied_p + (reg_equiv_mem (REGNO (operand)), cn))) + win = 1; + break; + case CT_ADDRESS: if (constraint_satisfied_p (operand, cn)) win = 1; Index: rtl.def =================================================================== --- rtl.def (revision 232571) +++ rtl.def (working copy) @@ -1035,6 +1035,7 @@ DEF_RTL_EXPR(DEFINE_REGISTER_CONSTRAINT, RTL object. */ DEF_RTL_EXPR(DEFINE_CONSTRAINT, "define_constraint", "sse", RTX_EXTRA) DEF_RTL_EXPR(DEFINE_MEMORY_CONSTRAINT, "define_memory_constraint", "sse", RTX_EXTRA) +DEF_RTL_EXPR(DEFINE_SPECIAL_MEMORY_CONSTRAINT, "define_special_memory_constraint", "sse", RTX_EXTRA) DEF_RTL_EXPR(DEFINE_ADDRESS_CONSTRAINT, "define_address_constraint", "sse", RTX_EXTRA) Index: stmt.c =================================================================== --- stmt.c (revision 232571) +++ stmt.c (working copy) @@ -434,7 +434,8 @@ parse_input_constraint (const char **con if (reg_class_for_constraint (cn) != NO_REGS || insn_extra_address_constraint (cn)) *allows_reg = true; - else if (insn_extra_memory_constraint (cn)) + else if (insn_extra_memory_constraint (cn) + || insn_extra_special_memory_constraint (cn)) *allows_mem = true; else insn_extra_constraint_allows_reg_mem (cn, allows_reg, allows_mem);