From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: by sourceware.org (Postfix, from userid 7810) id 2DAB13858D35; Tue, 1 Nov 2022 11:01:30 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 2DAB13858D35 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1667300503; bh=ik53wWpRU+B1F46+HtD1hM+E1YRpe+V1HV5ZFDHvfQA=; h=From:To:Subject:Date:From; b=EWRXyDVRWU2aIkvavoTc7OWZneVcnct9ISILj8Kd28CU2ngFdYmrt4Zhm6rI3RR86 2oX9+WVasPHZI3ZGzyHJUKBEhGYvcS6JncZezZR56ta7VZLI5fs/uQ4ZjTgXsiBiLg nmipb/DfNx9uThAlxVBOt7pUqUpzDQX7zqoSd0eM= Content-Type: text/plain; charset="us-ascii" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit From: Alex Coplan To: gcc-cvs@gcc.gnu.org Subject: [gcc(refs/vendors/ARM/heads/morello)] morello: Add immediate form of clrperm X-Act-Checkin: gcc X-Git-Author: Alex Coplan X-Git-Refname: refs/vendors/ARM/heads/morello X-Git-Oldrev: dfd24013eb422e9fd215d239e15c7a3520a14e88 X-Git-Newrev: 70cb98d7a702272cae4174f21046ab785226d74c Message-Id: <20221101110143.2DAB13858D35@sourceware.org> Date: Tue, 1 Nov 2022 11:01:30 +0000 (GMT) List-Id: https://gcc.gnu.org/g:70cb98d7a702272cae4174f21046ab785226d74c commit 70cb98d7a702272cae4174f21046ab785226d74c Author: Alex Coplan Date: Fri Oct 14 19:17:30 2022 +0100 morello: Add immediate form of clrperm This extends the pattern for clrperm in the AArch64 backend to generate the immediate variant where possible. We adjust the expander for __builtin_cheri_perms_and to use the immediate variant of the instruction where possible. Diff: --- gcc/config/aarch64/aarch64-morello.md | 26 +++-- gcc/config/aarch64/aarch64-protos.h | 1 + gcc/config/aarch64/aarch64.c | 33 ++++++ gcc/config/aarch64/constraints.md | 3 + gcc/config/aarch64/predicates.md | 12 ++ .../morello/builtin_cheri_perms_and_immed.c | 127 +++++++++++++++++++++ 6 files changed, 195 insertions(+), 7 deletions(-) diff --git a/gcc/config/aarch64/aarch64-morello.md b/gcc/config/aarch64/aarch64-morello.md index 50de65fedc5..cb57197e751 100644 --- a/gcc/config/aarch64/aarch64-morello.md +++ b/gcc/config/aarch64/aarch64-morello.md @@ -260,13 +260,15 @@ ) (define_insn "aarch64_cap_clear_perm" - [(set (match_operand:CADI 0 "register_operand" "=rk") - (unspec:CADI [(match_operand:CADI 1 "register_operand" "rk") - (match_operand:DI 2 "register_operand" "r")] - UNSPEC_CHERI_CLEAR_PERM)) + [(set (match_operand:CADI 0 "register_operand" "=rk,rk") + (unspec:CADI [(match_operand:CADI 1 "register_operand" "rk,rk") + (match_operand:DI 2 "aarch64_clrperm_operand" "r,Ucp")] + UNSPEC_CHERI_CLEAR_PERM)) ] "TARGET_MORELLO" - "clrperm\\t%0, %1, %2" + "@ + clrperm\\t%0, %1, %2 + * return aarch64_output_clrperm_immed (operands);" ) (define_insn "cap_global_data_get" @@ -280,10 +282,20 @@ (define_expand "cap_perms_and_cadi" [(match_operand:CADI 0 "register_operand") (match_operand:CADI 1 "register_operand") - (match_operand:DI 2 "register_operand")] + (match_operand:DI 2 "aarch64_reg_or_imm")] "TARGET_MORELLO" { - emit_insn (gen_one_cmpldi2 (operands[2], operands[2])); + if (CONST_INT_P (operands[2])) + { + rtx cand = gen_int_mode (~UINTVAL (operands[2]), DImode); + if (aarch64_clrperm_immediate (cand, DImode)) + operands[2] = cand; + else + operands[2] = force_reg (DImode, cand); + } + else + emit_insn (gen_one_cmpldi2 (operands[2], operands[2])); + emit_insn (gen_aarch64_cap_clear_perm (operands[0], operands[1], operands[2])); DONE; } diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 142ba4dfb7a..b365bf92421 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -564,6 +564,7 @@ bool aarch64_uimm12_shift (HOST_WIDE_INT); int aarch64_movk_shift (const wide_int_ref &, const wide_int_ref &); bool aarch64_use_return_insn_p (void); const char *aarch64_output_casesi (rtx *); +const char *aarch64_output_clrperm_immed (rtx *); bool aarch64_scbnds_immediate (unsigned HOST_WIDE_INT); unsigned int aarch64_tlsdesc_abi_id (); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index 456a2b10710..5179f310552 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -12114,6 +12114,39 @@ aarch64_output_casesi (rtx *operands) return ""; } +const char * +aarch64_output_clrperm_immed (rtx *operands) +{ + gcc_assert (REG_P (operands[0]) && GET_MODE (operands[0]) == CADImode); + gcc_assert (REG_P (operands[1]) && GET_MODE (operands[1]) == CADImode); + gcc_assert (CONST_INT_P (operands[2])); + + char immed[4]; + const unsigned rwx_bits = (UINTVAL (operands[2]) >> 15) & 7; + if (rwx_bits == 0) + snprintf (immed, sizeof (immed), "#0"); + else + { + char *p = immed; + enum { + X = (1 << 0), + W = (1 << 1), + R = (1 << 2) + }; + if (rwx_bits & R) + *p++ = 'r'; + if (rwx_bits & W) + *p++ = 'w'; + if (rwx_bits & X) + *p++ = 'x'; + *p = '\0'; + } + + asm_fprintf (asm_out_file, "\tclrperm\tc%u, c%u, %s\n", + REGNO (operands[0]), REGNO (operands[1]), immed); + return ""; +} + /* Return size in bits of an arithmetic operand which is shifted/scaled and masked such that it is suitable for a UXTB, UXTH, or UXTW extend diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 386ce5b64d6..568f91e0f67 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -90,6 +90,9 @@ (and (match_code "const_int") (match_test "aarch64_scbnds_immediate (ival)"))) +(define_constraint "Ucp" + "A constraint matching an immediate suitable for clrperm." + (match_operand 0 "aarch64_clrperm_immediate")) (define_constraint "J" "A constant that can be used with a SUB operation (once negated)." diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index 03bcc73ce9e..b4b0349843d 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -64,6 +64,18 @@ (ior (match_operand 0 "register_operand") (match_code "const_int"))) +; We can use the immediate form of clrperm if we're only clearing rwx +; bits (bits 16 through 18 inclusive), i.e. if all the low bits below +; these are cleared in the mask. +(define_predicate "aarch64_clrperm_immediate" + (and + (match_code "const_int") + (match_test "(UINTVAL (op) & 0x7fff) == 0"))) + +(define_predicate "aarch64_clrperm_operand" + (ior (match_operand 0 "register_operand") + (match_operand 0 "aarch64_clrperm_immediate"))) + (define_predicate "aarch64_simd_register" (and (match_code "reg") (match_test "FP_REGNUM_P (REGNO (op))"))) diff --git a/gcc/testsuite/gcc.target/aarch64/morello/builtin_cheri_perms_and_immed.c b/gcc/testsuite/gcc.target/aarch64/morello/builtin_cheri_perms_and_immed.c new file mode 100644 index 00000000000..90abaafedf0 --- /dev/null +++ b/gcc/testsuite/gcc.target/aarch64/morello/builtin_cheri_perms_and_immed.c @@ -0,0 +1,127 @@ +/* { dg-do assemble } */ +/* { dg-additional-options "-save-temps" } */ +/* { dg-final { check-function-bodies "**" "" { {-O[123s]} } } } */ +/* { dg-require-effective-target cheri_capability_pure } */ + +enum { + R = __CHERI_CAP_PERMISSION_PERMIT_LOAD__, + W = __CHERI_CAP_PERMISSION_PERMIT_STORE__, + X = __CHERI_CAP_PERMISSION_PERMIT_EXECUTE__, + + /* Here we make assumptions about the encoding of permisisons on + Morello in order to test the codegen. */ + EXTRA_HIGH_BIT = (R << 1), + LOWER_BIT = __CHERI_CAP_PERMISSION_PERMIT_LOAD_CAPABILITY__, +}; + +/* +** clear_x: +** clrperm c0, c0, x +** ret +*/ +void *clear_x(void *x) +{ + return __builtin_cheri_perms_and (x, ~X); +} + +/* +** clear_w: +** clrperm c0, c0, w +** ret +*/ +void *clear_w(void *x) +{ + return __builtin_cheri_perms_and (x, ~W); +} + +/* +** clear_r: +** clrperm c0, c0, r +** ret +*/ +void *clear_r(void *x) +{ + return __builtin_cheri_perms_and (x, ~R); +} + +/* +** clear_wx: +** clrperm c0, c0, wx +** ret +*/ +void *clear_wx(void *x) +{ + return __builtin_cheri_perms_and (x, ~(W | X)); +} + +/* +** clear_rx: +** clrperm c0, c0, rx +** ret +*/ +void *clear_rx(void *x) +{ + return __builtin_cheri_perms_and (x, ~(R | X)); +} + +/* +** clear_rw: +** clrperm c0, c0, rw +** ret +*/ +void *clear_rw(void *x) +{ + return __builtin_cheri_perms_and (x, ~(R | W)); +} + +/* +** all_three: +** clrperm c0, c0, rwx +** ret +*/ +void *all_three(void *x) +{ + return __builtin_cheri_perms_and (x, ~(R | W | X)); +} + +/* +** clear_none: +** clrperm c0, c0, #0 +** ret +*/ +void *clear_none(void *x) +{ + return __builtin_cheri_perms_and(x, ~0UL); +} + +/* +** extra_high_bits_dont_matter: +** clrperm c0, c0, rwx +** ret +*/ +void *extra_high_bits_dont_matter(void *x) +{ + return __builtin_cheri_perms_and (x, ~(R | W | X | EXTRA_HIGH_BIT)); +} + +/* +** scuppered: +** mov x1, 49152 +** clrperm c0, c0, x1 +** ret +*/ +void *scuppered(void *x) +{ + return __builtin_cheri_perms_and (x, ~(X | LOWER_BIT)); +} + +/* +** clear_just_low_bits: +** mov x1, 7 +** clrperm c0, c0, x1 +** ret +*/ +void *clear_just_low_bits (void *x) +{ + return __builtin_cheri_perms_and (x, ~7UL); +}