From patchwork Fri Aug 12 03:19:19 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kugan Vivekanandarajah X-Patchwork-Id: 658503 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 3s9VW80yxxz9sBf for ; Fri, 12 Aug 2016 13:20:03 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=hkM8iRQ6; 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; q=dns; s=default; b=sih7Zb0LSHvKRSPPe ueBHzjtY9ZyVmXtghScAayfYojWp3tW9SjkHQJOlu1/B7IYNpg/Q3wSs54+ns7UK 2b/uiBgYn2KhxRFaDUoA1316R6DiQ9VYza9gChIUPqTglT5FfD6JJAyrHqQtP8fc ieuyMxdano2UPrKoJ6tUNOTpVw= 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 :subject:to:references:cc:from:message-id:date:mime-version :in-reply-to:content-type; s=default; bh=oH28vu8SeC4KjHG1B9lwFTk APZo=; b=hkM8iRQ63j3WUdPY1r7Mu+CpoT5xMg8LLRP3dWQkTz2JciM7Hcxo/zd Zz8pYskmxTFjFIhVqikd/GLLqXXYQm2StjyVWA7WtdPERD/MAaeNRQvVonDoKzLC yvYEujbmtw0RaQxGxurcroOwXIc9L3GEfdxHrAx9UBzok/+13VNk= Received: (qmail 108113 invoked by alias); 12 Aug 2016 03:19:42 -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 98874 invoked by uid 89); 12 Aug 2016 03:19:36 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-0.1 required=5.0 tests=AWL, BAYES_50, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=ham version=3.3.2 spammy=2016-08-12, gimple_code, gsi_stmt, GIMPLE_COND X-HELO: mail-pa0-f43.google.com Received: from mail-pa0-f43.google.com (HELO mail-pa0-f43.google.com) (209.85.220.43) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Fri, 12 Aug 2016 03:19:25 +0000 Received: by mail-pa0-f43.google.com with SMTP id ti13so4431740pac.0 for ; Thu, 11 Aug 2016 20:19:25 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:subject:to:references:cc:from:message-id:date :user-agent:mime-version:in-reply-to; bh=WilJCWouyDuy73DONjGsMNp531g0HSvq6+eZDl9xfBY=; b=DH4laugg7FA+hK3AAnGR/9Cf53jTatOUDoY833zL1vYLKzKQCCpnYP/GnQVZEqHu9/ 750gMIcT+oQKZceTCgW6fc9m72E7enVrenAkduf/EqZGyCVPS/cnJmBanQGBXfJIsyWs fPWfNnTd7cweit+ffcTzjGpmNP/3vQJNQHeQre+JBgeb2U8u06jiyosNqnuDh4zch8b7 4BFZzoO+vocHhykhQ27zfIq6Wz2LjikVCpE/xtNWvozrn+a28CooVClPLwdZ2UhHtt9P XnscbAk7xLPnLWzuMa458924gsKjykFok9W+XHshMkbxDgDzlKkanqSruHcmgNrngzkg ZqKg== X-Gm-Message-State: AEkooutW2vqTRDqL5UVjASuQh5MaE9fqMSP3QtkN9CqBR+kx7H/fBXVIW4Efm7enByQ3IseG X-Received: by 10.66.137.107 with SMTP id qh11mr23265597pab.49.1470971963913; Thu, 11 Aug 2016 20:19:23 -0700 (PDT) Received: from [10.1.1.4] (58-6-183-210.dyn.iinet.net.au. [58.6.183.210]) by smtp.gmail.com with ESMTPSA id fe8sm8445321pad.2.2016.08.11.20.19.21 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Thu, 11 Aug 2016 20:19:23 -0700 (PDT) Subject: Re: [RFC][PR61839]Convert CST BINOP COND_EXPR to COND_EXPR ? (CST BINOP 1) : (CST BINOP 0) To: Richard Biener References: <5712C739.4080101@linaro.org> <028aa472-0193-1077-bad3-d1dba1b324e2@linaro.org> Cc: "gcc-patches@gcc.gnu.org" From: kugan Message-ID: Date: Fri, 12 Aug 2016 13:19:19 +1000 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101 Thunderbird/45.2.0 MIME-Version: 1.0 In-Reply-To: X-IsSubscribed: yes Hi Richard, On 11/08/16 20:04, Richard Biener wrote: > On Thu, Aug 11, 2016 at 6:11 AM, kugan > wrote: [SNIP] > > +two_valued_val_range_p (tree var, tree *a, tree *b) > +{ > + value_range *vr = get_value_range (var); > + if ((vr->type != VR_RANGE > + && vr->type != VR_ANTI_RANGE) > + || !range_int_cst_p (vr)) > + return false; > > range_int_cst_p checks for vr->type == VR_RANGE so the anti-range handling > doesn't ever trigger - which means you should add a testcase for it as well. Fixed it. I have also added a testcase. > > > + { > + *a = TYPE_MIN_VALUE (TREE_TYPE (var)); > + *b = TYPE_MAX_VALUE (TREE_TYPE (var)); > > note that for pointer types this doesn't work, please also use > vrp_val_min/max for > consistency. I think you want to add a INTEGRAL_TYPE_P (TREE_TYPE (var)) > to the guard of two_valued_val_range_p. > > + /* First canonicalize to simplify tests. */ > + if (commutative_tree_code (rhs_code) > + && TREE_CODE (rhs2) == INTEGER_CST) > + std::swap (rhs1, rhs2); > > note that this doesn't really address my comment - if you just want to handle > commutative ops then simply look for the constant in the second place rather > than the first which is the canonical operand order. But even for > non-commutative > operations we might want to apply this optimization - and then for both cases, > rhs1 or rhs2 being constant. Like x / 5 and 5 / x. > > Note that you can rely on int_const_binop returning NULL_TREE for "invalid" > ops like x % 0 or x / 0, so no need to explicitely guard this here. Sorry, I misunderstood you. I have changed it now. I also added test-case to check this. Bootstrapped and regression tested on x86_64-linux-gnu with no new regressions. Is this OK for trunk now? Thanks, Kugan gcc/testsuite/ChangeLog: 2016-08-12 Kugan Vivekanandarajah PR tree-optimization/61839 * gcc.dg/tree-ssa/pr61839_1.c: New test. * gcc.dg/tree-ssa/pr61839_2.c: New test. * gcc.dg/tree-ssa/pr61839_3.c: New test. * gcc.dg/tree-ssa/pr61839_4.c: New test. gcc/ChangeLog: 2016-08-12 Kugan Vivekanandarajah PR tree-optimization/61839 * tree-vrp.c (two_valued_val_range_p): New. (simplify_stmt_using_ranges): Convert CST BINOP VAR where VAR is two-valued to VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2). Also Convert VAR BINOP CST where VAR is two-valued to VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST). diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c index e69de29..9f8168a 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_1.c @@ -0,0 +1,44 @@ +/* PR tree-optimization/61839. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */ +/* { dg-require-effective-target int32plus } */ + +__attribute__ ((noinline)) +int foo () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) >> (1LU <= b); + if (c == 486097858) + ; + else + __builtin_abort (); + return 0; +} + +__attribute__ ((noinline)) +int bar () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) >> (b ? 2 : 3); + if (c == 243048929) + ; + else + __builtin_abort (); + return 0; +} + +int main () +{ + foo (); + bar (); +} + +/* Scan for c = 972195717) >> [0, 1] in function foo. */ +/* { dg-final { scan-tree-dump-times "486097858 : 972195717" 1 "vrp1" } } */ +/* Scan for c = 972195717) >> [2, 3] in function bar. */ +/* { dg-final { scan-tree-dump-times "243048929 : 121524464" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "486097858" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c index e69de29..ffa00a7 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_2.c @@ -0,0 +1,54 @@ +/* PR tree-optimization/61839. */ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-vrp1" } */ +/* { dg-require-effective-target int32plus } */ + +__attribute__ ((noinline)) +int foo () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) / (b ? 1 : 0); + if (c == 972195717) + ; + else + __builtin_abort (); + return 0; +} + +__attribute__ ((noinline)) +int bar () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195718) % (b ? 1 : 0); + if (c == 972195717) + ; + else + __builtin_abort (); + return 0; +} + +__attribute__ ((noinline)) +int bar2 () +{ + int a = -1; + volatile unsigned b = 1U; + int c = 1; + c = (a + 972195716) % (b ? 1 : 2); + if (c == 972195715) + ; + else + __builtin_abort (); + return 0; +} + + +/* Dont optimize 972195717 / 0 in function foo. */ +/* { dg-final { scan-tree-dump-times "972195717 / _" 1 "vrp1" } } */ +/* Dont optimize 972195717 % 0 in function bar. */ +/* { dg-final { scan-tree-dump-times "972195717 % _" 1 "vrp1" } } */ +/* Optimize in function bar2. */ +/* { dg-final { scan-tree-dump-times "972195715 % _" 0 "vrp1" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c index e69de29..5ceb073 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_3.c @@ -0,0 +1,26 @@ +/* PR tree-optimization/61839. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */ + +__attribute__ ((noinline)) +int foo (int a, unsigned b) +{ + int c = 1; + b = a ? 12 : 13; + c = b << 8; + if (c == 3072) + ; + else + __builtin_abort (); + return 0; +} + +int main () +{ + volatile unsigned b = 1U; + foo (-1, b); +} + +/* Scan for c [12, 13] << 8 in function foo. */ +/* { dg-final { scan-tree-dump-times "3072 : 3328" 2 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "3072" 0 "optimized" } } */ diff --git a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c index e69de29..5c026c8 100644 --- a/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c +++ b/gcc/testsuite/gcc.dg/tree-ssa/pr61839_4.c @@ -0,0 +1,28 @@ +/* PR tree-optimization/61839. */ +/* { dg-do run } */ +/* { dg-options "-O2 -fdump-tree-vrp1 -fdump-tree-optimized" } */ +/* { dg-require-effective-target int32plus } */ + +__attribute__ ((noinline)) +int foo (int a, unsigned b) +{ + unsigned c = 1; + if (b >= 1 && b <= ((unsigned)(-1) - 1)) + return 0; + c = b >> 4; + if (c == 268435455) + ; + else + __builtin_abort (); + return 0; +} + +int main () +{ + volatile unsigned b = (unsigned)(-1); + foo (-1, b); +} + +/* Scan for ~[1, 4294967294] >> 4 in function foo. */ +/* { dg-final { scan-tree-dump-times "0 : 268435455" 1 "vrp1" } } */ +/* { dg-final { scan-tree-dump-times "268435455" 0 "optimized" } } */ diff --git a/gcc/tree-vrp.c b/gcc/tree-vrp.c index 7c7ad91..837d768 100644 --- a/gcc/tree-vrp.c +++ b/gcc/tree-vrp.c @@ -10004,6 +10004,40 @@ simplify_internal_call_using_ranges (gimple_stmt_iterator *gsi, gimple *stmt) return true; } +/* Return true if VAR is a two-valued variable. Set a and b with the + two-values when it is true. Return false otherwise. */ + +static bool +two_valued_val_range_p (tree var, tree *a, tree *b) +{ + value_range *vr = get_value_range (var); + if ((vr->type != VR_RANGE + && vr->type != VR_ANTI_RANGE) + || TREE_CODE (vr->min) != INTEGER_CST + || TREE_CODE (vr->max) != INTEGER_CST) + return false; + + if (vr->type == VR_RANGE + && wi::sub (vr->max, vr->min) == 1) + { + *a = vr->min; + *b = vr->max; + return true; + } + + /* ~[TYPE_MIN + 1, TYPE_MAX - 1] */ + if (vr->type == VR_ANTI_RANGE + && wi::sub (vr->min, wi::min_value (TREE_TYPE (var))) == 1 + && wi::sub (wi::max_value (TREE_TYPE (var)), vr->max) == 1) + { + *a = vrp_val_min (TREE_TYPE (var)); + *b = vrp_val_max (TREE_TYPE (var)); + return true; + } + + return false; +} + /* Simplify STMT using ranges if possible. */ static bool @@ -10014,6 +10048,68 @@ simplify_stmt_using_ranges (gimple_stmt_iterator *gsi) { enum tree_code rhs_code = gimple_assign_rhs_code (stmt); tree rhs1 = gimple_assign_rhs1 (stmt); + tree rhs2 = gimple_assign_rhs2 (stmt); + tree lhs = gimple_assign_lhs (stmt); + tree val1 = NULL_TREE, val2 = NULL_TREE; + use_operand_p use_p; + gimple *use_stmt; + + /* Convert: + LHS = CST BINOP VAR + Where VAR is two-valued and LHS is used in GIMPLE_COND only + To: + LHS = VAR == VAL1 ? (CST BINOP VAL1) : (CST BINOP VAL2) + + Also handles: + LHS = VAR BINOP CST + Where VAR is two-valued and LHS is used in GIMPLE_COND only + To: + LHS = VAR == VAL1 ? (VAL1 BINOP CST) : (VAL2 BINOP CST) */ + + if (TREE_CODE_CLASS (rhs_code) == tcc_binary + && INTEGRAL_TYPE_P (TREE_TYPE (lhs)) + && ((TREE_CODE (rhs1) == INTEGER_CST + && TREE_CODE (rhs2) == SSA_NAME) + || (TREE_CODE (rhs2) == INTEGER_CST + && TREE_CODE (rhs1) == SSA_NAME)) + && single_imm_use (lhs, &use_p, &use_stmt) + && gimple_code (use_stmt) == GIMPLE_COND) + + { + tree new_rhs1 = NULL_TREE; + tree new_rhs2 = NULL_TREE; + tree cmp_var = NULL_TREE; + + if (TREE_CODE (rhs2) == SSA_NAME + && two_valued_val_range_p (rhs2, &val1, &val2)) + { + /* Optimize RHS1 OP [VAL1, VAL2]. */ + new_rhs1 = int_const_binop (rhs_code, rhs1, val1); + new_rhs2 = int_const_binop (rhs_code, rhs1, val2); + cmp_var = rhs2; + } + else if (TREE_CODE (rhs1) == SSA_NAME + && two_valued_val_range_p (rhs1, &val1, &val2)) + { + /* Optimize [VAL1, VAL2] OP RHS2. */ + new_rhs1 = int_const_binop (rhs_code, val1, rhs2); + new_rhs2 = int_const_binop (rhs_code, val2, rhs2); + cmp_var = rhs1; + } + + /* If we could not find two-vals or the optimzation is invalid as + in divide by zero, new_rhs1 / new_rhs will be NULL_TREE. */ + if (new_rhs1 && new_rhs2) + { + tree cond = build2 (EQ_EXPR, TREE_TYPE (cmp_var), cmp_var, val1); + gimple_assign_set_rhs_with_ops (gsi, + COND_EXPR, cond, + new_rhs1, + new_rhs2); + update_stmt (gsi_stmt (*gsi)); + return true; + } + } switch (rhs_code) {