From patchwork Mon Feb 24 09:18:28 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Zhenqiang Chen X-Patchwork-Id: 323511 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 88ED92C0212 for ; Mon, 24 Feb 2014 20:18:44 +1100 (EST) DomainKey-Signature: a=rsa-sha1; c=nofws; d=gcc.gnu.org; h=list-id :list-unsubscribe:list-archive:list-post:list-help:sender :mime-version:date:message-id:subject:from:to:cc:content-type; q=dns; s=default; b=kR65kNLAe5604D9ySSLYVrNeDqUPmnYvEjytZhSeGiT mpnaVwFxADaZKQiQ7FTle9IWxpoRhpvzx7X5WL3xTN02AySMIhDhueEZitz+ppfi nwgnkATtvZLdsJ6pVSxSYIy7wIPPuKMWZ2/OzEQOxvG7IN1LsHKciWUMJe4mhW2w = 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 :mime-version:date:message-id:subject:from:to:cc:content-type; s=default; bh=dosB6rFbUFCIaxAM6jnRRlMIVUs=; b=j8UA6ND7XZ8STrJvK 0vFlpFp4J5PRU/5+lQ3WuuaRFw/E4R7Ns8IX26QTn22ytrow/uYP4OLmVVsaQ278 CexbFeMEBeE8J2yCC9AsvgcxCvX0QDhEED5BHpWiDpQx1ykUvTE72HzUE0L/y9YU XjaQWC6d6WrldV9+UNvdnbVii0= Received: (qmail 14067 invoked by alias); 24 Feb 2014 09:18:36 -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 13947 invoked by uid 89); 24 Feb 2014 09:18:34 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.5 required=5.0 tests=AWL, BAYES_00, LIKELY_SPAM_BODY, RCVD_IN_DNSWL_LOW, SPF_PASS autolearn=no version=3.3.2 X-HELO: mail-la0-f46.google.com Received: from mail-la0-f46.google.com (HELO mail-la0-f46.google.com) (209.85.215.46) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES128-SHA encrypted) ESMTPS; Mon, 24 Feb 2014 09:18:33 +0000 Received: by mail-la0-f46.google.com with SMTP id b8so5347570lan.33 for ; Mon, 24 Feb 2014 01:18:29 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:date:message-id:subject:from:to:cc :content-type; bh=y0PDNeLRtODvPYsPmWngVz8Wk9d9ZTHHw7siArmnhMw=; b=A+CdxiWLccokiGz6t8Bw5l+0jXmMOS2jeqtbvTs+xZ2Y1Q8pGFFyVjGwym4EMvGoA2 g9urHbbCh06sZUswmxukgKdLGl6cGFpqDFF/6OPWQ8zcBGP7GU6o8FJ+Aw54vmx1LQpQ biliAChajQfZZFn6PCjaVuAlNSLrn35sNsCQM/nK6UID+AzFU1hoi06oPyjIlhJQVh2P K6iA1ejrcWCayEUUaDbuYpXoDiLZ5SzYaHEyrMhjlL2zjdnympMiQTW+MqjJJSKMA3yS pjVGh2c5u3K+HnVU8YiifzWZr2o73s7NY6ah4ALSrfPlGiyw44zEfBUxTH+bwZeacjTx oulg== X-Gm-Message-State: ALoCoQm2SLV2M8cG8hxCtgPtTMA3Y8SB9jIj+xnA76b5Y9d5QP2xfZQkTjHd+Opq6ld5kE2q3gTT MIME-Version: 1.0 X-Received: by 10.112.164.35 with SMTP id yn3mr10847076lbb.45.1393233509065; Mon, 24 Feb 2014 01:18:29 -0800 (PST) Received: by 10.112.173.137 with HTTP; Mon, 24 Feb 2014 01:18:28 -0800 (PST) Date: Mon, 24 Feb 2014 17:18:28 +0800 Message-ID: Subject: [PATCH 3/n] Add conditional compare support for AARCH64 From: Zhenqiang Chen To: "gcc-patches@gcc.gnu.org" Cc: Marcus Shawcroft , Richard Earnshaw X-IsSubscribed: yes Hi, Here is the patch to generate conditional compare instructions (CCMP/CCMN) for aarch64 port. No make check regression in qemu-aarch64 tests. Is it OK for next stage1? When the patch is OK, I will create another patch to support FCCMP/FCCMN. Thanks! -Zhenqiang ChangeLog: 2014-02-24 Zhenqiang Chen * config/aarch64/aarch64-modes.def (CC_DNE, CC_DEQ, CC_DLE, CC_DLT, CC_DGE, CC_DGT, CC_DLEU, CC_DLTU, CC_DGEU, CC_DGTU): New modes. * config/aarch64/aarch64-protos.h (aarch64_uimm5, aarch64_output_ccmp): New prototypes. * config/aarch64/aarch64.c (aarch64_get_condition_code_1): New function extracted from aarch64_get_condition_code and hand ccmp. (aarch64_code_to_ccmode, aarch64_convert_mode, aarch64_code_to_nzcv aarch64_mode_to_condition_code, aarch64_output_ccmp, aarch64_uimm5): New functions. (aarch64_gen_ccmp_first, aarch64_gen_ccmp_next): New hooks. (aarch64_get_condition_code): Call aarch64_get_condition_code_1. (AARCH64_CC_V, AARCH64_CC_C, AARCH64_CC_Z, AARCH64_CC_N): New MICROs. * config/aarch64/aarch64.md (cbranchcc4, ccmp_and, ccmp_ior): New instruction patterns. * config/aarch64/constraints.md (Usn): New constrain. * config/aarch64/predicates.md (ccmp_cc_register, aarch64_ccmp_operand, aarch64_ccmp_immediate): New predicates. diff --git a/gcc/config/aarch64/aarch64-modes.def b/gcc/config/aarch64/aarch64-modes.def index 1d2cc76..71fd2f0 100644 --- a/gcc/config/aarch64/aarch64-modes.def +++ b/gcc/config/aarch64/aarch64-modes.def @@ -25,6 +25,16 @@ CC_MODE (CC_ZESWP); /* zero-extend LHS (but swap to make it RHS). */ CC_MODE (CC_SESWP); /* sign-extend LHS (but swap to make it RHS). */ CC_MODE (CC_NZ); /* Only N and Z bits of condition flags are valid. */ CC_MODE (CC_Z); /* Only Z bit of condition flags is valid. */ +CC_MODE (CC_DNE); +CC_MODE (CC_DEQ); +CC_MODE (CC_DLE); +CC_MODE (CC_DLT); +CC_MODE (CC_DGE); +CC_MODE (CC_DGT); +CC_MODE (CC_DLEU); +CC_MODE (CC_DLTU); +CC_MODE (CC_DGEU); +CC_MODE (CC_DGTU); /* Vector modes. */ VECTOR_MODES (INT, 8); /* V8QI V4HI V2SI. */ diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h index 5542f02..48b4c09 100644 --- a/gcc/config/aarch64/aarch64-protos.h +++ b/gcc/config/aarch64/aarch64-protos.h @@ -228,6 +228,9 @@ void aarch64_init_expanders (void); void aarch64_print_operand (FILE *, rtx, char); void aarch64_print_operand_address (FILE *, rtx); +bool aarch64_uimm5 (HOST_WIDE_INT); +const char* aarch64_output_ccmp (rtx *, bool, int); + /* Initialize builtins for SIMD intrinsics. */ void init_aarch64_simd_builtins (void); diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c index ea90311..c154d02 100644 --- a/gcc/config/aarch64/aarch64.c +++ b/gcc/config/aarch64/aarch64.c @@ -3361,14 +3361,8 @@ aarch64_select_cc_mode (RTX_CODE code, rtx x, rtx y) } static unsigned -aarch64_get_condition_code (rtx x) +aarch64_get_condition_code_1 (enum machine_mode mode, enum rtx_code comp_code) { - enum machine_mode mode = GET_MODE (XEXP (x, 0)); - enum rtx_code comp_code = GET_CODE (x); - - if (GET_MODE_CLASS (mode) != MODE_CC) - mode = SELECT_CC_MODE (comp_code, XEXP (x, 0), XEXP (x, 1)); - switch (mode) { case CCFPmode: @@ -3391,6 +3385,27 @@ aarch64_get_condition_code (rtx x) } break; + case CC_DNEmode: + return comp_code == NE ? AARCH64_NE : AARCH64_EQ; + case CC_DEQmode: + return comp_code == NE ? AARCH64_EQ : AARCH64_NE; + case CC_DGEmode: + return comp_code == NE ? AARCH64_GE : AARCH64_LT; + case CC_DLTmode: + return comp_code == NE ? AARCH64_LT : AARCH64_GE; + case CC_DGTmode: + return comp_code == NE ? AARCH64_GT : AARCH64_LE; + case CC_DLEmode: + return comp_code == NE ? AARCH64_LE : AARCH64_GT; + case CC_DGEUmode: + return comp_code == NE ? AARCH64_CS : AARCH64_CC; + case CC_DLTUmode: + return comp_code == NE ? AARCH64_CC : AARCH64_CS; + case CC_DGTUmode: + return comp_code == NE ? AARCH64_HI : AARCH64_LS; + case CC_DLEUmode: + return comp_code == NE ? AARCH64_LS : AARCH64_HI; + case CCmode: switch (comp_code) { @@ -3454,6 +3469,20 @@ aarch64_get_condition_code (rtx x) } static unsigned +aarch64_get_condition_code (rtx x) +{ + enum machine_mode mode = GET_MODE (XEXP (x, 0)); + enum rtx_code comp_code = GET_CODE (x); + + gcc_assert (!ccmp_cc_register (x, mode) + || (comp_code == NE || comp_code == EQ)); + + if (GET_MODE_CLASS (mode) != MODE_CC) + mode = SELECT_CC_MODE (comp_code, XEXP (x, 0), XEXP (x, 1)); + return aarch64_get_condition_code_1 (mode, comp_code); +} + +static unsigned bit_count (unsigned HOST_WIDE_INT value) { unsigned count = 0; @@ -8304,6 +8333,245 @@ aarch64_cannot_change_mode_class (enum machine_mode from, return true; } +static enum machine_mode +aarch64_code_to_ccmode (enum rtx_code code) +{ + switch (code) + { + case NE: + return CC_DNEmode; + case EQ: + return CC_DEQmode; + case LE: + return CC_DLEmode; + case LT: + return CC_DLTmode; + case GE: + return CC_DGEmode; + case GT: + return CC_DGTmode; + case LEU: + return CC_DLEUmode; + case LTU: + return CC_DLTUmode; + case GEU: + return CC_DGEUmode; + case GTU: + return CC_DGTUmode; + default: + return CCmode; + } +} +/* N Z C V. */ +#define AARCH64_CC_V 1 +#define AARCH64_CC_C (1 << 1) +#define AARCH64_CC_Z (1 << 2) +#define AARCH64_CC_N (1 << 3) + +static unsigned int +aarch64_code_to_nzcv (enum rtx_code code, bool inverse) +{ + switch (code) + { + case NE: /* NE, Z == 0. */ + return inverse ? AARCH64_CC_Z : 0; + case EQ: /* EQ, Z == 1. */ + return inverse ? 0 : AARCH64_CC_Z; + case LE: /* LE, !(Z == 0 && N == V). */ + return inverse ? AARCH64_CC_N | AARCH64_CC_V : AARCH64_CC_Z; + case GT: /* GT, Z == 0 && N == V. */ + return inverse ? AARCH64_CC_Z : AARCH64_CC_N | AARCH64_CC_V; + case LT: /* LT, N != V. */ + return inverse ? AARCH64_CC_N | AARCH64_CC_V : AARCH64_CC_N; + case GE: /* GE, N == V. */ + return inverse ? AARCH64_CC_N : AARCH64_CC_N | AARCH64_CC_V; + case LEU: /* LS, !(C == 1 && Z == 0). */ + return inverse ? AARCH64_CC_C: AARCH64_CC_Z; + case GTU: /* HI, C ==1 && Z == 0. */ + return inverse ? AARCH64_CC_Z : AARCH64_CC_C; + case LTU: /* CC, C == 0. */ + return inverse ? AARCH64_CC_C : 0; + case GEU: /* CS, C == 1. */ + return inverse ? 0 : AARCH64_CC_C; + default: + gcc_unreachable (); + return 0; + } +} + +static unsigned +aarch64_mode_to_condition_code (enum machine_mode mode, bool inverse) +{ + switch (mode) + { + case CC_DNEmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, EQ) + : aarch64_get_condition_code_1 (CCmode, NE); + case CC_DEQmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, NE) + : aarch64_get_condition_code_1 (CCmode, EQ); + case CC_DLEmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, GT) + : aarch64_get_condition_code_1 (CCmode, LE); + case CC_DGTmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, LE) + : aarch64_get_condition_code_1 (CCmode, GT); + case CC_DLTmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, GE) + : aarch64_get_condition_code_1 (CCmode, LT); + case CC_DGEmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, LT) + : aarch64_get_condition_code_1 (CCmode, GE); + case CC_DLEUmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, GTU) + : aarch64_get_condition_code_1 (CCmode, LEU); + case CC_DGTUmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, LEU) + : aarch64_get_condition_code_1 (CCmode, GTU); + case CC_DLTUmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, GEU) + : aarch64_get_condition_code_1 (CCmode, LTU); + case CC_DGEUmode: + return inverse ? aarch64_get_condition_code_1 (CCmode, LTU) + : aarch64_get_condition_code_1 (CCmode, GEU); + default: + gcc_unreachable (); + } +} + +const char * +aarch64_output_ccmp (rtx *operands, bool is_and, int which_alternative) +{ + char buf[32]; + rtx cc = operands[0]; + enum rtx_code code = GET_CODE (operands[5]); + unsigned char nzcv = aarch64_code_to_nzcv (code, is_and); + enum machine_mode mode = GET_MODE (cc); + unsigned int cond_code = aarch64_mode_to_condition_code (mode, !is_and); + + if (GET_MODE (operands[2]) == SImode) + switch (which_alternative) + { + case 0: + snprintf (buf, sizeof (buf), "ccmp\t%%w2, %%w3, #%u, %s", + nzcv, aarch64_condition_codes[cond_code]); + break; + case 1: + snprintf (buf, sizeof (buf), "ccmp\t%%w2, #%%3, #%u, %s", + nzcv, aarch64_condition_codes[cond_code]); + break; + case 2: + snprintf (buf, sizeof (buf), "ccmn\t%%w2, #%%n3, #%u, %s", + nzcv, aarch64_condition_codes[cond_code]); + break; + default: + gcc_unreachable (); + } + else + switch (which_alternative) + { + case 0: + snprintf (buf, sizeof (buf), "ccmp\t%%x2, %%x3, #%u, %s", + nzcv, aarch64_condition_codes[cond_code]); + break; + case 1: + snprintf (buf, sizeof (buf), "ccmp\t%%x2, #%%3, #%u, %s", + nzcv, aarch64_condition_codes[cond_code]); + break; + case 2: + snprintf (buf, sizeof (buf), "ccmn\t%%x2, #%%n3, #%u, %s", + nzcv, aarch64_condition_codes[cond_code]); + break; + default: + gcc_unreachable (); + } + + output_asm_insn (buf, operands); + return ""; +} + +/* Return true if val can be encoded as a 5-bit unsigned immediate. */ +bool +aarch64_uimm5 (HOST_WIDE_INT val) +{ + return (val & ((unsigned HOST_WIDE_INT) 0x1f)) == val; +} + +static bool +aarch64_convert_mode (rtx* op0, rtx* op1, int unsignedp) +{ + enum machine_mode mode; + + mode = GET_MODE (*op0); + if (mode == VOIDmode) + mode = GET_MODE (*op1); + + if (mode == QImode || mode == HImode) + { + *op0 = convert_modes (SImode, mode, *op0, unsignedp); + *op1 = convert_modes (SImode, mode, *op1, unsignedp); + } + else if (mode != SImode && mode != DImode) + return false; + + return true; +} + +static rtx +aarch64_gen_ccmp_first (int code, rtx op0, rtx op1) +{ + enum machine_mode mode; + rtx cmp, target; + int unsignedp = code == LTU || code == LEU || code == GTU || code == GEU; + + if (!aarch64_convert_mode (&op0, &op1, unsignedp) + || !register_operand (op0, GET_MODE (op0)) + || !aarch64_ccmp_operand (op1, GET_MODE (op1))) + return NULL_RTX; + + mode = aarch64_code_to_ccmode ((enum rtx_code) code); + if (mode == CCmode) + return NULL_RTX; + + cmp = gen_rtx_fmt_ee (COMPARE, CCmode, op0, op1); + target = gen_rtx_REG (mode, CC_REGNUM); + emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM), cmp)); + return target; +} + +static rtx +aarch64_gen_ccmp_next (rtx prev, int cmp_code, rtx op0, rtx op1, int bit_code) +{ + rtx cmp0, cmp1, target, bit_op; + enum machine_mode mode = aarch64_code_to_ccmode ((enum rtx_code) cmp_code); + int unsignedp = cmp_code == LTU || cmp_code == LEU + || cmp_code == GTU || cmp_code == GEU; + + if (!aarch64_convert_mode (&op0, &op1, unsignedp) + || !register_operand (op0, GET_MODE (op0)) + || !aarch64_ccmp_operand (op1, GET_MODE (op1))) + return NULL_RTX; + + cmp1 = gen_rtx_fmt_ee ((enum rtx_code) cmp_code, SImode, op0, op1); + + cmp0 = gen_rtx_fmt_ee (NE, SImode, prev, const0_rtx); + + bit_op = gen_rtx_fmt_ee ((enum rtx_code) bit_code, SImode, cmp0, cmp1); + + /* Generate insn to match ccmp_and/ccmp_ior. */ + target = gen_rtx_REG (mode, CC_REGNUM); + emit_insn (gen_rtx_SET (VOIDmode, target, + gen_rtx_fmt_ee (COMPARE, VOIDmode, + bit_op, const0_rtx))); + return target; +} + +#undef TARGET_GEN_CCMP_FIRST +#define TARGET_GEN_CCMP_FIRST aarch64_gen_ccmp_first + +#undef TARGET_GEN_CCMP_NEXT +#define TARGET_GEN_CCMP_NEXT aarch64_gen_ccmp_next + #undef TARGET_ADDRESS_COST #define TARGET_ADDRESS_COST aarch64_address_cost /* Assembly output. */ diff --git a/gcc/config/aarch64/aarch64.md b/gcc/config/aarch64/aarch64.md index 99a6ac8..8f5fd92 100644 --- a/gcc/config/aarch64/aarch64.md +++ b/gcc/config/aarch64/aarch64.md @@ -212,6 +212,52 @@ " ) +(define_expand "cbranchcc4" + [(set (pc) (if_then_else + (match_operator 0 "aarch64_comparison_operator" + [(match_operand 1 "cc_register" "") + (const_int 0)]) + (label_ref (match_operand 3 "" "")) + (pc)))] + "" + " ") + +(define_insn "*ccmp_and" + [(set (match_operand 6 "ccmp_cc_register" "") + (compare + (and:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (match_operand 1 "aarch64_plus_operand" "")]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "" + { + return aarch64_output_ccmp (operands, true, which_alternative); + } + [(set_attr "type" "alus_reg,alus_imm,alus_imm")] +) + +(define_insn "*ccmp_ior" + [(set (match_operand 6 "ccmp_cc_register" "") + (compare + (ior:SI + (match_operator 4 "aarch64_comparison_operator" + [(match_operand 0 "ccmp_cc_register" "") + (match_operand 1 "aarch64_plus_operand" "")]) + (match_operator 5 "aarch64_comparison_operator" + [(match_operand:GPI 2 "register_operand" "r,r,r") + (match_operand:GPI 3 "aarch64_ccmp_operand" "r,Uss,Usn")])) + (const_int 0)))] + "" + { + return aarch64_output_ccmp (operands, false, which_alternative); + } + [(set_attr "type" "alus_reg,alus_imm,alus_imm")] +) + (define_insn "*condjump" [(set (pc) (if_then_else (match_operator 0 "aarch64_comparison_operator" [(match_operand 1 "cc_register" "") (const_int 0)]) diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md index 12ab570..6679efa 100644 --- a/gcc/config/aarch64/constraints.md +++ b/gcc/config/aarch64/constraints.md @@ -86,6 +86,11 @@ (and (match_code "const_int") (match_test "(unsigned HOST_WIDE_INT) ival < 32"))) +(define_constraint "Usn" + "A constant that can be used with a CCMN operation (once negated)." + (and (match_code "const_int") + (match_test "aarch64_uimm5 (-ival)"))) + (define_constraint "Usd" "@internal A constraint that matches an immediate shift constant in DImode." diff --git a/gcc/config/aarch64/predicates.md b/gcc/config/aarch64/predicates.md index c8e27d8..4b9f84b 100644 --- a/gcc/config/aarch64/predicates.md +++ b/gcc/config/aarch64/predicates.md @@ -26,6 +26,32 @@ && GET_MODE_CLASS (GET_MODE (op)) == MODE_CC")))) ) +(define_special_predicate "ccmp_cc_register" + (and (match_code "reg") + (and (match_test "REGNO (op) == CC_REGNUM") + (ior (match_test "mode == GET_MODE (op)") + (match_test "mode == VOIDmode + && (GET_MODE (op) == CC_DNEmode + || GET_MODE (op) == CC_DEQmode + || GET_MODE (op) == CC_DLEmode + || GET_MODE (op) == CC_DLTmode + || GET_MODE (op) == CC_DGEmode + || GET_MODE (op) == CC_DGTmode + || GET_MODE (op) == CC_DLEUmode + || GET_MODE (op) == CC_DLTUmode + || GET_MODE (op) == CC_DGEUmode + || GET_MODE (op) == CC_DGTUmode)")))) +) + +(define_predicate "aarch64_ccmp_immediate" + (and (match_code "const_int") + (ior (match_test "aarch64_uimm5 (INTVAL (op))") + (match_test "aarch64_uimm5 (-INTVAL (op))")))) + +(define_predicate "aarch64_ccmp_operand" + (ior (match_operand 0 "register_operand") + (match_operand 0 "aarch64_ccmp_immediate"))) + (define_predicate "aarch64_simd_register" (and (match_code "reg") (ior (match_test "REGNO_REG_CLASS (REGNO (op)) == FP_LO_REGS")