From: Kyrill Tkachov <kyrylo.tkachov@foss.arm.com>
To: Thomas Preudhomme <thomas.preudhomme@foss.arm.com>
Cc: Richard Earnshaw <Richard.Earnshaw@arm.com>,
Ramana Radhakrishnan <ramana.radhakrishnan@arm.com>,
gcc-patches@gcc.gnu.org
Subject: Re: [PATCH, ARM 6/7, ping1] Add support for CB(N)Z and (U|S)DIV to ARMv8-M Baseline
Date: Tue, 12 Jul 2016 14:57:00 -0000 [thread overview]
Message-ID: <57850565.9040407@foss.arm.com> (raw)
In-Reply-To: <2740193.ae6lGT2elt@e108577-lin>
On 12/07/16 11:26, Thomas Preudhomme wrote:
> Hi Kyrill,
Hi Thomas,
>
> On Friday 20 May 2016 14:22:48 Kyrill Tkachov wrote:
>> Hi Thomas,
>>
>> On 17/05/16 11:14, Thomas Preudhomme wrote:
>>> Ping?
>>>
>>> *** gcc/ChangeLog ***
>>>
>>> 2015-11-13 Thomas Preud'homme <thomas.preudhomme@arm.com>
>>>
>>> * 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.
>>>
>>> diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
>>> index
>>> f42e996e5a7ce979fe406b8261d50fb2ba005f6b..347b5b0a5cc0bc1e3b5020c8124d968e
>>> 76ce48a4 100644
>>> --- a/gcc/config/arm/arm.h
>>> +++ b/gcc/config/arm/arm.h
>>> @@ -271,9 +271,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
>>> 13b4b71ac8f9c1da8ef1945f7ff6985ca59f6832..445972ce0e3fd27d4411840ff69e9edb
>>> b23994fc 100644
>>> --- a/gcc/config/arm/arm.c
>>> +++ b/gcc/config/arm/arm.c
>>> @@ -22684,7 +22684,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 == '_')));
>>>
>>> }
>> Hmm, I'm not a fan of this change. arm_print_operand_punct_valid_p is an
>> implementation of a target hook that is used to validate user-provided
>> inline asm as well and is therefore the right place to reject such invalid
>> constructs.
>>
>> This is just working around the fact that the output template for the
>> [u]divsi3 patterns has a '%?' in it that is illegal in Thumb1 and will not
>> be used for ARMv8-M Baseline anyway. I'd prefer it if you add a second
>> alternative to those patterns and emit the sdiv/udiv mnemonic without the
>> '%?' and enable that for the v8mb arch attribute (and mark the existing
>> alternative as requiring the "32" arch attribute).
>>> diff --git a/gcc/config/arm/thumb1.md b/gcc/config/arm/thumb1.md
>>> index
>>> 4572456b8bc98503061846cad94bc642943db3a2..1b01ef6ce731fe3ff37c3d8c048fb9d5
>>> e7829b35 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"
>>> +{
>> s/TARGET_HAVE_MOVT/TARGET_HAVE_CBZ/
>>
>>> + 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")))
>> This pattern only has one alternative so "which_alternative"
>> will always be 0, so the (not (match_test "which_alternative"))
>> test inside the 'and' is redundant and can be removed.
> What about the attached updated patch?
This is ok with one ChangeLog nit.
Thanks,
Kyrill
> ChangeLog entry are as follow:
>
>
> *** gcc/ChangeLog ***
>
> 2016-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * config/arm/arm.h (TARGET_HAVE_CBZ): Define.
> (TARGET_IDIV): Set for all Thumb targets provided they have hardware
> divide feature.
> * config/arm/arm.md (divsi3): New unpredicable alternative for ARMv8-M
> Baseline. Make initial alternative TARGET_32BIT only.
> (udivsi3): Likewise.
> * config/arm/thumb1.md (thumb1_cbz): New insn.
I'd say "New define_insn." instead.
> * doc/sourcebuild.texi (arm_thumb1_cbz_ok): Document new effective
> target.
>
>
> *** gcc/testsuite/ChangeLog ***
>
> 2016-05-23 Thomas Preud'homme <thomas.preudhomme@arm.com>
>
> * lib/target-supports.exp (check_effective_target_arm_thumb1_cbz_ok):
> Add new arm_thumb1_cbz_ok effective target.
> * gcc.target/arm/cbz.c: New test.
>
>
> Best regards,
>
> Thomas
>
>> Thanks,
>> Kyrill
>>
>>> + (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"
>>>
>>> Best regards,
>>>
>>> Thomas
>>>
>>> On Thursday 17 December 2015 16:17:52 Thomas Preud'homme wrote:
>>>> 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 <thomas.preudhomme@arm.com>
>>>>
>>>> * 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.
>>>>
>>>> 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"
>>>>
>>>> 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
next prev parent reply other threads:[~2016-07-12 14:57 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-12-17 8:18 [PATCH, ARM 6/6] " Thomas Preud'homme
2016-05-17 10:14 ` [PATCH, ARM 6/7, ping1] " Thomas Preudhomme
2016-05-20 13:23 ` Kyrill Tkachov
2016-07-06 16:55 ` Thomas Preudhomme
2016-07-12 10:27 ` Thomas Preudhomme
2016-07-12 14:57 ` Kyrill Tkachov [this message]
2016-07-13 10:54 ` Thomas Preudhomme
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=57850565.9040407@foss.arm.com \
--to=kyrylo.tkachov@foss.arm.com \
--cc=Richard.Earnshaw@arm.com \
--cc=gcc-patches@gcc.gnu.org \
--cc=ramana.radhakrishnan@arm.com \
--cc=thomas.preudhomme@foss.arm.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).