This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: [PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern
- From: Sudi Das <Sudi dot Das at arm dot com>
- To: James Greenhalgh <James dot Greenhalgh at arm dot com>
- Cc: Richard Earnshaw <Richard dot Earnshaw at arm dot com>, "gcc-patches at gcc dot gnu dot org" <gcc-patches at gcc dot gnu dot org>, nd <nd at arm dot com>, Marcus Shawcroft <Marcus dot Shawcroft at arm dot com>
- Date: Wed, 27 Sep 2017 17:57:13 +0000
- Subject: Re: [PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern
- Authentication-results: sourceware.org; auth=none
- Authentication-results: spf=none (sender IP is ) smtp.mailfrom=Sudi dot Das at arm dot com;
- Nodisclaimer: True
- References: <VI1PR08MB2688AF6541412B89D11F691C98190@VI1PR08MB2688.eurprd08.prod.outlook.com> <403a4ea4-df9c-60f2-3fbe-0154329288c5@arm.com> <DB5PR08MB104841F21FC7981D7A17665798B50@DB5PR08MB1048.eurprd08.prod.outlook.com> <20170920103906.GA37848@arm.com> <DB5PR08MB1048C82AC75F2E8FA7A96C78987A0@DB5PR08MB1048.eurprd08.prod.outlook.com>,<20170926190437.GA40622@arm.com>
- Spamdiagnosticmetadata: NSPM
- Spamdiagnosticoutput: 1:99
Hi James
I have made the requested changes to the patch.
2017-09-27 Sudakshina Das <sudi.das@arm.com>
* config/aarch64/aarch64-protos.h (enum simd_immediate_check): New check type
for aarch64_simd_valid_immediate.
(aarch64_output_simd_mov_immediate): Update prototype.
(aarch64_simd_valid_immediate): Update prototype.
* config/aarch64/aarch64-simd.md (orr<mode>3): modified pattern to add
support for ORR-immediate.
(and<mode>3): modified pattern to add support for BIC-immediate.
* config/aarch64/aarch64.c (aarch64_simd_valid_immediate): Function now checks
for valid immediate for BIC and ORR based on new enum argument.
(aarch64_output_simd_mov_immediate): Function now used to output BIC/ORR imm
as well based on new enum argument.
* config/aarch64/constraints.md (Do): New vector immediate constraint.
(Db): Likewise.
2017-09-27 Sudakshina Das <sudi.das@arm.com>
* gcc.target/aarch64/bic_imm_1.c: New test.
* gcc.target/aarch64/orr_imm_1.c: Likewise.
Thanks
Sudi
From: James Greenhalgh <james.greenhalgh@arm.com>
Sent: Tuesday, September 26, 2017 8:04:38 PM
To: Sudi Das
Cc: Richard Earnshaw; gcc-patches@gcc.gnu.org; nd; Marcus Shawcroft
Subject: Re: [PATCH][AArch64] Add BIC-imm and ORR-imm SIMD pattern
On Mon, Sep 25, 2017 at 11:13:57AM +0100, Sudi Das wrote:
>
> Hi James
>
> I put aarch64_output_simd_general_immediate looking at the similarities of
> the immediates for mov/mvni and orr/bic. The CHECK macro in
> aarch64_simd_valid_immediate both checks
> and converts the immediates in a manner that are needed for the instructions.
>
> Having said that, I agree that maybe I could have refactored
> aarch64_output_simd_mov_immediate to do the work rather than creating a new
> functions to do similar things. I have done so in this patch.
Thanks, this looks much neater.
> I have also changed the names of the enum simd_immediate_check to be better
> indicative of what they are doing.
Thanks, I'd tweak them to look more like the bitmasks you use them as, but
that is a small change for my personal preference.
> Lastly I have added more cases in the tests (according to all the possible
> CHECKs) and made them dg-do assemble (although I had to add --save-temps so
> that the scan-assembler would work). Do you think I should not put that
> option and rather create separate tests?
This is good - thanks.
I think clean up the enum definitions and this patch will be good.
> @@ -308,6 +308,16 @@ enum aarch64_parse_opt_result
> AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
> };
>
> +/* Enum to distinguish which type of check is to be done in
> + aarch64_simd_valid_immediate. This is used as a bitmask where
> + AARCH64_CHECK_MOV has both bits set. Thus AARCH64_CHECK_MOV will
> + perform all checks. Adding new types would require changes accordingly. */
> +enum simd_immediate_check {
> + AARCH64_CHECK_ORR = 1, /* Perform immediate checks for ORR. */
> + AARCH64_CHECK_BIC = 2, /* Perform immediate checks for BIC. */
> + AARCH64_CHECK_MOV = 3 /* Perform all checks (used for MOVI/MNVI). */
These are used in bit-mask style, so how about:
AARCH64_CHECK_ORR = 1 << 0,
AARCH64_CHECK_BIC = 1 << 1,
AARCH64_CHECK_MOV = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
Which is more self-documenting.
> @@ -13001,7 +13013,8 @@ aarch64_float_const_representable_p (rtx x)
> char*
> aarch64_output_simd_mov_immediate (rtx const_vector,
> machine_mode mode,
> - unsigned width)
> + unsigned width,
> + enum simd_immediate_check which)
This function is sorely missing a comment explaining the parameters - it
would be very helpful if you could add one as part of this patch.
Thanks,
James
diff --git a/gcc/config/aarch64/aarch64-protos.h b/gcc/config/aarch64/aarch64-protos.h
index e67c2ed..5d7c5df 100644
--- a/gcc/config/aarch64/aarch64-protos.h
+++ b/gcc/config/aarch64/aarch64-protos.h
@@ -308,6 +308,16 @@ enum aarch64_parse_opt_result
AARCH64_PARSE_INVALID_ARG /* Invalid arch, tune, cpu arg. */
};
+/* Enum to distinguish which type of check is to be done in
+ aarch64_simd_valid_immediate. This is used as a bitmask where
+ AARCH64_CHECK_MOV has both bits set. Thus AARCH64_CHECK_MOV will
+ perform all checks. Adding new types would require changes accordingly. */
+enum simd_immediate_check {
+ AARCH64_CHECK_ORR = 1 << 0,
+ AARCH64_CHECK_BIC = 1 << 1,
+ AARCH64_CHECK_MOV = AARCH64_CHECK_ORR | AARCH64_CHECK_BIC
+};
+
extern struct tune_params aarch64_tune_params;
HOST_WIDE_INT aarch64_initial_elimination_offset (unsigned, unsigned);
@@ -345,7 +355,8 @@ bool aarch64_mov_operand_p (rtx, machine_mode);
rtx aarch64_reverse_mask (machine_mode);
bool aarch64_offset_7bit_signed_scaled_p (machine_mode, HOST_WIDE_INT);
char *aarch64_output_scalar_simd_mov_immediate (rtx, scalar_int_mode);
-char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned);
+char *aarch64_output_simd_mov_immediate (rtx, machine_mode, unsigned,
+ enum simd_immediate_check w = AARCH64_CHECK_MOV);
bool aarch64_pad_reg_upward (machine_mode, const_tree, bool);
bool aarch64_regno_ok_for_base_p (int, bool);
bool aarch64_regno_ok_for_index_p (int, bool);
@@ -356,7 +367,8 @@ bool aarch64_simd_imm_zero_p (rtx, machine_mode);
bool aarch64_simd_scalar_immediate_valid_for_move (rtx, scalar_int_mode);
bool aarch64_simd_shift_imm_p (rtx, machine_mode, bool);
bool aarch64_simd_valid_immediate (rtx, machine_mode, bool,
- struct simd_immediate_info *);
+ struct simd_immediate_info *,
+ enum simd_immediate_check w = AARCH64_CHECK_MOV);
bool aarch64_split_dimode_const_store (rtx, rtx);
bool aarch64_symbolic_address_p (rtx);
bool aarch64_uimm12_shift (HOST_WIDE_INT);
diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md
index 70e9339..0a7e5e8 100644
--- a/gcc/config/aarch64/aarch64-simd.md
+++ b/gcc/config/aarch64/aarch64-simd.md
@@ -558,21 +558,45 @@
[(set_attr "type" "neon_fp_abd_<stype><q>")]
)
+;; For AND (vector, register) and BIC (vector, immediate)
(define_insn "and<mode>3"
- [(set (match_operand:VDQ_I 0 "register_operand" "=w")
- (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w")
- (match_operand:VDQ_I 2 "register_operand" "w")))]
+ [(set (match_operand:VDQ_I 0 "register_operand" "=w,w")
+ (and:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+ (match_operand:VDQ_I 2 "nonmemory_operand" "w,Db")))]
"TARGET_SIMD"
- "and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return "and\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>";
+ case 1:
+ return aarch64_output_simd_mov_immediate (operands[2],
+ <MODE>mode, GET_MODE_BITSIZE (<MODE>mode), AARCH64_CHECK_BIC);
+ default:
+ gcc_unreachable ();
+ }
+ }
[(set_attr "type" "neon_logic<q>")]
)
+;; For ORR (vector, register) and ORR (vector, immediate)
(define_insn "ior<mode>3"
- [(set (match_operand:VDQ_I 0 "register_operand" "=w")
- (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w")
- (match_operand:VDQ_I 2 "register_operand" "w")))]
+ [(set (match_operand:VDQ_I 0 "register_operand" "=w,w")
+ (ior:VDQ_I (match_operand:VDQ_I 1 "register_operand" "w,0")
+ (match_operand:VDQ_I 2 "nonmemory_operand" "w,Do")))]
"TARGET_SIMD"
- "orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>"
+ {
+ switch (which_alternative)
+ {
+ case 0:
+ return "orr\t%0.<Vbtype>, %1.<Vbtype>, %2.<Vbtype>";
+ case 1:
+ return aarch64_output_simd_mov_immediate (operands[2],
+ <MODE>mode, GET_MODE_BITSIZE (<MODE>mode), AARCH64_CHECK_ORR);
+ default:
+ gcc_unreachable ();
+ }
+ }
[(set_attr "type" "neon_logic<q>")]
)
diff --git a/gcc/config/aarch64/aarch64.c b/gcc/config/aarch64/aarch64.c
index 5e26cb7..6a6b3d5 100644
--- a/gcc/config/aarch64/aarch64.c
+++ b/gcc/config/aarch64/aarch64.c
@@ -11471,7 +11471,8 @@ aarch64_vect_float_const_representable_p (rtx x)
/* Return true for valid and false for invalid. */
bool
aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
- struct simd_immediate_info *info)
+ struct simd_immediate_info *info,
+ enum simd_immediate_check which)
{
#define CHECK(STRIDE, ELSIZE, CLASS, TEST, SHIFT, NEG) \
matches = 1; \
@@ -11539,54 +11540,65 @@ aarch64_simd_valid_immediate (rtx op, machine_mode mode, bool inverse,
do
{
- CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0
- && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0);
+ if (which & AARCH64_CHECK_ORR)
+ {
+ CHECK (4, 32, 0, bytes[i] == bytes[0] && bytes[i + 1] == 0
+ && bytes[i + 2] == 0 && bytes[i + 3] == 0, 0, 0);
- CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1]
- && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
+ CHECK (4, 32, 1, bytes[i] == 0 && bytes[i + 1] == bytes[1]
+ && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
- CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0
- && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
+ CHECK (4, 32, 2, bytes[i] == 0 && bytes[i + 1] == 0
+ && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
- CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0
- && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0);
+ CHECK (4, 32, 3, bytes[i] == 0 && bytes[i + 1] == 0
+ && bytes[i + 2] == 0 && bytes[i + 3] == bytes[3], 24, 0);
- CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0);
+ CHECK (2, 16, 4, bytes[i] == bytes[0] && bytes[i + 1] == 0, 0, 0);
- CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0);
+ CHECK (2, 16, 5, bytes[i] == 0 && bytes[i + 1] == bytes[1], 8, 0);
+ }
- CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff
- && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1);
+ if (which & AARCH64_CHECK_BIC)
+ {
+ CHECK (4, 32, 6, bytes[i] == bytes[0] && bytes[i + 1] == 0xff
+ && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 0, 1);
- CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
- && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
+ CHECK (4, 32, 7, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
+ && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
- CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff
- && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
+ CHECK (4, 32, 8, bytes[i] == 0xff && bytes[i + 1] == 0xff
+ && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
- CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff
- && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1);
+ CHECK (4, 32, 9, bytes[i] == 0xff && bytes[i + 1] == 0xff
+ && bytes[i + 2] == 0xff && bytes[i + 3] == bytes[3], 24, 1);
- CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1);
+ CHECK (2, 16, 10, bytes[i] == bytes[0] && bytes[i + 1] == 0xff, 0, 1);
- CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1);
+ CHECK (2, 16, 11, bytes[i] == 0xff && bytes[i + 1] == bytes[1], 8, 1);
+ }
- CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
- && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
+ /* Shifting ones / 8-bit / 64-bit variants only checked
+ for 'ALL' (MOVI/MVNI). */
+ if (which == AARCH64_CHECK_MOV)
+ {
+ CHECK (4, 32, 12, bytes[i] == 0xff && bytes[i + 1] == bytes[1]
+ && bytes[i + 2] == 0 && bytes[i + 3] == 0, 8, 0);
- CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1]
- && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
+ CHECK (4, 32, 13, bytes[i] == 0 && bytes[i + 1] == bytes[1]
+ && bytes[i + 2] == 0xff && bytes[i + 3] == 0xff, 8, 1);
- CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff
- && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
+ CHECK (4, 32, 14, bytes[i] == 0xff && bytes[i + 1] == 0xff
+ && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0, 16, 0);
- CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0
- && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
+ CHECK (4, 32, 15, bytes[i] == 0 && bytes[i + 1] == 0
+ && bytes[i + 2] == bytes[2] && bytes[i + 3] == 0xff, 16, 1);
- CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
+ CHECK (1, 8, 16, bytes[i] == bytes[0], 0, 0);
- CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff)
- && bytes[i] == bytes[(i + 8) % idx], 0, 0);
+ CHECK (1, 64, 17, (bytes[i] == 0 || bytes[i] == 0xff)
+ && bytes[i] == bytes[(i + 8) % idx], 0, 0);
+ }
}
while (0);
@@ -12998,10 +13010,14 @@ aarch64_float_const_representable_p (rtx x)
return (exponent >= 0 && exponent <= 7);
}
+/* Returns the string with the instruction for AdvSIMD MOVI, MVNI, ORR or BIC
+ immediate with a CONST_VECTOR of MODE and WIDTH. WHICH selects whether to
+ output MOVI/MVNI, ORR or BIC immediate. */
char*
aarch64_output_simd_mov_immediate (rtx const_vector,
machine_mode mode,
- unsigned width)
+ unsigned width,
+ enum simd_immediate_check which)
{
bool is_valid;
static char templ[40];
@@ -13013,9 +13029,11 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
struct simd_immediate_info info = { NULL_RTX, 0, 0, false, false };
/* This will return true to show const_vector is legal for use as either
- a AdvSIMD MOVI instruction (or, implicitly, MVNI) immediate. It will
- also update INFO to show how the immediate should be generated. */
- is_valid = aarch64_simd_valid_immediate (const_vector, mode, false, &info);
+ a AdvSIMD MOVI instruction (or, implicitly, MVNI), ORR or BIC immediate.
+ It will also update INFO to show how the immediate should be generated.
+ WHICH selects whether to check for MOVI/MVNI, ORR or BIC. */
+ is_valid = aarch64_simd_valid_immediate (const_vector, mode, false,
+ &info, which);
gcc_assert (is_valid);
element_char = sizetochar (info.element_width);
@@ -13046,20 +13064,37 @@ aarch64_output_simd_mov_immediate (rtx const_vector,
}
}
- mnemonic = info.mvn ? "mvni" : "movi";
- shift_op = info.msl ? "msl" : "lsl";
-
gcc_assert (CONST_INT_P (info.value));
- if (lane_count == 1)
- snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX,
- mnemonic, UINTVAL (info.value));
- else if (info.shift)
- snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX
- ", %s %d", mnemonic, lane_count, element_char,
- UINTVAL (info.value), shift_op, info.shift);
+
+ if (which == AARCH64_CHECK_MOV)
+ {
+ mnemonic = info.mvn ? "mvni" : "movi";
+ shift_op = info.msl ? "msl" : "lsl";
+ if (lane_count == 1)
+ snprintf (templ, sizeof (templ), "%s\t%%d0, " HOST_WIDE_INT_PRINT_HEX,
+ mnemonic, UINTVAL (info.value));
+ else if (info.shift)
+ snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
+ HOST_WIDE_INT_PRINT_HEX ", %s %d", mnemonic, lane_count,
+ element_char, UINTVAL (info.value), shift_op, info.shift);
+ else
+ snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, "
+ HOST_WIDE_INT_PRINT_HEX, mnemonic, lane_count,
+ element_char, UINTVAL (info.value));
+ }
else
- snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, " HOST_WIDE_INT_PRINT_HEX,
- mnemonic, lane_count, element_char, UINTVAL (info.value));
+ {
+ /* For AARCH64_CHECK_BIC and AARCH64_CHECK_ORR. */
+ mnemonic = info.mvn ? "bic" : "orr";
+ if (info.shift)
+ snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
+ HOST_WIDE_INT_PRINT_DEC ", %s #%d", mnemonic, lane_count,
+ element_char, UINTVAL (info.value), "lsl", info.shift);
+ else
+ snprintf (templ, sizeof (templ), "%s\t%%0.%d%c, #"
+ HOST_WIDE_INT_PRINT_DEC, mnemonic, lane_count,
+ element_char, UINTVAL (info.value));
+ }
return templ;
}
diff --git a/gcc/config/aarch64/constraints.md b/gcc/config/aarch64/constraints.md
index 3649fb4..77c510c 100644
--- a/gcc/config/aarch64/constraints.md
+++ b/gcc/config/aarch64/constraints.md
@@ -190,6 +190,20 @@
(and (match_code "const_double")
(match_test "aarch64_can_const_movi_rtx_p (op, GET_MODE (op))")))
+(define_constraint "Do"
+ "@internal
+ A constraint that matches vector of immediates for orr."
+ (and (match_code "const_vector")
+ (match_test "aarch64_simd_valid_immediate (op, mode, false,
+ NULL, AARCH64_CHECK_ORR)")))
+
+(define_constraint "Db"
+ "@internal
+ A constraint that matches vector of immediates for bic."
+ (and (match_code "const_vector")
+ (match_test "aarch64_simd_valid_immediate (op, mode, false,
+ NULL, AARCH64_CHECK_BIC)")))
+
(define_constraint "Dn"
"@internal
A constraint that matches vector of immediates."
diff --git a/gcc/testsuite/gcc.target/aarch64/bic_imm_1.c b/gcc/testsuite/gcc.target/aarch64/bic_imm_1.c
new file mode 100644
index 0000000..b14f009
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/bic_imm_1.c
@@ -0,0 +1,56 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 --save-temps -ftree-vectorize" } */
+
+/* Each function uses the correspoding 'CLASS' in
+ Marco CHECK (aarch64_simd_valid_immediate). */
+
+void
+bic_6 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] &= ~(0xab);
+}
+
+void
+bic_7 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] &= ~(0xcd00);
+}
+
+void
+bic_8 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] &= ~(0xef0000);
+}
+
+void
+bic_9 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] &= ~(0x12000000);
+}
+
+void
+bic_10 (short *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] &= ~(0x34);
+}
+
+
+void
+bic_11 (short *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] &= ~(0x5600);
+}
+
+
+/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.4s, #171" } } */
+/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.4s, #205, lsl #8" } } */
+/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.4s, #239, lsl #16" } } */
+/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.4s, #18, lsl #24" } } */
+/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.8h, #52" } } */
+/* { dg-final { scan-assembler "bic\\tv\[0-9\]+.8h, #86, lsl #8" } } */
diff --git a/gcc/testsuite/gcc.target/aarch64/orr_imm_1.c b/gcc/testsuite/gcc.target/aarch64/orr_imm_1.c
new file mode 100644
index 0000000..ff6f683
--- /dev/null
+++ b/gcc/testsuite/gcc.target/aarch64/orr_imm_1.c
@@ -0,0 +1,54 @@
+/* { dg-do assemble } */
+/* { dg-options "-O2 --save-temps -ftree-vectorize" } */
+
+/* Each function uses the correspoding 'CLASS' in
+ Marco CHECK (aarch64_simd_valid_immediate). */
+
+void
+orr_0 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] |= 0xab;
+}
+
+void
+orr_1 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] |= 0x0000cd00;
+}
+
+void
+orr_2 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] |= 0x00ef0000;
+}
+
+void
+orr_3 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] |= 0x12000000;
+}
+
+void
+orr_4 (short *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] |= 0x00340034;
+}
+
+void
+orr_5 (int *a)
+{
+ for (int i = 0; i < 1024; i++)
+ a[i] |= 0x56005600;
+}
+
+/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.4s, #171" } } */
+/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.4s, #205, lsl #8" } } */
+/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.4s, #239, lsl #16" } } */
+/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.4s, #18, lsl #24" } } */
+/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.8h, #52" } } */
+/* { dg-final { scan-assembler "orr\\tv\[0-9\]+.8h, #86, lsl #8" } } */