From patchwork Thu Dec 17 08:17:52 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Thomas Preudhomme X-Patchwork-Id: 558076 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from sourceware.org (server1.sourceware.org [209.132.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 7E933140213 for ; Thu, 17 Dec 2015 19:18:13 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.b=Pw7h0t1I; dkim-atps=neutral DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; q=dns; s=default; b=VWKcOFkT1qRPxKRr Ud4hhF8tIaBEMtE+KgVz0f+vvi0u0Vbn5Du6f+b4wo+RieTRDVe4+9wYJUcDMing XAMcYhXf4PC6oX9lv07VsRR9jtbrR6mGg2ba7aEdiaLEhDBpUGrffcN6w3+YLfXR aHI5aWRJvhRnqArUnNrm8ZAPg7k= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender:from :to:subject:date:message-id:mime-version:content-type :content-transfer-encoding; s=default; bh=FZuR3qIN0lETSYfBlIsZ+0 iVooY=; b=Pw7h0t1IejmSVhivPgCWIrzGodJ/W1oh0iSMtNbW34wPL+9dgqlARd enK37hqNVnpEAzS6UbwYsxmUFNq/Bfi0Xwjy9XMU8kMENEiNAS0tWGTItHrOYzwI h+ytypK0Z62BiDctKd2Gxi8kBERGQiTbNkVG6nKiAh55JswQfzEd8= Received: (qmail 12675 invoked by alias); 17 Dec 2015 08:18:04 -0000 Mailing-List: contact gcc-patches-help@gcc.gnu.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Archive: List-Post: List-Help: Sender: gcc-patches-owner@gcc.gnu.org Delivered-To: mailing list gcc-patches@gcc.gnu.org Received: (qmail 12661 invoked by uid 89); 17 Dec 2015 08:18:03 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=2.1 required=5.0 tests=AWL, BAYES_50, KAM_LAZY_DOMAIN_SECURITY, T_RP_MATCHES_RCVD autolearn=no version=3.3.2 spammy=chip, libma, libnosysa, UD:crtn.o X-HELO: foss.arm.com Received: from foss.arm.com (HELO foss.arm.com) (217.140.101.70) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 17 Dec 2015 08:18:02 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 520664BF; Thu, 17 Dec 2015 00:17:36 -0800 (PST) Received: from SHAWIN202 (unknown [10.164.12.31]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id EE1013F21A; Thu, 17 Dec 2015 00:17:54 -0800 (PST) From: "Thomas Preud'homme" To: , "Richard Earnshaw" , "Ramana Radhakrishnan" , "Kyrylo Tkachov" Subject: [PATCH, ARM 6/6] Add support for CB(N)Z and (U|S)DIV to ARMv8-M Baseline Date: Thu, 17 Dec 2015 16:17:52 +0800 Message-ID: <004601d138a3$6e832c10$4b898430$@foss.arm.com> MIME-Version: 1.0 Hi, This patch is part of a patch series to add support for ARMv8-M[1] to GCC. This specific patch makes the compiler start generating code with the new CB(N)Z and (U|S)DIV instructions for ARMv8-M Baseline. Sharing of instruction patterns for div insn template with ARM or Thumb-2 was done by allowing %? punctuation character for Thumb-1. This is safe to do since the compiler would fault in arm_print_condition if a condition code is not handled by a branch in Thumb1. Unfortunately, cbz cannot be shared with cbranchsi4 because it would lead to worse code for Thumb-1. Indeed, choosing cb(n)z over the other alternatives for cbranchsi4 depends on the distance between target and pc which lead insn-attrtab to evaluate the minimum length of this pattern to be 2 as it cannot computer the distance statically. It would be possible to determine that this alternative is not available for non ARMv8-M Thumb-1 target statically but genattrtab is not currently capable to do it, so this is for a later patch. [1] For a quick overview of ARMv8-M please refer to the initial cover letter. ChangeLog entry is as follows: *** gcc/ChangeLog *** 2015-11-13 Thomas Preud'homme * config/arm/arm.c (arm_print_operand_punct_valid_p): Make %? valid for Thumb-1. * config/arm/arm.h (TARGET_HAVE_CBZ): Define. (TARGET_IDIV): Set for all Thumb targets provided they have hardware divide feature. * config/arm/thumb1.md (thumb1_cbz): New insn. Testing: * Toolchain was built successfully with and without the ARMv8-M support patches with the following multilib list: armv6-m,armv7-m,armv7e-m,cortex-m7. The code generation for crtbegin.o, crtend.o, crti.o, crtn.o, libgcc.a, libgcov.a, libc.a, libg.a, libgloss-linux.a, libm.a, libnosys.a, librdimon.a, librdpmon.a, libstdc++.a and libsupc++.a is unchanged for all these targets. * GCC also showed no testsuite regression when targeting ARMv8-M Baseline compared to ARMv6-M on ARM Fast Models and when targeting ARMv6-M and ARMv7-M (compared to without the patch) * GCC was bootstrapped successfully targeting Thumb-1 and targeting Thumb-2 Is this ok for stage3? Best regards, Thomas diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index 015df50..247f144 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -263,9 +263,12 @@ extern void (*arm_lang_output_object_attributes_hook)(void); /* Nonzero if this chip provides the movw and movt instructions. */ #define TARGET_HAVE_MOVT (arm_arch_thumb2 || arm_arch8) +/* Nonzero if this chip provides the cb{n}z instruction. */ +#define TARGET_HAVE_CBZ (arm_arch_thumb2 || arm_arch8) + /* Nonzero if integer division instructions supported. */ #define TARGET_IDIV ((TARGET_ARM && arm_arch_arm_hwdiv) \ - || (TARGET_THUMB2 && arm_arch_thumb_hwdiv)) + || (TARGET_THUMB && arm_arch_thumb_hwdiv)) /* Nonzero if disallow volatile memory access in IT block. */ #define TARGET_NO_VOLATILE_CE (arm_arch_no_volatile_ce) diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index d832309..5ef3a1d 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -22568,7 +22568,7 @@ arm_print_operand_punct_valid_p (unsigned char code) { return (code == '@' || code == '|' || code == '.' || code == '(' || code == ')' || code == '#' - || (TARGET_32BIT && (code == '?')) + || code == '?' || (TARGET_THUMB2 && (code == '!')) || (TARGET_THUMB && (code == '_'))); } diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md index 7e3bcb4..074b267 100644 --- a/gcc/config/arm/thumb1.md +++ b/gcc/config/arm/thumb1.md @@ -973,6 +973,92 @@ DONE; }) +;; A pattern for the cb(n)z instruction added in ARMv8-M baseline profile, +;; adapted from cbranchsi4_insn. Modifying cbranchsi4_insn instead leads to +;; code generation difference for ARMv6-M because the minimum length of the +;; instruction becomes 2 even for it due to a limitation in genattrtab's +;; handling of pc in the length condition. +(define_insn "thumb1_cbz" + [(set (pc) (if_then_else + (match_operator 0 "equality_operator" + [(match_operand:SI 1 "s_register_operand" "l") + (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc)))] + "TARGET_THUMB1 && TARGET_HAVE_MOVT" +{ + if (get_attr_length (insn) == 2) + { + if (GET_CODE (operands[0]) == EQ) + return "cbz\t%1, %l2"; + else + return "cbnz\t%1, %l2"; + } + else + { + rtx t = cfun->machine->thumb1_cc_insn; + if (t != NULL_RTX) + { + if (!rtx_equal_p (cfun->machine->thumb1_cc_op0, operands[1]) + || !rtx_equal_p (cfun->machine->thumb1_cc_op1, operands[2])) + t = NULL_RTX; + if (cfun->machine->thumb1_cc_mode == CC_NOOVmode) + { + if (!noov_comparison_operator (operands[0], VOIDmode)) + t = NULL_RTX; + } + else if (cfun->machine->thumb1_cc_mode != CCmode) + t = NULL_RTX; + } + if (t == NULL_RTX) + { + output_asm_insn ("cmp\t%1, #0", operands); + cfun->machine->thumb1_cc_insn = insn; + cfun->machine->thumb1_cc_op0 = operands[1]; + cfun->machine->thumb1_cc_op1 = operands[2]; + cfun->machine->thumb1_cc_mode = CCmode; + } + else + /* Ensure we emit the right type of condition code on the jump. */ + XEXP (operands[0], 0) = gen_rtx_REG (cfun->machine->thumb1_cc_mode, + CC_REGNUM); + + switch (get_attr_length (insn)) + { + case 4: return "b%d0\t%l2"; + case 6: return "b%D0\t.LCB%=;b\t%l2\t%@long jump\n.LCB%=:"; + case 8: return "b%D0\t.LCB%=;bl\t%l2\t%@far jump\n.LCB%=:"; + default: gcc_unreachable (); + } + } +} + [(set (attr "far_jump") + (if_then_else + (eq_attr "length" "8") + (const_string "yes") + (const_string "no"))) + (set (attr "length") + (if_then_else + (and (ge (minus (match_dup 2) (pc)) (const_int 2)) + (le (minus (match_dup 2) (pc)) (const_int 128)) + (not (match_test "which_alternative"))) + (const_int 2) + (if_then_else + (and (ge (minus (match_dup 2) (pc)) (const_int -250)) + (le (minus (match_dup 2) (pc)) (const_int 256))) + (const_int 4) + (if_then_else + (and (ge (minus (match_dup 2) (pc)) (const_int -2040)) + (le (minus (match_dup 2) (pc)) (const_int 2048))) + (const_int 6) + (const_int 8))))) + (set (attr "type") + (if_then_else + (eq_attr "length" "2") + (const_string "branch") + (const_string "multiple")))] +) + (define_insn "cbranchsi4_insn" [(set (pc) (if_then_else (match_operator 0 "arm_comparison_operator"