From patchwork Wed May 15 11:50:33 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ramana Radhakrishnan X-Patchwork-Id: 244050 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 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (Client CN "localhost", Issuer "www.qmailtoaster.com" (not verified)) by ozlabs.org (Postfix) with ESMTPS id 153642C00A5 for ; Wed, 15 May 2013 21:50:46 +1000 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; q= dns; s=default; b=sOlv0Ehm0lUlyBIR7MmVtaZsfxgG+NCaByidqSAAXwIERl IuTMSeDFXzreQkomoiKpkoMp8QHzEh2AaGheuFC8LDj627xY9/GM5DX6pmx2YhEg NtDb+4lHThDQLXyukTT6LYfv7n3HLaRdCnNKIufKxqNKpwXIGjgs9dnntxHH0= DKIM-Signature: v=1; a=rsa-sha1; c=relaxed; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :message-id:date:from:mime-version:to:subject:content-type; s= default; bh=IQgQGEGJoe1eX8GZUVucucJPMrk=; b=gn5EobdD326MPhfYtDKg 6/YNGZe+f/1q7NlBN2EPhEmWpqCnrOc4bC4wolF6kMC2w5TpqcasFiroGP0UiTVH HEB/MWM8EAkLnADIKxT5XR6ot1/HMr6dHJhuJgyvi6nygOKBmZ8yKd3UIlgx/gsv qAwogS5/TiQUsl3axAcLU6E= Received: (qmail 24826 invoked by alias); 15 May 2013 11:50:41 -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 24810 invoked by uid 89); 15 May 2013 11:50:40 -0000 X-Spam-SWARE-Status: No, score=-2.3 required=5.0 tests=AWL, BAYES_00, KAM_STOCKGEN, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.1 Received: from service87.mimecast.com (HELO service87.mimecast.com) (91.220.42.44) by sourceware.org (qpsmtpd/0.84/v0.84-167-ge50287c) with ESMTP; Wed, 15 May 2013 11:50:38 +0000 Received: from cam-owa1.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Wed, 15 May 2013 12:50:36 +0100 Received: from [10.1.209.152] ([10.1.255.212]) by cam-owa1.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.0); Wed, 15 May 2013 12:50:33 +0100 Message-ID: <51937689.6030101@arm.com> Date: Wed, 15 May 2013 12:50:33 +0100 From: Ramana Radhakrishnan User-Agent: Mozilla/5.0 (X11; Linux i686 on x86_64; rv:14.0) Gecko/20120713 Thunderbird/14.0 MIME-Version: 1.0 To: "gcc-patches@gcc.gnu.org ;" Subject: [Patch ARM] Fix PR target/19599 X-MC-Unique: 113051512503600501 X-Virus-Found: No Hi, Atlast a fix for this PR which has been on my plate for ages. I've chosen to create a new class for all caller save registers rather than just sticking to maybe a single temporary register as IP_REGNUM on the grounds that this means we have more registers to choose from - we need another constraint or a special indirect sibcall pattern anyway. In any case keeping a call clobbered core registers class might be useful in other areas so it's simple enough to add this. Bootstrapped and regression tested on A15 Linux ARM state. Applied to trunk. regards Ramana 2013-05-15 Ramana Radhakrishnan PR target/19599 * config/arm/predicates.md (call_insn_operand): New predicate. * config/arm/constraints.md ("Cs", "Ss"): New constraints. * config/arm/arm.md (*call_insn, *call_value_insn): Match only if insn is not a tail call. (*sibcall_insn, *sibcall_value_insn): Adjust for tailcalling through registers. * config/arm/arm.h (enum reg_class): New caller save register class. (REG_CLASS_NAMES): Likewise. (REG_CLASS_CONTENTS): Likewise. * config/arm/arm.c (arm_function_ok_for_sibcall): Allow tailcalling without decls. 2013-05-15 Ramana Radhakrishnan PR target/19599 * gcc.target/arm/pr40887.c: Adjust testcase. * gcc.target/arm/pr19599.c: New test. commit 5d0e570066009d361181be26e8ba858139ee5b8e Author: Ramana Radhakrishnan Date: Wed May 15 08:47:20 2013 +0100 Fix PR19599 properly. diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c index 170dcb7..036db8a 100644 --- a/gcc/config/arm/arm.c +++ b/gcc/config/arm/arm.c @@ -5376,9 +5376,8 @@ arm_function_ok_for_sibcall (tree decl, tree exp) if (cfun->machine->sibcall_blocked) return false; - /* Never tailcall something for which we have no decl, or if we - are generating code for Thumb-1. */ - if (decl == NULL || TARGET_THUMB1) + /* Never tailcall something if we are generating code for Thumb-1. */ + if (TARGET_THUMB1) return false; /* The PIC register is live on entry to VxWorks PLT entries, so we @@ -5388,13 +5387,14 @@ arm_function_ok_for_sibcall (tree decl, tree exp) /* Cannot tail-call to long calls, since these are out of range of a branch instruction. */ - if (arm_is_long_call_p (decl)) + if (decl && arm_is_long_call_p (decl)) return false; /* If we are interworking and the function is not declared static then we can't tail-call it unless we know that it exists in this compilation unit (since it might be a Thumb routine). */ - if (TARGET_INTERWORK && TREE_PUBLIC (decl) && !TREE_ASM_WRITTEN (decl)) + if (TARGET_INTERWORK && decl && TREE_PUBLIC (decl) + && !TREE_ASM_WRITTEN (decl)) return false; func_type = arm_current_func_type (); diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h index c47fdf6..8ce8a91 100644 --- a/gcc/config/arm/arm.h +++ b/gcc/config/arm/arm.h @@ -1142,6 +1142,7 @@ enum reg_class STACK_REG, BASE_REGS, HI_REGS, + CALLER_SAVE_REGS, GENERAL_REGS, CORE_REGS, VFP_D0_D7_REGS, @@ -1168,6 +1169,7 @@ enum reg_class "STACK_REG", \ "BASE_REGS", \ "HI_REGS", \ + "CALLER_SAVE_REGS", \ "GENERAL_REGS", \ "CORE_REGS", \ "VFP_D0_D7_REGS", \ @@ -1193,6 +1195,7 @@ enum reg_class { 0x00002000, 0x00000000, 0x00000000, 0x00000000 }, /* STACK_REG */ \ { 0x000020FF, 0x00000000, 0x00000000, 0x00000000 }, /* BASE_REGS */ \ { 0x00005F00, 0x00000000, 0x00000000, 0x00000000 }, /* HI_REGS */ \ + { 0x0000100F, 0x00000000, 0x00000000, 0x00000000 }, /* CALLER_SAVE_REGS */ \ { 0x00005FFF, 0x00000000, 0x00000000, 0x00000000 }, /* GENERAL_REGS */ \ { 0x00007FFF, 0x00000000, 0x00000000, 0x00000000 }, /* CORE_REGS */ \ { 0xFFFF0000, 0x00000000, 0x00000000, 0x00000000 }, /* VFP_D0_D7_REGS */ \ diff --git a/gcc/config/arm/arm.md b/gcc/config/arm/arm.md index 06b3c18..d3bc760 100644 --- a/gcc/config/arm/arm.md +++ b/gcc/config/arm/arm.md @@ -8889,7 +8889,7 @@ (match_operand 1 "" "")) (use (match_operand 2 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_ARM && arm_arch5" + "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)" "blx%?\\t%0" [(set_attr "type" "call")] ) @@ -8899,7 +8899,7 @@ (match_operand 1 "" "")) (use (match_operand 2 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_ARM && !arm_arch5" + "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)" "* return output_call (operands); " @@ -8918,7 +8918,7 @@ (match_operand 1 "" "")) (use (match_operand 2 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_ARM && !arm_arch5" + "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)" "* return output_call_mem (operands); " @@ -8931,7 +8931,7 @@ (match_operand 1 "" "")) (use (match_operand 2 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_THUMB1 && arm_arch5" + "TARGET_THUMB1 && arm_arch5 && !SIBLING_CALL_P (insn)" "blx\\t%0" [(set_attr "length" "2") (set_attr "type" "call")] @@ -8942,7 +8942,7 @@ (match_operand 1 "" "")) (use (match_operand 2 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_THUMB1 && !arm_arch5" + "TARGET_THUMB1 && !arm_arch5 && !SIBLING_CALL_P (insn)" "* { if (!TARGET_CALLER_INTERWORKING) @@ -9001,7 +9001,7 @@ (match_operand 2 "" ""))) (use (match_operand 3 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_ARM && arm_arch5" + "TARGET_ARM && arm_arch5 && !SIBLING_CALL_P (insn)" "blx%?\\t%1" [(set_attr "type" "call")] ) @@ -9012,7 +9012,7 @@ (match_operand 2 "" ""))) (use (match_operand 3 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_ARM && !arm_arch5" + "TARGET_ARM && !arm_arch5 && !SIBLING_CALL_P (insn)" "* return output_call (&operands[1]); " @@ -9028,7 +9028,8 @@ (match_operand 2 "" ""))) (use (match_operand 3 "" "")) (clobber (reg:SI LR_REGNUM))] - "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))" + "TARGET_ARM && !arm_arch5 && (!CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) + && !SIBLING_CALL_P (insn)" "* return output_call_mem (&operands[1]); " @@ -9078,6 +9079,7 @@ (use (match_operand 2 "" "")) (clobber (reg:SI LR_REGNUM))] "TARGET_32BIT + && !SIBLING_CALL_P (insn) && (GET_CODE (operands[0]) == SYMBOL_REF) && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[0]))" "* @@ -9094,6 +9096,7 @@ (use (match_operand 3 "" "")) (clobber (reg:SI LR_REGNUM))] "TARGET_32BIT + && !SIBLING_CALL_P (insn) && (GET_CODE (operands[1]) == SYMBOL_REF) && !arm_is_long_call_p (SYMBOL_REF_DECL (operands[1]))" "* @@ -9139,6 +9142,10 @@ "TARGET_32BIT" " { + if (!REG_P (XEXP (operands[0], 0)) + && (GET_CODE (XEXP (operands[0], 0)) != SYMBOL_REF)) + XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0)); + if (operands[2] == NULL_RTX) operands[2] = const0_rtx; }" @@ -9153,32 +9160,52 @@ "TARGET_32BIT" " { + if (!REG_P (XEXP (operands[1], 0)) && + (GET_CODE (XEXP (operands[1],0)) != SYMBOL_REF)) + XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0)); + if (operands[3] == NULL_RTX) operands[3] = const0_rtx; }" ) (define_insn "*sibcall_insn" - [(call (mem:SI (match_operand:SI 0 "" "X")) + [(call (mem:SI (match_operand:SI 0 "call_insn_operand" "Cs,Ss")) (match_operand 1 "" "")) (return) (use (match_operand 2 "" ""))] - "TARGET_32BIT && GET_CODE (operands[0]) == SYMBOL_REF" + "TARGET_32BIT && SIBLING_CALL_P (insn)" "* - return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; + if (which_alternative == 1) + return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\"; + else + { + if (arm_arch5 || arm_arch4t) + return \" bx\\t%0\\t%@ indirect register sibling call\"; + else + return \"mov%?\\t%|pc, %0\\t%@ indirect register sibling call\"; + } " [(set_attr "type" "call")] ) (define_insn "*sibcall_value_insn" - [(set (match_operand 0 "" "") - (call (mem:SI (match_operand:SI 1 "" "X")) + [(set (match_operand 0 "s_register_operand" "") + (call (mem:SI (match_operand:SI 1 "call_insn_operand" "Cs,Ss")) (match_operand 2 "" ""))) (return) (use (match_operand 3 "" ""))] - "TARGET_32BIT && GET_CODE (operands[1]) == SYMBOL_REF" + "TARGET_32BIT && SIBLING_CALL_P (insn)" "* - return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; + if (which_alternative == 1) + return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\"; + else + { + if (arm_arch5 || arm_arch4t) + return \"bx\\t%1\"; + else + return \"mov%?\\t%|pc, %1\\t@ indirect sibling call \"; + } " [(set_attr "type" "call")] ) diff --git a/gcc/config/arm/constraints.md b/gcc/config/arm/constraints.md index 767ebfb..7e7b3e6 100644 --- a/gcc/config/arm/constraints.md +++ b/gcc/config/arm/constraints.md @@ -96,6 +96,9 @@ (define_register_constraint "c" "CC_REG" "@internal The condition code register.") +(define_register_constraint "Cs" "CALLER_SAVE_REGS" + "@internal The caller save registers. Useful for sibcalls.") + (define_constraint "I" "In ARM/Thumb-2 state a constant that can be used as an immediate value in a Data Processing instruction. In Thumb-1 state a constant in the range @@ -400,3 +403,9 @@ ;; Additionally, we used to have a Q constraint in Thumb state, but ;; this wasn't really a valid memory constraint. Again, all uses of ;; this now seem to have been removed. + +(define_constraint "Ss" + "@internal + Ss is a symbol reference." + (match_code "symbol_ref") +) diff --git a/gcc/config/arm/predicates.md b/gcc/config/arm/predicates.md index 2e0de08..92de9fe 100644 --- a/gcc/config/arm/predicates.md +++ b/gcc/config/arm/predicates.md @@ -635,3 +635,7 @@ (define_predicate "mem_noofs_operand" (and (match_code "mem") (match_code "reg" "0"))) + +(define_predicate "call_insn_operand" + (ior (match_code "symbol_ref") + (match_operand 0 "s_register_operand"))) diff --git a/gcc/testsuite/gcc.target/arm/pr19599.c b/gcc/testsuite/gcc.target/arm/pr19599.c new file mode 100644 index 0000000..e3e066c --- /dev/null +++ b/gcc/testsuite/gcc.target/arm/pr19599.c @@ -0,0 +1,10 @@ +/* { dg-skip-if "need at least armv5te" { *-*-* } { "-march=armv[234]*" } { "" } } */ +/* { dg-options "-O2 -march=armv5te -marm" } */ +/* { dg-final { scan-assembler "bx" } } */ + +int (*indirect_func)(); + +int indirect_call() +{ + return indirect_func(); +} diff --git a/gcc/testsuite/gcc.target/arm/pr40887.c b/gcc/testsuite/gcc.target/arm/pr40887.c index 0b5e873..5cabe3a 100644 --- a/gcc/testsuite/gcc.target/arm/pr40887.c +++ b/gcc/testsuite/gcc.target/arm/pr40887.c @@ -2,9 +2,9 @@ /* { dg-options "-O2 -march=armv5te" } */ /* { dg-final { scan-assembler "blx" } } */ -int (*indirect_func)(); +int (*indirect_func)(int x); int indirect_call() { - return indirect_func(); + return indirect_func(20) + indirect_func (40); }