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 <zhenqiang.c...@linaro.org> * 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));