From patchwork Sun Jun 12 09:19:42 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Marc Glisse X-Patchwork-Id: 634164 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 3rS9Nw4fVTz9t0K for ; Sun, 12 Jun 2016 19:20:11 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=JtsSkMI2; 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:date :from:to:cc:subject:message-id:mime-version:content-type; q=dns; s=default; b=NjAKhw3XDkRZFzHDIy1dvh44YCXrOiXkvOFuuVIW6uK39M+Fy+ tKw+4IoL+THkLWBxBFN85nOko7Ea+xJRSM7SdQ57ncCmY6peJx0AZoUadEQHvqIn o24fnvCqS2InzGmV1aHo8lQKSHrGvL7ioRzU/BA1KaB5pUd5ugW5HBALM= 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:date :from:to:cc:subject:message-id:mime-version:content-type; s= default; bh=4Fz6GxsMHnnOJViQGpF4n0TRNBg=; b=JtsSkMI2Al1YXyrtB48f xydTOs+6JNTxdu3ojHEzsgl8FSWdyMVAfdtAeMGuZaftg1HuZD9G0OISmfFiHICJ aCMku9kWvc+/V5Cu6T6Eq2y8e/e44EHngquO0qveby8j21DPzBlg+6X0hJGkSEN2 11Rmp/raulBIvNnHTrzLmbU= Received: (qmail 31915 invoked by alias); 12 Jun 2016 09:20:02 -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 31866 invoked by uid 89); 12 Jun 2016 09:20:00 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, KAM_LAZY_DOMAIN_SECURITY, RP_MATCHES_RCVD autolearn=ham version=3.3.2 spammy=20160613, 2016-06-13, TYPE_SIGN, type_sign X-Spam-User: qpsmtpd, 2 recipients X-HELO: mail2-relais-roc.national.inria.fr Received: from mail2-relais-roc.national.inria.fr (HELO mail2-relais-roc.national.inria.fr) (192.134.164.83) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-GCM-SHA384 encrypted) ESMTPS; Sun, 12 Jun 2016 09:19:50 +0000 Received: from 81-65-27-132.rev.numericable.fr (HELO laptop-mg.local) ([81.65.27.132]) by mail2-relais-roc.national.inria.fr with ESMTP/TLS/DHE-RSA-AES256-SHA; 12 Jun 2016 11:19:46 +0200 Date: Sun, 12 Jun 2016 11:19:42 +0200 (CEST) From: Marc Glisse To: gcc-patches@gcc.gnu.org cc: ro@gcc.gnu.org Subject: Vectorize 2*x as x+x if needed Message-ID: User-Agent: Alpine 2.02 (DEB 1266 2009-07-14) MIME-Version: 1.0 Hello, canonicalizing x+x to x*2 made us regress some vectorization tests on sparc. As suggested by Richard, this lets the vectorizer handle x*2 as x+x if that helps. Let me copy a few remarks I had in the PR: « We could probably also handle x*3 as x+x+x, but where to stop? I don't understand why the optab test for LSHIFT_EXPR was using optab_vector, as far as I understand we are creating vec<<3, so optab_scalar makes more sense. I gave priority to x+x over x<<1, not sure if that's right, it probably doesn't matter much as one will probably be turned into the other in later passes. » Rainer bootstrapped and regtested the patch on sparc. As a bonus, it now vectorizes one more loop in gcc.dg/vect/vect-iv-9.c, I'll let someone else tweak the test (which will temporarily appear as a FAIL). 2016-06-13 Marc Glisse PR tree-optimization/70923 * tree-vect-patterns.c (vect_recog_mult_pattern): Use optab_scalar for LSHIFT_EXPR. Handle 2 * X as X + X. Index: gcc/tree-vect-patterns.c =================================================================== *** gcc/tree-vect-patterns.c (revision 237336) --- gcc/tree-vect-patterns.c (working copy) *************** vect_recog_vector_vector_shift_pattern ( *** 2166,2189 **** * Return value: A new stmt that will be used to replace the multiplication S1 or S2 stmt. */ static gimple * vect_recog_mult_pattern (vec *stmts, tree *type_in, tree *type_out) { gimple *last_stmt = stmts->pop (); tree oprnd0, oprnd1, vectype, itype; ! gimple *pattern_stmt, *def_stmt; optab optab; stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); ! int power2_val, power2_neg_val; tree shift; if (!is_gimple_assign (last_stmt)) return NULL; if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR) return NULL; oprnd0 = gimple_assign_rhs1 (last_stmt); oprnd1 = gimple_assign_rhs2 (last_stmt); --- 2166,2189 ---- * Return value: A new stmt that will be used to replace the multiplication S1 or S2 stmt. */ static gimple * vect_recog_mult_pattern (vec *stmts, tree *type_in, tree *type_out) { gimple *last_stmt = stmts->pop (); tree oprnd0, oprnd1, vectype, itype; ! gimple *pattern_stmt; optab optab; stmt_vec_info stmt_vinfo = vinfo_for_stmt (last_stmt); ! int power2_val; tree shift; if (!is_gimple_assign (last_stmt)) return NULL; if (gimple_assign_rhs_code (last_stmt) != MULT_EXPR) return NULL; oprnd0 = gimple_assign_rhs1 (last_stmt); oprnd1 = gimple_assign_rhs2 (last_stmt); *************** vect_recog_mult_pattern (vec * *** 2203,2261 **** don't attempt to optimize this. */ optab = optab_for_tree_code (MULT_EXPR, vectype, optab_default); if (optab != unknown_optab) { machine_mode vec_mode = TYPE_MODE (vectype); int icode = (int) optab_handler (optab, vec_mode); if (icode != CODE_FOR_nothing) return NULL; } ! /* If target cannot handle vector left shift then we cannot ! optimize and bail out. */ ! optab = optab_for_tree_code (LSHIFT_EXPR, vectype, optab_vector); ! if (!optab ! || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing) ! return NULL; ! ! power2_val = wi::exact_log2 (oprnd1); ! power2_neg_val = wi::exact_log2 (wi::neg (oprnd1)); ! /* Handle constant operands that are postive or negative powers of 2. */ ! if (power2_val != -1) ! { ! shift = build_int_cst (itype, power2_val); ! pattern_stmt ! = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), ! LSHIFT_EXPR, oprnd0, shift); ! } ! else if (power2_neg_val != -1) { /* If the target cannot handle vector NEGATE then we cannot do the optimization. */ ! optab = optab_for_tree_code (NEGATE_EXPR, vectype, optab_vector); if (!optab || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing) return NULL; ! shift = build_int_cst (itype, power2_neg_val); ! def_stmt = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), ! LSHIFT_EXPR, oprnd0, shift); ! new_pattern_def_seq (stmt_vinfo, def_stmt); pattern_stmt ! = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), ! NEGATE_EXPR, gimple_assign_lhs (def_stmt)); } else return NULL; /* Pattern detected. */ if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "vect_recog_mult_pattern: detected:\n"); if (dump_enabled_p ()) dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt,0); stmts->safe_push (last_stmt); --- 2203,2271 ---- don't attempt to optimize this. */ optab = optab_for_tree_code (MULT_EXPR, vectype, optab_default); if (optab != unknown_optab) { machine_mode vec_mode = TYPE_MODE (vectype); int icode = (int) optab_handler (optab, vec_mode); if (icode != CODE_FOR_nothing) return NULL; } ! bool negate = wi::neg_p (oprnd1, TYPE_SIGN (TREE_TYPE (oprnd1))); ! if (negate) { /* If the target cannot handle vector NEGATE then we cannot do the optimization. */ ! optab = optab_for_tree_code (NEGATE_EXPR, vectype, optab_default); if (!optab || optab_handler (optab, TYPE_MODE (vectype)) == CODE_FOR_nothing) return NULL; + power2_val = wi::exact_log2 (wi::neg (oprnd1)); + } + else + { + power2_val = wi::exact_log2 (oprnd1); + } ! /* Handle constant operands +-2 if target can handle vector addition. */ ! if (power2_val == 1 ! && (optab = optab_for_tree_code (PLUS_EXPR, vectype, optab_default)) ! && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing) ! { ! pattern_stmt = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), ! PLUS_EXPR, oprnd0, oprnd0); ! } ! /* Handle constant operands that are positive or negative powers of 2 ! if target can handle vector left shift. */ ! else if (power2_val != -1 ! && (optab = optab_for_tree_code (LSHIFT_EXPR, vectype, optab_scalar)) ! && optab_handler (optab, TYPE_MODE (vectype)) != CODE_FOR_nothing) ! { ! shift = build_int_cst (itype, power2_val); pattern_stmt ! = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), ! LSHIFT_EXPR, oprnd0, shift); } else return NULL; + if (negate) + { + tree tmp_var = gimple_assign_lhs (pattern_stmt); + new_pattern_def_seq (stmt_vinfo, pattern_stmt); + pattern_stmt + = gimple_build_assign (vect_recog_temp_ssa_var (itype, NULL), + NEGATE_EXPR, tmp_var); + } + /* Pattern detected. */ if (dump_enabled_p ()) dump_printf_loc (MSG_NOTE, vect_location, "vect_recog_mult_pattern: detected:\n"); if (dump_enabled_p ()) dump_gimple_stmt_loc (MSG_NOTE, vect_location, TDF_SLIM, pattern_stmt,0); stmts->safe_push (last_stmt);