From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 42271 invoked by alias); 21 May 2019 14:24:37 -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 42246 invoked by uid 89); 21 May 2019 14:24:37 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-6.0 required=5.0 tests=AWL,BAYES_00,FREEMAIL_FROM,GIT_PATCH_2,GIT_PATCH_3,LIKELY_SPAM_BODY,RCVD_IN_DNSWL_NONE,SPF_PASS autolearn=ham version=3.3.1 spammy=cddce2 X-HELO: mail-lj1-f196.google.com Received: from mail-lj1-f196.google.com (HELO mail-lj1-f196.google.com) (209.85.208.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 21 May 2019 14:24:34 +0000 Received: by mail-lj1-f196.google.com with SMTP id q62so6544917ljq.7 for ; Tue, 21 May 2019 07:24:34 -0700 (PDT) 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 :cc; bh=6HLV/m8DIWQNzXevbS6Le/FU3qufzDTS/Jf/P6PMWK4=; b=d/UYno14PiT7qM0yXLjFXDoCeNURIj4t3pNwiIidHscIJ3kelFirrN8rtgD2y3ireB ZpT96rKv0H+QYg2vl1VLHqWt9M3Sh1oDMUgn8CoyeDWyfld6XMV6NoUNukxFIfF9XDs7 9P92ooL1giEeX5+ikv+fpDOzWCEe0iZW2rE2J1dS6ZfVJ3DTDshqDF3TMu6SXLc8GXmn xkWA/vRkw3UQbtMytzGz6c/uB5jDQGw83u4Q3xv5Xr+ioUnkxN0Mazo31q0O6KzD7osd swvigjsvuytOhMCH0m9miaPh5Zfkv0uxmEqp5hLyHiJ4vieVk/LY9PynqX1TX2ULf0Mo JZrg== MIME-Version: 1.0 References: <334e4382-d393-4a83-0fa6-abd80a949f44@redhat.com> In-Reply-To: From: Richard Biener Date: Tue, 21 May 2019 14:24:00 -0000 Message-ID: Subject: Re: [PATCH] Remove empty loop with assumed finiteness (PR tree-optimization/89713) To: Feng Xue OS Cc: "gcc-patches@gcc.gnu.org" , Jeff Law Content-Type: text/plain; charset="UTF-8" X-IsSubscribed: yes X-SW-Source: 2019-05/txt/msg01394.txt.bz2 On Tue, May 21, 2019 at 12:12 PM Richard Biener wrote: > > On Mon, May 20, 2019 at 4:51 PM Feng Xue OS wrote: > > > > > I don't see how it is safe in a late pass when it is not safe in an > > > > > earlier one. Optimization is imperfect - we could fail to remove > > > an "obvious" never taken exit and still have a loop that appears to be > > > finite according to our definition. > > > > Yes. it is. This is somewhat similar to strict-alias option/loop dep pragma. > > Compiler tries to do something based on hint you tell it, but does not ensure correctness. > > > > > The only way > > > to define it would be if there was, at any point, an exit from the > > > loop (and there it _may_ be exclude EH edges) then > > > the loop is assumed to be finite. > > > > No catch your point. If we treat an infinite loop as finite, it's bad because the loop might be removed. > > > > Suppose we have a function: > > > > void foo(int bound) > > { for (int i = 0; i <= bound; i++); } > > > > In an early CD-DCE pass, "bound" is represented as a variable, and loop has a exit, so it is assumed to finite, and is removed. > > > > But in a late pass, this function is inlined into another one, and "bound" has value of INT_MAX, this loop is infinite, and here we can know it should not be removed. > > But if "bound" is always INT_MAX but that's not visible to the > compiler we will still remove the > loop so I see no difference with removing it always. > > > This is why I suggest doing the optimization as late as possible. > > But this will defeat the purpose of allowing followup optimizations. > > IMHO the only "sensible" thing is to do > > Index: gcc/tree-ssa-dce.c > =================================================================== > --- gcc/tree-ssa-dce.c (revision 271415) > +++ gcc/tree-ssa-dce.c (working copy) > @@ -417,7 +417,7 @@ find_obviously_necessary_stmts (bool agg > } > > FOR_EACH_LOOP (loop, 0) > - if (!finite_loop_p (loop)) > + if (!loop_has_exit_edges (loop)) > { > if (dump_file) > fprintf (dump_file, "cannot prove finiteness of loop > %i\n", loop->num); Bootstrapped / tested on x86_64-unknown-linux-gnu. Fallout: FAIL: gcc.dg/loop-unswitch-1.c scan-tree-dump unswitch ";; Unswitching loop" FAIL: gcc.dg/predict-9.c scan-tree-dump-times profile_estimate "first match heuristics: 2.20%" 3 FAIL: gcc.dg/predict-9.c scan-tree-dump-times profile_estimate "first match heuristics: 5.50%" 1 FAIL: gcc.dg/uninit-28-gimple.c (test for bogus messages, line 9) FAIL: gcc.dg/graphite/scop-19.c scan-tree-dump-times graphite "number of SCoPs: 0" 2 ... UNRESOLVED: gcc.dg/tree-ssa/20040211-1.c scan-tree-dump cddce2 "if " FAIL: gcc.dg/tree-ssa/loop-10.c scan-tree-dump-times optimized "if " 3 FAIL: gcc.dg/tree-ssa/pr84648.c scan-tree-dump-times cddce1 "Found loop 1 to be finite: upper bound found" 1 FAIL: gcc.dg/tree-ssa/split-path-6.c scan-tree-dump-times split-paths "Duplicating join block" 3 FAIL: gcc.dg/tree-ssa/ssa-thread-12.c scan-tree-dump thread2 "FSM" FAIL: gcc.dg/tree-ssa/ssa-thread-12.c scan-tree-dump thread3 "FSM" I didn't look if the testcases are sensible for loop removal (or what actually happens). Richard. > that also has the obvious advantage that we don't need to replace the loop > with a trap() but have a place to forward control flow to. The loop in the > following testcase is then successfully removed: > > int main(int argc, char **argv) > { > unsigned i = argc; > while (i+=2); > return 0; > } > > Likewise is the loop > > void **q; > int main(int argc, char **argv) > { > void **p = q; > while (p = (void **)*p); > return 0; > } > > (that's the pointer-chasing). Not with -fnon-call-exceptions > -fexceptions though. > > Richard. > > > Feng > >