For previous architectures emulate operation abs.
gcc/ChangeLog:
* config/s390/s390-builtins.def (s390_vec_abs_s128): Add.
(s390_vlpq): Add.
* config/s390/s390-builtin-types.def: Update accordingly.
* config/s390/vector.md (abs<mode>2): Emulate w/o VXE3.
(*abs<mode>2): Add 128-bit variant.
(*vec_sel0<mode>): Make it a ...
(vec_sel0<mode>): named pattern.
gcc/testsuite/ChangeLog:
* gcc.target/s390/vector/vec-abs-emu.c: New test.
DEF_FN_TYPE_0 (BT_FN_INT, BT_INT)
DEF_FN_TYPE_0 (BT_FN_UINT, BT_UINT)
DEF_FN_TYPE_0 (BT_FN_VOID, BT_VOID)
+DEF_FN_TYPE_1 (BT_FN_INT128_INT128, BT_INT128, BT_INT128)
DEF_FN_TYPE_1 (BT_FN_INT128_V2DI, BT_INT128, BT_V2DI)
DEF_FN_TYPE_1 (BT_FN_INT_INT, BT_INT, BT_INT)
DEF_FN_TYPE_1 (BT_FN_INT_VOIDPTR, BT_INT, BT_VOIDPTR)
OB_DEF_VAR (s390_vec_abs_s16, s390_vlph, 0, 0, BT_OV_V8HI_V8HI)
OB_DEF_VAR (s390_vec_abs_s32, s390_vlpf, 0, 0, BT_OV_V4SI_V4SI)
OB_DEF_VAR (s390_vec_abs_s64, s390_vlpg, 0, 0, BT_OV_V2DI_V2DI)
+OB_DEF_VAR (s390_vec_abs_s128, s390_vlpq, 0, 0, BT_OV_V1TI_V1TI) /* NOGEN */
OB_DEF_VAR (s390_vec_abs_flt, s390_vflpsb, B_VXE, 0, BT_OV_V4SF_V4SF)
OB_DEF_VAR (s390_vec_abs_dbl, s390_vflpdb, 0, 0, BT_OV_V2DF_V2DF)
B_DEF (s390_vlph, absv8hi2, 0, B_VX, 0, BT_FN_V8HI_V8HI)
B_DEF (s390_vlpf, absv4si2, 0, B_VX, 0, BT_FN_V4SI_V4SI)
B_DEF (s390_vlpg, absv2di2, 0, B_VX, 0, BT_FN_V2DI_V2DI)
+B_DEF (s390_vlpq, absti2, 0, B_VX, 0, BT_FN_INT128_INT128)
B_DEF (s390_vflpsb, absv4sf2, 0, B_VXE, 0, BT_FN_V4SF_V4SF)
B_DEF (s390_vflpdb, absv2df2, 0, B_VX, 0, BT_FN_V2DF_V2DF)
"vlc<bhfgq>\t%v0,%v1"
[(set_attr "op_type" "VRR")])
-; vlpb, vlph, vlpf, vlpg
-(define_insn "abs<mode>2"
- [(set (match_operand:VI 0 "register_operand" "=v")
- (abs:VI (match_operand:VI 1 "register_operand" "v")))]
+(define_expand "abs<mode>2"
+ [(set (match_operand:VIT 0 "register_operand" "=v")
+ (abs:VIT (match_operand:VIT 1 "register_operand" "v")))]
+ "TARGET_VX"
+{
+ // Emulate via vec_sel (op1, -op1, op1 < 0)
+ if ((<MODE>mode == V1TImode || <MODE>mode == TImode) && !TARGET_VXE3)
+ {
+ rtx zero = gen_reg_rtx (<MODE>mode);
+ rtx neg_op1 = gen_reg_rtx (<MODE>mode);
+ rtx lt = gen_reg_rtx (<MODE>mode);
+ emit_move_insn (zero, GEN_INT (0));
+ emit_move_insn (neg_op1, gen_rtx_MINUS (<MODE>mode, zero, operands[1]));
+ s390_expand_vec_compare (lt, LT, operands[1], zero);
+ emit_insn (gen_vec_sel0<mode> (operands[0], operands[1], neg_op1, lt, GEN_INT (0)));
+ DONE;
+ }
+})
+
+; vlpb, vlph, vlpf, vlpg, vlpq
+(define_insn "*abs<mode>2"
+ [(set (match_operand:VIT_VXE3 0 "register_operand" "=v")
+ (abs:VIT_VXE3 (match_operand:VIT_VXE3 1 "register_operand" "v")))]
"TARGET_VX"
"vlp<bhfgq>\t%v0,%v1"
[(set_attr "op_type" "VRR")])
})
; op0 = op3 == 0 ? op1 : op2
-(define_insn "*vec_sel0<mode>"
+(define_insn "vec_sel0<mode>"
[(set (match_operand:VT 0 "register_operand" "=v")
(if_then_else:VT
(eq (match_operand:<TOINTVEC> 3 "register_operand" "v")
--- /dev/null
+/* { dg-do run } */
+/* { dg-options "-O3 -mzarch -march=z13 -save-temps" } */
+/* { dg-require-effective-target int128 } */
+/* { dg-final { check-function-bodies "**" "" "" } } */
+/* { dg-final { scan-assembler-not {\tvlpq\t} } } */
+
+#include <assert.h>
+
+typedef __attribute__ ((vector_size (16))) signed long long v2di;
+typedef __attribute__ ((vector_size (16))) signed __int128 v1ti;
+
+/*
+** my_abs:
+** vzero %v[0-9]+
+** vchlg %v[0-9]+,%v[0-9]+,%v[0-9]+
+** vceqg %v[0-9]+,%v[0-9]+,%v[0-9]+
+** vpdi %v[0-9]+,%v[0-9]+,%v[0-9]+,4
+** vchg %v[0-9]+,%v[0-9]+,%v[0-9]+
+** vn %v[0-9]+,%v[0-9]+,%v[0-9]+
+** vo %v[0-9]+,%v[0-9]+,%v[0-9]+
+** vrepg %v[0-9]+,%v[0-9]+,1
+** vsq %v[0-9]+,%v[0-9]+,%v[0-9]+
+** vsel %v[0-9]+,%v[0-9]+,%v[0-9]+,%v[0-9]+
+** br %r14
+*/
+__attribute__ ((noipa)) v1ti
+my_abs (v1ti x)
+{
+ return __builtin_s390_vec_abs (x);
+}
+
+int
+main (void)
+{
+ v2di x;
+
+ x = (v2di){ -1, -42 };
+ x = (v2di) my_abs ((v1ti) x);
+ assert (x[0] == 0 && x[1] == 42);
+
+ x = (v2di){ 0, 42 };
+ x = (v2di) my_abs ((v1ti) x);
+ assert (x[0] == 0 && x[1] == 42);
+
+ return 0;
+}