From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 28063 invoked by alias); 15 Nov 2019 11:07:21 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Received: (qmail 28048 invoked by uid 89); 15 Nov 2019 11:07:21 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-9.7 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_1,GIT_PATCH_2,GIT_PATCH_3,KAM_ASCII_DIVIDERS,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy= X-HELO: mail-lj1-f194.google.com Received: from mail-lj1-f194.google.com (HELO mail-lj1-f194.google.com) (209.85.208.194) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 15 Nov 2019 11:07:19 +0000 Received: by mail-lj1-f194.google.com with SMTP id r7so10268745ljg.2 for ; Fri, 15 Nov 2019 03:07:19 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=mime-version:references:in-reply-to:from:date:message-id:subject:to; bh=De3p8uHaDfAHOdHQOKktudBNxRC+h4mHVwex94U+nNs=; b=aQkHdQOaLFRfl/jmfk4JELVei1NFTELUOfzutgvHWXIxJ3+Jb/+Lznq0cbx78erkJX vfUIhfoMElcjklgGLg5vb0pg9SmnCXKdOtDAYO7SX6aDXbRcrK7xU7++it9erqrg6bs4 G4Ckdo3A3NnwRwJKqfgUnD8oEkUIVcDh2Imfw74OqD/lApC/d2hD62ld6frKpiLkhd9d UaU4U6+IAd2HPlHSSwJMbfANH7JeXEnlCEtezI1LSB+V9GezAe/je5i/iaYgX/HQuocl OTrWUtNaAX9tU4+RsCNLH4dEZLfZXWYyekZBz7Iub864R4wLBdy3gHn/SmZyCiaKwiW7 wbVg== MIME-Version: 1.0 References: In-Reply-To: From: Richard Biener Date: Fri, 15 Nov 2019 11:08:00 -0000 Message-ID: Subject: Re: [4/8] Record whether a dr_with_seg_len contains mixed steps To: GCC Patches , Richard Sandiford Content-Type: text/plain; charset="UTF-8" X-IsSubscribed: yes X-SW-Source: 2019-11/txt/msg01365.txt.bz2 On Mon, Nov 11, 2019 at 7:48 PM Richard Sandiford wrote: > > prune_runtime_alias_test_list can merge dr_with_seg_len_pair_ts that > have different steps for the first reference or different steps for the > second reference. This patch adds a flag to record that. > > I don't know whether the change to create_intersect_range_checks_index > fixes anything in practice. It would have to be a corner case if so, > since at present we only merge two alias pairs if either the first or > the second references are identical and only the other references differ. > And the vectoriser uses VF-based segment lengths only if both references > in a pair have the same step. Either way, it still seems wrong to use > DR_STEP when it doesn't represent all checks that have been merged into > the pair. OK. > > 2019-11-11 Richard Sandiford > > gcc/ > * tree-data-ref.h (DR_ALIAS_MIXED_STEPS): New flag. > * tree-data-ref.c (prune_runtime_alias_test_list): Set it when > merging data references with different steps. > (create_intersect_range_checks_index): Take a > dr_with_seg_len_pair_t instead of two dr_with_seg_lens. > Bail out if DR_ALIAS_MIXED_STEPS is set. > (create_intersect_range_checks): Take a dr_with_seg_len_pair_t > instead of two dr_with_seg_lens. Update call to > create_intersect_range_checks_index. > (create_runtime_alias_checks): Update call accordingly. > > Index: gcc/tree-data-ref.h > =================================================================== > --- gcc/tree-data-ref.h 2019-11-11 18:30:50.527193443 +0000 > +++ gcc/tree-data-ref.h 2019-11-11 18:30:53.863170161 +0000 > @@ -250,6 +250,12 @@ typedef struct data_reference *data_refe > Temporary flags that indicate whether there is a pair P whose > DRs have or haven't been swapped around. > > + DR_ALIAS_MIXED_STEPS: > + The DR_STEP for one of the data references in the pair does not > + accurately describe that reference for all members of P. (Note > + that the flag does not say anything about whether the DR_STEPs > + of the two references in the pair are the same.) > + > The ordering assumption mentioned above is that for every pair > (DR_A, DR_B) in P: > > @@ -287,6 +293,7 @@ const unsigned int DR_ALIAS_WAW = 1U << > const unsigned int DR_ALIAS_ARBITRARY = 1U << 3; > const unsigned int DR_ALIAS_SWAPPED = 1U << 4; > const unsigned int DR_ALIAS_UNSWAPPED = 1U << 5; > +const unsigned int DR_ALIAS_MIXED_STEPS = 1U << 6; > > /* This struct contains two dr_with_seg_len objects with aliasing data > refs. Two comparisons are generated from them. */ > Index: gcc/tree-data-ref.c > =================================================================== > --- gcc/tree-data-ref.c 2019-11-11 18:30:50.527193443 +0000 > +++ gcc/tree-data-ref.c 2019-11-11 18:30:53.863170161 +0000 > @@ -1618,6 +1618,11 @@ prune_runtime_alias_test_list (vec std::swap (init_a1, init_a2); > } > > + /* The DR_Bs are equal, so only the DR_As can introduce > + mixed steps. */ > + if (!operand_equal_p (DR_STEP (dr_a1->dr), DR_STEP (dr_a2->dr), 0)) > + alias_pair1->flags |= DR_ALIAS_MIXED_STEPS; > + > if (new_seg_len_p) > { > dr_a1->seg_len = build_int_cst (TREE_TYPE (dr_a1->seg_len), > @@ -1663,11 +1668,14 @@ prune_runtime_alias_test_list (vec } > } > > -/* Given LOOP's two data references and segment lengths described by DR_A > - and DR_B, create expression checking if the two addresses ranges intersect > - with each other based on index of the two addresses. This can only be > - done if DR_A and DR_B referring to the same (array) object and the index > - is the only difference. For example: > +/* Try to generate a runtime condition that is true if ALIAS_PAIR is > + free of aliases, using a condition based on index values instead > + of a condition based on addresses. Return true on success, > + storing the condition in *COND_EXPR. > + > + This can only be done if the two data references in ALIAS_PAIR access > + the same array object and the index is the only difference. For example, > + if the two data references are DR_A and DR_B: > > DR_A DR_B > data-ref arr[i] arr[j] > @@ -1690,10 +1698,12 @@ prune_runtime_alias_test_list (vec > static bool > create_intersect_range_checks_index (class loop *loop, tree *cond_expr, > - const dr_with_seg_len& dr_a, > - const dr_with_seg_len& dr_b) > + const dr_with_seg_len_pair_t &alias_pair) > { > - if (integer_zerop (DR_STEP (dr_a.dr)) > + const dr_with_seg_len &dr_a = alias_pair.first; > + const dr_with_seg_len &dr_b = alias_pair.second; > + if ((alias_pair.flags & DR_ALIAS_MIXED_STEPS) > + || integer_zerop (DR_STEP (dr_a.dr)) > || integer_zerop (DR_STEP (dr_b.dr)) > || DR_NUM_DIMENSIONS (dr_a.dr) != DR_NUM_DIMENSIONS (dr_b.dr)) > return false; > @@ -1915,24 +1925,26 @@ get_segment_min_max (const dr_with_seg_l > *seg_max_out = fold_build_pointer_plus (addr_base, max_reach); > } > > -/* Given two data references and segment lengths described by DR_A and DR_B, > - create expression checking if the two addresses ranges intersect with > - each other: > +/* Generate a runtime condition that is true if ALIAS_PAIR is free of aliases, > + storing the condition in *COND_EXPR. The fallback is to generate a > + a test that the two accesses do not overlap: > > - ((DR_A_addr_0 + DR_A_segment_length_0) <= DR_B_addr_0) > - || (DR_B_addr_0 + DER_B_segment_length_0) <= DR_A_addr_0)) */ > + end_a <= start_b || end_b <= start_a. */ > > static void > create_intersect_range_checks (class loop *loop, tree *cond_expr, > - const dr_with_seg_len& dr_a, > - const dr_with_seg_len& dr_b) > + const dr_with_seg_len_pair_t &alias_pair) > { > + const dr_with_seg_len& dr_a = alias_pair.first; > + const dr_with_seg_len& dr_b = alias_pair.second; > *cond_expr = NULL_TREE; > - if (create_intersect_range_checks_index (loop, cond_expr, dr_a, dr_b)) > + if (create_intersect_range_checks_index (loop, cond_expr, alias_pair)) > return; > > unsigned HOST_WIDE_INT min_align; > tree_code cmp_code; > + /* We don't have to check DR_ALIAS_MIXED_STEPS here, since both versions > + are equivalent. This is just an optimization heuristic. */ > if (TREE_CODE (DR_STEP (dr_a.dr)) == INTEGER_CST > && TREE_CODE (DR_STEP (dr_b.dr)) == INTEGER_CST) > { > @@ -1989,18 +2001,19 @@ create_runtime_alias_checks (class loop > tree part_cond_expr; > > fold_defer_overflow_warnings (); > - for (size_t i = 0, s = alias_pairs->length (); i < s; ++i) > + dr_with_seg_len_pair_t *alias_pair; > + unsigned int i; > + FOR_EACH_VEC_ELT (*alias_pairs, i, alias_pair) > { > - const dr_with_seg_len& dr_a = (*alias_pairs)[i].first; > - const dr_with_seg_len& dr_b = (*alias_pairs)[i].second; > - > + gcc_assert (alias_pair->flags); > if (dump_enabled_p ()) > dump_printf (MSG_NOTE, > "create runtime check for data references %T and %T\n", > - DR_REF (dr_a.dr), DR_REF (dr_b.dr)); > + DR_REF (alias_pair->first.dr), > + DR_REF (alias_pair->second.dr)); > > /* Create condition expression for each pair data references. */ > - create_intersect_range_checks (loop, &part_cond_expr, dr_a, dr_b); > + create_intersect_range_checks (loop, &part_cond_expr, *alias_pair); > if (*cond_expr) > *cond_expr = fold_build2 (TRUTH_AND_EXPR, boolean_type_node, > *cond_expr, part_cond_expr);