Hi,
During expand, function vcond<mode><mode> inverses some CMP, e.g.
a LE b -> b GE a
But if "b" is "CONST0_RTX", "b GE a" will be an illegal insn.
(insn 933 932 934 113 (set (reg:V4SI 1027)
(unspec:V4SI [
(const_vector:V4SI [
(const_int 0 [0])
(const_int 0 [0])
(const_int 0 [0])
(const_int 0 [0])
])
(reg:V4SI 1023 [ vect_var_.49 ])
(const_int 1 [0x1])
] UNSPEC_VCGE)) PUGHSlab/Mapping.c:567 -1
(nil))
Refer https://bugs.launchpad.net/linaro-toolchain-binaries/+bug/1189445
for more. And the bug also happens for FSF trunk.
The similar issue
(https://bugs.launchpad.net/linaro-toolchain-binaries/+bug/1163942)
had fixed on AARCH64:
http://gcc.gnu.org/ml/gcc-patches/2013-04/msg00581.html
The patch is similar to the fix for aarch64.
Bootstrap and no make check regression on Panda Board.
Is it OK for trunk and 4.8?
Thanks!
-Zhenqiang
ChangeLog:
2013-06-18 Zhenqiang Chen <[email protected]>
* config/arm/neon.md (vcond): Fix floating-point vector
comparisons against 0.
diff --git a/gcc/config/arm/neon.md b/gcc/config/arm/neon.md
index e814df0..9299ae5 100644
--- a/gcc/config/arm/neon.md
+++ b/gcc/config/arm/neon.md
@@ -1671,6 +1671,7 @@
? 3 : 1;
rtx magic_rtx = GEN_INT (magic_word);
int inverse = 0;
+ int use_zero_form = 0;
int swap_bsl_operands = 0;
rtx mask = gen_reg_rtx (<V_cmp_result>mode);
rtx tmp = gen_reg_rtx (<V_cmp_result>mode);
@@ -1681,12 +1682,16 @@
switch (GET_CODE (operands[3]))
{
case GE:
+ case GT:
case LE:
+ case LT:
case EQ:
- if (!REG_P (operands[5])
- && (operands[5] != CONST0_RTX (<MODE>mode)))
- operands[5] = force_reg (<MODE>mode, operands[5]);
- break;
+ if (operands[5] == CONST0_RTX (<MODE>mode))
+ {
+ use_zero_form = 1;
+ break;
+ }
+ /* Fall through. */
default:
if (!REG_P (operands[5]))
operands[5] = force_reg (<MODE>mode, operands[5]);
@@ -1737,7 +1742,26 @@
a GT b -> a GT b
a LE b -> b GE a
a LT b -> b GT a
- a EQ b -> a EQ b */
+ a EQ b -> a EQ b
+ Note that there also exist direct comparison against 0 forms,
+ so catch those as a special case. */
+ if (use_zero_form)
+ {
+ inverse = 0;
+ switch (GET_CODE (operands[3]))
+ {
+ case LT:
+ base_comparison = gen_neon_vclt<mode>;
+ break;
+ case LE:
+ base_comparison = gen_neon_vcle<mode>;
+ break;
+ default:
+ /* Do nothing, other zero form cases already have the correct
+ base_comparison. */
+ break;
+ }
+ }
if (!inverse)
emit_insn (base_comparison (mask, operands[4], operands[5], magic_rtx));