Hi all,
Previously, the compiler will generate the following pattern, which will
cause an ICE during postreload pass. Meanwhile, the instruction itself
produces UNKNOWN result when the source and destination register are the
same according to ARM instruction manual. The same rule applies to vtrn
and vzip patterns.
(insn 50 71 106 3 (parallel [
(set (reg:V2SI 48 d16 [172])
(unspec:V2SI [
(reg:V2SI 48 d16 [172])
(reg:V2SI 48 d16 [172])
] UNSPEC_VUZP1))
(set (reg:V2SI 48 d16 [172])
(unspec:V2SI [
(reg:V2SI 48 d16 [172])
(reg:V2SI 48 d16 [172])
] UNSPEC_VUZP2))
]) /src/gcc/gcc/testsuite/gcc.dg/vect/pr37474.c:21 1991
{*neon_vuzpv2si_insn}
(nil))
The ICE is triggered when compiling gcc.dg/vect/pr37474.c using
arm-none-linux-gnueabihf toolchain.
Adding "&" modifier to operands[0] and operands[2] will explicitly
prevent those two register operands getting the same register.
I made the same changes to neon_vtrn<mode>_insn and neon_vzip<mode>_insn
pattern as well.
arm-none-linux-gnueabihf regression tests Okay. Okay to commit?
Regards,
Renlin Li
gcc/ChangeLog:
2015-10-06 Renlin Li <renlin...@arm.com>
* config/arm/neon.md (neon_vuzp<mode>_insn): Add & modifier for
operands[0] and operands[2].
(neon_vtrn<mode>_insn): Likewise.
(neon_vzip<mode>_insn): Likewise.
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index 2667866..e5a2b0f 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -4074,11 +4074,11 @@ if (BYTES_BIG_ENDIAN)
;; Note: Different operand numbering to handle tied registers correctly.
(define_insn "*neon_vtrn<mode>_insn"
- [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ [(set (match_operand:VDQW 0 "s_register_operand" "=&w")
(unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
(match_operand:VDQW 3 "s_register_operand" "2")]
UNSPEC_VTRN1))
- (set (match_operand:VDQW 2 "s_register_operand" "=w")
+ (set (match_operand:VDQW 2 "s_register_operand" "=&w")
(unspec:VDQW [(match_dup 1) (match_dup 3)]
UNSPEC_VTRN2))]
"TARGET_NEON"
@@ -4100,11 +4100,11 @@ if (BYTES_BIG_ENDIAN)
;; Note: Different operand numbering to handle tied registers correctly.
(define_insn "*neon_vzip<mode>_insn"
- [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ [(set (match_operand:VDQW 0 "s_register_operand" "=&w")
(unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
(match_operand:VDQW 3 "s_register_operand" "2")]
UNSPEC_VZIP1))
- (set (match_operand:VDQW 2 "s_register_operand" "=w")
+ (set (match_operand:VDQW 2 "s_register_operand" "=&w")
(unspec:VDQW [(match_dup 1) (match_dup 3)]
UNSPEC_VZIP2))]
"TARGET_NEON"
@@ -4126,11 +4126,11 @@ if (BYTES_BIG_ENDIAN)
;; Note: Different operand numbering to handle tied registers correctly.
(define_insn "*neon_vuzp<mode>_insn"
- [(set (match_operand:VDQW 0 "s_register_operand" "=w")
+ [(set (match_operand:VDQW 0 "s_register_operand" "=&w")
(unspec:VDQW [(match_operand:VDQW 1 "s_register_operand" "0")
(match_operand:VDQW 3 "s_register_operand" "2")]
UNSPEC_VUZP1))
- (set (match_operand:VDQW 2 "s_register_operand" "=w")
+ (set (match_operand:VDQW 2 "s_register_operand" "=&w")
(unspec:VDQW [(match_dup 1) (match_dup 3)]
UNSPEC_VUZP2))]
"TARGET_NEON"