[(set_attr "type" "simd_int_arith")
(set_attr "mode" "<MODE>")])
-(define_expand "copysign<mode>3"
- [(set (match_dup 4)
- (and:FLASX
- (not:FLASX (match_dup 3))
- (match_operand:FLASX 1 "register_operand")))
- (set (match_dup 5)
- (and:FLASX (match_dup 3)
- (match_operand:FLASX 2 "reg_or_vector_same_val_operand")))
- (set (match_operand:FLASX 0 "register_operand")
- (ior:FLASX (match_dup 4) (match_dup 5)))]
- "ISA_HAS_LASX"
-{
- /* copysign (x, -1) should instead be expanded as setting the sign
- bit. */
- if (!REG_P (operands[2]))
- {
- rtx op2_elt = unwrap_const_vec_duplicate (operands[2]);
- if (GET_CODE (op2_elt) == CONST_DOUBLE
- && real_isneg (CONST_DOUBLE_REAL_VALUE (op2_elt)))
- {
- rtx n = GEN_INT (8 * GET_MODE_SIZE (<UNITMODE>mode) - 1);
- operands[0] = lowpart_subreg (<VIMODE256>mode, operands[0],
- <MODE>mode);
- operands[1] = lowpart_subreg (<VIMODE256>mode, operands[1],
- <MODE>mode);
- emit_insn (gen_lasx_xvbitseti_<lasxfmt> (operands[0],
- operands[1], n));
- DONE;
- }
- }
-
- operands[2] = force_reg (<MODE>mode, operands[2]);
- operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
-
- operands[4] = gen_reg_rtx (<MODE>mode);
- operands[5] = gen_reg_rtx (<MODE>mode);
-})
-
-(define_expand "xorsign<mode>3"
- [(set (match_dup 4)
- (and:FLASX (match_dup 3)
- (match_operand:FLASX 2 "register_operand")))
- (set (match_operand:FLASX 0 "register_operand")
- (xor:FLASX (match_dup 4)
- (match_operand:FLASX 1 "register_operand")))]
- "ISA_HAS_LASX"
-{
- operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
-
- operands[4] = gen_reg_rtx (<MODE>mode);
-})
-
-
(define_insn "absv4df2"
[(set (match_operand:V4DF 0 "register_operand" "=f")
(abs:V4DF (match_operand:V4DF 1 "register_operand" "f")))]
&& (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT
|| GET_MODE_CLASS (mode) == MODE_VECTOR_INT))
{
- unsigned HOST_WIDE_INT val;
-
- if (GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT)
- {
- rtx val_s = CONST_VECTOR_ELT (op, 0);
- const REAL_VALUE_TYPE *x = CONST_DOUBLE_REAL_VALUE (val_s);
- if (GET_MODE (val_s) == DFmode)
- {
- long tmp[2];
- REAL_VALUE_TO_TARGET_DOUBLE (*x, tmp);
- val = (unsigned HOST_WIDE_INT) tmp[1] << 32 | tmp[0];
- }
- else
- {
- long tmp;
- REAL_VALUE_TO_TARGET_SINGLE (*x, tmp);
- val = (unsigned HOST_WIDE_INT) tmp;
- }
- }
- else
- val = UINTVAL (CONST_VECTOR_ELT (op, 0));
-
+ unsigned HOST_WIDE_INT val = UINTVAL (CONST_VECTOR_ELT (op, 0));
int vlog2 = exact_log2 (val & GET_MODE_MASK (GET_MODE_INNER (mode)));
if (vlog2 != -1)
{
machine_mode mode = GET_MODE_INNER (GET_MODE (op));
rtx val_s = CONST_VECTOR_ELT (op, 0);
- unsigned HOST_WIDE_INT val;
-
- if (GET_MODE_CLASS (mode) == MODE_FLOAT)
+ if (CONST_INT_P (val_s))
{
- const REAL_VALUE_TYPE *x = CONST_DOUBLE_REAL_VALUE (val_s);
- if (GET_MODE (val_s) == DFmode)
- {
- long tmp[2];
- REAL_VALUE_TO_TARGET_DOUBLE (*x, tmp);
- val = (unsigned HOST_WIDE_INT) (tmp[1] << 32 | tmp[0]);
- }
- else
+ unsigned HOST_WIDE_INT val = UINTVAL (val_s);
+ int vlog2 = exact_log2 (val & GET_MODE_MASK (mode));
+ if (vlog2 != -1)
{
- long tmp;
- REAL_VALUE_TO_TARGET_SINGLE (*x, tmp);
- val = (unsigned HOST_WIDE_INT) tmp;
+ fprintf (file, "%d", vlog2);
+ break;
}
}
- else
- val = UINTVAL (val_s);
-
- int vlog2 = exact_log2 (val & GET_MODE_MASK (mode));
- if (vlog2 != -1)
- fprintf (file, "%d", vlog2);
- else
- output_operand_lossage ("invalid use of '%%%c'", letter);
}
- else
- output_operand_lossage ("invalid use of '%%%c'", letter);
+ output_operand_lossage ("invalid use of '%%%c'", letter);
break;
case 'W':
return force_reg (inner_mode, mask);
v = loongarch_build_const_vector (vec_mode, vect, mask);
- return force_reg (vec_mode, v);
+ return v;
}
/* Use rsqrte instruction and Newton-Rhapson to compute the approximation of
if (VECTOR_MODE_P (mode))
{
machine_mode imode = related_int_vector_mode (mode).require ();
- rtx mask = gen_reg_rtx (imode);
- emit_insn (gen_rtx_SET (mask, gen_rtx_NE (imode, a, zero)));
- emit_insn (gen_rtx_SET (x0, gen_rtx_AND (mode, x0,
- gen_lowpart (mode, mask))));
+ rtx mask = force_reg (imode, gen_rtx_NE (imode, a, zero));
+ emit_move_insn (gen_lowpart (imode, x0),
+ gen_rtx_AND (imode,
+ gen_lowpart (imode, x0),
+ mask));
}
else
{
[(set_attr "type" "simd_int_arith")
(set_attr "mode" "<MODE>")])
-(define_expand "copysign<mode>3"
- [(set (match_dup 4)
- (and:FLSX
- (not:FLSX (match_dup 3))
- (match_operand:FLSX 1 "register_operand")))
- (set (match_dup 5)
- (and:FLSX (match_dup 3)
- (match_operand:FLSX 2 "reg_or_vector_same_val_operand")))
- (set (match_operand:FLSX 0 "register_operand")
- (ior:FLSX (match_dup 4) (match_dup 5)))]
- "ISA_HAS_LSX"
-{
- /* copysign (x, -1) should instead be expanded as setting the sign
- bit. */
- if (!REG_P (operands[2]))
- {
- rtx op2_elt = unwrap_const_vec_duplicate (operands[2]);
- if (GET_CODE (op2_elt) == CONST_DOUBLE
- && real_isneg (CONST_DOUBLE_REAL_VALUE (op2_elt)))
- {
- rtx n = GEN_INT (8 * GET_MODE_SIZE (<UNITMODE>mode) - 1);
- operands[0] = lowpart_subreg (<VIMODE>mode, operands[0],
- <MODE>mode);
- operands[1] = lowpart_subreg (<VIMODE>mode, operands[1],
- <MODE>mode);
- emit_insn (gen_lsx_vbitseti_<lsxfmt> (operands[0], operands[1],
- n));
- DONE;
- }
- }
-
- operands[2] = force_reg (<MODE>mode, operands[2]);
- operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
-
- operands[4] = gen_reg_rtx (<MODE>mode);
- operands[5] = gen_reg_rtx (<MODE>mode);
-})
-
-(define_expand "@xorsign<mode>3"
- [(set (match_dup 4)
- (and:FLSX (match_dup 3)
- (match_operand:FLSX 2 "register_operand")))
- (set (match_operand:FLSX 0 "register_operand")
- (xor:FLSX (match_dup 4)
- (match_operand:FLSX 1 "register_operand")))]
- "ISA_HAS_LSX"
-{
- operands[3] = loongarch_build_signbit_mask (<MODE>mode, 1, 0);
-
- operands[4] = gen_reg_rtx (<MODE>mode);
-})
-
-
(define_insn "absv2df2"
[(set (match_operand:V2DF 0 "register_operand" "=f")
(abs:V2DF (match_operand:V2DF 1 "register_operand" "f")))]
return loongarch_const_vector_same_int_p (op, mode);
})
+(define_predicate "const_vector_neg_fp_operand"
+ (match_code "const_vector")
+{
+ machine_mode imode = related_int_vector_mode (mode).require ();
+ rtx mask = loongarch_build_signbit_mask (imode, 1, 0);
+
+ op = gen_lowpart (imode, op);
+ return rtx_equal_p (mask,
+ simplify_const_binary_operation (AND, imode, mask,
+ op));
+})
+
(define_predicate "par_const_vector_shf_set_operand"
(match_code "parallel")
{
(ior (match_operand 0 "register_operand")
(match_operand 0 "const_vector_same_uimm_operand")))
+(define_predicate "reg_or_vector_neg_fp_operand"
+ (ior (match_operand 0 "register_operand")
+ (match_operand 0 "const_vector_neg_fp_operand")))
+
;; PARALLEL for a vec_select that selects all the even or all the odd
;; elements of a vector of MODE.
(define_special_predicate "vect_par_cnst_even_or_odd_half"
})
(define_insn "xor<mode>3"
- [(set (match_operand:ALLVEC 0 "register_operand" "=f,f,f")
- (xor:ALLVEC
- (match_operand:ALLVEC 1 "register_operand" "f,f,f")
- (match_operand:ALLVEC 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
+ [(set (match_operand:IVEC 0 "register_operand" "=f,f,f")
+ (xor:IVEC
+ (match_operand:IVEC 1 "register_operand" "f,f,f")
+ (match_operand:IVEC 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
""
"@
<x>vxor.v\t%<wu>0,%<wu>1,%<wu>2
(set_attr "mode" "<MODE>")])
(define_insn "ior<mode>3"
- [(set (match_operand:ALLVEC 0 "register_operand" "=f,f,f")
- (ior:ALLVEC
- (match_operand:ALLVEC 1 "register_operand" "f,f,f")
- (match_operand:ALLVEC 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
+ [(set (match_operand:IVEC 0 "register_operand" "=f,f,f")
+ (ior:IVEC
+ (match_operand:IVEC 1 "register_operand" "f,f,f")
+ (match_operand:IVEC 2 "reg_or_vector_same_val_operand" "f,YC,Urv8")))]
""
"@
<x>vor.v\t%<wu>0,%<wu>1,%<wu>2
(set_attr "mode" "<MODE>")])
(define_insn "and<mode>3"
- [(set (match_operand:ALLVEC 0 "register_operand" "=f,f,f")
- (and:ALLVEC
- (match_operand:ALLVEC 1 "register_operand" "f,f,f")
- (match_operand:ALLVEC 2 "reg_or_vector_same_val_operand" "f,YZ,Urv8")))]
+ [(set (match_operand:IVEC 0 "register_operand" "=f,f,f")
+ (and:IVEC
+ (match_operand:IVEC 1 "register_operand" "f,f,f")
+ (match_operand:IVEC 2 "reg_or_vector_same_val_operand" "f,YZ,Urv8")))]
""
{
switch (which_alternative)
return "<x>vand.v\t%<wu>0,%<wu>1,%<wu>2";
case 1:
{
- rtx elt0 = CONST_VECTOR_ELT (operands[2], 0);
- unsigned HOST_WIDE_INT val;
- if (GET_MODE_CLASS (<MODE>mode) == MODE_VECTOR_FLOAT)
- {
- const REAL_VALUE_TYPE *x = CONST_DOUBLE_REAL_VALUE (elt0);
- if (GET_MODE (elt0) == DFmode)
- {
- long tmp[2];
- REAL_VALUE_TO_TARGET_DOUBLE (*x, tmp);
- val = ~((unsigned HOST_WIDE_INT) tmp[1] << 32 | tmp[0]);
- }
- else
- {
- long tmp;
- REAL_VALUE_TO_TARGET_SINGLE (*x, tmp);
- val = ~((unsigned HOST_WIDE_INT) tmp);
- }
- }
- else
- val = ~UINTVAL (elt0);
- operands[2] = loongarch_gen_const_int_vector (<VIMODE>mode, val & (-val));
+ operands[2] = simplify_const_unary_operation (NOT, <MODE>mode,
+ operands[2],
+ <MODE>mode);
return "<x>vbitclri.%v0\t%<wu>0,%<wu>1,%V2";
}
case 2:
[(set_attr "type" "simd_logic,simd_bit,simd_logic")
(set_attr "mode" "<MODE>")])
+(define_expand "copysign<mode>3"
+ [(match_operand:FVEC 0 "register_operand")
+ (match_operand:FVEC 1 "register_operand")
+ (match_operand:FVEC 2 "reg_or_vector_neg_fp_operand")]
+ ""
+{
+ machine_mode imode = <VIMODE>mode;
+ rtx op[3], mask = loongarch_build_signbit_mask (imode, 1, 0);
+
+ /* Pun the operation into fixed-point bitwise operations. */
+ for (int i = 0; i < 3; i++)
+ op[i] = lowpart_subreg (imode, operands[i], <MODE>mode);
+
+ /* Copysign from a positive const should have been already simplified
+ to abs, ignore the case here. Copysign from a negative const is
+ a simple vbitset which is an alternative of ior (see above). */
+ if (const_vector_neg_fp_operand (operands[2], <MODE>mode))
+ emit_insn (gen_ior<vimode>3 (op[0], op[1], mask));
+ else
+ {
+ mask = force_reg (imode, mask);
+ emit_insn (gen_<simd_isa>_<x>vbitsel_<simdfmt_as_i> (op[0], op[1],
+ op[2], mask));
+ }
+
+ DONE;
+})
+
+(define_expand "@xorsign<mode>3"
+ [(match_operand:FVEC 0 "register_operand")
+ (match_operand:FVEC 1 "register_operand")
+ (match_operand:FVEC 2 "register_operand")]
+ ""
+{
+ machine_mode imode = <VIMODE>mode;
+ rtx op[3];
+
+ for (int i = 0; i < 3; i++)
+ op[i] = lowpart_subreg (imode, operands[i], <MODE>mode);
+
+ rtx t = loongarch_build_signbit_mask (imode, 1, 0);
+ t = force_reg (imode, simplify_gen_binary (AND, imode, op[2], t));
+ emit_move_insn (op[0], simplify_gen_binary (XOR, imode, op[1], t));
+ DONE;
+})
+
(define_insn "@simd_vshuf_<mode>"
[(set (match_operand:QIVEC 0 "register_operand" "=f")
(unspec:QIVEC [(match_operand:QIVEC 1 "register_operand" "f")