From patchwork Tue Nov 20 07:37:41 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Modra X-Patchwork-Id: 1000289 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=gcc.gnu.org (client-ip=209.132.180.131; helo=sourceware.org; envelope-from=gcc-patches-return-490478-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gmail.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="uTo3kF2y"; dkim=pass (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="lzEcpDTd"; dkim-atps=neutral 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 42zcxl2Jvhz9rxp for ; Tue, 20 Nov 2018 18:38:00 +1100 (AEDT) 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=R99hot1pQ77uiJZ01LIcIhaEKOeiu4J6WUfFjOXYnYO1MwdQt6 BwhzZ28Ci57aVDZTjmrMClhsuAA3T0hSlzsNFbThz26I+kiCTYj1vfX0OqOY2XRd dNzaHPO0VCwpTrGBXnzvpi8aQ0K481a83woCrE/lWchGF+hryhLcv/GGY= 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=DqBphQjnOO7ee/BXPhxrKjFHYOc=; b=uTo3kF2yf/zjZqaRWH73 AlFiy4kbriij15eBZK/iF/tWSnmynaYuCtNoqYJUgGNKKt9ESuayQDx05LAL9Sth fAH/3VGGvM77bZNXtxZi9LP6gs9gl+UopKk1t8CuCI5ZnBzy+PKlRZYGifabbYTX JJ8r9ghsrTxlOvbhJqsRmyg= Received: (qmail 92034 invoked by alias); 20 Nov 2018 07:37: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 92024 invoked by uid 89); 20 Nov 2018 07:37:50 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-25.7 required=5.0 tests=AWL, BAYES_00, FREEMAIL_FROM, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_PASS autolearn=ham version=3.3.2 spammy=regress, investigating, _32bit, sk:easy_ve X-HELO: mail-pl1-f196.google.com Received: from mail-pl1-f196.google.com (HELO mail-pl1-f196.google.com) (209.85.214.196) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Tue, 20 Nov 2018 07:37:48 +0000 Received: by mail-pl1-f196.google.com with SMTP id t13so557070ply.13 for ; Mon, 19 Nov 2018 23:37:48 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=date:from:to:cc:subject:message-id:mime-version:content-disposition :user-agent; bh=aU8l5wk25c+NvnoljHmxEgyROPIHDQRBBkLkLZJ9fV4=; b=lzEcpDTdH691Lvqsy8zsklSckz4US42P47T2QqWYqM+gjTGimUP5iWMl/u2//d+nVl cxvJ5wZtRV1okdpwJJsTXXbxNNlPK2UeirliQhxD0/n9J1649iUBV/fAwAYFw/bDkSR6 92xW3afVpm3eg5ZymctTxBTR4jV6c1QhnUbteA6dTpzSkkvTCqmFfmya6XoxoRTVWqsO eXRgcSkmOieqvw9wk9cnacdwL+vgdAFlLT73Mrett9IC2SCsvu608c0grhC8oIjX6NVI t8qutLwiXZ85xWptgOdQqmykDim9qW4W9afMe4dmmsKBJSIdKM4BoFcoX5ivKPksgr/R zSBA== Received: from bubble.grove.modra.org ([58.175.241.133]) by smtp.gmail.com with ESMTPSA id u69sm37875509pfj.116.2018.11.19.23.37.44 (version=TLS1_2 cipher=ECDHE-RSA-CHACHA20-POLY1305 bits=256/256); Mon, 19 Nov 2018 23:37:45 -0800 (PST) Received: by bubble.grove.modra.org (Postfix, from userid 1000) id 48364805F4; Tue, 20 Nov 2018 18:07:41 +1030 (ACDT) Date: Tue, 20 Nov 2018 18:07:41 +1030 From: Alan Modra To: gcc-patches@gcc.gnu.org Cc: Segher Boessenkool Subject: [RS6000] num_insns_constant ICE Message-ID: <20181120073740.GG21617@bubble.grove.modra.org> MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.4 (2018-02-28) X-IsSubscribed: yes This patch came about from investigating an ICE that appeared when I was retesting an old half-baked patch of mine to rs6000_rtx_costs. The num_insns_constant ICE was introduced with git commit f337168d97. If a const_double is fed to rs6000_is_valid_and_mask and from there to rs6000_is_valid_mask where INTVAL is used, gcc will ICE. However, the code was buggy before that. When const_double no longer was used for integers there was no point in testing for a mask since the mask predicates only handle const_int. In fact, I don't think the function ever handled floating point constants that might match a load of minus one and mask. It does now. I've added a few comments regarding splitters so the next person looking at this code can see how this works. I also looked at all places (*) where num_insns_constant is called. That lead to finding two cases where the "G" and "H" constraints were used incorrectly. Their purpose is calculating insn lengths. Thus it never makes sense to put "GH" together or with "F" in an insn alternative. movdi_internal32 used "GHF" in an alternative (and always selected 64 byte insn length) so I replaced that with "F". The FMOVE128 version of mov_softfloat also had "GHF" in an alternative but from what I see in rs6000_emit_move, I believe TFmode insns loading constants will be splt. So this insn doesn't need to handle FP constants (it also doesn't need an iterator as only TFmode will be selected - not fixed with this patch). *) Besides the G and H constraint use of num_insns_constant, there are three uses of num_insns_constant in rs6000.md each only dealing with const_int or const_wide_int operands. The rs6000.c call in rs6000_emit_move only deals with const_int, so no const_double code is touched. easy_fp_constant in predicates.md does appear to need a num_insns_constant that handles const_double in DImode. easy_fp_constant is called from easy_vector_constant, input_operand and vector.md mov pattern but not with a DImode operand. In rs6000.c, the first call in rs6000_emit_move is also not DImode. The second call might indeed match, so there's one possible use. The easy_fp_constant call in rs6000_legitimate_constant_p also might call num_insns_constant, but only in 32-bit mode. Bootstrapped and regression tested powerpc64le-linux and powerpc64-linux. I'm running the powerpc64-linux tests again as I forgot to test -m32 on the first run. OK for trunk, assuming the -m32 tests don't regress? * config/rs6000/rs6000.c (num_insns_constant_wide): Make static. (num_insns_constant ): Don't ICE on call to rs6000_is_valid_and_mask. Formatting. Simplify and extract code common to both CONST_INT and CONST_DOUBLE. Handle floating point constants in SImode/DImode. Add gcc_unreachable for unhandled const_double modes. * config/rs6000/rs6000-protos.h (num_insns_const_wide): Delete. * config/rs6000/rs6000.md (movdi_internal32): Remove "GH" from alternative handling "F". (mov_softfloat ): Delete "GHF" from alternative. * config/rs6000/contraints.md (G, H): Comment. diff --git a/gcc/config/rs6000/constraints.md b/gcc/config/rs6000/constraints.md index 90aba1e77d3..21c7a808919 100644 --- a/gcc/config/rs6000/constraints.md +++ b/gcc/config/rs6000/constraints.md @@ -252,7 +252,8 @@ (define_constraint "P" (and (match_code "const_int") (match_test "((- (unsigned HOST_WIDE_INT) ival) + 0x8000) < 0x10000"))) -;; Floating-point constraints +;; Floating-point constraints. These two are defined so that insn +;; length attributes can be calculated exactly. (define_constraint "G" "Constant that can be copied into GPR with two insns for DF/DI diff --git a/gcc/config/rs6000/rs6000-protos.h b/gcc/config/rs6000/rs6000-protos.h index 1dfe7995ff1..dfee1f28aa9 100644 --- a/gcc/config/rs6000/rs6000-protos.h +++ b/gcc/config/rs6000/rs6000-protos.h @@ -36,7 +36,6 @@ extern int vspltis_shifted (rtx); extern HOST_WIDE_INT const_vector_elt_as_int (rtx, unsigned int); extern bool macho_lo_sum_memory_operand (rtx, machine_mode); extern int num_insns_constant (rtx, machine_mode); -extern int num_insns_constant_wide (HOST_WIDE_INT); extern int small_data_operand (rtx, machine_mode); extern bool mem_operand_gpr (rtx, machine_mode); extern bool mem_operand_ds_form (rtx, machine_mode); diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 479dae547fa..1eabf9cd612 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -5818,7 +5818,7 @@ direct_return (void) /* Return the number of instructions it takes to form a constant in an integer register. */ -int +static int num_insns_constant_wide (HOST_WIDE_INT value) { /* signed constant loadable with addi */ @@ -5856,16 +5856,13 @@ num_insns_constant_wide (HOST_WIDE_INT value) int num_insns_constant (rtx op, machine_mode mode) { - HOST_WIDE_INT low, high; + HOST_WIDE_INT val; switch (GET_CODE (op)) { case CONST_INT: - if ((INTVAL (op) >> 31) != 0 && (INTVAL (op) >> 31) != -1 - && rs6000_is_valid_and_mask (op, mode)) - return 2; - else - return num_insns_constant_wide (INTVAL (op)); + val = INTVAL (op); + break; case CONST_WIDE_INT: { @@ -5876,50 +5873,62 @@ num_insns_constant (rtx op, machine_mode mode) return ins; } - case CONST_DOUBLE: + case CONST_DOUBLE: + { + const struct real_value *rv = CONST_DOUBLE_REAL_VALUE (op); + if (mode == SFmode || mode == SDmode) { long l; - if (DECIMAL_FLOAT_MODE_P (mode)) - REAL_VALUE_TO_TARGET_DECIMAL32 - (*CONST_DOUBLE_REAL_VALUE (op), l); + if (mode == SDmode) + REAL_VALUE_TO_TARGET_DECIMAL32 (*rv, l); else - REAL_VALUE_TO_TARGET_SINGLE (*CONST_DOUBLE_REAL_VALUE (op), l); - return num_insns_constant_wide ((HOST_WIDE_INT) l); + REAL_VALUE_TO_TARGET_SINGLE (*rv, l); + /* See the first define_split in rs6000.md handling a + const_double_operand. */ + val = l; + mode = SImode; } - - long l[2]; - if (DECIMAL_FLOAT_MODE_P (mode)) - REAL_VALUE_TO_TARGET_DECIMAL64 (*CONST_DOUBLE_REAL_VALUE (op), l); - else - REAL_VALUE_TO_TARGET_DOUBLE (*CONST_DOUBLE_REAL_VALUE (op), l); - high = l[WORDS_BIG_ENDIAN == 0]; - low = l[WORDS_BIG_ENDIAN != 0]; - - if (TARGET_32BIT) - return (num_insns_constant_wide (low) - + num_insns_constant_wide (high)); - else + else if (mode == DFmode || mode == DDmode) { - if ((high == 0 && low >= 0) - || (high == -1 && low < 0)) - return num_insns_constant_wide (low); - - else if (rs6000_is_valid_and_mask (op, mode)) - return 2; - - else if (low == 0) - return num_insns_constant_wide (high) + 1; + long l[2]; + if (mode == DDmode) + REAL_VALUE_TO_TARGET_DECIMAL64 (*rv, l); else - return (num_insns_constant_wide (high) - + num_insns_constant_wide (low) + 1); + REAL_VALUE_TO_TARGET_DOUBLE (*rv, l); + + HOST_WIDE_INT high = l[WORDS_BIG_ENDIAN == 0]; + HOST_WIDE_INT low = l[WORDS_BIG_ENDIAN != 0]; + + if (TARGET_32BIT) + /* We'll be loading the double into two registers. + See the second define_split in rs6000.md handling a + const_double_operand. */ + return (num_insns_constant_wide (low) + + num_insns_constant_wide (high)); + + /* See the third define_split in rs6000.md handling a + const_double_operand. */ + val = (low & 0xffffffffUL) | (high << 32); + mode = DImode; } + else + gcc_unreachable (); + op = NULL_RTX; + } + break; default: gcc_unreachable (); } + + int ins = num_insns_constant_wide (val); + if (ins > 2 + && rs6000_is_valid_and_mask (op ? op : GEN_INT (val), mode)) + ins = 2; + return ins; } /* Interpret element ELT of the CONST_VECTOR OP as an integer value. diff --git a/gcc/config/rs6000/rs6000.md b/gcc/config/rs6000/rs6000.md index 8e50f5b822b..0a16b1f5d41 100644 --- a/gcc/config/rs6000/rs6000.md +++ b/gcc/config/rs6000/rs6000.md @@ -7713,7 +7713,7 @@ (define_insn_and_split "*mov_32bit" (define_insn_and_split "*mov_softfloat" [(set (match_operand:FMOVE128 0 "nonimmediate_operand" "=Y,r,r") - (match_operand:FMOVE128 1 "input_operand" "r,YGHF,r"))] + (match_operand:FMOVE128 1 "input_operand" "r,Y,r"))] "TARGET_SOFT_FLOAT && (gpc_reg_operand (operands[0], mode) || gpc_reg_operand (operands[1], mode))" @@ -8670,7 +8670,7 @@ (define_insn "*movdi_internal32" (match_operand:DI 1 "input_operand" "r, Y, r, ^d, m, ^d, - IJKnGHF, ^wb, $wv, wY, Z, ^wi, + IJKnF, ^wb, $wv, wY, Z, ^wi, Oj, wM, OjwM, Oj, wM, wS, wB"))]