From patchwork Wed Jun 22 13:09:14 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kai Tietz X-Patchwork-Id: 101460 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]) by ozlabs.org (Postfix) with SMTP id EBE53B6F68 for ; Wed, 22 Jun 2011 23:09:35 +1000 (EST) Received: (qmail 12741 invoked by alias); 22 Jun 2011 13:09:33 -0000 Received: (qmail 12559 invoked by uid 22791); 22 Jun 2011 13:09:31 -0000 X-SWARE-Spam-Status: No, hits=-1.0 required=5.0 tests=AWL, BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_ENVFROM_END_DIGIT, FREEMAIL_FROM, RCVD_IN_DNSWL_LOW, RFC_ABUSE_POST, TW_TM X-Spam-Check-By: sourceware.org Received: from mail-qw0-f47.google.com (HELO mail-qw0-f47.google.com) (209.85.216.47) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 22 Jun 2011 13:09:15 +0000 Received: by qwh5 with SMTP id 5so422173qwh.20 for ; Wed, 22 Jun 2011 06:09:15 -0700 (PDT) MIME-Version: 1.0 Received: by 10.229.26.84 with SMTP id d20mr452810qcc.203.1308748154983; Wed, 22 Jun 2011 06:09:14 -0700 (PDT) Received: by 10.229.98.146 with HTTP; Wed, 22 Jun 2011 06:09:14 -0700 (PDT) Date: Wed, 22 Jun 2011 15:09:14 +0200 Message-ID: Subject: [patch tree-ssa-forwprop]: Improve binary and/or/xor folding From: Kai Tietz To: GCC Patches Cc: Richard Guenther X-IsSubscribed: yes 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 Hello, This patch improves via type-sinking folding of binary and, or, and xor operations. First we do sinking also for compatible types with same precision, as those don't need to be preserved for these operations. Additional try to fold patterns (TYPE) X bin-op (Y CMP Z) and (TYPE) X bin-op !Y, if type of X is compatible to Y. ChangeLog gcc 2011-06-22 Kai Tietz * tree-ssa-forwprop.c (simplify_bitwise_binary): Improve binary folding regarding casts. ChangeLog gcc/testsuite 2011-06-22 Kai Tietz * gcc.dg/binop-notand1a.c: New test. * gcc.dg/binop-notand2a.c: New test. * gcc.dg/binop-notand3a.c: New test. * gcc.dg/binop-notand4a.c: New test. * gcc.dg/binop-notand5a.c: New test. * gcc.dg/binop-notand6a.c: New test. Bootstrapped and regression tested for all standard languages, Ada, and Obj-C++. Ok for apply? Regards, Kai Index: gcc/gcc/tree-ssa-forwprop.c =================================================================== --- gcc.orig/gcc/tree-ssa-forwprop.c 2011-06-17 11:52:51.000000000 +0200 +++ gcc/gcc/tree-ssa-forwprop.c 2011-06-22 12:36:49.432774100 +0200 @@ -1682,10 +1682,11 @@ simplify_bitwise_binary (gimple_stmt_ite if (CONVERT_EXPR_CODE_P (def1_code) && CONVERT_EXPR_CODE_P (def2_code) && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1)) - /* Make sure that the conversion widens the operands or that it - changes the operation to a bitfield precision. */ + /* Make sure that the conversion widens the operands, or has same + precision, or that it changes the operation to a bitfield + precision. */ && ((TYPE_PRECISION (TREE_TYPE (def1_arg1)) - < TYPE_PRECISION (TREE_TYPE (arg1))) + <= TYPE_PRECISION (TREE_TYPE (arg1))) || (GET_MODE_CLASS (TYPE_MODE (TREE_TYPE (arg1))) != MODE_INT) || (TYPE_PRECISION (TREE_TYPE (arg1)) @@ -1704,6 +1705,88 @@ simplify_bitwise_binary (gimple_stmt_ite return true; } + /* Try to fold (TYPE) X op (Y CMP Z), or (TYPE) X op !Y, if type + of X is compatible to type of Y. */ + if (CONVERT_EXPR_CODE_P (def1_code) + && (TREE_CODE_CLASS (def2_code) == tcc_comparison + || def2_code == TRUTH_NOT_EXPR) + && types_compatible_p (TREE_TYPE (def1_arg1), TREE_TYPE (def2_arg1))) + { + tree t; + if (def2_code == TRUTH_NOT_EXPR) + t = fold_build1_loc (gimple_location (def2), def2_code, + TREE_TYPE (def1_arg1), def2_arg1); + else + t = fold_build2_loc (gimple_location (def2), def2_code, + TREE_TYPE (def1_arg1), def2_arg1, + gimple_assign_rhs2 (def2)); + t = fold_binary_loc (gimple_location (stmt), code, + TREE_TYPE (def1_arg1), def1_arg1, t); + if (t && TREE_CODE (t) == INTEGER_CST) + { + t = fold_convert (TREE_TYPE (arg1), t); + gimple_assign_set_rhs_from_tree (gsi, t); + update_stmt (gsi_stmt (*gsi)); + return true; + } + else if (t && TREE_CODE_CLASS (TREE_CODE (t)) == tcc_comparison) + { + gimple newop; + tree tem = create_tmp_reg (boolean_type_node, NULL); + newop = gimple_build_assign_with_ops (TREE_CODE (t), tem, + TREE_OPERAND (t, 0), + TREE_OPERAND (t, 1)); + tem = make_ssa_name (tem, newop); + gimple_assign_set_lhs (newop, tem); + gsi_insert_before (gsi, newop, GSI_SAME_STMT); + gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR, + tem, NULL_TREE, NULL_TREE); + update_stmt (gsi_stmt (*gsi)); + return true; + } + } + + /* Try to fold (Y CMP Z) op (TYPE) X, or !Y op (TYPE) X, if type + of X is compatible to type of Y. */ + if (CONVERT_EXPR_CODE_P (def2_code) + && (TREE_CODE_CLASS (def1_code) == tcc_comparison + || def1_code == TRUTH_NOT_EXPR) + && types_compatible_p (TREE_TYPE (def2_arg1), TREE_TYPE (def1_arg1))) + { + tree t; + if (def1_code == TRUTH_NOT_EXPR) + t = fold_build1_loc (gimple_location (def1), def1_code, + TREE_TYPE (def2_arg1), def1_arg1); + else + t = fold_build2_loc (gimple_location (def1), def1_code, + TREE_TYPE (def2_arg1), def1_arg1, + gimple_assign_rhs2 (def1)); + t = fold_binary_loc (gimple_location (stmt), code, + TREE_TYPE (def2_arg1), t, def2_arg1); + if (t && TREE_CODE (t) == INTEGER_CST) + { + t = fold_convert (TREE_TYPE (arg2), t); + gimple_assign_set_rhs_from_tree (gsi, t); + update_stmt (gsi_stmt (*gsi)); + return true; + } + else if (t && TREE_CODE_CLASS (TREE_CODE (t)) == tcc_comparison) + { + gimple newop; + tree tem = create_tmp_reg (boolean_type_node, NULL); + newop = gimple_build_assign_with_ops (TREE_CODE (t), tem, + TREE_OPERAND (t, 0), + TREE_OPERAND (t, 1)); + tem = make_ssa_name (tem, newop); + gimple_assign_set_lhs (newop, tem); + gsi_insert_before (gsi, newop, GSI_SAME_STMT); + gimple_assign_set_rhs_with_ops_1 (gsi, NOP_EXPR, + tem, NULL_TREE, NULL_TREE); + update_stmt (gsi_stmt (*gsi)); + return true; + } + } + /* (a | CST1) & CST2 -> (a & CST2) | (CST1 & CST2). */ if (code == BIT_AND_EXPR && def1_code == BIT_IOR_EXPR Index: gcc/gcc/testsuite/gcc.dg/binop-notand1a.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.dg/binop-notand1a.c 2011-06-22 11:03:03.735901300 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (char a, unsigned short b) +{ + return (a & !a) | (b & !b); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/gcc/testsuite/gcc.dg/binop-notand2a.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.dg/binop-notand2a.c 2011-06-22 11:05:43.629705200 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (int a) +{ + return (!a & 1) != (a == 0); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/gcc/testsuite/gcc.dg/binop-notand3a.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.dg/binop-notand3a.c 2011-06-22 11:09:05.107289600 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (short a) +{ + return (!a & 1) != ((a == 0) & 1); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/gcc/testsuite/gcc.dg/binop-notand4a.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.dg/binop-notand4a.c 2011-06-22 11:09:43.515666900 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (unsigned char a, _Bool b) +{ + return (!a & a) | (b & !b); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/gcc/testsuite/gcc.dg/binop-notand5a.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.dg/binop-notand5a.c 2011-06-22 11:10:11.556727600 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (long a, unsigned long b) +{ + return (a & (a == 0)) | (b & !b); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */ Index: gcc/gcc/testsuite/gcc.dg/binop-notand6a.c =================================================================== --- /dev/null 1970-01-01 00:00:00.000000000 +0000 +++ gcc/gcc/testsuite/gcc.dg/binop-notand6a.c 2011-06-22 11:10:30.816673300 +0200 @@ -0,0 +1,11 @@ +/* { dg-do compile } */ +/* { dg-options "-O2 -fdump-tree-optimized" } */ + +int +foo (unsigned long a, long b) +{ + return (a & !a) | (b & (b == 0)); +} + +/* { dg-final { scan-tree-dump-times "return 0" 1 "optimized" } } */ +/* { dg-final { cleanup-tree-dump "optimized" } } */