From patchwork Wed Mar 4 09:36:57 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Kyrylo Tkachov X-Patchwork-Id: 446158 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 2ED9D14016A for ; Wed, 4 Mar 2015 20:37:11 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass reason="1024-bit key; unprotected key" header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=V0mxht+f; dkim-adsp=none (unprotected policy); 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 :message-id:date:from:mime-version:to:cc:subject:content-type; q=dns; s=default; b=TN38ucZk05/asww3s9tpwHB8L3re4bf6FHVKB6iRRXE E02qjZK4/oeyVlPJsoFK31fSuZ89IGAwDA6Dsrhzlfmz9jwBKChDjK3nBNTSYCYe Hm3Sq8vx7Nv60Hx27ZQn4EvWalSCXRpTzJOWMPk3/GlriJQIU16XzbapD0bmA4Tc = 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 :message-id:date:from:mime-version:to:cc:subject:content-type; s=default; bh=SVsN1DCaIBUErLxr6PEpU6RBwdo=; b=V0mxht+fKtTsSJQ9+ Dnzl0eQ8ZLQb2PItTR8HvB4OPyZ/l44JlXLahYrkTWdjlUYPwt2jUg5f0ROZbbNl AlmnlOG18zcBcNSExGPH7AIxA9fLVn6Qo2adllRXyPPYoMfCjEeyAa0Xhk6q5jEP rMFMiBga3orNVuBu3QXCaQXm64= Received: (qmail 90155 invoked by alias); 4 Mar 2015 09:37:03 -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 90146 invoked by uid 89); 4 Mar 2015 09:37:02 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.8 required=5.0 tests=AWL, BAYES_00, SPF_PASS autolearn=ham version=3.3.2 X-HELO: service87.mimecast.com Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 04 Mar 2015 09:37:00 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.140]) by service87.mimecast.com; Wed, 04 Mar 2015 09:36:57 +0000 Received: from [10.2.207.50] ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 4 Mar 2015 09:36:57 +0000 Message-ID: <54F6D239.2010902@arm.com> Date: Wed, 04 Mar 2015 09:36:57 +0000 From: Kyrill Tkachov User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:31.0) Gecko/20100101 Thunderbird/31.2.0 MIME-Version: 1.0 To: GCC Patches CC: Eric Botcazou Subject: [PATCH][simplify-rtx] PR 65235: Calculate element size correctly when simplifying (vec_select (vec_concat (const_int) (...)) [...]) X-MC-Unique: 115030409365719701 X-IsSubscribed: yes Hi all, This patch fixes PR rtl-optimization 65235. As mentioned in bugzilla: Combine tries to combine: (insn 72 71 73 2 (set (reg:V2DI 117 [ D.18177 ]) (vec_concat:V2DI (reg:DI 176 [ D.18179 ]) (reg:DI 114 [ D.18168 ]))) (expr_list:REG_DEAD (reg:DI 176 [ D.18179 ]) (expr_list:REG_DEAD (reg:DI 114 [ D.18168 ]) and (insn 104 102 105 2 (set (reg:DI 193 [ D.18168 ]) (vec_select:DI (reg:V2DI 117 [ D.18177 ]) (parallel [ (const_int 0 [0]) ]))) (expr_list:REG_DEAD (reg:V2DI 117 [ D.18177 ]) (nil))) but ends up generating: (set (reg:DI 193 [ D.18168 ]) (reg:DI 114 [ D.18168 ])) that is, it gets the wrong element of the vec_concat. The problem is that in simplify-rtx it tries to get the size of the first element, compare the requested offset against it and pick the second element if the offset is greater than that size. If the first element is a const_int, the size is 0, so it will always pick the second part. The patch fixes that by calculating the size of the first element by taking the size of the outer mode and subtracting the size of the second element. I've added an assert to make sure that the second element is not also a const_int, as a vec_concat of const_ints doesn't make sense as far as I can see. Bootstrapped and tested on aarch64-none-linux-gnu, arm-none-linux-gnueabihf, x86_64-linux-gnu. This bug appears on trunk, 4.9 and 4.8, so it's not a regression on the release branches but it is a wrong-code bug. Should this go in now? Or wait for stage 1? Thanks, Kyrill 2015-03-04 Kyrylo Tkachov PR rtl-optimization 65235 * simplify-rtx.c (simplify_binary_operation_1, VEC_SELECT case): When first element of vec_concat is const_int, calculate its size using second element. 2015-03-04 Kyrylo Tkachov PR rtl-optimization 65235 * gcc.target/aarch64/pr65235_1.c: New test. commit 816f7592617681c48e5303aaa9e3b0ee8a858457 Author: Kyrylo Tkachov Date: Thu Feb 26 16:40:52 2015 +0000 [simplify-rtx] Calculate vector size correctly when simplifying (vec_select (vec_concat (const_int) (...)) [...]) diff --git a/gcc/simplify-rtx.c b/gcc/simplify-rtx.c index a003b41..3a6159f 100644 --- a/gcc/simplify-rtx.c +++ b/gcc/simplify-rtx.c @@ -3555,7 +3555,19 @@ simplify_binary_operation_1 (enum rtx_code code, machine_mode mode, while (GET_MODE (vec) != mode && GET_CODE (vec) == VEC_CONCAT) { - HOST_WIDE_INT vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); + HOST_WIDE_INT vec_size; + + if (CONST_INT_P (XEXP (vec, 0))) + { + /* vec_concat of two const_ints doesn't make sense with + respect to modes. */ + gcc_assert (!CONST_INT_P (XEXP (vec, 1))); + vec_size = GET_MODE_SIZE (GET_MODE (trueop0)) + - GET_MODE_SIZE (GET_MODE (XEXP (vec, 1))); + } + else + vec_size = GET_MODE_SIZE (GET_MODE (XEXP (vec, 0))); + if (offset < vec_size) vec = XEXP (vec, 0); else diff --git a/gcc/testsuite/gcc.target/aarch64/pr65235_1.c b/gcc/testsuite/gcc.target/aarch64/pr65235_1.c new file mode 100644 index 0000000..ca12cd5 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/pr65235_1.c @@ -0,0 +1,30 @@ +/* { dg-do run } */ +/* { dg-options "-O2" } */ + +#include "arm_neon.h" + +int +main (int argc, char** argv) +{ + int64x1_t val1; + int64x1_t val2; + int64x1_t val3; + uint64x1_t val13; + uint64x2_t val14; + uint64_t got; + uint64_t exp; + val1 = vcreate_s64(UINT64_C(0xffffffff80008000)); + val2 = vcreate_s64(UINT64_C(0x0000f38d00000000)); + val3 = vcreate_s64(UINT64_C(0xffff7fff0000809b)); + /* Expect: "val13" = 8000000000001553. */ + val13 = vcreate_u64 (UINT64_C(0x8000000000001553)); + /* Expect: "val14" = 0010 0000 0000 0002 0000 0000 0000 0000. */ + val14 = vcombine_u64(vcgt_s64(vqrshl_s64(val1, val2), + vshr_n_s64(val3, 18)), + vshr_n_u64(val13, 11)); + /* Should be 0000000000000000. */ + got = vgetq_lane_u64(val14, 0); + exp = 0; + if(exp != got) + __builtin_abort (); +}