@@ -8619,7 +8619,6 @@ print_operand_address (FILE *file, rtx addr)
't': CONST_INT: "start" of contiguous bitmask X in SImode.
'x': print integer X as if it's an unsigned halfword.
'v': print register number as vector register (v1 instead of f1).
- 'V': print the second word of a TFmode operand as vector register.
*/
void
@@ -8873,13 +8872,13 @@ print_operand (FILE *file, rtx x, int code)
case REG:
/* Print FP regs as fx instead of vx when they are accessed
through non-vector mode. */
- if ((code == 'v' || code == 'V')
+ if (code == 'v'
|| VECTOR_NOFP_REG_P (x)
|| (FP_REG_P (x) && VECTOR_MODE_P (GET_MODE (x)))
|| (VECTOR_REG_P (x)
&& (GET_MODE_SIZE (GET_MODE (x)) /
s390_class_max_nregs (FP_REGS, GET_MODE (x))) > 8))
- fprintf (file, "%%v%s", reg_names[REGNO (x) + (code == 'V')] + 2);
+ fprintf (file, "%%v%s", reg_names[REGNO (x)] + 2);
else
fprintf (file, "%s", reg_names[REGNO (x)]);
break;
@@ -241,6 +241,8 @@
UNSPEC_VEC_VFMIN
UNSPEC_VEC_VFMAX
+ UNSPEC_TF_TO_FPRX2
+
UNSPEC_NNPA_VCLFNHS_V8HI
UNSPEC_NNPA_VCLFNLS_V8HI
UNSPEC_NNPA_VCRNFS_V8HI
@@ -907,36 +907,45 @@
"vmrlg\t%0,%1,%2";
[(set_attr "op_type" "VRR")])
-
-(define_insn "*tf_to_fprx2_0"
- [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 0)
- (subreg:DF (match_operand:TF 1 "general_operand" "v") 0))]
- "TARGET_VXE"
- ; M4 == 1 corresponds to %v0[0] = %v1[0]; %v0[1] = %v0[1];
- "vpdi\t%v0,%v1,%v0,1"
- [(set_attr "op_type" "VRR")])
-
-(define_insn "*tf_to_fprx2_1"
- [(set (subreg:DF (match_operand:FPRX2 0 "nonimmediate_operand" "+f") 8)
- (subreg:DF (match_operand:TF 1 "general_operand" "v") 8))]
+(define_insn "tf_to_fprx2"
+ [(set (match_operand:FPRX2 0 "register_operand" "=f,f ,f")
+ (unspec:FPRX2 [(match_operand:TF 1 "general_operand" "v,AR,AT")]
+ UNSPEC_TF_TO_FPRX2))]
"TARGET_VXE"
- ; M4 == 5 corresponds to %V0[0] = %v1[1]; %V0[1] = %V0[1];
- "vpdi\t%V0,%v1,%V0,5"
- [(set_attr "op_type" "VRR")])
-
-(define_insn_and_split "tf_to_fprx2"
- [(set (match_operand:FPRX2 0 "nonimmediate_operand" "=f,f")
- (subreg:FPRX2 (match_operand:TF 1 "general_operand" "v,AR") 0))]
- "TARGET_VXE"
- "#"
- "!(MEM_P (operands[1]) && MEM_VOLATILE_P (operands[1]))"
- [(set (match_dup 2) (match_dup 3))
- (set (match_dup 4) (match_dup 5))]
{
- operands[2] = simplify_gen_subreg (DFmode, operands[0], FPRX2mode, 0);
- operands[3] = simplify_gen_subreg (DFmode, operands[1], TFmode, 0);
- operands[4] = simplify_gen_subreg (DFmode, operands[0], FPRX2mode, 8);
- operands[5] = simplify_gen_subreg (DFmode, operands[1], TFmode, 8);
+ char buf[64];
+ const char *reg_pair = reg_names[REGNO (operands[0]) + 1];
+ switch (which_alternative)
+ {
+ case 0:
+ if (REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ reg_pair += 2; // get rid of prefix %f
+ snprintf (buf, sizeof (buf), "vpdi\t%%%%v%s,%%v1,%%%%v%s,5", reg_pair, reg_pair);
+ output_asm_insn (buf, operands);
+ return "";
+ }
+ else
+ {
+ reg_pair += 2; // get rid of prefix %f
+ snprintf (buf, sizeof (buf), "ldr\t%%f0,%%f1;vpdi\t%%%%v%s,%%v1,%%%%v%s,5", reg_pair, reg_pair);
+ output_asm_insn (buf, operands);
+ return "";
+ }
+ case 1:
+ {
+ snprintf (buf, sizeof (buf), "ld\t%%f0,%%1;ld\t%%%s,8+%%1", reg_pair);
+ output_asm_insn (buf, operands);
+ return "";
+ }
+ case 2:
+ {
+ snprintf (buf, sizeof (buf), "ldy\t%%f0,%%1;ldy\t%%%s,8+%%1", reg_pair);
+ output_asm_insn (buf, operands);
+ return "";
+ }
+ default: gcc_unreachable ();
+ }
})
;; VECTOR REVERSE ELEMENTS V16QI
@@ -2830,9 +2839,8 @@
; There is no instruction for rounding an extended BFP operand in a VR into
; a signed integer, therefore copy it into a FPR pair first.
(define_expand "fix_trunctf<mode>2_vr"
- [(set (subreg:DF (match_dup 2) 0)
- (subreg:DF (match_operand:TF 1 "register_operand" "") 0))
- (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
+ [(set (match_dup 2)
+ (unspec:FPRX2 [(match_operand:TF 1 "register_operand")] UNSPEC_TF_TO_FPRX2))
(parallel [(set (match_operand:GPR 0 "register_operand" "")
(fix:GPR (match_dup 2)))
(unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
@@ -2863,9 +2871,8 @@
; There is no instruction for rounding an extended BFP operand in a VR into
; an unsigned integer, therefore copy it into a FPR pair first.
(define_expand "fixuns_trunctf<mode>2_vr"
- [(set (subreg:DF (match_dup 2) 0)
- (subreg:DF (match_operand:TF 1 "register_operand" "") 0))
- (set (subreg:DF (match_dup 2) 8) (subreg:DF (match_dup 1) 8))
+ [(set (match_dup 2)
+ (unspec:FPRX2 [(match_operand:TF 1 "register_operand")] UNSPEC_TF_TO_FPRX2))
(parallel [(set (match_operand:GPR 0 "register_operand" "")
(unsigned_fix:GPR (match_dup 2)))
(unspec:GPR [(const_int BFP_RND_TOWARD_0)] UNSPEC_ROUND)
new file mode 100644
@@ -0,0 +1,26 @@
+/* { dg-do run } */
+/* { dg-require-effective-target s390_vxe } */
+/* { dg-options "-O2 -march=z14 -mzarch" } */
+
+__attribute__ ((noipa))
+long long trunctf (long double x)
+{
+ /* Ensure via ++x that x is in a register. */
+ ++x;
+ return x;
+}
+
+__attribute__ ((noipa))
+long long trunctf_from_mem (long double x)
+{
+ return x;
+}
+
+int main (void)
+{
+ if (trunctf (0x7ffffffffffffffeLL) != 0x7fffffffffffffffLL)
+ __builtin_abort ();
+ if (trunctf_from_mem (0x7fffffffffffffffLL) != 0x7fffffffffffffffLL)
+ __builtin_abort ();
+ return 0;
+}
@@ -14,7 +14,7 @@ xsqrt (long double x)
/* Check that the generated code is very small and straightforward. In
particular, there must be no unnecessary copying and no stack frame. */
-/* { dg-final { scan-assembler {\n\tld\t[^\n]*\n\tld\t[^\n]*\n(#[^\n]*\n)*\tsqxbr\t.*\n(#[^\n]*\n)*\tstd\t[^\n]*\n\tstd\t[^\n]*\n\tbr\t%r14\n} } } */
+/* { dg-final { scan-assembler {\n\tld\t[^\n]*;ld\t[^\n]*\n(#[^\n]*\n)*\tsqxbr\t.*\n(#[^\n]*\n)*\tstd\t[^\n]*\n\tstd\t[^\n]*\n\tbr\t%r14\n} } } */
int
main (void)
@@ -10,8 +10,6 @@ long_double_to_i64 (long double x)
return x;
}
-/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,1\n} 1 } } */
-/* { dg-final { scan-assembler-times {\n\tvpdi\t%v\d+,%v\d+,%v\d+,5\n} 1 } } */
/* { dg-final { scan-assembler-times {\n\tcgxbr\t} 1 } } */
int