diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 90399d58f49..75da80b5cbf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,11 @@ +2015-12-16 Kyrylo Tkachov + + PR target/68696 + * config/aarch64/aarch64-simd.md (*aarch64_simd_bsl_alt): + New pattern. + (aarch64_simd_bsl_internal): Update comment to reflect + the above. + 2015-12-16 Richard Biener PR tree-optimization/68870 diff --git a/gcc/config/aarch64/aarch64-simd.md b/gcc/config/aarch64/aarch64-simd.md index 030a1013caa..2856f017c16 100644 --- a/gcc/config/aarch64/aarch64-simd.md +++ b/gcc/config/aarch64/aarch64-simd.md @@ -2153,6 +2153,10 @@ ;; bit op0, op2, mask ;; if (op0 = op2) (so 0-bits in mask choose bits from op1, else op0) ;; bif op0, op1, mask +;; +;; This pattern is expanded to by the aarch64_simd_bsl expander. +;; Some forms of straight-line code may generate the equivalent form +;; in *aarch64_simd_bsl_alt. (define_insn "aarch64_simd_bsl_internal" [(set (match_operand:VSDQ_I_DI 0 "register_operand" "=w,w,w") @@ -2172,6 +2176,29 @@ [(set_attr "type" "neon_bsl")] ) +;; We need this form in addition to the above pattern to match the case +;; when combine tries merging three insns such that the second operand of +;; the outer XOR matches the second operand of the inner XOR rather than +;; the first. The two are equivalent but since recog doesn't try all +;; permutations of commutative operations, we have to have a separate pattern. + +(define_insn "*aarch64_simd_bsl_alt" + [(set (match_operand:VSDQ_I_DI 0 "register_operand" "=w,w,w") + (xor:VSDQ_I_DI + (and:VSDQ_I_DI + (xor:VSDQ_I_DI + (match_operand:VSDQ_I_DI 3 "register_operand" "w,w,0") + (match_operand:VSDQ_I_DI 2 "register_operand" "w,0,w")) + (match_operand:VSDQ_I_DI 1 "register_operand" "0,w,w")) + (match_dup:VSDQ_I_DI 2)))] + "TARGET_SIMD" + "@ + bsl\\t%0., %3., %2. + bit\\t%0., %3., %1. + bif\\t%0., %2., %1." + [(set_attr "type" "neon_bsl")] +) + (define_expand "aarch64_simd_bsl" [(match_operand:VALLDIF 0 "register_operand") (match_operand: 1 "register_operand")