From patchwork Thu Jul 23 15:47:56 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jozef Lawrynowicz X-Patchwork-Id: 1334960 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mittosystems.com header.i=@mittosystems.com header.a=rsa-sha256 header.s=google header.b=cJQijxrv; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BCGtS1NJKz9sPf for ; Fri, 24 Jul 2020 01:47:28 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 6D38A388A82B; Thu, 23 Jul 2020 15:47:25 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x32c.google.com (mail-wm1-x32c.google.com [IPv6:2a00:1450:4864:20::32c]) by sourceware.org (Postfix) with ESMTPS id 391173857C5A for ; Thu, 23 Jul 2020 15:47:22 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 391173857C5A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wm1-x32c.google.com with SMTP id f18so5642158wml.3 for ; Thu, 23 Jul 2020 08:47:22 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=j5xb4bV12LS6PD8y0fDSy3Z8cyP+fJmyIJ1g+nF6wyg=; b=cJQijxrvXc6+gVKFomzPC2/RvVylE8Z4/HADi4HTfJ/ukjWa7Bulej4JVHH2uFD2x5 E8J2ypWngBNxdNRJt36o6BYC4k/aHgS8Vxn7XI8ycaujxwp21bf4nTU/ue0RQRiZj0/R 2ndHWOZcNYzOgR7DKWSrE4RlSYm+0KSLkXSsZybUiBX+N5JQ9qT82L96vQEeKeJy19ms /4Rc+IrUJGp0twzqvysjGdqBzIinLF3+qTlqRFwh1J5O/GsRjYsPYju+wGrLtyiZCnag Sog88YSYjRiRy4dLx/qeXyx/w5PAiK0rmGS4ER2alhNQdQ72cxQ8BrBC06vbaJtZGRXi NG6g== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to; bh=j5xb4bV12LS6PD8y0fDSy3Z8cyP+fJmyIJ1g+nF6wyg=; b=quXRFSFsg1evj3Gy3rSUX/1Vu8ESZk52HZdlYxSDjFMUkfa03fyRI7nKFPtpGzCQAF oRxxjGYaXCyFMSVu8tC1h79Q3lbFoVBk3sFfD21Pn2Z4PqlEBX++F7Oe9epluOW96l4v f8Emcr13XwzaQpvHq6DjsZehKM+JolrZDJDsQMvYfZHQrspc9HDSj2LHgrGhK+zyBFcj 0LyY2UksdkCd22v5T/P4EvWySGMHY0cvoOyBCRhZQOqCU0Yc3+tgNyTp8K3GzcXzXrYt I5YsyMMYlzTMOl+kp6v3Il5PrYJRGdVgrqSNwDZgmFYrRnmu3PwP6BHmIGfIfnq8boxG zNVA== X-Gm-Message-State: AOAM530XRbSVJz0U7qdvUvrYMY2QNe4MzI6Me7Nqz0WqyzItv+6kQ3+B PQXR0OT5PiIqBX2C1sjpQpOL9ysbklk= X-Google-Smtp-Source: ABdhPJz7HRmPY8BuGAQssdre7iYeV0naavjMtr1bF3tdNpEH/7bTNSMHM/xf7h9PdV4LgbFtAQUOsQ== X-Received: by 2002:a7b:cf16:: with SMTP id l22mr5150583wmg.68.1595519241130; Thu, 23 Jul 2020 08:47:21 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id v29sm4605626wrv.51.2020.07.23.08.47.20 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:47:20 -0700 (PDT) Date: Thu, 23 Jul 2020 16:47:56 +0100 From: Jozef Lawrynowicz To: gcc-patches@gcc.gnu.org Subject: [PATCH 1/5] MSP430: Implement TARGET_MEMORY_MOVE_COST Message-ID: <20200723154756.dgh7y6l6ngej6gpe@jozef-acer-manjaro> Mail-Followup-To: gcc-patches@gcc.gnu.org References: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" The cycle and size cost of a MOV instruction in different addressing modes can be used to calculate the TARGET_MEMORY_MOVE_COST relative to TARGET_REGISTER_MOVE_COST. From c801a2851d47601218578c411854de9540486335 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 16 Jul 2020 11:28:11 +0100 Subject: [PATCH 1/5] MSP430: Implement TARGET_MEMORY_MOVE_COST The cycle and size cost of a MOV instruction in different addressing modes can be used to calculate the TARGET_MEMORY_MOVE_COST relative to TARGET_REGISTER_MOVE_COST. gcc/ChangeLog: * config/msp430/msp430.c (struct single_op_cost): New struct. (struct double_op_cost): Likewise. (TARGET_REGISTER_MOVE_COST): Don't define but add comment. (TARGET_MEMORY_MOVE_COST): Define to... (msp430_memory_move_cost): New function. (BRANCH_COST): Don't define but add comment. --- gcc/config/msp430/msp430.c | 131 +++++++++++++++++++++++++++++++++++++ 1 file changed, 131 insertions(+) diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index c2b24974364..9e739233fa0 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -1043,6 +1043,137 @@ msp430_legitimate_constant (machine_mode mode, rtx x) } +/* Describing Relative Costs of Operations + To model the cost of an instruction, use the number of cycles when + optimizing for speed, and the number of words when optimizing for size. + The cheapest instruction will execute in one cycle and cost one word. + The cycle and size costs correspond to 430 ISA instructions, not 430X + instructions or 430X "address" instructions. The relative costs of 430X + instructions is accurately modeled with the 430 costs. The relative costs + of some "address" instructions can differ, but these are not yet handled. + Adding support for this could improve performance/code size. */ + +const int debug_rtx_costs = 0; + +struct single_op_cost +{ + const int reg; + /* Indirect register (@Rn) or indirect autoincrement (@Rn+). */ + const int ind; + const int mem; +}; + +static const struct single_op_cost cycle_cost_single_op = +{ + 1, 3, 4 +}; + +static const struct single_op_cost size_cost_single_op = +{ + 1, 1, 2 +}; + +/* When the destination of an insn is memory, the cost is always the same + regardless of whether that memory is accessed using indirect register, + indexed or absolute addressing. + When the source operand is memory, indirect register and post-increment have + the same cost, which is lower than indexed and absolute, which also have + the same cost. */ +struct double_op_cost +{ + /* Source operand is a register. */ + const int r2r; + const int r2pc; + const int r2m; + + /* Source operand is memory, using indirect register (@Rn) or indirect + autoincrement (@Rn+) addressing modes. */ + const int ind2r; + const int ind2pc; + const int ind2m; + + /* Source operand is an immediate. */ + const int imm2r; + const int imm2pc; + const int imm2m; + + /* Source operand is memory, using indexed (x(Rn)) or absolute (&ADDR) + addressing modes. */ + const int mem2r; + const int mem2pc; + const int mem2m; +}; + +/* These structures describe the cost of MOV, BIT and CMP instructions, in terms + of clock cycles or words. */ +static const struct double_op_cost cycle_cost_double_op_mov = +{ + 1, 3, 3, + 2, 4, 4, + 2, 3, 4, + 3, 5, 5 +}; + +/* Cycle count when memory is the destination operand is one larger than above + for instructions that aren't MOV, BIT or CMP. */ +static const struct double_op_cost cycle_cost_double_op = +{ + 1, 3, 4, + 2, 4, 5, + 2, 3, 5, + 3, 5, 6 +}; + +static const struct double_op_cost size_cost_double_op = +{ + 1, 1, 2, + 1, 1, 2, + 2, 2, 3, + 2, 2, 3 +}; + +/* TARGET_REGISTER_MOVE_COST + There is only one class of general-purpose, non-fixed registers, and the + relative cost of moving data between them is always the same. + Therefore, the default of 2 is optimal. */ + +#undef TARGET_MEMORY_MOVE_COST +#define TARGET_MEMORY_MOVE_COST msp430_memory_move_cost + +/* Return the cost of moving data between registers and memory. + The returned cost must be relative to the default TARGET_REGISTER_MOVE_COST + of 2. + IN is false if the value is to be written to memory. */ +static int +msp430_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED, + reg_class_t rclass ATTRIBUTE_UNUSED, + bool in) +{ + int cost; + const struct double_op_cost *cost_p; + /* Optimize with a code size focus by default, unless -O2 or above is + specified. */ + bool speed = (!optimize_size && optimize >= 2); + + cost_p = (speed ? &cycle_cost_double_op_mov : &size_cost_double_op); + + if (in) + /* Reading from memory using indirect addressing is assumed to be the more + common case. */ + cost = cost_p->ind2r; + else + cost = cost_p->r2m; + + /* All register to register moves cost 1 cycle or 1 word, so multiply by 2 + to get the costs relative to TARGET_REGISTER_MOVE_COST of 2. */ + return 2 * cost; +} + +/* BRANCH_COST + Changing from the default of 1 doesn't affect code generation, presumably + because there are no conditional move insns - when a condition is involved, + the only option is to use a cbranch. */ + #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS msp430_rtx_costs From patchwork Thu Jul 23 15:49:59 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jozef Lawrynowicz X-Patchwork-Id: 1334961 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mittosystems.com header.i=@mittosystems.com header.a=rsa-sha256 header.s=google header.b=LLDhsNfZ; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BCGwq5jllz9sPf for ; Fri, 24 Jul 2020 01:49:31 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 2B6CF388A816; Thu, 23 Jul 2020 15:49:29 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x330.google.com (mail-wm1-x330.google.com [IPv6:2a00:1450:4864:20::330]) by sourceware.org (Postfix) with ESMTPS id BA5F7386F457 for ; Thu, 23 Jul 2020 15:49:25 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org BA5F7386F457 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wm1-x330.google.com with SMTP id o2so5654941wmh.2 for ; Thu, 23 Jul 2020 08:49:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=VovOXzELC6OLWaUnHAnAB5zquW9+gRC0ULjj4Qj9RCQ=; b=LLDhsNfZJvLUdhcZBwEAZXpw3yxq6TdHPKkqb807988bV+AMpFkXzspnRUiIwg8se+ uoJI+OPYJZoCn8hiGtXDVdkH3n4LMj0sJJiBs8L2It+HgHU9ANL/nGfkBSzTQcAsJr/C +BaYwgjfC4imRZgQI+0gD7KFHpwStDq7AxD57A76PCZOMt7ThNkSzm+TOoUUuxBo57Vl X9xpMUDJMUjR+246Me37zL8czWO5SGyCLzXLTLAaH/r9RkaELsNyyAhvinRhpHg2nM+d bbS8borv4sjfY5SlU0UeUUqDL+8TiR29k2OnxMQLnyjQ+EQ5GEMrSx1fhWIGlp2/uCkO R26A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to; bh=VovOXzELC6OLWaUnHAnAB5zquW9+gRC0ULjj4Qj9RCQ=; b=oRLIw0OGCHblxsbKliTu720uR640LZPURQXhhpxKNGovZ4okQ8lrQsTdcvu8SHX4MJ cFCrD9vEAP/d9lxyeyrqm2Y04PW2hlDrJPvpovsKJhodLcu9wjCFVfxw0MBsojiRaY5a rUFKlWHdo/AbKQBqYi7pv6H5W6CpK4NCZyci5BaWspkmKzryU3WwpGZW4PB9Qp+anil2 H+0/+qCjT5Ee63qQkOsA93D/YwmIOiOSwOhpbQqTttKS2BZ5ybJCltowvy9lDj7TdJaQ VmoM8sB9185sxnfSmCa4RWIrz6/rBY+KIqME+GvV+RidPxK1GgzSPI0mROmlBNsBykU/ evOA== X-Gm-Message-State: AOAM532uSz9MgcA78yPpTKHr1fnqeEYxx/R3JcGTiW3twHnzMA8YChVr fPzTrbmpkADmuNZDSh5kppayguEnlpI= X-Google-Smtp-Source: ABdhPJwYR3zC8FbZSMYSKJPaPDh2M0KJ0sexI63sgRcFgWckSC6P9At7HEM7FsH0/aRaS/MxQdm73Q== X-Received: by 2002:a1c:6106:: with SMTP id v6mr4547838wmb.178.1595519364494; Thu, 23 Jul 2020 08:49:24 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id k131sm4272207wmb.36.2020.07.23.08.49.23 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:49:23 -0700 (PDT) Date: Thu, 23 Jul 2020 16:49:59 +0100 From: Jozef Lawrynowicz To: gcc-patches@gcc.gnu.org Subject: [PATCH 2/5] MSP430: Implement TARGET_RTX_COSTS Message-ID: <20200723154959.6hszuzththygc2tn@jozef-acer-manjaro> Mail-Followup-To: gcc-patches@gcc.gnu.org References: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> X-Spam-Status: No, score=-10.9 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" Costs of MSP430 instructions are mostly just a function of the type and number of operands. In these cases, TARGET_RTX_COSTS just needs to examine the operands to calculate the cost of the expression. For more complicated operations where library helper functions are required, if the cost cannot be accurately calculated, it is estimated and disparaged relative to the cost of a single instruction. From f5cbd8967d9c64a4ea6eb9fb8846b4361e16e396 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 16 Jul 2020 11:28:59 +0100 Subject: [PATCH 2/5] MSP430: Implement TARGET_RTX_COSTS Costs of MSP430 instructions are mostly just a function of the type and number of operands. In these cases, TARGET_RTX_COSTS just needs to examine the operands to calculate the cost of the expression. For more complicated operations where library helper functions are required, if the cost cannot be accurately calculated, it is estimated and disparaged relative to the cost of a single instruction. gcc/ChangeLog: * config/msp430/msp430.c (use_helper_for_const_shift): Add forward declaration. Remove unused argument. (struct msp430_multlib_costs): New struct. (msp430_is_mem_indirect): New function. (msp430_costs): Likewise. (msp430_shift_costs): Likewise. (msp430_muldiv_costs): Likewise. (msp430_get_inner_dest_code): Likewise. (msp430_single_op_cost): Likewise. (msp430_rtx_costs): Rewrite from scratch. (msp430_expand_shift): Adjust use_helper_for_const_shift call. --- gcc/config/msp430/msp430.c | 545 ++++++++++++++++++++++++++++++++++++- 1 file changed, 530 insertions(+), 15 deletions(-) diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index 9e739233fa0..81ee5075a57 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -49,6 +49,9 @@ #include "msp430-devices.h" #include "incpath.h" #include "prefix.h" +#include "insn-config.h" +#include "insn-attr.h" +#include "recog.h" /* This file should be included last. */ #include "target-def.h" @@ -56,6 +59,7 @@ static void msp430_compute_frame_info (void); static bool use_32bit_hwmult (void); +static bool use_helper_for_const_shift (machine_mode mode, HOST_WIDE_INT amt); @@ -1132,6 +1136,28 @@ static const struct double_op_cost size_cost_double_op = 2, 2, 3 }; +struct msp430_multlib_costs +{ + const int mulhi; + const int mulsi; + const int muldi; +}; + +/* There is no precise size cost when using libcalls, instead it is disparaged + relative to other instructions. + The cycle costs are from the CALL to the RET, inclusive. + FIXME muldi cost is not accurate. */ +static const struct msp430_multlib_costs cycle_cost_multlib_32bit = +{ + 27, 33, 66 +}; + +/* 32bit multiply takes a few more instructions on 16bit hwmult. */ +static const struct msp430_multlib_costs cycle_cost_multlib_16bit = +{ + 27, 42, 66 +}; + /* TARGET_REGISTER_MOVE_COST There is only one class of general-purpose, non-fixed registers, and the relative cost of moving data between them is always the same. @@ -1174,29 +1200,516 @@ msp430_memory_move_cost (machine_mode mode ATTRIBUTE_UNUSED, because there are no conditional move insns - when a condition is involved, the only option is to use a cbranch. */ +/* For X, which must be a MEM RTX, return TRUE if it is an indirect memory + reference, @Rn or @Rn+. */ +static bool +msp430_is_mem_indirect (rtx x) +{ + gcc_assert (GET_CODE (x) == MEM); + rtx op0 = XEXP (x, 0); + return (GET_CODE (op0) == REG || GET_CODE (op0) == POST_INC); +} + +/* Costs of MSP430 instructions are generally based on the addressing mode + combination of the source and destination operands. + Given source operand SRC (which may be NULL to indicate a single-operand + instruction) and destination operand DST return the cost of this + expression. */ +static int +msp430_costs (rtx src, rtx dst, bool speed, rtx outer_rtx) +{ + enum rtx_code src_code = GET_CODE (src); + enum rtx_code dst_code = GET_CODE (dst); + enum rtx_code outer_code = GET_CODE (outer_rtx); + machine_mode outer_mode = GET_MODE (outer_rtx); + const struct double_op_cost *cost_p; + cost_p = (speed ? &cycle_cost_double_op : &size_cost_double_op); + + if (outer_code == TRUNCATE + && (outer_mode == QImode + || outer_mode == HImode + || outer_mode == PSImode)) + /* Truncation to these modes is normally free as a side effect of the + instructions themselves. */ + return 0; + + if (dst_code == SYMBOL_REF + || dst_code == LABEL_REF + || dst_code == CONST_INT) + /* Catch RTX like (minus (const_int 0) (reg)) but don't add any cost. */ + return 0; + + if (debug_rtx_costs && dst_code != REG && dst_code != MEM && dst_code != PC) + { + fprintf (stderr, "msp430_costs unhandled dst operand:\n"); + debug_rtx (dst); + fprintf (stderr, "from:\n"); + debug_rtx (outer_rtx); + } + + switch (src_code) + { + case REG: + return (dst_code == REG ? cost_p->r2r + : (dst_code == PC ? cost_p->r2pc : cost_p->r2m)); + + case CONST_INT: + case SYMBOL_REF: + case LABEL_REF: + case CONST: + return (dst_code == REG ? cost_p->imm2r + : (dst_code == PC ? cost_p->imm2pc : cost_p->imm2m)); + + + case MEM: + if (msp430_is_mem_indirect (src)) + return (dst_code == REG ? cost_p->ind2r : (dst_code == PC + ? cost_p->ind2pc + : cost_p->ind2m)); + else + return (dst_code == REG ? cost_p->mem2r : (dst_code == PC + ? cost_p->mem2pc + : cost_p->mem2m)); + default: + if (debug_rtx_costs) + { + fprintf (stderr, "msp430_costs unhandled src operand:\n"); + debug_rtx (src); + fprintf (stderr, "from:\n"); + debug_rtx (outer_rtx); + } + return cost_p->mem2m; + } +} + +/* Given source operand SRC and destination operand DST from the shift or + rotate RTX OUTER_RTX, return the cost of performing that shift, assuming + optimization for speed when SPEED is true. */ +static int +msp430_shift_costs (rtx src, rtx dst, bool speed, rtx outer_rtx) +{ + int amt; + enum rtx_code src_code = GET_CODE (src); + enum rtx_code dst_code = GET_CODE (dst); + const struct single_op_cost *cost_p; + + cost_p = (speed ? &cycle_cost_single_op : &size_cost_single_op); + + if (debug_rtx_costs + && dst_code != REG + && dst_code != MEM + && dst_code != CONST + && dst_code != SYMBOL_REF + && dst_code != CONST_INT) + { + fprintf (stderr, "msp430_shift_costs unhandled dst operand:\n"); + debug_rtx (dst); + } + + if (debug_rtx_costs + && src_code != CONST_INT + && src_code != REG) + { + fprintf (stderr, "msp430_shift_costs unhandled src operand:\n"); + debug_rtx (src); + } + + if (src_code != CONST_INT) + /* The size or speed cost when the shift amount is unknown cannot be + accurately calculated, so just disparage it slightly. */ + return 2 * msp430_costs (src, dst, speed, outer_rtx); + + if (use_helper_for_const_shift (GET_MODE (outer_rtx), amt = INTVAL (src))) + { + /* GCC sometimes tries to perform shifts in some very inventive ways, + resulting in much larger code size usage than necessary, if + they are disparaged too much here. So in general, if + use_helper_for_const_shift thinks a helper should be used, obey + that and don't disparage the shift any more than a regular + instruction, even though the shift may actually cost more. + This ensures that the RTL generated at the initial expand pass has the + expected shift instructions, which can be mapped to the helper + functions. */ + return msp430_costs (src, dst, speed, outer_rtx); + } + + if (!msp430x) + { + /* Each shift by one place will be emitted individually. */ + switch (dst_code) + { + case REG: + case CONST_INT: + return amt * cost_p->reg; + case MEM: + if (msp430_is_mem_indirect (dst)) + return amt * cost_p->ind; + else + return amt * cost_p->mem; + default: + return amt * cost_p->mem; + } + } + + /* RRAM, RRCM, RRUM, RLAM are used for shift counts <= 4, otherwise, the 'X' + versions are used. + Instructions which shift a MEM operand will never actually be output. It + will always be copied into a register to allow for efficient shifting. So + the cost just takes into account the cost of an additional copy in that + case. */ + return (amt <= 4 ? (speed ? amt : 1) : (speed ? amt + 1 : 2) + + (dst_code == REG ? 0 + : msp430_costs (dst, gen_rtx_REG (HImode, 10), speed, outer_rtx))); +} + +/* Given source operand SRC and destination operand DST from the MULT/DIV/MOD + RTX OUTER_RTX, return the cost of performing that operation, assuming + optimization for speed when SPEED is true. */ +static int +msp430_muldiv_costs (rtx src, rtx dst, bool speed, rtx outer_rtx, + machine_mode outer_mode) +{ + enum rtx_code outer_code = GET_CODE (outer_rtx); + const struct msp430_multlib_costs *cost_p; + bool hwmult_16bit = (msp430_has_hwmult () && !(msp430_use_f5_series_hwmult () + || use_32bit_hwmult ())); + cost_p = (hwmult_16bit + ? &cycle_cost_multlib_32bit + : &cycle_cost_multlib_16bit); + + int factor = 1; + /* Only used in some calculations. */ + int mode_factor = 1; + if (outer_mode == SImode) + mode_factor = 2; + else if (outer_mode == PSImode) + /* PSImode multiplication is performed using SImode operands, so has extra + cost to factor in the conversions necessary before/after the + operation. */ + mode_factor = 3; + else if (outer_mode == DImode) + mode_factor = 4; + + if (!speed) + { + /* The codesize cost of using a helper function to perform the + multiplication or division cannot be accurately calculated, since the + cost depends on how many times the operation is performed in the + entire program. */ + if (outer_code != MULT) + /* Division is always expensive. */ + factor = 7; + else if (((hwmult_16bit && outer_mode != DImode) + || use_32bit_hwmult () || msp430_use_f5_series_hwmult ())) + /* When the hardware multiplier is available, only disparage + slightly. */ + factor = 2; + else + factor = 5; + return factor * mode_factor * msp430_costs (src, dst, speed, outer_rtx); + } + + /* When there is hardware multiply support, there is a relatively low, fixed + cycle cost to performing any multiplication, but when there is no hardware + multiply support it is very costly. That precise cycle cost has not been + calculated here. + Division is extra slow since it always uses a software library. + The 16-bit hardware multiply library cannot be used to produce 64-bit + results. */ + if (outer_code != MULT || !msp430_has_hwmult () + || (outer_mode == DImode && hwmult_16bit)) + { + factor = (outer_code == MULT ? 50 : 70); + return factor * mode_factor * msp430_costs (src, dst, speed, outer_rtx); + } + + switch (outer_mode) + { + case E_QImode: + case E_HImode: + /* Include the cost of copying the operands into and out of the hardware + multiply routine. */ + return cost_p->mulhi + (3 * msp430_costs (src, dst, speed, outer_rtx)); + + case E_PSImode: + /* Extra factor for the conversions necessary to do PSI->SI before the + operation. */ + factor = 2; + /* fallthru. */ + case E_SImode: + return factor * (cost_p->mulsi + + (6 * msp430_costs (src, dst, speed, outer_rtx))); + + case E_DImode: + default: + return cost_p->muldi + (12 * msp430_costs (src, dst, speed, outer_rtx)); + } +} + +/* Recurse within X to find the actual destination operand of the expression. + For example: + (plus (ashift (minus (ashift (reg) + (const_int) ...... + should return the reg RTX. */ +static rtx +msp430_get_inner_dest_code (rtx x) +{ + enum rtx_code code = GET_CODE (x); + rtx op0 = XEXP (x, 0); + switch (code) + { + case REG: + case SYMBOL_REF: + case CONST_INT: + case CONST: + case LABEL_REF: + return x; + + case MEM: + /* Return the MEM expr not the inner REG for these cases. */ + switch (GET_CODE (op0)) + { + case REG: + case SYMBOL_REF: + case LABEL_REF: + case CONST: + case POST_INC: + return x; + + case PLUS: + /* return MEM (PLUS (REG) (CONST)) */ + if (GET_CODE (XEXP (op0, 0)) == REG) + { + if (GET_CODE (XEXP (op0, 1)) == CONST_INT + || GET_CODE (XEXP (op0, 1)) == CONST + || GET_CODE (XEXP (op0, 1)) == LABEL_REF + || GET_CODE (XEXP (op0, 1)) == SYMBOL_REF) + return x; + else + return msp430_get_inner_dest_code (op0); + } + return msp430_get_inner_dest_code (op0); + + default: + if (GET_RTX_FORMAT (code)[0] != 'e') + return x; + return msp430_get_inner_dest_code (op0); + } + break; + + default: + if (op0 == NULL_RTX) + gcc_unreachable (); + else + { + if (GET_RTX_FORMAT (code)[0] != 'e' + && code != ENTRY_VALUE) + return x; + return msp430_get_inner_dest_code (op0); + } + } +} + +/* Calculate the cost of an MSP430 single-operand instruction, for operand DST + within the RTX OUTER_RTX, optimizing for speed if SPEED is true. */ +static int +msp430_single_op_cost (rtx dst, bool speed, rtx outer_rtx) +{ + enum rtx_code dst_code = GET_CODE (dst); + const struct single_op_cost *cost_p; + const struct double_op_cost *double_op_cost_p; + + cost_p = (speed ? &cycle_cost_single_op : &size_cost_single_op); + double_op_cost_p = (speed ? &cycle_cost_double_op : &size_cost_double_op); + + switch (dst_code) + { + case REG: + return cost_p->reg; + case MEM: + if (msp430_is_mem_indirect (dst)) + return cost_p->ind; + else + return cost_p->mem; + + case CONST_INT: + case CONST_FIXED: + case CONST_DOUBLE: + case SYMBOL_REF: + case CONST: + /* A constant value would need to be copied into a register first. */ + return double_op_cost_p->imm2r + cost_p->reg; + + default: + if (debug_rtx_costs) + { + fprintf (stderr, "msp430_single_op_cost unhandled " + "dst operand:\n"); + debug_rtx (dst); + fprintf (stderr, "from:\n"); + debug_rtx (outer_rtx); + } + return cost_p->mem; + } +} + #undef TARGET_RTX_COSTS #define TARGET_RTX_COSTS msp430_rtx_costs -static bool msp430_rtx_costs (rtx x ATTRIBUTE_UNUSED, - machine_mode mode, - int outer_code ATTRIBUTE_UNUSED, - int opno ATTRIBUTE_UNUSED, - int * total, - bool speed ATTRIBUTE_UNUSED) +/* This target hook describes the relative costs of RTL expressions. + The function recurses to just before the lowest level of the expression, + when both of the operands of the expression can be examined at the same time. + This is because the cost of the expression depends on the specific + addressing mode combination of the operands. + The hook returns true when all subexpressions of X have been processed, and + false when rtx_cost should recurse. */ +static bool +msp430_rtx_costs (rtx x, + machine_mode mode, + int outer_code ATTRIBUTE_UNUSED, + int opno ATTRIBUTE_UNUSED, + int * total, + bool speed) { - int code = GET_CODE (x); + enum rtx_code code = GET_CODE (x); + rtx dst, src; + rtx dst_inner, src_inner; + + *total = 0; + dst = XEXP (x, 0); + if (GET_RTX_LENGTH (code) == 1) + /* Some RTX that are single-op in GCC are double-op when translated to + MSP430 instructions e.g NOT, NEG, ZERO_EXTEND. */ + src = dst; + else + src = XEXP (x, 1); + switch (code) { + case SET: + /* Ignoring SET improves codesize. */ + if (!speed) + return true; + /* fallthru. */ + case PLUS: + if (outer_code == MEM) + /* Do not add any cost for the plus itself, but recurse in case there + are more complicated RTX inside. */ + return false; + /* fallthru. */ + case MINUS: + case AND: + case IOR: + case XOR: + case NOT: + case ZERO_EXTEND: + case TRUNCATE: + case NEG: + case ZERO_EXTRACT: + case SIGN_EXTRACT: + case IF_THEN_ELSE: + dst_inner = msp430_get_inner_dest_code (dst); + src_inner = msp430_get_inner_dest_code (src); + *total = COSTS_N_INSNS (msp430_costs (src_inner, dst_inner, speed, x)); + if (mode == SImode) + *total *= 2; + if (mode == DImode) + *total *= 4; + return false; + + case ROTATE: + case ASHIFT: + case ASHIFTRT: + case LSHIFTRT: + dst_inner = msp430_get_inner_dest_code (dst); + src_inner = msp430_get_inner_dest_code (src); + *total = COSTS_N_INSNS (msp430_shift_costs (src_inner, dst_inner, + speed, x)); + if (mode == SImode) + *total *= 2; + if (mode == DImode) + *total *= 4; + return false; + + case MULT: + case DIV: + case MOD: + case UDIV: + case UMOD: + dst_inner = msp430_get_inner_dest_code (dst); + src_inner = msp430_get_inner_dest_code (src); + *total = COSTS_N_INSNS (msp430_muldiv_costs (src_inner, dst_inner, speed, + x, mode)); + return false; + + case CALL: case SIGN_EXTEND: - if (mode == SImode && outer_code == SET) + dst_inner = msp430_get_inner_dest_code (dst); + *total = COSTS_N_INSNS (msp430_single_op_cost (dst_inner, speed, x)); + if (mode == SImode) + *total *= 2; + if (mode == DImode) + *total *= 4; + return false; + + case CONST_INT: + case CONST_FIXED: + case CONST_DOUBLE: + case SYMBOL_REF: + case CONST: + case LABEL_REF: + case REG: + case PC: + case POST_INC: + if (mode == SImode) + *total = COSTS_N_INSNS (2); + else if (mode == DImode) + *total = COSTS_N_INSNS (4); + return true; + + case MEM: + /* PSImode operands are expensive when in memory. */ + if (mode == PSImode) + *total = COSTS_N_INSNS (1); + else if (mode == SImode) + *total = COSTS_N_INSNS (2); + else if (mode == DImode) + *total = COSTS_N_INSNS (4); + /* Recurse into the MEM. */ + return false; + + case EQ: + case NE: + case GT: + case GTU: + case GE: + case GEU: + case LT: + case LTU: + case LE: + case LEU: + /* Conditions are mostly equivalent, changing their relative + costs has no effect. */ + return false; + + case ASM_OPERANDS: + case ASM_INPUT: + case CLOBBER: + case COMPARE: + case CONCAT: + case ENTRY_VALUE: + /* Other unhandled expressions. */ + return false; + + default: + if (debug_rtx_costs) { - *total = COSTS_N_INSNS (4); - return true; + fprintf (stderr, "\nUnhandled RTX\n"); + debug_rtx (x); } - break; + return false; } - return false; } /* Function Entry and Exit */ @@ -2915,8 +3428,7 @@ msp430_expand_helper (rtx *operands, const char *helper_name, /* Return TRUE if the helper function should be used and FALSE if the shifts insns should be emitted inline. */ static bool -use_helper_for_const_shift (enum rtx_code code, machine_mode mode, - HOST_WIDE_INT amt) +use_helper_for_const_shift (machine_mode mode, HOST_WIDE_INT amt) { const int default_inline_shift = 4; /* We initialize the option to 65 so we know if the user set it or not. */ @@ -2927,6 +3439,9 @@ use_helper_for_const_shift (enum rtx_code code, machine_mode mode, the heuristic accordingly. */ int max_inline_32 = max_inline / 2; + if (mode == E_DImode) + return true; + /* Don't use helpers for these modes on 430X, when optimizing for speed, or when emitting a small number of insns. */ if ((mode == E_QImode || mode == E_HImode || mode == E_PSImode) @@ -2964,7 +3479,7 @@ msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands) constant. */ if (!CONST_INT_P (operands[2]) || mode == E_DImode - || use_helper_for_const_shift (code, mode, INTVAL (operands[2]))) + || use_helper_for_const_shift (mode, INTVAL (operands[2]))) { const char *helper_name = NULL; /* The const variants of mspabi shifts have significantly larger code From patchwork Thu Jul 23 15:54:24 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jozef Lawrynowicz X-Patchwork-Id: 1334962 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=2620:52:3:1:0:246e:9693:128c; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mittosystems.com header.i=@mittosystems.com header.a=rsa-sha256 header.s=google header.b=MaO3/xrR; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [IPv6:2620:52:3:1:0:246e:9693:128c]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BCH1y6SGYz9sPf for ; Fri, 24 Jul 2020 01:53:57 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 1CD57386F457; Thu, 23 Jul 2020 15:53:55 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wm1-x329.google.com (mail-wm1-x329.google.com [IPv6:2a00:1450:4864:20::329]) by sourceware.org (Postfix) with ESMTPS id 7C4F03850437 for ; Thu, 23 Jul 2020 15:53:49 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 7C4F03850437 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wm1-x329.google.com with SMTP id c80so5425199wme.0 for ; Thu, 23 Jul 2020 08:53:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=hxOzSS0OOAyy+iZSs1vdzPiDCu7UKFn4kAGKroxss/M=; b=MaO3/xrRdOtQ71LLW7Qvcr7YXsBmtgSQRk1MC3GhHbZ3ASQDYH1+zujam/FGcT5j/k zKjAXP/Dmz33l03+O/W+WXF5Rp/y2x/PgpHtj4ZmW/Bk5nKUV2oBOUoA+NyzOm9ib+3h nVSM4/UEUygBgAOO36WG6sHGLYTL8McDMq/R9UPZK32WUe8JASv3qPVNpRLSBigjNRoy jNmR01ddInDrw6xGbGzBZAkgiJVJC80KBJWw7VOsnWZH4RTXR7HiZgZVekaPgIKv9+oH eXIFGWBN4OCSBYsuW1dM8lJ8fK9yARjaLx2eQuTR8KQAe8N71bKsC/lJKX/E5bDO1INT 8ykw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to; bh=hxOzSS0OOAyy+iZSs1vdzPiDCu7UKFn4kAGKroxss/M=; b=R0W8XXOLtXzKAZFfMfwxizD7+r8t6IC69x8l0w8Qnz87kkSEv0uv0hmyZfp/u6o+/d hxuso+Hq5BFKYVYbdIoDYTNuA4XkwRCNjXdzGzPiDqAsCgYerHCLAMWyRfjEiFBy1YMg 1+hxbusAfoOik/fyQNMe/Po6tMKti8QHRF68/1zYXrLgi8w1EsgEt21NUSr0qqeHi/SM vPKqRVwQAWWUrN+kFY0XJVKvvbYKK63aj+5csvwTZotHI2MaWF9QWTUFYgsJObafUIyp zurNFvJITA0ML3HOgyqMtNB+JhCpSsWUPwtEaHZLrZ1SLXETtrSWQgVc5jzZZfl8uPHM AhVg== X-Gm-Message-State: AOAM530fh43//dJvP/PlmC0GKmkqBWEd9K1++L21M+NaO33icPq6npfK 2C4De6nolwqKHRRmWJlwTTYtbWTd8T4= X-Google-Smtp-Source: ABdhPJwbx4vOlA7iZwTGcg8DSkv2XSvnxmGj0P4DnUUJ9/ZcUdsKPNaTEmPAwlG8+Z5MlmZbZVX8dg== X-Received: by 2002:a1c:28a:: with SMTP id 132mr4615613wmc.109.1595519628405; Thu, 23 Jul 2020 08:53:48 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id c7sm4389768wrq.58.2020.07.23.08.53.47 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:53:47 -0700 (PDT) Date: Thu, 23 Jul 2020 16:54:24 +0100 From: Jozef Lawrynowicz To: gcc-patches@gcc.gnu.org Subject: [PATCH 3/5] MSP430: Add defaulting to the insn length attribute Message-ID: <20200723155424.45qrdjwyltdr2oyw@jozef-acer-manjaro> Mail-Followup-To: gcc-patches@gcc.gnu.org References: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> X-Spam-Status: No, score=-9.8 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_ASCII_DIVIDERS, KAM_STOCKGEN, 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" The length of MSP430 instructions is mostly just a function of the type and number of operands. Setting the "type" attribute on all insns describes the number of operands, and the position of the source and destination operands. In most cases, defaulting in the "length" and "extension" attribute definitions can then be used to calculate the total length of the instruction by using the value of the "type" attribute to examine the operands. From 0e39cc3f13c604df1225d3c1eef6b05e629c184b Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 16 Jul 2020 11:32:01 +0100 Subject: [PATCH 3/5] MSP430: Add defaulting to the insn length attribute The length of MSP430 instructions is mostly just a function of the type and number of operands. Setting the "type" attribute on all insns describes the number of operands, and the position of the source and destination operands. In most cases, defaulting in the "length" and "extension" attribute definitions can then be used to calculate the total length of the instruction by using the value of the "type" attribute to examine the operands. gcc/ChangeLog: * config/msp430/msp430-protos.h (msp430x_extendhisi): Return int instead of char *. (msp430_output_asm_shift_insns): Likewise. Add new return_length argument. (msp430x_insn_required): Add prototype. * config/msp430/msp430.c (msp430_output_asm_shift_insns): Return the total length, in bytes, of the emitted instructions. (msp430x_insn_required): New function. (msp430x_extendhisi): Return the total length, in bytes, of the emitted instructions. * config/msp430/msp430.h (ADJUST_INSN_LENGTH): Define. * config/msp430/msp430.md: New define_attr "type". New define_attr "extension". New define_attr "length_multiplier". New define_attr "extra_length". Rewrite define_attr "length". Set type, extension, length, length_multiplier or extra_length insn attributes on all insns, as appropriate. (andneghi3): Rewrite using constraints instead of C code to decide output insns. * config/msp430/predicates.md (msp430_cheap_operand): New predicate. (msp430_high_memory_operand): New predicate. --- gcc/config/msp430/msp430-protos.h | 5 +- gcc/config/msp430/msp430.c | 162 ++++++++--- gcc/config/msp430/msp430.h | 10 + gcc/config/msp430/msp430.md | 439 ++++++++++++++++++++++++------ gcc/config/msp430/predicates.md | 13 + 5 files changed, 507 insertions(+), 122 deletions(-) diff --git a/gcc/config/msp430/msp430-protos.h b/gcc/config/msp430/msp430-protos.h index 0b4d9a42b41..33ad1adc61f 100644 --- a/gcc/config/msp430/msp430-protos.h +++ b/gcc/config/msp430/msp430-protos.h @@ -26,7 +26,7 @@ void msp430_expand_eh_return (rtx); void msp430_expand_epilogue (int); void msp430_expand_helper (rtx *operands, const char *, bool); void msp430_expand_prologue (void); -const char * msp430x_extendhisi (rtx *); +int msp430x_extendhisi (rtx *, bool); void msp430_fixup_compare_operands (machine_mode, rtx *); int msp430_hard_regno_nregs_has_padding (int, machine_mode); int msp430_hard_regno_nregs_with_padding (int, machine_mode); @@ -49,10 +49,11 @@ rtx msp430_subreg (machine_mode, rtx, machine_mode, int); bool msp430_use_f5_series_hwmult (void); bool msp430_has_hwmult (void); bool msp430_op_not_in_high_mem (rtx op); +bool msp430x_insn_required (rtx op); #ifdef RTX_CODE int msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands); -const char * msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, rtx *operands); +int msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, rtx *operands, bool); #endif #endif /* GCC_MSP430_PROTOS_H */ diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index 81ee5075a57..b7daafcc11a 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -3535,18 +3535,22 @@ msp430_expand_shift (enum rtx_code code, machine_mode mode, rtx *operands) For 430X it is inneficient to do so for any modes except SI and DI, since we can make use of R*M insns or RPT with 430X insns, so this function is only used for SImode in that case. */ -const char * +int msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, - rtx *operands) + rtx *operands, bool return_length) { int i; int amt; int max_shift = GET_MODE_BITSIZE (mode) - 1; + int length = 0; + gcc_assert (CONST_INT_P (operands[2])); amt = INTVAL (operands[2]); if (amt == 0 || amt > max_shift) { + if (return_length) + return 0; switch (code) { case ASHIFT: @@ -3564,17 +3568,28 @@ msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, default: gcc_unreachable (); } - return ""; + return 0; } if (code == ASHIFT) { if (!msp430x && mode == HImode) - for (i = 0; i < amt; i++) - output_asm_insn ("RLA.W\t%0", operands); + { + if (return_length) + length = 2 + (MEM_P (operands[0]) ? 2 : 0); + else + for (i = 0; i < amt; i++) + output_asm_insn ("RLA.W\t%0", operands); + } else if (mode == SImode) - for (i = 0; i < amt; i++) - output_asm_insn ("RLA%X0.W\t%L0 { RLC%X0.W\t%H0", operands); + { + if (return_length) + length = 4 + (MEM_P (operands[0]) ? 4 : 0) + + (4 * msp430x_insn_required (operands[0])); + else + for (i = 0; i < amt; i++) + output_asm_insn ("RLA%X0.W\t%L0 { RLC%X0.W\t%H0", operands); + } else /* Catch unhandled cases. */ gcc_unreachable (); @@ -3582,33 +3597,61 @@ msp430_output_asm_shift_insns (enum rtx_code code, machine_mode mode, else if (code == ASHIFTRT) { if (!msp430x && mode == HImode) - for (i = 0; i < amt; i++) - output_asm_insn ("RRA.W\t%0", operands); + { + if (return_length) + length = 2 + (MEM_P (operands[0]) ? 2 : 0); + else + for (i = 0; i < amt; i++) + output_asm_insn ("RRA.W\t%0", operands); + } else if (mode == SImode) - for (i = 0; i < amt; i++) - output_asm_insn ("RRA%X0.W\t%H0 { RRC%X0.W\t%L0", operands); + { + if (return_length) + length = 4 + (MEM_P (operands[0]) ? 4 : 0) + + (4 * msp430x_insn_required (operands[0])); + else + for (i = 0; i < amt; i++) + output_asm_insn ("RRA%X0.W\t%H0 { RRC%X0.W\t%L0", operands); + } else gcc_unreachable (); } else if (code == LSHIFTRT) { if (!msp430x && mode == HImode) - for (i = 0; i < amt; i++) - output_asm_insn ("CLRC { RRC.W\t%0", operands); + { + if (return_length) + length = 4 + (MEM_P (operands[0]) ? 2 : 0); + else + for (i = 0; i < amt; i++) + output_asm_insn ("CLRC { RRC.W\t%0", operands); + } else if (mode == SImode) - for (i = 0; i < amt; i++) - output_asm_insn ("CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0", operands); + { + if (return_length) + length = 6 + (MEM_P (operands[0]) ? 4 : 0) + + (4 * msp430x_insn_required (operands[0])); + else + for (i = 0; i < amt; i++) + output_asm_insn ("CLRC { RRC%X0.W\t%H0 { RRC%X0.W\t%L0", + operands); + } /* FIXME: Why doesn't "RRUX.W\t%H0 { RRC%X0.W\t%L0" work for msp430x? It causes execution timeouts e.g. pr41963.c. */ #if 0 else if (msp430x && mode == SImode) - for (i = 0; i < amt; i++) - output_asm_insn ("RRUX.W\t%H0 { RRC%X0.W\t%L0", operands); + { + if (return_length) + length = 2; + else + for (i = 0; i < amt; i++) + output_asm_insn ("RRUX.W\t%H0 { RRC%X0.W\t%L0", operands); + } #endif else gcc_unreachable (); } - return ""; + return length * amt; } /* Called by cbranch4 to coerce operands into usable forms. */ @@ -4130,6 +4173,20 @@ msp430_op_not_in_high_mem (rtx op) return false; } +/* Based on the operand OP, is a 430X insn required to handle it? + There are only 3 conditions for which a 430X insn is required: + - PSImode operand + - memory reference to a symbol which could be in upper memory + (so its address is > 0xFFFF) + - absolute address which has VOIDmode, i.e. (mem:HI (const_int)) + Use a 430 insn if none of these conditions are true. */ +bool +msp430x_insn_required (rtx op) +{ + return (GET_MODE (op) == PSImode + || !msp430_op_not_in_high_mem (op)); +} + #undef TARGET_PRINT_OPERAND #define TARGET_PRINT_OPERAND msp430_print_operand @@ -4462,35 +4519,52 @@ msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED, /* Generate a sequence of instructions to sign-extend an HI value into an SI value. Handles the tricky case where - we are overwriting the destination. */ - -const char * -msp430x_extendhisi (rtx * operands) + we are overwriting the destination. + Return the number of bytes used by the emitted instructions. + If RETURN_LENGTH is true then do not emit the assembly instruction + sequence. */ +int +msp430x_extendhisi (rtx * operands, bool return_length) { if (REGNO (operands[0]) == REGNO (operands[1])) - /* Low word of dest == source word. 8-byte sequence. */ - return "BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0"; - - if (! msp430x) - /* Note: This sequence is approximately the same length as invoking a helper - function to perform the sign-extension, as in: - - MOV.W %1, %L0 - MOV.W %1, r12 - CALL __mspabi_srai_15 - MOV.W r12, %H0 - - but this version does not involve any function calls or using argument - registers, so it reduces register pressure. 10-byte sequence. */ - return "MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 " - "{ INV.W\t%H0, %H0"; - - if (REGNO (operands[0]) + 1 == REGNO (operands[1])) - /* High word of dest == source word. 6-byte sequence. */ - return "MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0"; + { + /* Low word of dest == source word. */ + if (!return_length) + output_asm_insn ("BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0", + operands); + return 8; + } + else if (! msp430x) + { + /* Note: This sequence is approximately the same length as invoking a + helper function to perform the sign-extension, as in: + + MOV.W %1, %L0 + MOV.W %1, r12 + CALL __mspabi_srai_15 + MOV.W r12, %H0 + + but this version does not involve any function calls or using argument + registers, so it reduces register pressure. */ + if (!return_length) + output_asm_insn ("MOV.W\t%1, %L0 { BIT.W\t#0x8000, %L0 { SUBC.W\t%H0, %H0 { INV.W\t%H0, %H0", + operands); + return 10; + } + else if (REGNO (operands[0]) + 1 == REGNO (operands[1])) + { + /* High word of dest == source word. */ + if (!return_length) + output_asm_insn ("MOV.W\t%1, %L0 { RPT\t#15 { RRAX.W\t%H0", + operands); + return 6; + } - /* No overlap between dest and source. 8-byte sequence. */ - return "MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0"; + /* No overlap between dest and source. */ + if (!return_length) + output_asm_insn ("MOV.W\t%1, %L0 { MOV.W\t%1, %H0 { RPT\t#15 { RRAX.W\t%H0", + operands); + return 8; } /* Stop GCC from thinking that it can eliminate (SUBREG:PSI (SI)). */ diff --git a/gcc/config/msp430/msp430.h b/gcc/config/msp430/msp430.h index fd48549f5c2..b813e825311 100644 --- a/gcc/config/msp430/msp430.h +++ b/gcc/config/msp430/msp430.h @@ -532,3 +532,13 @@ void msp430_register_pre_includes (const char *sysroot ATTRIBUTE_UNUSED, #define SYMBOL_FLAG_LOW_MEM (SYMBOL_FLAG_MACH_DEP << 0) + +#define ADJUST_INSN_LENGTH(insn, length) \ + do \ + { \ + if (recog_memoized (insn) >= 0) \ + { \ + length += get_attr_extra_length (insn); \ + length *= get_attr_length_multiplier (insn); \ + } \ + } while (0) diff --git a/gcc/config/msp430/msp430.md b/gcc/config/msp430/msp430.md index f70e61b97dd..68e1a66dbb1 100644 --- a/gcc/config/msp430/msp430.md +++ b/gcc/config/msp430/msp430.md @@ -58,8 +58,100 @@ (define_c_enum "unspec" UNS_DELAY_END ]) -;; This is an approximation. -(define_attr "length" "" (const_int 4)) +;; Instruction length is calculated by examining the type and number of +;; operands. +;; Whether the insn uses the 430X extension word, or is a 430X address +;; instruction also has an effect. +;; "Cheap" source operands do not contribute to the overall length of the insn +;; and are register (Rn), indirect post-increment (@Rn+) and indirect register +;; (@Rn). +;; The lengths of instructions in bytes are: +;; Single-op 430: Cheap op == 2 +;; (also CALLA) Other op == 4 +;; Double-op 430: Source is not cheap == 2 +;; (also MOVA, Dest is register == 2 +;; CMPA, ADDA, Dest is not a register == 4 +;; SUBA) (sum the source and dest cost) +;; Single-op 430X: For insn names ending in 'X' add 2 to single-op 430 cost. +;; Double-op 430X: Insn name ends in 'M' == 2 +;; Others have the same cost as double-op 430 but add 2. +;; +;; The insn type describes whether it is a single or double operand MSP430 +;; instruction (some single-operand GCC instructions are actually +;; double-operand on the target). +;; "triple" and "cmp" types use the costs of a double operand type but +;; instead assume that the src operand is in op2, and also cmp types assume the +;; dst operand is in op1. +;; This attribute also describes which operands are safe to examine +;; when calculating the length or extension. GCC will segfault trying to +;; examine a non-existant operand of an insn. +(define_attr "type" "none,single,double,triple,cmp" (const_string "none")) + +;; The M extension is for instructions like RRAM - they always +;; only, and the operand must be a register. +(define_attr "extension" "none,x,a,m" + (cond [(eq_attr "type" "none") + (const_string "none") + (match_operand 0 "msp430_high_memory_operand" "") + (const_string "x") + (and (eq_attr "type" "double") + (match_operand 1 "msp430_high_memory_operand" "")) + (const_string "x") + (and (ior (eq_attr "type" "triple") (eq_attr "type" "cmp")) + (ior (match_operand 1 "msp430_high_memory_operand" "") + (match_operand 2 "msp430_high_memory_operand" ""))) + (const_string "x")] + (const_string "none"))) + +;; Multiply the default length by this constant value. +(define_attr "length_multiplier" "" (const_int 1)) + +;; Add an additional amount to the total length of the insn. +(define_attr "extra_length" "" (const_int 0)) + +;; FIXME for some reason if we move the addition of 2 for extension == x to +;; ADJUST_INSN_LENGTH, codesize gets much worse. +(define_attr "length" "" + (cond [(eq_attr "extension" "m") + (const_int 2) + (eq_attr "type" "single") + (plus (if_then_else (match_operand 0 "msp430_cheap_operand" "") + (const_int 2) + (const_int 4)) + (if_then_else (eq_attr "extension" "x") + (const_int 2) + (const_int 0))) + (eq_attr "type" "double") + (plus (plus (if_then_else (match_operand 0 "register_operand" "") + (const_int 2) + (const_int 4)) + (if_then_else (match_operand 1 "msp430_cheap_operand" "") + (const_int 0) + (const_int 2))) + (if_then_else (eq_attr "extension" "x") + (const_int 2) + (const_int 0))) + (eq_attr "type" "triple") + (plus (plus (if_then_else (match_operand 0 "register_operand" "") + (const_int 2) + (const_int 4)) + (if_then_else (match_operand 2 "msp430_cheap_operand" "") + (const_int 0) + (const_int 2))) + (if_then_else (eq_attr "extension" "x") + (const_int 2) + (const_int 0))) + (eq_attr "type" "cmp") + (plus (plus (if_then_else (match_operand 1 "register_operand" "") + (const_int 2) + (const_int 4)) + (if_then_else (match_operand 2 "msp430_cheap_operand" "") + (const_int 0) + (const_int 2))) + (if_then_else (eq_attr "extension" "x") + (const_int 2) + (const_int 0)))] + (const_int 2))) (include "predicates.md") (include "constraints.md") @@ -97,35 +189,43 @@ (define_insn "push" (match_operand:HI 0 "register_operand" "r"))] "" "PUSH\t%0" - ) + [(set_attr "type" "single")] +) (define_insn "pusha" [(set (mem:PSI (pre_dec:PSI (reg:PSI SP_REGNO))) (match_operand:PSI 0 "register_operand" "r"))] "TARGET_LARGE" "PUSHX.A\t%0" - ) + [(set_attr "type" "single") + (set_attr "extension" "x")] +) (define_insn "pushm" [(unspec_volatile [(match_operand 0 "register_operand" "r") (match_operand 1 "immediate_operand" "n")] UNS_PUSHM)] "" "PUSHM%b0\t%1, %0" - ) + [(set_attr "type" "single") + (set_attr "extension" "m")] +) (define_insn "pop" [(set (match_operand:HI 0 "register_operand" "=r") (mem:HI (post_inc:HI (reg:HI SP_REGNO))))] "" "POP\t%0" - ) + [(set_attr "type" "single")] +) (define_insn "popa" [(set (match_operand:PSI 0 "register_operand" "=r") (mem:PSI (post_inc:PSI (reg:PSI SP_REGNO))))] "TARGET_LARGE" "POPX.A\t%0" - ) + [(set_attr "type" "single") + (set_attr "extension" "x")] +) ;; This is nasty. Operand0 is bogus. It is only there so that we can get a ;; mode for the %b0 to work. We should use operand1 for this, but that does @@ -144,7 +244,9 @@ (define_insn "popm" (match_operand 2 "immediate_operand" "i")] UNS_POPM)] "" "POPM%b0\t%2, r%J1" - ) + [(set_attr "type" "single") + (set_attr "extension" "m")] +) ;; The next two patterns are here to support a "feature" of how GCC implements ;; varargs. When a function uses varargs and the *second* to last named @@ -170,6 +272,10 @@ (define_insn "grow_and_swap" return \"SUBA\t#2, r1 { MOVX.A\t2(r1), 0(r1)\"; return \"SUB\t#2, r1 { MOV.W\t2(r1), 0(r1)\"; " + [(set (attr "length") + (if_then_else (match_test "TARGET_LARGE") + (const_int 8) + (const_int 6)))] ) (define_insn "swap_and_shrink" @@ -178,7 +284,12 @@ (define_insn "swap_and_shrink" "* return TARGET_LARGE ? \"MOVX.A\t0(r1), 2(r1) { ADDA\t#2, SP\" : \"MOV.W\t0(r1), 2(r1) { ADD\t#2, SP\"; - ") + " + [(set (attr "length") + (if_then_else (match_test "TARGET_LARGE") + (const_int 10) + (const_int 8)))] +) ; I set LOAD_EXTEND_OP and WORD_REGISTER_OPERATIONS, but gcc puts in a ; zero_extend anyway. Catch it here. @@ -189,6 +300,7 @@ (define_insn "movqihi" "@ MOV.B\t%1, %0 MOV%X1.B\t%1, %0" + [(set_attr "type" "double")] ) (define_insn "movqi_topbyte" @@ -196,6 +308,8 @@ (define_insn "movqi_topbyte" (subreg:QI (match_operand:PSI 1 "msp430_general_operand" "r") 2))] "msp430x" "PUSHM.A\t#1,%1 { POPM.W\t#1,%0 { POPM.W\t#1,%0" + [(set_attr "length" "6") + (set_attr "type" "double")] ) (define_insn "movqi" @@ -205,6 +319,7 @@ (define_insn "movqi" "@ MOV.B\t%1, %0 MOVX.B\t%1, %0" + [(set_attr "type" "double")] ) (define_insn "movhi" @@ -215,6 +330,7 @@ (define_insn "movhi" MOV.B\t%1, %0 MOV.W\t%1, %0 MOVX.W\t%1, %0" + [(set_attr "type" "double")] ) (define_expand "movsi" @@ -222,7 +338,7 @@ (define_expand "movsi" (match_operand:SI 1 "general_operand"))] "" "" - ) +) (define_insn_and_split "movsi_s" [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") @@ -235,7 +351,8 @@ (define_insn_and_split "movsi_s" (set (match_operand:HI 3 "msp430_general_dst_nonv_operand") (match_operand:HI 5 "general_operand"))] "msp430_split_movsi (operands);" - ) + [(set_attr "type" "double")] +) (define_insn_and_split "movsi_x" [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=rm") @@ -248,6 +365,7 @@ (define_insn_and_split "movsi_x" (set (match_operand:HI 3 "msp430_general_dst_nonv_operand") (match_operand:HI 5 "general_operand"))] "msp430_split_movsi (operands);" + [(set_attr "type" "double")] ) ;; FIXME: Some MOVX.A cases can be done with MOVA, this is only a few of them. @@ -260,7 +378,10 @@ (define_insn "movpsi" MOV.W\t%1, %0 MOVA\t%1, %0 MOVA\t%1, %0 - MOVX.A\t%1, %0") + MOVX.A\t%1, %0" + [(set_attr "extension" "none,none,a,a,x") + (set_attr "type" "double")] +) ; This pattern is identical to the truncsipsi2 pattern except ; that it uses a SUBREG instead of a TRUNC. It is needed in @@ -274,6 +395,8 @@ (define_insn "movsipsi2" (subreg:PSI (match_operand:SI 1 "register_operand" "r") 0))] "msp430x" "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A #1, %0 ; Move reg-pair %L1:%H1 into pointer %0" + [(set_attr "length" "6") + (set_attr "type" "double")] ) ;; Produced when converting a pointer to an integer via a union, eg gcc.dg/pr47201.c. @@ -282,6 +405,8 @@ (define_insn "*movpsihi2_lo" (subreg:HI (match_operand:PSI 1 "msp430_symbol_operand" "i") 0))] "msp430x" "MOVA\t%1, %0" + [(set_attr "extension" "a") + (set_attr "type" "double")] ) ;;------------------------------------------------------------ @@ -295,6 +420,8 @@ (define_insn "addpsi3" "@ ADDA\t%2, %0 ADDX.A\t%2, %0" + [(set_attr "extension" "a,x") + (set_attr "type" "triple")] ) (define_insn "addqi3" @@ -305,6 +432,7 @@ (define_insn "addqi3" "@ ADD.B\t%2, %0 ADDX.B\t%2, %0" + [(set_attr "type" "triple")] ) (define_insn "addhi3" @@ -315,6 +443,7 @@ (define_insn "addhi3" "@ ADD.W\t%2, %0 ADDX.W\t%2, %0" + [(set_attr "type" "triple")] ) ; This pattern is needed in order to avoid reload problems. @@ -327,6 +456,13 @@ (define_insn "addsipsi3" (match_operand 2 "general_operand" "rmi")))] "" "ADD%X2.W\t%L2, %L0 { ADDC%X2.W\t%H2, %H0 { PUSH.W\t%H0 { PUSH.W\t%L0 { POPM.A\t#1, %0" + [(set (attr "length") + (if_then_else (match_operand 2 "register_operand" "") + (const_int 10) + (if_then_else (match_operand 2 "msp430_high_memory_operand" "") + (const_int 18) + (const_int 14)))) + (set_attr "type" "triple")] ) (define_insn "addsi3" @@ -337,6 +473,8 @@ (define_insn "addsi3" "@ ADD\t%L2, %L0 { ADDC\t%H2, %H0 ADDX\t%L2, %L0 { ADDCX\t%H2, %H0" + [(set_attr "length_multiplier" "2") + (set_attr "type" "triple")] ) ; Version of addhi that exposes the carry operations, for SImode adds. @@ -382,7 +520,8 @@ (define_insn "addhi3_cy" "@ ADD\t%2, %1 ; cy ADDX\t%2, %1 ; cy" - ) + [(set_attr "type" "triple")] +) (define_insn "addhi3_cy_i" [(set (match_operand:HI 0 "msp430_general_dst_nonv_operand" "=r,rm") @@ -397,7 +536,8 @@ (define_insn "addhi3_cy_i" "@ ADD\t%2, %1 ; cy ADD%X0\t%2, %1 ; cy" - ) + [(set_attr "type" "triple")] +) ; Version of addhi that adds the carry, for SImode adds. (define_insn "addchi4_cy" @@ -410,7 +550,8 @@ (define_insn "addchi4_cy" "@ ADDC\t%2, %1 ADDCX\t%2, %1" - ) + [(set_attr "type" "triple")] +) ; Split an SImode add into two HImode adds, keeping track of the carry ; so that gcc knows when it can and can't optimize away the two @@ -440,7 +581,7 @@ (define_split if (msp430_split_addsi (operands)) FAIL; " - ) +) ;; Alternatives 2 and 3 are to handle cases generated by reload. @@ -454,6 +595,9 @@ (define_insn "subpsi3" SUBX.A\t%2, %0 MOVX.A\t%1, %0 { SUBX.A\t%2, %0 MOVX.A\t%1, %0 { SUBA\t%2, %0" + [(set_attr "type" "triple") + (set_attr "extension" "a,x,x,x") + (set_attr "length_multiplier" "1,1,2,2")] ) ;; Alternatives 2 and 3 are to handle cases generated by reload. @@ -467,6 +611,8 @@ (define_insn "subqi3" SUBX.B\t%2, %0 MOV%X2.B\t%1, %0 { SUB%X2.B\t%2, %0 MOV%X0.B\t%1, %0 { SUB%X0.B\t%2, %0" + [(set_attr "length_multiplier" "1,1,2,2") + (set_attr "type" "triple")] ) ;; Alternatives 2 and 3 are to handle cases generated by reload. @@ -480,6 +626,8 @@ (define_insn "subhi3" SUBX.W\t%2, %0 MOV%X2.W\t%1, %0 { SUB%X2.W\t%2, %0 MOV%X0.W\t%1, %0 { SUB%X0.W\t%2, %0" + [(set_attr "length_multiplier" "1,1,2,2") + (set_attr "type" "triple")] ) (define_insn "subsi3" @@ -490,6 +638,8 @@ (define_insn "subsi3" "@ SUB\t%L2, %L0 { SUBC\t%H2, %H0 SUBX\t%L2, %L0 { SUBCX\t%H2, %H0" + [(set_attr "length_multiplier" "2") + (set_attr "type" "triple")] ) (define_insn "*bic_cg" @@ -500,6 +650,8 @@ (define_insn "*bic_cg" "@ BIC%x0%b0\t#%I2, %0 BIC%X0%b0\t#%I2, %0" + [(set_attr "length" "2") ; Smaller length achieved by using constant generator + (set_attr "type" "double")] ) (define_insn "bic3" @@ -510,6 +662,7 @@ (define_insn "bic3" "@ BIC%x0%b0\t%1, %0 BICX%b0\t%1, %0" + [(set_attr "type" "double")] ) (define_insn "and3" @@ -521,6 +674,7 @@ (define_insn "and3" AND%x0.B\t%2, %0 AND%x0%b0\t%2, %0 ANDX%b0\t%2, %0" + [(set_attr "type" "triple")] ) (define_insn "ior3" @@ -531,6 +685,7 @@ (define_insn "ior3" "@ BIS%x0%b0\t%2, %0 BISX%b0\t%2, %0" + [(set_attr "type" "triple")] ) (define_insn "xor3" @@ -541,6 +696,7 @@ (define_insn "xor3" "@ XOR%x0%b0\t%2, %0 XORX%b0\t%2, %0" + [(set_attr "type" "triple")] ) ;; Macro : XOR #~0, %0 @@ -551,6 +707,7 @@ (define_insn "one_cmpl2" "@ INV%x0%b0\t%0 INV%X0%b0\t%0" + [(set_attr "type" "double")] ) (define_insn "extendqihi2" @@ -560,6 +717,7 @@ (define_insn "extendqihi2" "@ SXT%X0\t%0 SXT%X0\t%0" + [(set_attr "type" "single")] ) (define_insn "extendqipsi2" @@ -569,6 +727,8 @@ (define_insn "extendqipsi2" "@ SXT\t%0 SXTX.A\t%0" + [(set_attr "type" "single") + (set_attr "extension" "none,x")] ) ;; ------------------------ @@ -590,6 +750,7 @@ (define_insn "zero_extendqihi2" MOV.B\t%1, %0 MOV%X1.B\t%1, %0 AND%X0\t#0xff, %0" + [(set_attr "type" "double")] ) (define_insn "zero_extendqipsi2" @@ -599,6 +760,7 @@ (define_insn "zero_extendqipsi2" "@ MOV.B\t%1, %0 MOV%X1.B\t%1, %0" + [(set_attr "type" "double")] ) (define_insn "zero_extendqisi2" @@ -608,6 +770,9 @@ (define_insn "zero_extendqisi2" "@ CLR\t%H0 MOV%X1.B\t%1,%L0 { CLR\t%H0" + [(set_attr "extra_length" "2") + (set_attr "length_multiplier" "1,2") + (set_attr "type" "double")] ) (define_insn "zero_extendhipsi2" @@ -618,6 +783,7 @@ (define_insn "zero_extendhipsi2" MOV.W\t%1, %0 MOV%X1\t%1, %0 MOVX.A\t%1, %0" + [(set_attr "type" "double")] ) (define_insn "zero_extendhisi2" @@ -627,6 +793,8 @@ (define_insn "zero_extendhisi2" "@ MOV%X0.W\t#0,%H0 MOV.W\t%1,%L0 { MOV.W\t#0,%H0" + [(set_attr "length_multiplier" "1,2") + (set_attr "type" "double")] ) (define_insn "zero_extendhisipsi2" @@ -636,6 +804,8 @@ (define_insn "zero_extendhisipsi2" "@ AND.W\t#-1,%0 MOV.W\t%1,%0" + [(set_attr "length" "4,2") + (set_attr "type" "double")] ) ; Nasty - we are sign-extending a 20-bit PSI value in one register into @@ -671,6 +841,13 @@ (define_insn "zero_extendpsisi2" else \ return \"PUSHM.A\t#1, %1 { POPX.W\t%L0 { POPX.W\t%H0 ; move pointer in %1 into reg-pair %L0:%H0\"; MOVX.A %1, %0" + [(set (attr "length") + (cond [(match_test "REGNO (operands[1]) == SP_REGNO") + (const_int 18) + (eq_attr "alternative" "1") + (const_int 6)] + (const_int 10))) + (set_attr "type" "double")] ) ;; Below are unnamed insn patterns to catch pointer manipulation insns @@ -687,6 +864,7 @@ (define_insn "" (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0)))] "msp430x" "MOV%X1.B\t%1, %0" + [(set_attr "type" "double")] ) (define_insn "" @@ -696,6 +874,7 @@ (define_insn "" "@ MOV.B\t%1, %0 MOV%X1.B\t%1, %0" + [(set_attr "type" "double")] ) ;; The next three insns emit identical assembly code. @@ -711,6 +890,9 @@ (define_insn "" RLAM.W %2, %L0 { CLR %H0 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" + [(set_attr "length" "4,*,*") + (set_attr "extra_length" "0,4,6") + (set_attr "type" "double")] ) (define_insn "" @@ -722,6 +904,9 @@ (define_insn "" RLAM.W %2, %L0 { CLR %H0 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" + [(set_attr "length" "4,*,*") + (set_attr "extra_length" "0,4,6") + (set_attr "type" "double")] ) ;; Same as above but with a NOP sign_extend round the subreg @@ -734,6 +919,9 @@ (define_insn "" RLAM.W %2, %L0 { CLR %H0 MOV%X1.B %1, %L0 { RLAM.W %2, %L0 { CLR %H0 MOV%X1.B %1, %L0 { RPT %2 { RLAX.W %L0 { CLR %H0" + [(set_attr "length" "4,*,*") + (set_attr "extra_length" "0,4,6") + (set_attr "type" "double")] ) (define_insn "" @@ -741,6 +929,8 @@ (define_insn "" (zero_extend:SI (sign_extend:PSI (subreg:HI (match_operand:QI 1 "general_operand" "rm") 0))))] "msp430x" "MOV%X1.B %1, %L0 { CLR %H0" + [(set_attr "extra_length" "4") + (set_attr "type" "double")] ) (define_insn "" @@ -752,6 +942,9 @@ (define_insn "" RLAM.W %2, %0 MOV%X1.B %1, %0 { RLAM.W %2, %0 MOV%X1.B %1, %0 { RPT %2 { RLAX.A %0" + [(set_attr "length" "2,*,*") + (set_attr "extra_length" "0,2,4") + (set_attr "type" "double")] ) ;; END msp430 pointer manipulation combine insn patterns @@ -771,13 +964,18 @@ (define_insn "truncpsihi2" (truncate:HI (match_operand:PSI 1 "register_operand" "r")))] "" "MOVX\t%1, %0" + [(set_attr "extension" "m") + (set_attr "type" "double")] ) (define_insn "extendhisi2" [(set (match_operand:SI 0 "msp430_general_dst_nonv_operand" "=r") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))] "" - { return msp430x_extendhisi (operands); } + { msp430x_extendhisi (operands, 0); return ""; } + [(set (attr "length") + (symbol_ref "msp430x_extendhisi (operands, 1)")) + (set_attr "type" "double")] ) (define_insn "extendhipsi2" @@ -785,6 +983,9 @@ (define_insn "extendhipsi2" (subreg:PSI (sign_extend:SI (match_operand:HI 1 "general_operand" "0")) 0))] "msp430x" "RLAM.A #4, %0 { RRAM.A #4, %0" + [(set_attr "length_multiplier" "2") + (set_attr "extension" "m") + (set_attr "type" "double")] ) ;; Look for cases where integer/pointer conversions are suboptimal due @@ -798,6 +999,9 @@ (define_insn "extend_and_shift1_hipsi2" (const_int 1)))] "msp430x" "RLAM.A #4, %0 { RRAM.A #3, %0" + [(set_attr "length_multiplier" "2") + (set_attr "extension" "m") + (set_attr "type" "double")] ) (define_insn "extend_and_shift2_hipsi2" @@ -806,6 +1010,9 @@ (define_insn "extend_and_shift2_hipsi2" (const_int 2)))] "msp430x" "RLAM.A #4, %0 { RRAM.A #2, %0" + [(set_attr "length_multiplier" "2") + (set_attr "extension" "m") + (set_attr "type" "double")] ) ;; We also need to be able to sign-extend pointer types (eg ptrdiff_t). @@ -827,6 +1034,8 @@ (define_insn "extendpsisi2" else return \"MOV.W\t%1, %L0 { MOVX.A\t%1, %H0 { RPT\t#16 { RRAX.A\t%H0 ; sign extend pointer in %1 into %L0:%H0\"; " + [(set_attr "length" "10") + (set_attr "type" "double")] ) ; See the movsipsi2 pattern above for another way that GCC performs this @@ -836,6 +1045,8 @@ (define_insn "truncsipsi2" (truncate:PSI (match_operand:SI 1 "register_operand" "r")))] "" "PUSH.W\t%H1 { PUSH.W\t%L1 { POPM.A\t#1, %L0" + [(set_attr "length" "6") + (set_attr "type" "single")] ) ;;------------------------------------------------------------ @@ -886,7 +1097,10 @@ (define_insn "hi3_430" (any_shift:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "const_int_operand" "n")))] "!msp430x" - "* return msp430_output_asm_shift_insns (, HImode, operands);" + "* msp430_output_asm_shift_insns (, HImode, operands, false); return \"\";" + [(set (attr "length") + (symbol_ref "msp430_output_asm_shift_insns (, HImode, operands, true)")) + (set_attr "type" "single")] ) ;; All 430 and 430X SImode constant shifts @@ -895,7 +1109,10 @@ (define_insn "si3_const" (any_shift:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "const_int_operand" "n")))] "" - "* return msp430_output_asm_shift_insns (, SImode, operands);" + "* msp430_output_asm_shift_insns (, SImode, operands, false); return \"\";" + [(set (attr "length") + (symbol_ref "msp430_output_asm_shift_insns (, SImode, operands, true)")) + (set_attr "type" "single")] ) (define_insn "ashl3_430x" @@ -908,6 +1125,8 @@ (define_insn "ashl3_430x" RPT\t%2 { RLAX%b0\t%0 RPT\t#16 { RLAX%b0\t%0 { RPT\t%W2 { RLAX%b0\t%0 # undefined behavior left shift of %1 by %2" + [(set_attr "length" "2,4,8,0") + (set_attr "type" "single")] ) (define_insn "ashr3_430x" @@ -920,6 +1139,8 @@ (define_insn "ashr3_430x" RPT\t%2 { RRAX%b0\t%0 RPT\t#16 { RRAX%b0\t%0 { RPT\t%W2 { RRAX%b0\t%0 # undefined behavior arithmetic right shift of %1 by %2" + [(set_attr "length" "2,4,8,0") + (set_attr "type" "single")] ) (define_insn "lshr3_430x" @@ -932,6 +1153,8 @@ (define_insn "lshr3_430x" RPT\t%2 { RRUX%b0\t%0 RPT\t#16 { RRUX%b0\t%0 { RPT\t%W2 { RRUX%b0\t%0 # undefined behavior logical right shift of %1 by %2" + [(set_attr "length" "2,4,8,0") + (set_attr "type" "single")] ) ;;------------------------------------------------------------ @@ -941,39 +1164,43 @@ (define_expand "prologue" [(const_int 0)] "" "msp430_expand_prologue (); DONE;" - ) +) (define_expand "epilogue" [(const_int 0)] "" "msp430_expand_epilogue (0); DONE;" - ) +) (define_insn "epilogue_helper" [(set (pc) - (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)) + (unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_EPILOGUE_HELPER)) (return)] - "" + "!msp430x" "BR%Q0\t#__mspabi_func_epilog_%J0" - ) + [(set_attr "length" "2")] +) (define_insn "prologue_start_marker" [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_START_MARKER)] "" "; start of prologue" - ) + [(set_attr "length" "0")] +) (define_insn "prologue_end_marker" [(unspec_volatile [(const_int 0)] UNS_PROLOGUE_END_MARKER)] "" "; end of prologue" - ) + [(set_attr "length" "0")] +) (define_insn "epilogue_start_marker" [(unspec_volatile [(const_int 0)] UNS_EPILOGUE_START_MARKER)] "" "; start of epilogue" - ) + [(set_attr "length" "0")] +) ;; This makes the linker add a call to exit() after the call to main() ;; in crt0 @@ -981,7 +1208,8 @@ (define_insn "msp430_refsym_need_exit" [(unspec_volatile [(const_int 0)] UNS_REFSYM_NEED_EXIT)] "" ".refsym\t__crt0_call_exit" - ) + [(set_attr "length" "0")] +) ;;------------------------------------------------------------ ;; Jumps @@ -998,6 +1226,8 @@ (define_insn "call_internal" (match_operand 1 ""))] "" "CALL%Q0\t%0" + [(set_attr "extension" "none") + (set_attr "type" "single")] ) (define_expand "call_value" @@ -1014,12 +1244,15 @@ (define_insn "call_value_internal" (match_operand 2 "")))] "" "CALL%Q0\t%1" + [(set_attr "extension" "none") + (set_attr "type" "single")] ) (define_insn "msp430_return" [(return)] "" { return msp430_is_interrupt_func () ? "RETI" : (TARGET_LARGE ? "RETA" : "RET"); } + [(set_attr "length" "2")] ) ;; This pattern is NOT, as expected, a return pattern. It's called @@ -1045,13 +1278,15 @@ (define_insn_and_split "msp430_eh_epilogue" "reload_completed" [(const_int 0)] "msp430_expand_epilogue (1); DONE;" - ) + [(set_attr "length" "40")] +) (define_insn "jump" [(set (pc) (label_ref (match_operand 0 "" "")))] "" "BR%Q0\t#%l0" + [(set_attr "length" "4")] ) ;; FIXME: GCC currently (8/feb/2013) cannot handle symbol_refs @@ -1061,6 +1296,10 @@ (define_insn "indirect_jump" (match_operand 0 "nonimmediate_operand" "rYl"))] "" "BR%Q0\t%0" + [(set (attr "length") + (if_then_else (match_operand 0 "register_operand" "") + (const_int 2) + (const_int 4)))] ) ;;------------------------------------------------------------ @@ -1077,14 +1316,14 @@ (define_expand "cbranch4" )] "" "msp430_fixup_compare_operands (mode, operands);" - ) +) (define_insn "cbranchpsi4_real" [(set (pc) (if_then_else (match_operator 0 "msp430_cmp_operator" [(match_operand:PSI 1 "msp430_general_dst_nonv_operand" "r,rYs,rm") (match_operand:PSI 2 "general_operand" "rLs,rYsi,rmi")]) - (label_ref (match_operand 3 "" "")) + (label_ref (match_operand 3 "" "")) (pc))) (clobber (reg:BI CARRY)) ] @@ -1093,7 +1332,9 @@ (define_insn "cbranchpsi4_real" CMP%Q0\t%2, %1 { J%0\t%l3 CMPX.A\t%2, %1 { J%0\t%l3 CMPX.A\t%2, %1 { J%0\t%l3" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "cmp")] +) (define_insn "cbranchqi4_real" [(set (pc) (if_then_else @@ -1108,7 +1349,9 @@ (define_insn "cbranchqi4_real" "@ CMP.B\t%2, %1 { J%0\t%l3 CMPX.B\t%2, %1 { J%0\t%l3" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "cmp")] +) (define_insn "cbranchhi4_real" [(set (pc) (if_then_else @@ -1123,6 +1366,8 @@ (define_insn "cbranchhi4_real" "@ CMP.W\t%2, %1 { J%0\t%l3 CMPX.W\t%2, %1 { J%0\t%l3" + [(set_attr "extra_length" "2") + (set_attr "type" "cmp")] ) (define_insn "cbranchpsi4_reversed" @@ -1139,7 +1384,9 @@ (define_insn "cbranchpsi4_reversed" CMP%Q0\t%1, %2 { J%R0\t%l3 CMPX.A\t%1, %2 { J%R0\t%l3 CMPX.A\t%1, %2 { J%R0\t%l3" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "cmp")] +) (define_insn "cbranchqi4_reversed" [(set (pc) (if_then_else @@ -1154,7 +1401,9 @@ (define_insn "cbranchqi4_reversed" "@ CMP.B\t%1, %2 { J%R0\t%l3 CMPX.B\t%1, %2 { J%R0\t%l3" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "cmp")] +) (define_insn "cbranchhi4_reversed" [(set (pc) (if_then_else @@ -1169,14 +1418,16 @@ (define_insn "cbranchhi4_reversed" "@ CMP.W\t%1, %2 { J%R0\t%l3 CMPX.W\t%1, %2 { J%R0\t%l3" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "cmp")] +) (define_insn "*bitbranch4" [(set (pc) (if_then_else (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) (const_int 0)) - (label_ref (match_operand 2 "" "")) + (label_ref (match_operand 2 "" "")) (pc))) (clobber (reg:BI CARRY)) ] @@ -1184,14 +1435,16 @@ (define_insn "*bitbranch4" "@ BIT%x0%b0\t%1, %0 { JNE\t%l2 BITX%b0\t%1, %0 { JNE\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) (define_insn "*bitbranch4" [(set (pc) (if_then_else (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) (const_int 0)) - (label_ref (match_operand 2 "" "")) + (label_ref (match_operand 2 "" "")) (pc))) (clobber (reg:BI CARRY)) ] @@ -1199,14 +1452,16 @@ (define_insn "*bitbranch4" "@ BIT%x0%b0\t%1, %0 { JEQ\t%l2 BITX%b0\t%1, %0 { JEQ\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) (define_insn "*bitbranch4" [(set (pc) (if_then_else (eq (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) (const_int 0)) - (pc) + (pc) (label_ref (match_operand 2 "" "")))) (clobber (reg:BI CARRY)) ] @@ -1214,14 +1469,16 @@ (define_insn "*bitbranch4" "@ BIT%x0%b0\t%1, %0 { JNE\t%l2 BITX%b0\t%1, %0 { JNE\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) (define_insn "*bitbranch4" [(set (pc) (if_then_else (ne (and:QHI (match_operand:QHI 0 "msp430_general_dst_operand" "rYsYx,rm") (match_operand:QHI 1 "msp430_general_operand" "rYsYxi,rmi")) (const_int 0)) - (pc) + (pc) (label_ref (match_operand 2 "" "")))) (clobber (reg:BI CARRY)) ] @@ -1229,7 +1486,9 @@ (define_insn "*bitbranch4" "@ BIT%x0%b0\t%1, %0 { JEQ\t%l2 BITX%b0\t%1, %0 { JEQ\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) ;;------------------------------------------------------------ ;; zero-extract versions of the above @@ -1240,7 +1499,7 @@ (define_insn "*bitbranch4_z" (const_int 1) (match_operand 1 "const_0_to_15_operand" "i,i")) (const_int 0)) - (label_ref (match_operand 2 "" "")) + (label_ref (match_operand 2 "" "")) (pc))) (clobber (reg:BI CARRY)) ] @@ -1248,7 +1507,9 @@ (define_insn "*bitbranch4_z" "@ BIT%x0%b0\t%p1, %0 { JNE\t%l2 BIT%X0%b0\t%p1, %0 { JNE\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) (define_insn "*bitbranch4_z" [(set (pc) (if_then_else @@ -1256,13 +1517,15 @@ (define_insn "*bitbranch4_z" (const_int 1) (match_operand 1 "const_0_to_15_operand" "i")) (const_int 0)) - (label_ref (match_operand 2 "" "")) + (label_ref (match_operand 2 "" "")) (pc))) (clobber (reg:BI CARRY)) ] "" "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) (define_insn "*bitbranch4_z" [(set (pc) (if_then_else @@ -1270,13 +1533,15 @@ (define_insn "*bitbranch4_z" (const_int 1) (match_operand 1 "const_0_to_15_operand" "i")) (const_int 0)) - (pc) + (pc) (label_ref (match_operand 2 "" "")))) (clobber (reg:BI CARRY)) ] "" "BIT%X0%b0\t%p1, %0 { JNE\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) (define_insn "*bitbranch4_z" [(set (pc) (if_then_else @@ -1284,13 +1549,15 @@ (define_insn "*bitbranch4_z" (const_int 1) (match_operand 1 "const_0_to_15_operand" "i")) (const_int 0)) - (pc) + (pc) (label_ref (match_operand 2 "" "")))) (clobber (reg:BI CARRY)) ] "" "BIT%X0%b0\t%p1, %0 { JEQ\t%l2" - ) + [(set_attr "extra_length" "2") + (set_attr "type" "double")] +) ;;------------------------------------------------------------ ;; Misc @@ -1299,31 +1566,36 @@ (define_insn "nop" [(const_int 0)] "1" "NOP" + [(set_attr "length" "2")] ) (define_insn "disable_interrupts" [(unspec_volatile [(const_int 0)] UNS_DINT)] "" "DINT \; NOP" - ) + [(set_attr "length" "2")] +) (define_insn "enable_interrupts" [(unspec_volatile [(const_int 0)] UNS_EINT)] "" "EINT" - ) + [(set_attr "length" "2")] +) (define_insn "push_intr_state" [(unspec_volatile [(const_int 0)] UNS_PUSH_INTR)] "" "PUSH\tSR" - ) + [(set_attr "length" "2")] +) (define_insn "pop_intr_state" [(unspec_volatile [(const_int 0)] UNS_POP_INTR)] "" "POP\tSR" - ) + [(set_attr "length" "2")] +) ;; Clear bits in the copy of the status register that is currently ;; saved on the stack at the top of the interrupt handler. @@ -1331,7 +1603,9 @@ (define_insn "bic_SR" [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIC_SR)] "" "BIC.W\t%0, %O0(SP)" - ) + [(set_attr "type" "single") + (set_attr "extra_length" "2")] +) ;; Set bits in the copy of the status register that is currently ;; saved on the stack at the top of the interrupt handler. @@ -1339,37 +1613,40 @@ (define_insn "bis_SR" [(unspec_volatile [(match_operand 0 "nonmemory_operand" "ir")] UNS_BIS_SR)] "" "BIS.W\t%0, %O0(SP)" - ) + [(set_attr "type" "single") + (set_attr "extra_length" "2")] +) ;; For some reason GCC is generating (set (reg) (and (neg (reg)) (int))) ;; very late on in the compilation and not splitting it into separate ;; instructions, so we provide a pattern to support it here. (define_insn "andneghi3" - [(set (match_operand:HI 0 "register_operand" "=r") - (and:HI (neg:HI (match_operand:HI 1 "register_operand" "r")) - (match_operand 2 "immediate_operand" "n")))] + [(set (match_operand:HI 0 "register_operand" "=r,r") + (and:HI (neg:HI (match_operand:HI 1 "register_operand" "0,r")) + (match_operand 2 "immediate_operand" "n,n")))] "" - "* - if (REGNO (operands[0]) != REGNO (operands[1])) - return \"MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\"; - else - return \"INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0\"; - " - ) + "@ + INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0 + MOV.W\t%1, %0 { INV.W\t%0 { INC.W\t%0 { AND.W\t%2, %0" + [(set_attr "length" "12,14") + (set_attr "type" "double")] +) (define_insn "delay_cycles_start" [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_DELAY_START)] "" "; Begin %J0 cycle delay" - ) + [(set_attr "length" "0")] +) (define_insn "delay_cycles_end" [(unspec_volatile [(match_operand 0 "immediate_operand" "i")] UNS_DELAY_END)] "" "; End %J0 cycle delay" - ) + [(set_attr "length" "0")] +) (define_insn "delay_cycles_32" [(unspec_volatile [(match_operand 0 "immediate_operand" "i") @@ -1387,7 +1664,8 @@ (define_insn "delay_cycles_32" JNE 1b POP r14 POP r13" - ) + [(set_attr "length" "32")] +) (define_insn "delay_cycles_32x" [(unspec_volatile [(match_operand 0 "immediate_operand" "i") @@ -1403,7 +1681,8 @@ (define_insn "delay_cycles_32x" TST.W r13 JNE 1b POPM.A #2,r14" - ) + [(set_attr "length" "28")] +) (define_insn "delay_cycles_16" [(unspec_volatile [(match_operand 0 "immediate_operand" "i") @@ -1415,7 +1694,8 @@ (define_insn "delay_cycles_16" 1: SUB.W #1, r13 JNE 1b POP r13" - ) + [(set_attr "length" "14")] +) (define_insn "delay_cycles_16x" [(unspec_volatile [(match_operand 0 "immediate_operand" "i") @@ -1427,19 +1707,22 @@ (define_insn "delay_cycles_16x" 1: SUB.W #1, r13 JNE 1b POPM.A #1,r13" - ) + [(set_attr "length" "14")] +) (define_insn "delay_cycles_2" [(unspec_volatile [(const_int 0) ] UNS_DELAY_2)] "" "JMP .+2" - ) + [(set_attr "length" "2")] +) (define_insn "delay_cycles_1" [(unspec_volatile [(const_int 0) ] UNS_DELAY_1)] "" "NOP" - ) + [(set_attr "length" "2")] +) ; libgcc helper functions for widening multiplication aren't currently ; generated by gcc, so we can't catch them later and map them to the mspabi @@ -1494,6 +1777,7 @@ (define_insn "*mulhisi3_inline" else return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0132 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\"; " + [(set_attr "length" "24")] ) (define_insn "*umulhisi3_inline" @@ -1507,6 +1791,7 @@ (define_insn "*umulhisi3_inline" else return \"PUSH.W sr { DINT { NOP { MOV.W %1, &0x0130 { MOV.W %2, &0x0138 { MOV.W &0x013A, %L0 { MOV.W &0x013C, %H0 { POP.W sr\"; " + [(set_attr "length" "24")] ) (define_insn "mulsidi3" @@ -1520,6 +1805,7 @@ (define_insn "mulsidi3" else return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0144 { MOV.W %H1, &0x0146 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\"; " + [(set_attr "length" "40")] ) (define_insn "umulsidi3" @@ -1533,4 +1819,5 @@ (define_insn "umulsidi3" else return \"PUSH.W sr { DINT { NOP { MOV.W %L1, &0x0140 { MOV.W %H1, &0x0142 { MOV.W %L2, &0x0150 { MOV.W %H2, &0x0152 { MOV.W &0x0154, %A0 { MOV.W &0x0156, %B0 { MOV.W &0x0158, %C0 { MOV.W &0x015A, %D0 { POP.W sr\"; " + [(set_attr "length" "40")] ) diff --git a/gcc/config/msp430/predicates.md b/gcc/config/msp430/predicates.md index 4bfa0c0f2d5..eb1f61df780 100644 --- a/gcc/config/msp430/predicates.md +++ b/gcc/config/msp430/predicates.md @@ -131,3 +131,16 @@ (define_predicate "const_1_to_19_operand" (define_predicate "msp430_symbol_operand" (match_code "symbol_ref") ) + +; Used in length attribute tests - if a source operand is a reg, +; (mem (post_inc)), or (mem (reg)) then it is cheap compared to other operand +; types. +(define_predicate "msp430_cheap_operand" + (ior (match_code "reg") + (and (match_code "mem") + (ior (match_code "reg" "0") + (match_code "post_inc" "0"))))) + +; Used for insn attributes only. For insn patterns themselves, use constraints. +(define_predicate "msp430_high_memory_operand" + (match_test "msp430x_insn_required (op)")) From patchwork Thu Jul 23 15:56:14 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jozef Lawrynowicz X-Patchwork-Id: 1334963 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mittosystems.com header.i=@mittosystems.com header.a=rsa-sha256 header.s=google header.b=RItbECJ2; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BCH415Ssnz9sRR for ; Fri, 24 Jul 2020 01:55:45 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id A173B3850437; Thu, 23 Jul 2020 15:55:42 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x435.google.com (mail-wr1-x435.google.com [IPv6:2a00:1450:4864:20::435]) by sourceware.org (Postfix) with ESMTPS id 999F13850422 for ; Thu, 23 Jul 2020 15:55:39 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 999F13850422 Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wr1-x435.google.com with SMTP id r12so5626111wrj.13 for ; Thu, 23 Jul 2020 08:55:39 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=8dA5JznZXM07JexgrlLHtXVtKqnpl992I/FCY5OInZU=; b=RItbECJ2NzgRZY3IC7vk5ZgtGtZ3f1o3T5ulPd89/SwiVDQu7JKimKUffoVNIG3EN5 nS1hB/xOrIVGZKwTYG0hK780pXr5pWcbXE9Rs4xQL7GLHFE4r+GSAUqWpX0vnD68hqza yMfAm0Sn0SMBeu1U22D9URqP4UZtV0MO70J+HmDYJQfR/Qdc9qYMP3ISvFZM+LqrLk6T C9euzZxM88wulIOa+8ZVwpI0Dnq+Swc0updBXO1j7uQRBF7MKu/aOZoi4gHHlIl+odOp f7IQTK7bANPPqyB9zRu/fgN1wrt6dlCx9nI28glz8WkztW8IY4nlazgqufpW3fZSId5B TfbQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to; bh=8dA5JznZXM07JexgrlLHtXVtKqnpl992I/FCY5OInZU=; b=IE3k/9JMTeIDmad59u1vkorp9jDIWAUZvSshNu9TvwVShG86IQXKVEFBaClONxB/Ni NkSgpwk65fcvsE4A9cbV1RtJHpbSax40Na2VsGR4t/ph4UeJcaev0iSCVb0RfxT9Wp7K 6pPyruVGy36r3vOsD0D8oSttYR4/EuYEImUTiJVQp5CN7+ZJG70DMrUOQIghqoQVhoA2 YtwYfCYUetkb0930VB5q+53XySwMQXC7Vqbo3T23AxLrkVoUbDA5dB+fbcGOV9zBJ9+X 5fu2NCBI2yzB99fQ9HZ1PfcW1VBxrDtNpHQbHsF+Kl/S4pl76GlT35kv0fQuvzaE96V5 pAig== X-Gm-Message-State: AOAM531kQd4tY5GCKxk/Z45+LFEmQYQ34ExGMua5BdUFrlcSd4LCVKzu KbyBnD+chDbGm8E7v5/o2EgoMmwmsJ8= X-Google-Smtp-Source: ABdhPJyjHKZmLUHHXiy1vFAuasb3IiikUJ3BNQfOeRKl/yzZ1gbn3lCAMQgNnA8Is6yNxImL6uCgZw== X-Received: by 2002:a5d:4746:: with SMTP id o6mr4977294wrs.410.1595519738391; Thu, 23 Jul 2020 08:55:38 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id o30sm4526134wra.67.2020.07.23.08.55.37 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:55:37 -0700 (PDT) Date: Thu, 23 Jul 2020 16:56:14 +0100 From: Jozef Lawrynowicz To: gcc-patches@gcc.gnu.org Subject: [PATCH 4/5] MSP430: Implement TARGET_INSN_COST Message-ID: <20200723155614.jqjgkqtdrnwjahxo@jozef-acer-manjaro> Mail-Followup-To: gcc-patches@gcc.gnu.org References: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" The length of an insn can be used to calculate its cost, when optimizing for size. When optimizing for speed, this is a good estimate, since the cycle cost of an MSP430 instruction increases with its length. From e4c5f9c3f567489f89b41a0d96e321acb5d18152 Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 16 Jul 2020 11:34:50 +0100 Subject: [PATCH 4/5] MSP430: Implement TARGET_INSN_COST The length of an insn can be used to calculate its cost, when optimizing for size. When optimizing for speed, this is a good estimate, since the cycle cost of an MSP430 instruction increases with its length. gcc/ChangeLog: * config/msp430/msp430.c (TARGET_INSN_COST): Define. (msp430_insn_cost): New function. * config/msp430/msp430.opt: Add -mdebug-insn-costs option. gcc/testsuite/ChangeLog: * gcc.target/msp430/rtx-cost-O3-default.c: New test. * gcc.target/msp430/rtx-cost-O3-f5series.c: New test. * gcc.target/msp430/rtx-cost-Os-default.c: New test. * gcc.target/msp430/rtx-cost-Os-f5series.c: New test. --- gcc/config/msp430/msp430.c | 29 +++++++++++++ gcc/config/msp430/msp430.opt | 4 ++ .../gcc.target/msp430/rtx-cost-O3-default.c | 42 ++++++++++++++++++ .../gcc.target/msp430/rtx-cost-O3-f5series.c | 38 ++++++++++++++++ .../gcc.target/msp430/rtx-cost-Os-default.c | 43 +++++++++++++++++++ .../gcc.target/msp430/rtx-cost-Os-f5series.c | 38 ++++++++++++++++ 6 files changed, 194 insertions(+) create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c create mode 100644 gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c diff --git a/gcc/config/msp430/msp430.c b/gcc/config/msp430/msp430.c index b7daafcc11a..7ef651fb324 100644 --- a/gcc/config/msp430/msp430.c +++ b/gcc/config/msp430/msp430.c @@ -1711,6 +1711,35 @@ msp430_rtx_costs (rtx x, return false; } } + +#undef TARGET_INSN_COST +#define TARGET_INSN_COST msp430_insn_cost + +static int +msp430_insn_cost (rtx_insn *insn, bool speed ATTRIBUTE_UNUSED) +{ + int cost; + + if (recog_memoized (insn) < 0) + return 0; + + cost = get_attr_length (insn); + if (TARGET_DEBUG_INSN_COSTS) + { + fprintf (stderr, "cost %d for insn:\n", cost); + debug_rtx (insn); + } + + /* The returned cost must be relative to COSTS_N_INSNS (1). An insn with a + length of 2 bytes is the smallest possible size and so must be equivalent + to COSTS_N_INSNS (1). */ + return COSTS_N_INSNS (cost) / (2 * COSTS_N_INSNS (1)); + + /* FIXME Add more detailed costs when optimizing for speed. + For now the length of the instruction is a good approximiation and roughly + correlates with cycle cost. */ +} + /* Function Entry and Exit */ diff --git a/gcc/config/msp430/msp430.opt b/gcc/config/msp430/msp430.opt index 8134ca7ac95..448c41aa81c 100644 --- a/gcc/config/msp430/msp430.opt +++ b/gcc/config/msp430/msp430.opt @@ -115,3 +115,7 @@ Target RejectNegative Joined UInteger IntegerRange(0,65) Var(msp430_max_inline_s For shift operations by a constant amount, which require an individual instruction to shift by one position, set the maximum number of inline shift instructions (maximum value 64) to emit instead of using the corresponding __mspabi helper function. The default value is 4. + +mdebug-insn-costs +Target Report Mask(DEBUG_INSN_COSTS) +Print insns and their costs as calculated by TARGET_INSN_COSTS. diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c new file mode 100644 index 00000000000..1bd6a142002 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-default.c @@ -0,0 +1,42 @@ +/* { dg-do compile } */ +/* { dg-options "-O3" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* Verify the MSP430 cost model is working as expected for the default ISA + (msp430x) and hwmult (none), when compiling at -O3. */ + +char arr[2]; +char a; +char *ptr; + +/* +** foo: +** ... +** MOV.B \&a, \&arr\+1 +** MOV.* #arr\+2, \&ptr +** ... +*/ + +void +foo (void) +{ + arr[1] = a; + ptr = arr + 2; +} + +extern void ext (void); + +/* +** bar: +** ... +** CALL.* #ext +** CALL.* #ext +** ... +*/ + +void +bar (void) +{ + ext (); + ext (); +} diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c new file mode 100644 index 00000000000..1e48625f2e5 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-O3-f5series.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-O3 -mhwmult=f5series" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* Verify the MSP430 cost model is working as expected for the default ISA + (msp430x) and f5series hwmult, when compiling at -O3. */ + +volatile unsigned long a; +volatile unsigned int b; +volatile unsigned long c; +unsigned long res1; +unsigned long res2; +unsigned long res3; + +/* +** foo: +** ... +** MOV.B #16, R14 +** CALL.* #__mspabi_slll +** ... +** MOV.* \&res2.* +** ... +** RLA.*RLC.* +** ... +** MOV.* \&res3.* +** ... +** RLA.*RLC.* +** ... +*/ +void foo (void) +{ + /* Use the shift library function for this. */ + res1 = (a << 16) | b; + /* Emit 7 inline shifts for this. */ + res2 *= 128; + /* Perform this multiplication inline, using addition and shifts. */ + res3 *= 100; +} diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c new file mode 100644 index 00000000000..8f3d1b28049 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-default.c @@ -0,0 +1,43 @@ +/* { dg-do compile } */ +/* { dg-options "-Os" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* Verify the MSP430 cost model is working as expected for the default ISA + (msp430x) and hwmult (none), when compiling at -Os. */ + +char arr[2]; +char a; +char *ptr; + +/* +** foo: +** ... +** MOV.B \&a, \&arr\+1 +** MOV.* #arr\+2, \&ptr +** ... +*/ + +void +foo (void) +{ + arr[1] = a; + ptr = arr + 2; +} + +extern void ext (void); + +/* +** bar: +** ... +** MOV.* #ext, R10 +** CALL.* R10 +** CALL.* R10 +** ... +*/ + +void +bar (void) +{ + ext (); + ext (); +} diff --git a/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c new file mode 100644 index 00000000000..bb37f9083d9 --- /dev/null +++ b/gcc/testsuite/gcc.target/msp430/rtx-cost-Os-f5series.c @@ -0,0 +1,38 @@ +/* { dg-do compile } */ +/* { dg-options "-Os -mhwmult=f5series" } */ +/* { dg-final { check-function-bodies "**" "" } } */ + +/* Verify the MSP430 cost model is working as expected for the default ISA + (msp430x) and f5series hwmult, when compiling at -Os. */ + +volatile unsigned long a; +volatile unsigned int b; +volatile unsigned long c; +unsigned long res1; +unsigned long res2; +unsigned long res3; + +/* +** foo: +** ... +** MOV.B #16, R14 +** CALL.* #__mspabi_slll +** ... +** MOV.B #7, R14 +** CALL.* #__mspabi_slll +** ... +** MOV.B #100, R14 +** MOV.B #0, R15 +** ... +** CALL.* #__mulsi2_f5 +** ... +*/ +void foo (void) +{ + /* Use the shift library function for this. */ + res1 = (a << 16) | b; + /* Likewise. */ + res2 *= 128; + /* Use the hardware multiply library function for this. */ + res3 *= 100; +} From patchwork Thu Jul 23 15:57:09 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jozef Lawrynowicz X-Patchwork-Id: 1334964 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: ozlabs.org; dkim=pass (2048-bit key; unprotected) header.d=mittosystems.com header.i=@mittosystems.com header.a=rsa-sha256 header.s=google header.b=nE+DFvyH; dkim-atps=neutral Received: from sourceware.org (server2.sourceware.org [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4BCH534x5Sz9sPf for ; Fri, 24 Jul 2020 01:56:39 +1000 (AEST) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 00511388C033; Thu, 23 Jul 2020 15:56:37 +0000 (GMT) X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from mail-wr1-x433.google.com (mail-wr1-x433.google.com [IPv6:2a00:1450:4864:20::433]) by sourceware.org (Postfix) with ESMTPS id 1BF40388C01A for ; Thu, 23 Jul 2020 15:56:35 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org 1BF40388C01A Authentication-Results: sourceware.org; dmarc=none (p=none dis=none) header.from=mittosystems.com Authentication-Results: sourceware.org; spf=pass smtp.mailfrom=jozef.l@mittosystems.com Received: by mail-wr1-x433.google.com with SMTP id r4so2702946wrx.9 for ; Thu, 23 Jul 2020 08:56:35 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=mittosystems.com; s=google; h=date:from:to:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to; bh=3EKhPe6eWVTAku4F4I+h8TulPr9gqbjY1+5XKH+zeS0=; b=nE+DFvyHH2LYnWTz3HONb4btcdIgOIcvasJX65MeX65+13FWnZAcg57Sxli3dgmw8q BjPTHLfXZrc4l/E49a3J76gpYoIxtCP9nRXTkwrZYhS4Cd3IxOxjEIGNYAXBPDGdatBd gYgKD8SYSdK6gSHrlqtCXIorTIzqejnqGf21EBv9jBwGXRhZgvXiUbC4CYPJhJ7+Jj0c IRmfF60+Pa4/OXHnvS/W1MiyWuYmwLNT3E8oKcAvPMCqlYvfJDZX8ozIJKAv+D6czXXo KVMfbZpH7SE6pBNYoyhBHHHB3xSzyLdotAlAbKtL+H47lL7cHJ083Hh5YNEFMG3Tut2K 4r+Q== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:subject:message-id:mail-followup-to :references:mime-version:content-disposition:in-reply-to; bh=3EKhPe6eWVTAku4F4I+h8TulPr9gqbjY1+5XKH+zeS0=; b=F/t4Rxlom9is8HWxSblQBjM73YtIFzUogSP09OkHBoVOLnPl3ufu15fT55XEDhxvkT 8BpncrKkMq6wEv7fHtMvEo3feCKPy6ykMui4G9rCYaQyxakDFkXZ09DzxFiiHRBSSY+Q 0gBXcqxtZ3qVvxRwtD7d/ePQK+ptIyOa+dwvXtaJoXQ9qwpjCVB1wt13FoR1rSM12vTA t7x2z3EZY7UJTungkXRUkTtq4fnrj+VzGWFyZXcInfTe8GgMxe3KFODnp8A1+iNrXWF+ RkHY/aiQg5awjBOpnWyzvnPRZ4NFgCB3jr6zE68e6NC1RTqN2v5578qhEYZu7mX/hltX nrhg== X-Gm-Message-State: AOAM533IeRCp21NUmlhjivAtgI4JIzsKTLVuVHpvzhnbZvl+TYY7ir+5 rXXo51Ozs21P0qEObAM81fLlVerXkGw= X-Google-Smtp-Source: ABdhPJwGEqXgk9ul1eXDi5qYKCjXFLDj5LqEvAmS/dEz3O1O2e9VifJBNAZ93goFl8k/xSux2zlN1w== X-Received: by 2002:a5d:4407:: with SMTP id z7mr4546751wrq.404.1595519794029; Thu, 23 Jul 2020 08:56:34 -0700 (PDT) Received: from jozef-acer-manjaro ([2a01:4b00:87fd:900:5e1d:5c99:56da:76e8]) by smtp.gmail.com with ESMTPSA id l15sm4162471wro.33.2020.07.23.08.56.33 for (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 23 Jul 2020 08:56:33 -0700 (PDT) Date: Thu, 23 Jul 2020 16:57:09 +0100 From: Jozef Lawrynowicz To: gcc-patches@gcc.gnu.org Subject: [PATCH 5/5] MSP430: Skip index-1.c test Message-ID: <20200723155709.djdmun6uuoxkdjzu@jozef-acer-manjaro> Mail-Followup-To: gcc-patches@gcc.gnu.org References: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20200723154356.63ws2xairlmdufji@jozef-acer-manjaro> X-Spam-Status: No, score=-11.0 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, 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: , Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" To access the "n - 100000"th element of "a" in this test, GCC will generate the following code for msp430-elf with -mcpu=msp430x: RLAM.W #1, R12 MOV.W a-3392(R12), R12 Since there aren't actually 100,000 elements in a, this means that "a-3392" offset calculated by the linker can overflow, as the address of "a" can validly be less than 3392. The relocations used for -mcpu=msp430 and -mlarge are not as strict and the calculated value is allowed to wrap around the address space, avoiding relocation overflows. From bfafc633013952c1a5cac2dbb10b774f66be920e Mon Sep 17 00:00:00 2001 From: Jozef Lawrynowicz Date: Thu, 16 Jul 2020 11:35:25 +0100 Subject: [PATCH 5/5] MSP430: Skip index-1.c test To access the "n - 100000"th element of "a" in this test, GCC will generate the following code for msp430-elf with -mcpu=msp430x: RLAM.W #1, R12 MOV.W a-3392(R12), R12 Since there aren't actually 100,000 elements in a, this means that "a-3392" offset calculated by the linker can overflow, as the address of "a" can validly be less than 3392. The relocations used for -mcpu=msp430 and -mlarge are not as strict and the calculated value is allowed to wrap around the address space, avoiding relocation overflows. gcc/testsuite/ChangeLog: * gcc.c-torture/execute/index-1.c: Skip for the default MSP430 430X ISA. --- gcc/testsuite/gcc.c-torture/execute/index-1.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gcc/testsuite/gcc.c-torture/execute/index-1.c b/gcc/testsuite/gcc.c-torture/execute/index-1.c index b00090d834a..d96be4c77b8 100644 --- a/gcc/testsuite/gcc.c-torture/execute/index-1.c +++ b/gcc/testsuite/gcc.c-torture/execute/index-1.c @@ -1,3 +1,5 @@ +/* { dg-skip-if "strict reloc overflow checking" { msp430-*-* } { "*" } { "-mcpu=msp430" "-mlarge"} } */ + int a[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,