From patchwork Thu Aug 30 07:19:11 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jakub Jelinek X-Patchwork-Id: 963761 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-484771-incoming=patchwork.ozlabs.org@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=redhat.com Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b="XalP3huc"; 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 421DQC62B7z9s3x for ; Thu, 30 Aug 2018 17:19:28 +1000 (AEST) 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:reply-to:mime-version :content-type; q=dns; s=default; b=gjQBr2Lqehqtv4z/OW3GYJuxIjXub u8QiZ9d8t5yYYS34wpgGCaNxSdIeK+7M/izkx1WgkcfPeeJi7JI5CsTiFHa9a9eA QGO2ULDw1pLO16xbFFqM/LxU5gHQQyYdBBg0rTCF4ZxpELQaFVzQxmAFuXehtl/n j7Z9PNHr81NYPs= 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:reply-to:mime-version :content-type; s=default; bh=q79ftZPAENuB0HZ3A6l+Oh5N8j0=; b=Xal P3huc/vM04USflC4S/0e2rzbbUdelDHolv4cGU34bWbzVbMN2cYNdG8982cuAYpl B0uxBzO2ThdolaC3s+zllmH7Al+QNnAWx8Ciu9LPlAl9I4qF1TySY4byzJmVZAlY VOuBW5ypvSXul2dVI7xBiGKbQJGjJEK3vriOjvcc= Received: (qmail 68853 invoked by alias); 30 Aug 2018 07:19:21 -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 68840 invoked by uid 89); 30 Aug 2018 07:19:21 -0000 Authentication-Results: sourceware.org; auth=none X-Spam-SWARE-Status: No, score=-11.9 required=5.0 tests=BAYES_00, GIT_PATCH_2, GIT_PATCH_3, SPF_HELO_PASS autolearn=ham version=3.3.2 spammy= X-HELO: mx1.redhat.com Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 30 Aug 2018 07:19:19 +0000 Received: from smtp.corp.redhat.com (int-mx10.intmail.prod.int.phx2.redhat.com [10.5.11.25]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 5C02B88311; Thu, 30 Aug 2018 07:19:18 +0000 (UTC) Received: from tucnak.zalov.cz (ovpn-116-92.ams2.redhat.com [10.36.116.92]) by smtp.corp.redhat.com (Postfix) with ESMTPS id DC51C2010CAA; Thu, 30 Aug 2018 07:19:17 +0000 (UTC) Received: from tucnak.zalov.cz (localhost [127.0.0.1]) by tucnak.zalov.cz (8.15.2/8.15.2) with ESMTP id w7U7JF73000895; Thu, 30 Aug 2018 09:19:15 +0200 Received: (from jakub@localhost) by tucnak.zalov.cz (8.15.2/8.15.2/Submit) id w7U7JC8H000894; Thu, 30 Aug 2018 09:19:12 +0200 Date: Thu, 30 Aug 2018 09:19:11 +0200 From: Jakub Jelinek To: Richard Biener , Eric Botcazou , Richard Sandiford Cc: gcc-patches@gcc.gnu.org Subject: [PATCH] Fix expand_mult_const (PR middle-end/87138) Message-ID: <20180830071911.GI2218@tucnak> Reply-To: Jakub Jelinek MIME-Version: 1.0 Content-Disposition: inline User-Agent: Mutt/1.9.2 (2017-12-15) X-IsSubscribed: yes Hi! The following testcase is miscompiled, because expand_mult_const adds an incorrect REG_EQUAL note to a temporary pseudo. In the testcase, we do an unsigned __int128 multiplication of a variable by 0x7fffffffffffffff, which is determined to be best performed as shift left by 63 (multiplication by 0x8000000000000000U) followed by subtraction, i.e. (x << 63) - x. The val_so_far is tracked in an UHWI and is necessarily always non-negative even because the caller ensures that, if (is_neg && mode_bitsize > HOST_BITS_PER_WIDE_INT) then it performs expand_mult_const on the negation and negates afterwards the result. The problem is that it calls gen_int_mode, where the argument is signed hwi (well, these days poly_int64). That is fine for DImode multiplication, we don't really care about bits above the mode, but for TImode multiplication it is significant. Without this patch we emit in that case: (expr_list:REG_EQUAL (mult:TI (reg/v:TI 85 [ x ]) (const_int -9223372036854775808 [0x8000000000000000])) but that is for TImode actually multiplication by 0xffffffffffffffff8000000000000000 rather than 0x00000000000000008000000000000000, so we need to emit (const_wide_int 0x08000000000000000) instead. Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk and after a while for 8.3? 2018-08-30 Jakub Jelinek PR middle-end/87138 * expmed.c (expand_mult_const): If val_so_far has MSB set, use immed_wide_int_const instead of gen_int_mode. Formatting fixes. * gcc.target/i386/avx512bw-pr87138.c: New test. Jakub --- gcc/expmed.c.jj 2018-08-29 14:20:53.427109187 +0200 +++ gcc/expmed.c 2018-08-29 17:22:52.416860714 +0200 @@ -3347,19 +3347,27 @@ expand_mult_const (machine_mode mode, rt /* Write a REG_EQUAL note on the last insn so that we can cse multiplication sequences. Note that if ACCUM is a SUBREG, we've set the inner register and must properly indicate that. */ - tem = op0, nmode = mode; - accum_inner = accum; - if (GET_CODE (accum) == SUBREG) + tem = op0, nmode = mode; + accum_inner = accum; + if (GET_CODE (accum) == SUBREG) { accum_inner = SUBREG_REG (accum); nmode = GET_MODE (accum_inner); tem = gen_lowpart (nmode, op0); } - insn = get_last_insn (); - set_dst_reg_note (insn, REG_EQUAL, - gen_rtx_MULT (nmode, tem, - gen_int_mode (val_so_far, nmode)), + insn = get_last_insn (); + rtx c; + if (val_so_far > (unsigned HOST_WIDE_INT) HOST_WIDE_INT_MAX) + { + wide_int wval_so_far + = wi::uhwi (val_so_far, + GET_MODE_PRECISION (as_a (nmode))); + c = immed_wide_int_const (wval_so_far, nmode); + } + else + c = gen_int_mode (val_so_far, nmode); + set_dst_reg_note (insn, REG_EQUAL, gen_rtx_MULT (nmode, tem, c), accum_inner); } } --- gcc/testsuite/gcc.target/i386/avx512bw-pr87138.c.jj 2018-08-29 17:55:08.550154082 +0200 +++ gcc/testsuite/gcc.target/i386/avx512bw-pr87138.c 2018-08-29 17:56:11.112131910 +0200 @@ -0,0 +1,29 @@ +/* PR middle-end/87138 */ +/* { dg-do run { target int128 } } */ +/* { dg-options "-O -fno-tree-fre -mavx512bw -mtune=k8" } */ +/* { dg-require-effective-target avx512bw } */ + +#include "avx512bw-check.h" + +typedef int U __attribute__ ((vector_size (64))); +typedef __int128 V __attribute__ ((vector_size (64))); +V g, i; + +static inline void +foo (unsigned h, V j, U k, V n) +{ + k /= h; + __builtin_memmove (&h, &n, 1); + n[j[1]] *= 0x7FFFFFFFFFFFFFFF; + j[k[5]] = 0; + g = n; + i = h + j + n; +} + +void +avx512bw_test () +{ + foo (~0, (V) { }, (U) { 5 }, (V) { 3 }); + if (g[0] != (__int128) 3 * 0x7FFFFFFFFFFFFFFF) + abort (); +}