From patchwork Mon Oct 23 11:25:40 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Sandiford X-Patchwork-Id: 116701 Delivered-To: patch@linaro.org Received: by 10.140.22.164 with SMTP id 33csp4530582qgn; Mon, 23 Oct 2017 04:26:06 -0700 (PDT) X-Received: by 10.98.58.69 with SMTP id h66mr12692009pfa.121.1508757966061; Mon, 23 Oct 2017 04:26:06 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1508757966; cv=none; d=google.com; s=arc-20160816; b=AQigKrjKXEOD6fbEQOBq+Iw9r3KKuNhhWKpkvfGT/PfK+lJ7MQQVtPC03hCJlL4EpR e+pbSjry8TqWRVODUu3Ld/8NIaRMUJs8Zpj5p3okKXU4Pbd84JH4Q1AZX8m0s+N1iEYg Eg2qEpx9vl419kOudcAsc9cr+M7HrlIPLkX0a9xFsnjHKkpmzxy0i+y5FaoMTqwPBSda mY5WKr2ImQ10brOzafuou1NSfigVTTRhdv/HGYfa//cZ24R3GXOxGzYPl4fINiJo3hIP LIgB0DtwzwMxXtLQtltOjP8HwgYvAicGE3+WaejaobcgoUs1/3z9m7RDL01mT1KdL+Bb 8+tQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=mime-version:user-agent:message-id:in-reply-to:date:references :subject:mail-followup-to:to:from:delivered-to:sender:list-help :list-post:list-archive:list-unsubscribe:list-id:precedence :mailing-list:dkim-signature:domainkey-signature :arc-authentication-results; bh=s7wuzU5x3/X35YQd6M7vjUBU8EenPmrP13WBOS6XRUU=; b=Hkm2Gt5SJtdPPCSEvgqraYeF8V7ZRwiuhyzcKjRdCO8wiAiIZgorUUrXaBpBANMVh5 SST/1YboK6KpOfKFXtYXnd3ret7cr0hqphIRu3M91BnqwtOGgM22RRoqnoKwR0ZfZYL2 88qTDYoWrPxZQGI1Z2N5PXWiZxmbjsJV3pDKUyGNHV+WzEdxmtKY1ElG2IRN4juU89O0 X243/Sd/C/Tiu0d3F/P78NkHfg+0krvbu+N82R/RmtjhiVpN7lmdr9y9Kackx/LTlaNF cFADD/6U2qM7wtLx0r0Rx7mY56oj/C1EJjrLB758vo2RrMK9+tW7es9OfAIJNy1x8FER 8JFw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=BKwMXu2/; spf=pass (google.com: domain of gcc-patches-return-464741-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-464741-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from sourceware.org (server1.sourceware.org. [209.132.180.131]) by mx.google.com with ESMTPS id f64si5236700pff.49.2017.10.23.04.26.05 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 23 Oct 2017 04:26:06 -0700 (PDT) Received-SPF: pass (google.com: domain of gcc-patches-return-464741-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) client-ip=209.132.180.131; Authentication-Results: mx.google.com; dkim=pass header.i=@gcc.gnu.org header.s=default header.b=BKwMXu2/; spf=pass (google.com: domain of gcc-patches-return-464741-patch=linaro.org@gcc.gnu.org designates 209.132.180.131 as permitted sender) smtp.mailfrom=gcc-patches-return-464741-patch=linaro.org@gcc.gnu.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; q=dns; s=default; b=HOFPOLywU9cJ2PM6xC2KZjoMln0ZQ L/q3RpyWA3xvdhDAcWpRFdg18He8qMsoLjgstZiWm1pJj3cYU45R0s3I1T2Q1aJ8 q1iPgFyVFvcXFQ6KluZ39bkRjmJgg6lEWCDFXpfyaQMKlSEaUeoMey6qObOH34bn f8wtXgyOK9uiBg= 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:from :to:subject:references:date:in-reply-to:message-id:mime-version :content-type; s=default; bh=IWp0W6Y6hXYjN07DNyMYhm48aYg=; b=BKw MXu2/60J+soWkHabtwNr23SdlYmKH96B8Q9Jzj0flIIqvaNegu4Lr2J3S4ZBUSGx 487/k7qEE0gv88jE0F07gmDNuhm5JL/u0ESIy71B3Blr+PPngvrSywzxRpdpKvu6 BYbMTnY5/fdviNebQYp6t7F2a+3gGGTywKFTWlqU= Received: (qmail 68127 invoked by alias); 23 Oct 2017 11:25:51 -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 68112 invoked by uid 89); 23 Oct 2017 11:25:50 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-10.5 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_2, GIT_PATCH_3, KAM_ASCII_DIVIDERS, RCVD_IN_DNSWL_NONE, RCVD_IN_SORBS_SPAM, SPF_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mail-wm0-f47.google.com Received: from mail-wm0-f47.google.com (HELO mail-wm0-f47.google.com) (74.125.82.47) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Mon, 23 Oct 2017 11:25:46 +0000 Received: by mail-wm0-f47.google.com with SMTP id p75so8826164wmg.3 for ; Mon, 23 Oct 2017 04:25:45 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:mail-followup-to:subject:references:date :in-reply-to:message-id:user-agent:mime-version; bh=s7wuzU5x3/X35YQd6M7vjUBU8EenPmrP13WBOS6XRUU=; b=Ehn1+1OAsYZ1HcWqOzIdnCQBj4O/XIOjPMCyOfIpjjhEfowVRsQeCO3ZpMII8M67wO iq0LLetiqF++3qGW6ybIZUFGro2RVyTM9Re1r+VnD0L6FUgPLGcLP5xu0rG38BsRXwwt fu5J2Jae8NutC+J2PJ+npFn/a/CUlHs3gaHHWascN37gUfFTHAxTxIFhb2VSjan9cW/D cPLqxrA6pSoUf1i/qaYHZhGPwL+huKKKYvOlkLkDrSWMZn7P5+8H2tBVAuBpOFzydzaN aBKCZvNjQGWP6G88q2mI08ANR4+P/EF7KvXVi0IUlsNUF2pByCa2u1MAgEvKYUFaGtnt T38A== X-Gm-Message-State: AMCzsaXIPQBh0RJmyJacNbLNxF5lCwTDy1olO0NxjomtF5mWPYfBJav6 UIrtCso67g71k4nKp4awZDGQxXSPpRM= X-Google-Smtp-Source: ABhQp+Rga8rduVpYEWjGAAX3ZIlGyQ4gAjabasm/nfo5e1rj3N+g/TuSgeGkuapvT29WPGkFNMb00w== X-Received: by 10.28.182.85 with SMTP id g82mr4701107wmf.32.1508757943179; Mon, 23 Oct 2017 04:25:43 -0700 (PDT) Received: from localhost ([2.26.27.199]) by smtp.gmail.com with ESMTPSA id 19sm3746793wms.7.2017.10.23.04.25.41 for (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 23 Oct 2017 04:25:42 -0700 (PDT) From: Richard Sandiford To: gcc-patches@gcc.gnu.org Mail-Followup-To: gcc-patches@gcc.gnu.org, richard.sandiford@linaro.org Subject: [14/nn] Add helpers for shift count modes References: <87wp3mxgir.fsf@linaro.org> Date: Mon, 23 Oct 2017 12:25:40 +0100 In-Reply-To: <87wp3mxgir.fsf@linaro.org> (Richard Sandiford's message of "Mon, 23 Oct 2017 12:14:36 +0100") Message-ID: <878tg2w1fv.fsf@linaro.org> User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/25.2 (gnu/linux) MIME-Version: 1.0 This patch adds a stub helper routine to provide the mode of a scalar shift amount, given the mode of the values being shifted. One long-standing problem has been to decide what this mode should be for arbitrary rtxes (as opposed to those directly tied to a target pattern). Is it the mode of the shifted elements? Is it word_mode? Or maybe QImode? Is it whatever the corresponding target pattern says? (In which case what should the mode be when the target doesn't have a pattern?) For now the patch picks word_mode, which should be safe on all targets but could perhaps become suboptimal if the helper routine is used more often than it is in this patch. As it stands the patch does not change the generated code. The patch also adds a helper function that constructs rtxes for constant shift amounts, again given the mode of the value being shifted. As well as helping with the SVE patches, this is one step towards allowing CONST_INTs to have a real mode. 2017-10-23 Richard Sandiford Alan Hayward David Sherwood gcc/ * target.h (get_shift_amount_mode): New function. * emit-rtl.h (gen_int_shift_amount): Declare. * emit-rtl.c (gen_int_shift_amount): New function. * asan.c (asan_emit_stack_protection): Use gen_int_shift_amount instead of GEN_INT. * calls.c (shift_return_value): Likewise. * cse.c (fold_rtx): Likewise. * dse.c (find_shift_sequence): Likewise. * expmed.c (init_expmed_one_mode, store_bit_field_1, expand_shift_1) (expand_shift, expand_smod_pow2): Likewise. * lower-subreg.c (shift_cost): Likewise. * simplify-rtx.c (simplify_unary_operation_1): Likewise. (simplify_binary_operation_1): Likewise. * combine.c (try_combine, find_split_point, force_int_to_mode) (simplify_shift_const_1, simplify_shift_const): Likewise. (change_zero_ext): Likewise. Use simplify_gen_binary. * optabs.c (expand_superword_shift, expand_doubleword_mult) (expand_unop): Use gen_int_shift_amount instead of GEN_INT. (expand_binop): Likewise. Use get_shift_amount_mode instead of word_mode as the mode of a CONST_INT shift amount. (shift_amt_for_vec_perm_mask): Add a machine_mode argument. Use gen_int_shift_amount instead of GEN_INT. (expand_vec_perm): Update caller accordingly. Use gen_int_shift_amount instead of GEN_INT. Index: gcc/target.h =================================================================== --- gcc/target.h 2017-10-23 11:47:06.643477568 +0100 +++ gcc/target.h 2017-10-23 11:47:11.277288162 +0100 @@ -209,6 +209,17 @@ #define HOOKSTRUCT(FRAGMENT) FRAGMENT extern struct gcc_target targetm; +/* Return the mode that should be used to hold a scalar shift amount + when shifting values of the given mode. */ +/* ??? This could in principle be generated automatically from the .md + shift patterns, but for now word_mode should be universally OK. */ + +inline scalar_int_mode +get_shift_amount_mode (machine_mode) +{ + return word_mode; +} + #ifdef GCC_TM_H #ifndef CUMULATIVE_ARGS_MAGIC Index: gcc/emit-rtl.h =================================================================== --- gcc/emit-rtl.h 2017-10-23 11:47:06.643477568 +0100 +++ gcc/emit-rtl.h 2017-10-23 11:47:11.274393237 +0100 @@ -369,6 +369,7 @@ extern void set_reg_attrs_for_parm (rtx, extern void set_reg_attrs_for_decl_rtl (tree t, rtx x); extern void adjust_reg_mode (rtx, machine_mode); extern int mem_expr_equal_p (const_tree, const_tree); +extern rtx gen_int_shift_amount (machine_mode, HOST_WIDE_INT); extern bool need_atomic_barrier_p (enum memmodel, bool); Index: gcc/emit-rtl.c =================================================================== --- gcc/emit-rtl.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/emit-rtl.c 2017-10-23 11:47:11.273428262 +0100 @@ -6478,6 +6478,15 @@ need_atomic_barrier_p (enum memmodel mod } } +/* Return a constant shift amount for shifting a value of mode MODE + by VALUE bits. */ + +rtx +gen_int_shift_amount (machine_mode mode, HOST_WIDE_INT value) +{ + return gen_int_mode (value, get_shift_amount_mode (mode)); +} + /* Initialize fields of rtl_data related to stack alignment. */ void Index: gcc/asan.c =================================================================== --- gcc/asan.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/asan.c 2017-10-23 11:47:11.270533336 +0100 @@ -1388,7 +1388,7 @@ asan_emit_stack_protection (rtx base, rt TREE_ASM_WRITTEN (id) = 1; emit_move_insn (mem, expand_normal (build_fold_addr_expr (decl))); shadow_base = expand_binop (Pmode, lshr_optab, base, - GEN_INT (ASAN_SHADOW_SHIFT), + gen_int_shift_amount (Pmode, ASAN_SHADOW_SHIFT), NULL_RTX, 1, OPTAB_DIRECT); shadow_base = plus_constant (Pmode, shadow_base, Index: gcc/calls.c =================================================================== --- gcc/calls.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/calls.c 2017-10-23 11:47:11.270533336 +0100 @@ -2749,15 +2749,17 @@ shift_return_value (machine_mode mode, b HOST_WIDE_INT shift; gcc_assert (REG_P (value) && HARD_REGISTER_P (value)); - shift = GET_MODE_BITSIZE (GET_MODE (value)) - GET_MODE_BITSIZE (mode); + machine_mode value_mode = GET_MODE (value); + shift = GET_MODE_BITSIZE (value_mode) - GET_MODE_BITSIZE (mode); if (shift == 0) return false; /* Use ashr rather than lshr for right shifts. This is for the benefit of the MIPS port, which requires SImode values to be sign-extended when stored in 64-bit registers. */ - if (!force_expand_binop (GET_MODE (value), left_p ? ashl_optab : ashr_optab, - value, GEN_INT (shift), value, 1, OPTAB_WIDEN)) + if (!force_expand_binop (value_mode, left_p ? ashl_optab : ashr_optab, + value, gen_int_shift_amount (value_mode, shift), + value, 1, OPTAB_WIDEN)) gcc_unreachable (); return true; } Index: gcc/cse.c =================================================================== --- gcc/cse.c 2017-10-23 11:47:03.707058235 +0100 +++ gcc/cse.c 2017-10-23 11:47:11.273428262 +0100 @@ -3611,9 +3611,9 @@ fold_rtx (rtx x, rtx_insn *insn) || INTVAL (const_arg1) < 0)) { if (SHIFT_COUNT_TRUNCATED) - canon_const_arg1 = GEN_INT (INTVAL (const_arg1) - & (GET_MODE_UNIT_BITSIZE (mode) - - 1)); + canon_const_arg1 = gen_int_shift_amount + (mode, (INTVAL (const_arg1) + & (GET_MODE_UNIT_BITSIZE (mode) - 1))); else break; } @@ -3660,9 +3660,9 @@ fold_rtx (rtx x, rtx_insn *insn) || INTVAL (inner_const) < 0)) { if (SHIFT_COUNT_TRUNCATED) - inner_const = GEN_INT (INTVAL (inner_const) - & (GET_MODE_UNIT_BITSIZE (mode) - - 1)); + inner_const = gen_int_shift_amount + (mode, (INTVAL (inner_const) + & (GET_MODE_UNIT_BITSIZE (mode) - 1))); else break; } @@ -3692,7 +3692,8 @@ fold_rtx (rtx x, rtx_insn *insn) /* As an exception, we can turn an ASHIFTRT of this form into a shift of the number of bits - 1. */ if (code == ASHIFTRT) - new_const = GEN_INT (GET_MODE_UNIT_BITSIZE (mode) - 1); + new_const = gen_int_shift_amount + (mode, GET_MODE_UNIT_BITSIZE (mode) - 1); else if (!side_effects_p (XEXP (y, 0))) return CONST0_RTX (mode); else Index: gcc/dse.c =================================================================== --- gcc/dse.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/dse.c 2017-10-23 11:47:11.273428262 +0100 @@ -1605,8 +1605,9 @@ find_shift_sequence (int access_size, store_mode, byte); if (ret && CONSTANT_P (ret)) { + rtx shift_rtx = gen_int_shift_amount (new_mode, shift); ret = simplify_const_binary_operation (LSHIFTRT, new_mode, - ret, GEN_INT (shift)); + ret, shift_rtx); if (ret && CONSTANT_P (ret)) { byte = subreg_lowpart_offset (read_mode, new_mode); @@ -1642,7 +1643,8 @@ find_shift_sequence (int access_size, of one dsp where the cost of these two was not the same. But this really is a rare case anyway. */ target = expand_binop (new_mode, lshr_optab, new_reg, - GEN_INT (shift), new_reg, 1, OPTAB_DIRECT); + gen_int_shift_amount (new_mode, shift), + new_reg, 1, OPTAB_DIRECT); shift_seq = get_insns (); end_sequence (); Index: gcc/expmed.c =================================================================== --- gcc/expmed.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/expmed.c 2017-10-23 11:47:11.274393237 +0100 @@ -222,7 +222,8 @@ init_expmed_one_mode (struct init_expmed PUT_MODE (all->zext, wider_mode); PUT_MODE (all->wide_mult, wider_mode); PUT_MODE (all->wide_lshr, wider_mode); - XEXP (all->wide_lshr, 1) = GEN_INT (mode_bitsize); + XEXP (all->wide_lshr, 1) + = gen_int_shift_amount (wider_mode, mode_bitsize); set_mul_widen_cost (speed, wider_mode, set_src_cost (all->wide_mult, wider_mode, speed)); @@ -908,12 +909,14 @@ store_bit_field_1 (rtx str_rtx, unsigned to make sure that for big-endian machines the higher order bits are used. */ if (new_bitsize < BITS_PER_WORD && BYTES_BIG_ENDIAN && !backwards) - value_word = simplify_expand_binop (word_mode, lshr_optab, - value_word, - GEN_INT (BITS_PER_WORD - - new_bitsize), - NULL_RTX, true, - OPTAB_LIB_WIDEN); + { + int shift = BITS_PER_WORD - new_bitsize; + rtx shift_rtx = gen_int_shift_amount (word_mode, shift); + value_word = simplify_expand_binop (word_mode, lshr_optab, + value_word, shift_rtx, + NULL_RTX, true, + OPTAB_LIB_WIDEN); + } if (!store_bit_field_1 (op0, new_bitsize, bitnum + bit_offset, @@ -2366,8 +2369,9 @@ expand_shift_1 (enum tree_code code, mac if (CONST_INT_P (op1) && ((unsigned HOST_WIDE_INT) INTVAL (op1) >= (unsigned HOST_WIDE_INT) GET_MODE_BITSIZE (scalar_mode))) - op1 = GEN_INT ((unsigned HOST_WIDE_INT) INTVAL (op1) - % GET_MODE_BITSIZE (scalar_mode)); + op1 = gen_int_shift_amount (mode, + (unsigned HOST_WIDE_INT) INTVAL (op1) + % GET_MODE_BITSIZE (scalar_mode)); else if (GET_CODE (op1) == SUBREG && subreg_lowpart_p (op1) && SCALAR_INT_MODE_P (GET_MODE (SUBREG_REG (op1))) @@ -2384,7 +2388,8 @@ expand_shift_1 (enum tree_code code, mac && IN_RANGE (INTVAL (op1), GET_MODE_BITSIZE (scalar_mode) / 2 + left, GET_MODE_BITSIZE (scalar_mode) - 1)) { - op1 = GEN_INT (GET_MODE_BITSIZE (scalar_mode) - INTVAL (op1)); + op1 = gen_int_shift_amount (mode, (GET_MODE_BITSIZE (scalar_mode) + - INTVAL (op1))); left = !left; code = left ? LROTATE_EXPR : RROTATE_EXPR; } @@ -2464,8 +2469,8 @@ expand_shift_1 (enum tree_code code, mac if (op1 == const0_rtx) return shifted; else if (CONST_INT_P (op1)) - other_amount = GEN_INT (GET_MODE_BITSIZE (scalar_mode) - - INTVAL (op1)); + other_amount = gen_int_shift_amount + (mode, GET_MODE_BITSIZE (scalar_mode) - INTVAL (op1)); else { other_amount @@ -2538,8 +2543,9 @@ expand_shift_1 (enum tree_code code, mac expand_shift (enum tree_code code, machine_mode mode, rtx shifted, int amount, rtx target, int unsignedp) { - return expand_shift_1 (code, mode, - shifted, GEN_INT (amount), target, unsignedp); + return expand_shift_1 (code, mode, shifted, + gen_int_shift_amount (mode, amount), + target, unsignedp); } /* Likewise, but return 0 if that cannot be done. */ @@ -3855,7 +3861,7 @@ expand_smod_pow2 (scalar_int_mode mode, { HOST_WIDE_INT masklow = (HOST_WIDE_INT_1 << logd) - 1; signmask = force_reg (mode, signmask); - shift = GEN_INT (GET_MODE_BITSIZE (mode) - logd); + shift = gen_int_shift_amount (mode, GET_MODE_BITSIZE (mode) - logd); /* Use the rtx_cost of a LSHIFTRT instruction to determine which instruction sequence to use. If logical right shifts Index: gcc/lower-subreg.c =================================================================== --- gcc/lower-subreg.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/lower-subreg.c 2017-10-23 11:47:11.274393237 +0100 @@ -129,7 +129,7 @@ shift_cost (bool speed_p, struct cost_rt PUT_CODE (rtxes->shift, code); PUT_MODE (rtxes->shift, mode); PUT_MODE (rtxes->source, mode); - XEXP (rtxes->shift, 1) = GEN_INT (op1); + XEXP (rtxes->shift, 1) = gen_int_shift_amount (mode, op1); return set_src_cost (rtxes->shift, mode, speed_p); } Index: gcc/simplify-rtx.c =================================================================== --- gcc/simplify-rtx.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/simplify-rtx.c 2017-10-23 11:47:11.277288162 +0100 @@ -1165,7 +1165,8 @@ simplify_unary_operation_1 (enum rtx_cod if (STORE_FLAG_VALUE == 1) { temp = simplify_gen_binary (ASHIFTRT, inner, XEXP (op, 0), - GEN_INT (isize - 1)); + gen_int_shift_amount (inner, + isize - 1)); if (int_mode == inner) return temp; if (GET_MODE_PRECISION (int_mode) > isize) @@ -1175,7 +1176,8 @@ simplify_unary_operation_1 (enum rtx_cod else if (STORE_FLAG_VALUE == -1) { temp = simplify_gen_binary (LSHIFTRT, inner, XEXP (op, 0), - GEN_INT (isize - 1)); + gen_int_shift_amount (inner, + isize - 1)); if (int_mode == inner) return temp; if (GET_MODE_PRECISION (int_mode) > isize) @@ -2679,7 +2681,8 @@ simplify_binary_operation_1 (enum rtx_co { val = wi::exact_log2 (rtx_mode_t (trueop1, mode)); if (val >= 0) - return simplify_gen_binary (ASHIFT, mode, op0, GEN_INT (val)); + return simplify_gen_binary (ASHIFT, mode, op0, + gen_int_shift_amount (mode, val)); } /* x*2 is x+x and x*(-1) is -x */ @@ -3303,7 +3306,8 @@ simplify_binary_operation_1 (enum rtx_co /* Convert divide by power of two into shift. */ if (CONST_INT_P (trueop1) && (val = exact_log2 (UINTVAL (trueop1))) > 0) - return simplify_gen_binary (LSHIFTRT, mode, op0, GEN_INT (val)); + return simplify_gen_binary (LSHIFTRT, mode, op0, + gen_int_shift_amount (mode, val)); break; case DIV: @@ -3423,10 +3427,12 @@ simplify_binary_operation_1 (enum rtx_co && IN_RANGE (INTVAL (trueop1), GET_MODE_UNIT_PRECISION (mode) / 2 + (code == ROTATE), GET_MODE_UNIT_PRECISION (mode) - 1)) - return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE, - mode, op0, - GEN_INT (GET_MODE_UNIT_PRECISION (mode) - - INTVAL (trueop1))); + { + int new_amount = GET_MODE_UNIT_PRECISION (mode) - INTVAL (trueop1); + rtx new_amount_rtx = gen_int_shift_amount (mode, new_amount); + return simplify_gen_binary (code == ROTATE ? ROTATERT : ROTATE, + mode, op0, new_amount_rtx); + } #endif /* FALLTHRU */ case ASHIFTRT: @@ -3466,8 +3472,8 @@ simplify_binary_operation_1 (enum rtx_co == GET_MODE_BITSIZE (inner_mode) - GET_MODE_BITSIZE (int_mode)) && subreg_lowpart_p (op0)) { - rtx tmp = GEN_INT (INTVAL (XEXP (SUBREG_REG (op0), 1)) - + INTVAL (op1)); + rtx tmp = gen_int_shift_amount + (inner_mode, INTVAL (XEXP (SUBREG_REG (op0), 1)) + INTVAL (op1)); tmp = simplify_gen_binary (code, inner_mode, XEXP (SUBREG_REG (op0), 0), tmp); @@ -3478,7 +3484,8 @@ simplify_binary_operation_1 (enum rtx_co { val = INTVAL (op1) & (GET_MODE_UNIT_PRECISION (mode) - 1); if (val != INTVAL (op1)) - return simplify_gen_binary (code, mode, op0, GEN_INT (val)); + return simplify_gen_binary (code, mode, op0, + gen_int_shift_amount (mode, val)); } break; Index: gcc/combine.c =================================================================== --- gcc/combine.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/combine.c 2017-10-23 11:47:11.272463287 +0100 @@ -3773,8 +3773,9 @@ try_combine (rtx_insn *i3, rtx_insn *i2, && INTVAL (XEXP (*split, 1)) > 0 && (i = exact_log2 (UINTVAL (XEXP (*split, 1)))) >= 0) { + rtx i_rtx = gen_int_shift_amount (split_mode, i); SUBST (*split, gen_rtx_ASHIFT (split_mode, - XEXP (*split, 0), GEN_INT (i))); + XEXP (*split, 0), i_rtx)); /* Update split_code because we may not have a multiply anymore. */ split_code = GET_CODE (*split); @@ -3788,8 +3789,10 @@ try_combine (rtx_insn *i3, rtx_insn *i2, && (i = exact_log2 (UINTVAL (XEXP (XEXP (*split, 0), 1)))) >= 0) { rtx nsplit = XEXP (*split, 0); + rtx i_rtx = gen_int_shift_amount (GET_MODE (nsplit), i); SUBST (XEXP (*split, 0), gen_rtx_ASHIFT (GET_MODE (nsplit), - XEXP (nsplit, 0), GEN_INT (i))); + XEXP (nsplit, 0), + i_rtx)); /* Update split_code because we may not have a multiply anymore. */ split_code = GET_CODE (*split); @@ -5057,12 +5060,12 @@ find_split_point (rtx *loc, rtx_insn *in GET_MODE (XEXP (SET_SRC (x), 0)))))) { machine_mode mode = GET_MODE (XEXP (SET_SRC (x), 0)); - + rtx pos_rtx = gen_int_shift_amount (mode, pos); SUBST (SET_SRC (x), gen_rtx_NEG (mode, gen_rtx_LSHIFTRT (mode, XEXP (SET_SRC (x), 0), - GEN_INT (pos)))); + pos_rtx))); split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) @@ -5120,11 +5123,11 @@ find_split_point (rtx *loc, rtx_insn *in { unsigned HOST_WIDE_INT mask = (HOST_WIDE_INT_1U << len) - 1; + rtx pos_rtx = gen_int_shift_amount (mode, pos); SUBST (SET_SRC (x), gen_rtx_AND (mode, gen_rtx_LSHIFTRT - (mode, gen_lowpart (mode, inner), - GEN_INT (pos)), + (mode, gen_lowpart (mode, inner), pos_rtx), gen_int_mode (mask, mode))); split = find_split_point (&SET_SRC (x), insn, true); @@ -5133,14 +5136,15 @@ find_split_point (rtx *loc, rtx_insn *in } else { + int left_bits = GET_MODE_PRECISION (mode) - len - pos; + int right_bits = GET_MODE_PRECISION (mode) - len; SUBST (SET_SRC (x), gen_rtx_fmt_ee (unsignedp ? LSHIFTRT : ASHIFTRT, mode, gen_rtx_ASHIFT (mode, gen_lowpart (mode, inner), - GEN_INT (GET_MODE_PRECISION (mode) - - len - pos)), - GEN_INT (GET_MODE_PRECISION (mode) - len))); + gen_int_shift_amount (mode, left_bits)), + gen_int_shift_amount (mode, right_bits))); split = find_split_point (&SET_SRC (x), insn, true); if (split && split != &SET_SRC (x)) @@ -8915,10 +8919,11 @@ force_int_to_mode (rtx x, scalar_int_mod /* Must be more sign bit copies than the mask needs. */ && ((int) num_sign_bit_copies (XEXP (x, 0), GET_MODE (XEXP (x, 0))) >= exact_log2 (mask + 1))) - x = simplify_gen_binary (LSHIFTRT, xmode, XEXP (x, 0), - GEN_INT (GET_MODE_PRECISION (xmode) - - exact_log2 (mask + 1))); - + { + int nbits = GET_MODE_PRECISION (xmode) - exact_log2 (mask + 1); + x = simplify_gen_binary (LSHIFTRT, xmode, XEXP (x, 0), + gen_int_shift_amount (xmode, nbits)); + } goto shiftrt; case ASHIFTRT: @@ -10415,7 +10420,7 @@ simplify_shift_const_1 (enum rtx_code co { enum rtx_code orig_code = code; rtx orig_varop = varop; - int count; + int count, log2; machine_mode mode = result_mode; machine_mode shift_mode; scalar_int_mode tmode, inner_mode, int_mode, int_varop_mode, int_result_mode; @@ -10618,13 +10623,11 @@ simplify_shift_const_1 (enum rtx_code co is cheaper. But it is still better on those machines to merge two shifts into one. */ if (CONST_INT_P (XEXP (varop, 1)) - && exact_log2 (UINTVAL (XEXP (varop, 1))) >= 0) + && (log2 = exact_log2 (UINTVAL (XEXP (varop, 1)))) >= 0) { - varop - = simplify_gen_binary (ASHIFT, GET_MODE (varop), - XEXP (varop, 0), - GEN_INT (exact_log2 ( - UINTVAL (XEXP (varop, 1))))); + rtx log2_rtx = gen_int_shift_amount (GET_MODE (varop), log2); + varop = simplify_gen_binary (ASHIFT, GET_MODE (varop), + XEXP (varop, 0), log2_rtx); continue; } break; @@ -10632,13 +10635,11 @@ simplify_shift_const_1 (enum rtx_code co case UDIV: /* Similar, for when divides are cheaper. */ if (CONST_INT_P (XEXP (varop, 1)) - && exact_log2 (UINTVAL (XEXP (varop, 1))) >= 0) + && (log2 = exact_log2 (UINTVAL (XEXP (varop, 1)))) >= 0) { - varop - = simplify_gen_binary (LSHIFTRT, GET_MODE (varop), - XEXP (varop, 0), - GEN_INT (exact_log2 ( - UINTVAL (XEXP (varop, 1))))); + rtx log2_rtx = gen_int_shift_amount (GET_MODE (varop), log2); + varop = simplify_gen_binary (LSHIFTRT, GET_MODE (varop), + XEXP (varop, 0), log2_rtx); continue; } break; @@ -10773,10 +10774,10 @@ simplify_shift_const_1 (enum rtx_code co mask_rtx = gen_int_mode (nonzero_bits (varop, int_varop_mode), int_result_mode); - + rtx count_rtx = gen_int_shift_amount (int_result_mode, count); mask_rtx = simplify_const_binary_operation (code, int_result_mode, - mask_rtx, GEN_INT (count)); + mask_rtx, count_rtx); /* Give up if we can't compute an outer operation to use. */ if (mask_rtx == 0 @@ -10832,9 +10833,10 @@ simplify_shift_const_1 (enum rtx_code co if (code == ASHIFTRT && int_mode != int_result_mode) break; + rtx count_rtx = gen_int_shift_amount (int_result_mode, count); rtx new_rtx = simplify_const_binary_operation (code, int_mode, XEXP (varop, 0), - GEN_INT (count)); + count_rtx); varop = gen_rtx_fmt_ee (code, int_mode, new_rtx, XEXP (varop, 1)); count = 0; continue; @@ -10900,7 +10902,7 @@ simplify_shift_const_1 (enum rtx_code co && (new_rtx = simplify_const_binary_operation (code, int_result_mode, gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode), - GEN_INT (count))) != 0 + gen_int_shift_amount (int_result_mode, count))) != 0 && CONST_INT_P (new_rtx) && merge_outer_ops (&outer_op, &outer_const, GET_CODE (varop), INTVAL (new_rtx), int_result_mode, @@ -11043,7 +11045,7 @@ simplify_shift_const_1 (enum rtx_code co && (new_rtx = simplify_const_binary_operation (ASHIFT, int_result_mode, gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode), - GEN_INT (count))) != 0 + gen_int_shift_amount (int_result_mode, count))) != 0 && CONST_INT_P (new_rtx) && merge_outer_ops (&outer_op, &outer_const, PLUS, INTVAL (new_rtx), int_result_mode, @@ -11064,7 +11066,7 @@ simplify_shift_const_1 (enum rtx_code co && (new_rtx = simplify_const_binary_operation (code, int_result_mode, gen_int_mode (INTVAL (XEXP (varop, 1)), int_result_mode), - GEN_INT (count))) != 0 + gen_int_shift_amount (int_result_mode, count))) != 0 && CONST_INT_P (new_rtx) && merge_outer_ops (&outer_op, &outer_const, XOR, INTVAL (new_rtx), int_result_mode, @@ -11119,12 +11121,12 @@ simplify_shift_const_1 (enum rtx_code co - GET_MODE_UNIT_PRECISION (GET_MODE (varop))))) { rtx varop_inner = XEXP (varop, 0); - - varop_inner - = gen_rtx_LSHIFTRT (GET_MODE (varop_inner), - XEXP (varop_inner, 0), - GEN_INT - (count + INTVAL (XEXP (varop_inner, 1)))); + int new_count = count + INTVAL (XEXP (varop_inner, 1)); + rtx new_count_rtx = gen_int_shift_amount (GET_MODE (varop_inner), + new_count); + varop_inner = gen_rtx_LSHIFTRT (GET_MODE (varop_inner), + XEXP (varop_inner, 0), + new_count_rtx); varop = gen_rtx_TRUNCATE (GET_MODE (varop), varop_inner); count = 0; continue; @@ -11176,7 +11178,8 @@ simplify_shift_const_1 (enum rtx_code co x = NULL_RTX; if (x == NULL_RTX) - x = simplify_gen_binary (code, shift_mode, varop, GEN_INT (count)); + x = simplify_gen_binary (code, shift_mode, varop, + gen_int_shift_amount (shift_mode, count)); /* If we were doing an LSHIFTRT in a wider mode than it was originally, turn off all the bits that the shift would have turned off. */ @@ -11238,7 +11241,8 @@ simplify_shift_const (rtx x, enum rtx_co return tem; if (!x) - x = simplify_gen_binary (code, GET_MODE (varop), varop, GEN_INT (count)); + x = simplify_gen_binary (code, GET_MODE (varop), varop, + gen_int_shift_amount (GET_MODE (varop), count)); if (GET_MODE (x) != result_mode) x = gen_lowpart (result_mode, x); return x; @@ -11429,8 +11433,9 @@ change_zero_ext (rtx pat) if (BITS_BIG_ENDIAN) start = GET_MODE_PRECISION (inner_mode) - size - start; - if (start) - x = gen_rtx_LSHIFTRT (inner_mode, XEXP (x, 0), GEN_INT (start)); + if (start != 0) + x = gen_rtx_LSHIFTRT (inner_mode, XEXP (x, 0), + gen_int_shift_amount (inner_mode, start)); else x = XEXP (x, 0); if (mode != inner_mode) Index: gcc/optabs.c =================================================================== --- gcc/optabs.c 2017-10-23 11:47:06.643477568 +0100 +++ gcc/optabs.c 2017-10-23 11:47:11.276323187 +0100 @@ -431,8 +431,9 @@ expand_superword_shift (optab binoptab, if (binoptab != ashr_optab) emit_move_insn (outof_target, CONST0_RTX (word_mode)); else - if (!force_expand_binop (word_mode, binoptab, - outof_input, GEN_INT (BITS_PER_WORD - 1), + if (!force_expand_binop (word_mode, binoptab, outof_input, + gen_int_shift_amount (word_mode, + BITS_PER_WORD - 1), outof_target, unsignedp, methods)) return false; } @@ -789,7 +790,8 @@ expand_doubleword_mult (machine_mode mod { int low = (WORDS_BIG_ENDIAN ? 1 : 0); int high = (WORDS_BIG_ENDIAN ? 0 : 1); - rtx wordm1 = umulp ? NULL_RTX : GEN_INT (BITS_PER_WORD - 1); + rtx wordm1 = (umulp ? NULL_RTX + : gen_int_shift_amount (word_mode, BITS_PER_WORD - 1)); rtx product, adjust, product_high, temp; rtx op0_high = operand_subword_force (op0, high, mode); @@ -1185,7 +1187,7 @@ expand_binop (machine_mode mode, optab b unsigned int bits = GET_MODE_PRECISION (int_mode); if (CONST_INT_P (op1)) - newop1 = GEN_INT (bits - INTVAL (op1)); + newop1 = gen_int_shift_amount (int_mode, bits - INTVAL (op1)); else if (targetm.shift_truncation_mask (int_mode) == bits - 1) newop1 = negate_rtx (GET_MODE (op1), op1); else @@ -1399,11 +1401,11 @@ expand_binop (machine_mode mode, optab b shift_mask = targetm.shift_truncation_mask (word_mode); op1_mode = (GET_MODE (op1) != VOIDmode ? as_a (GET_MODE (op1)) - : word_mode); + : get_shift_amount_mode (word_mode)); /* Apply the truncation to constant shifts. */ if (double_shift_mask > 0 && CONST_INT_P (op1)) - op1 = GEN_INT (INTVAL (op1) & double_shift_mask); + op1 = gen_int_mode (INTVAL (op1) & double_shift_mask, op1_mode); if (op1 == CONST0_RTX (op1_mode)) return op0; @@ -1513,7 +1515,7 @@ expand_binop (machine_mode mode, optab b else { rtx into_temp1, into_temp2, outof_temp1, outof_temp2; - rtx first_shift_count, second_shift_count; + HOST_WIDE_INT first_shift_count, second_shift_count; optab reverse_unsigned_shift, unsigned_shift; reverse_unsigned_shift = (left_shift ^ (shift_count < BITS_PER_WORD) @@ -1524,20 +1526,24 @@ expand_binop (machine_mode mode, optab b if (shift_count > BITS_PER_WORD) { - first_shift_count = GEN_INT (shift_count - BITS_PER_WORD); - second_shift_count = GEN_INT (2 * BITS_PER_WORD - shift_count); + first_shift_count = shift_count - BITS_PER_WORD; + second_shift_count = 2 * BITS_PER_WORD - shift_count; } else { - first_shift_count = GEN_INT (BITS_PER_WORD - shift_count); - second_shift_count = GEN_INT (shift_count); + first_shift_count = BITS_PER_WORD - shift_count; + second_shift_count = shift_count; } + rtx first_shift_count_rtx + = gen_int_shift_amount (word_mode, first_shift_count); + rtx second_shift_count_rtx + = gen_int_shift_amount (word_mode, second_shift_count); into_temp1 = expand_binop (word_mode, unsigned_shift, - outof_input, first_shift_count, + outof_input, first_shift_count_rtx, NULL_RTX, unsignedp, next_methods); into_temp2 = expand_binop (word_mode, reverse_unsigned_shift, - into_input, second_shift_count, + into_input, second_shift_count_rtx, NULL_RTX, unsignedp, next_methods); if (into_temp1 != 0 && into_temp2 != 0) @@ -1550,10 +1556,10 @@ expand_binop (machine_mode mode, optab b emit_move_insn (into_target, inter); outof_temp1 = expand_binop (word_mode, unsigned_shift, - into_input, first_shift_count, + into_input, first_shift_count_rtx, NULL_RTX, unsignedp, next_methods); outof_temp2 = expand_binop (word_mode, reverse_unsigned_shift, - outof_input, second_shift_count, + outof_input, second_shift_count_rtx, NULL_RTX, unsignedp, next_methods); if (inter != 0 && outof_temp1 != 0 && outof_temp2 != 0) @@ -2793,25 +2799,29 @@ expand_unop (machine_mode mode, optab un if (optab_handler (rotl_optab, mode) != CODE_FOR_nothing) { - temp = expand_binop (mode, rotl_optab, op0, GEN_INT (8), target, - unsignedp, OPTAB_DIRECT); + temp = expand_binop (mode, rotl_optab, op0, + gen_int_shift_amount (mode, 8), + target, unsignedp, OPTAB_DIRECT); if (temp) return temp; } if (optab_handler (rotr_optab, mode) != CODE_FOR_nothing) { - temp = expand_binop (mode, rotr_optab, op0, GEN_INT (8), target, - unsignedp, OPTAB_DIRECT); + temp = expand_binop (mode, rotr_optab, op0, + gen_int_shift_amount (mode, 8), + target, unsignedp, OPTAB_DIRECT); if (temp) return temp; } last = get_last_insn (); - temp1 = expand_binop (mode, ashl_optab, op0, GEN_INT (8), NULL_RTX, + temp1 = expand_binop (mode, ashl_optab, op0, + gen_int_shift_amount (mode, 8), NULL_RTX, unsignedp, OPTAB_WIDEN); - temp2 = expand_binop (mode, lshr_optab, op0, GEN_INT (8), NULL_RTX, + temp2 = expand_binop (mode, lshr_optab, op0, + gen_int_shift_amount (mode, 8), NULL_RTX, unsignedp, OPTAB_WIDEN); if (temp1 && temp2) { @@ -5369,11 +5379,11 @@ vector_compare_rtx (machine_mode cmp_mod } /* Checks if vec_perm mask SEL is a constant equivalent to a shift of the first - vec_perm operand, assuming the second operand is a constant vector of zeroes. - Return the shift distance in bits if so, or NULL_RTX if the vec_perm is not a - shift. */ + vec_perm operand (which has mode OP0_MODE), assuming the second + operand is a constant vector of zeroes. Return the shift distance in + bits if so, or NULL_RTX if the vec_perm is not a shift. */ static rtx -shift_amt_for_vec_perm_mask (rtx sel) +shift_amt_for_vec_perm_mask (machine_mode op0_mode, rtx sel) { unsigned int i, first, nelt = GET_MODE_NUNITS (GET_MODE (sel)); unsigned int bitsize = GET_MODE_UNIT_BITSIZE (GET_MODE (sel)); @@ -5393,7 +5403,7 @@ shift_amt_for_vec_perm_mask (rtx sel) return NULL_RTX; } - return GEN_INT (first * bitsize); + return gen_int_shift_amount (op0_mode, first * bitsize); } /* A subroutine of expand_vec_perm for expanding one vec_perm insn. */ @@ -5473,7 +5483,7 @@ expand_vec_perm (machine_mode mode, rtx && (shift_code != CODE_FOR_nothing || shift_code_qi != CODE_FOR_nothing)) { - shift_amt = shift_amt_for_vec_perm_mask (sel); + shift_amt = shift_amt_for_vec_perm_mask (mode, sel); if (shift_amt) { struct expand_operand ops[3]; @@ -5563,7 +5573,8 @@ expand_vec_perm (machine_mode mode, rtx NULL, 0, OPTAB_DIRECT); else sel = expand_simple_binop (selmode, ASHIFT, sel, - GEN_INT (exact_log2 (u)), + gen_int_shift_amount (selmode, + exact_log2 (u)), NULL, 0, OPTAB_DIRECT); gcc_assert (sel != NULL);