LoongArch: rework copysign and xorsign implementation
The copysign and xorsign implementation had two significant bugs:
1. The GCC Internal documentation explicitly says the IOR, XOR, and AND
optabs are only for fixed-point modes, i.e. they cannot be used for
floating-point modes.
2. The handling of "%V" uses a very nasty way to pun floating-point
const value to integer representation, invoking undefined behavior on
32-bit hosts by shifting left a "long" by 32 bits. In fact
lowpart_subreg handles punning of const values correctly despite the
name contains "reg."
Fix the bugs by using lowpart_subreg to pun the modes in the expanders.
gcc/
* config/loongarch/predicates.md (const_vector_neg_fp_operand):
New define_predicate.
(reg_or_vector_neg_fp_operand): New define_predicate.
* config/loongarch/lasx.md (copysign<mode>3): Remove.
(xorsign<mode>3): Remove.
* config/loongarch/lsx.md (copysign<mode>3): Remove.
(@xorsign<mode>3): Remove.
* config/loongarch/simd.md (copysign<mode>3): New define_expand.
(@xorsign<mode>3): New define_expand.
(and<mode>3): Only allow IVEC instead of ALLVEC.
(ior<mode>3): Likewise.
(xor<mode>3): Likewise.
* config/loongarch/loongarch.cc (loongarch_print_operand): No
longer allow floating-point vector constants for %V.
(loongarch_const_vector_bitimm_set_p): Always return false for
floating-point vector constants.
(loongarch_build_signbit_mask): Factor out force_reg.
(loongarch_emit_swrsqrtsf): Use integer vector mode instead of
floating-point vector mode when masking zero inputs.