From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-pj1-x1030.google.com (mail-pj1-x1030.google.com [IPv6:2607:f8b0:4864:20::1030]) by sourceware.org (Postfix) with ESMTPS id 26608396E832 for ; Tue, 15 Sep 2020 01:20:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 26608396E832 Received: by mail-pj1-x1030.google.com with SMTP id gf14so874517pjb.5 for ; Mon, 14 Sep 2020 18:20:49 -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:cc:subject:date:message-id:in-reply-to :references; bh=YRc8d3dHMwf2DJfC4h7vSYutkdPAYEGPa1ShS2jlAg0=; b=E8AB5m72kPbB0XlFusUIkXdNTOnAdW2/RVgsdcXhiu5ym9KXcFn6onSZ7fCHe1oEgW pJvGecGUUJGFMXOCnS0hmOA9VHj6AvxT9T+y0vMz7OQvR/yg/wM1uXPRt/d93or9ncXD 3JfzbCADwmqA53SVs3otoH0fYepJ+LdjvarZlIGoJkzzl8jUWPrjLNDDjyTxqGmw0Vls oyt26izE3IQJIIpaqq34hyG+0Q+xrek2W49GuJk5IZ+ByLvI8zDgoVmrtdMApxH2EW2p OTZ0N32SlxIenw8/WWbI/q/XE/axLujwLwgaXt0sNrWzBHz6RyqatIX7fCv4CoytgUSz LWxA== X-Gm-Message-State: AOAM532J+ZuWnWh5sPeZmS2y7YiTCTcOk/62eiZ5WglHBN3P/rMbwLNu aNzoyT3Jiu1IlJSR8tAzFBE= X-Google-Smtp-Source: ABdhPJwYt87UK8O0K8miZRtFZzzW+Ds0s4H8QKDotJ++moKVKdxCkCYN66yOPkuB27/xB8p8Te5PDA== X-Received: by 2002:a17:90a:5282:: with SMTP id w2mr1924671pjh.77.1600132848288; Mon, 14 Sep 2020 18:20:48 -0700 (PDT) Received: from bubble.grove.modra.org ([2406:3400:51d:8cc0:2474:1d78:84bf:1670]) by smtp.gmail.com with ESMTPSA id e207sm12210851pfh.171.2020.09.14.18.20.46 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Mon, 14 Sep 2020 18:20:47 -0700 (PDT) From: Alan Modra To: Segher Boessenkool Cc: gcc-patches@sourceware.org, Alan Modra Subject: [RS6000] rotate and mask constants Date: Tue, 15 Sep 2020 10:49:46 +0930 Message-Id: <20200915011946.3395-9-amodra@gmail.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20200915011946.3395-1-amodra@gmail.com> References: <20200915011946.3395-1-amodra@gmail.com> X-Spam-Status: No, score=-10.3 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Tue, 15 Sep 2020 01:20:50 -0000 Implement more two insn constants. PR 94393 * config/rs6000/rs6000.c (rotate_and_mask_constant): New function. (num_insns_constant_multi, rs6000_emit_set_long_const): Use it here. diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c index 86c90c4d756..1848cb57ef8 100644 --- a/gcc/config/rs6000/rs6000.c +++ b/gcc/config/rs6000/rs6000.c @@ -1112,6 +1112,8 @@ static tree rs6000_handle_altivec_attribute (tree *, tree, tree, int, bool *); static tree rs6000_handle_struct_attribute (tree *, tree, tree, int, bool *); static tree rs6000_builtin_vectorized_libmass (combined_fn, tree, tree); static void rs6000_emit_set_long_const (rtx, HOST_WIDE_INT); +static bool rotate_and_mask_constant (unsigned HOST_WIDE_INT, HOST_WIDE_INT *, + int *, unsigned HOST_WIDE_INT *); static int rs6000_memory_move_cost (machine_mode, reg_class_t, bool); static bool rs6000_debug_rtx_costs (rtx, machine_mode, int, int, int *, bool); static int rs6000_debug_address_cost (rtx, machine_mode, addr_space_t, @@ -5789,7 +5791,8 @@ num_insns_constant_multi (HOST_WIDE_INT value, machine_mode mode) /* We won't get more than 2 from num_insns_constant_gpr except when TARGET_POWERPC64 and mode is DImode or wider, so the register mode must be DImode. */ - && rs6000_is_valid_and_mask (GEN_INT (low), DImode)) + && (rs6000_is_valid_and_mask (GEN_INT (low), DImode) + || rotate_and_mask_constant (low, NULL, NULL, NULL))) insns = 2; total += insns; /* If BITS_PER_WORD is the number of bits in HOST_WIDE_INT, doing @@ -9420,6 +9423,82 @@ rs6000_emit_set_const (rtx dest, rtx source) return true; } +/* Detect cases where a constant can be formed by li; rldicl, li; rldicr, + or lis; rldicl. */ + +static bool +rotate_and_mask_constant (unsigned HOST_WIDE_INT c, + HOST_WIDE_INT *val, int *shift, + unsigned HOST_WIDE_INT *mask) +{ + /* We know C can't be formed by lis,addi so that puts constraints + on the max leading zeros. lead_zeros won't be larger than + HOST_BITS_PER_WIDE_INT - 31. */ + int lead_zeros = wi::clz (c); + int non_zero = HOST_BITS_PER_WIDE_INT - lead_zeros; + /* 00...01xxxxxxxxxxxxxx0..00 (up to 14 x's, any number of leading + and trailing 0's) can be implemented as a li, rldicl. */ + if ((c & ~(HOST_WIDE_INT_UC (0x7fff) << (non_zero - 15))) == 0) + { + /* eg. c = 1100 0000 0000 ... 0000 + -> val = 0x3000, shift = 49, mask = -1ull. */ + if (val) + { + *val = c >> (non_zero - 15); + *shift = non_zero - 15; + *mask = HOST_WIDE_INT_M1U; + } + return true; + } + /* 00...01xxxxxxxxxxxxxxx1..11 (up to 15 x's, any number of leading + 0's and trailing 1's) can be implemented as a li, rldicl. */ + if ((c | (HOST_WIDE_INT_M1U << (non_zero - 16))) == HOST_WIDE_INT_M1U) + { + /* eg. c = 0000 1011 1111 1111 ... 1111 + -> val = sext(0xbfff), shift = 44, mask = 0x0fffffffffffffff. */ + if (val) + { + *val = (((c >> (non_zero - 16)) & 0xffff) ^ 0x8000) - 0x8000; + *shift = non_zero - 16; + *mask = HOST_WIDE_INT_M1U >> lead_zeros; + } + return true; + } + /* 00...01xxxxxxxxxxxxxxx00..01..11 (up to 15 x's followed by 16 0's, + any number of leading 0's and trailing 1's) can be implemented as + lis, rldicl. */ + if (non_zero >= 32 + && (c & ((HOST_WIDE_INT_1U << (non_zero - 16)) + - (HOST_WIDE_INT_1U << (non_zero - 32)))) == 0 + && (c | (HOST_WIDE_INT_M1U << (non_zero - 32))) == HOST_WIDE_INT_M1U) + { + if (val) + { + *val = (((c >> (non_zero - 32)) & 0xffffffff) + ^ 0x80000000) - 0x80000000; + *shift = non_zero - 32; + *mask = HOST_WIDE_INT_M1U >> lead_zeros; + } + return true; + } + /* 11..1xxxxxxxxxxxxxxx0..0 (up to 15 x's, any number of leading 1's + and trailing 0's) can be implemented as a li, rldicr. */ + int trail_zeros = wi::ctz (c); + if (trail_zeros >= 48 + || ((c | ((HOST_WIDE_INT_1U << (trail_zeros + 15)) - 1)) + == HOST_WIDE_INT_M1U)) + { + if (val) + { + *val = (((c >> trail_zeros) & 0xffff) ^ 0x8000) - 0x8000; + *shift = trail_zeros; + *mask = HOST_WIDE_INT_M1U << trail_zeros; + } + return true; + } + return false; +} + /* Subroutine of rs6000_emit_set_const, handling PowerPC64 DImode. Output insns to set DEST equal to the constant C as a series of lis, ori and shl instructions. */ @@ -9429,6 +9508,9 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c) { rtx temp; HOST_WIDE_INT ud1, ud2, ud3, ud4; + HOST_WIDE_INT val = c; + int shift; + unsigned HOST_WIDE_INT mask; ud1 = c & 0xffff; c = c >> 16; @@ -9454,6 +9536,15 @@ rs6000_emit_set_long_const (rtx dest, HOST_WIDE_INT c) gen_rtx_IOR (DImode, copy_rtx (temp), GEN_INT (ud1))); } + else if (rotate_and_mask_constant (val, &val, &shift, &mask)) + { + temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode); + emit_move_insn (temp, GEN_INT (val)); + rtx x = gen_rtx_ROTATE (DImode, copy_rtx (temp), GEN_INT (shift)); + if (mask != HOST_WIDE_INT_M1U) + x = gen_rtx_AND (DImode, x, GEN_INT (mask)); + emit_move_insn (dest, x); + } else if (ud3 == 0 && ud4 == 0) { temp = !can_create_pseudo_p () ? dest : gen_reg_rtx (DImode);