public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH] s390: implement flags output
@ 2023-11-15 13:15 Juergen Christ
  2023-11-23 14:36 ` Andreas Krebbel
  0 siblings, 1 reply; 3+ messages in thread
From: Juergen Christ @ 2023-11-15 13:15 UTC (permalink / raw)
  To: krebbel, gcc-patches

Implement flags output for inline assemblies.  Only use one output constraint
that captures the whole condition code.  No breakout into different condition
codes is allowed.  Also, only one condition code variable is allowed.

Add further logic to canonicalize various cases where we combine different
cases of possible condition codes.

Bootstrapped and tested on s390.  OK for mainline?

gcc/ChangeLog:

	* config/s390/s390-c.cc (s390_cpu_cpp_builtins): Define
	__GCC_ASM_FLAG_OUTPUTS__.
	* config/s390/s390.cc (s390_canonicalize_comparison): More
	UNSPEC_CC_TO_INT cases.
	(s390_md_asm_adjust): Implement flags output.
	* config/s390/s390.md (ccstore4): Allow mask operands.
	* doc/extend.texi: Document flags output.

gcc/testsuite/ChangeLog:

	* gcc.target/s390/ccor.c: New test.

Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>
---
 gcc/config/s390/s390-c.cc            |   1 +
 gcc/config/s390/s390.cc              | 139 ++++++++++++++++++++++++++-
 gcc/config/s390/s390.md              |   8 +-
 gcc/doc/extend.texi                  |   5 +
 gcc/testsuite/gcc.target/s390/ccor.c |  88 +++++++++++++++++
 5 files changed, 232 insertions(+), 9 deletions(-)
 create mode 100644 gcc/testsuite/gcc.target/s390/ccor.c

diff --git a/gcc/config/s390/s390-c.cc b/gcc/config/s390/s390-c.cc
index 269f4f8e978d..c126e6d323d7 100644
--- a/gcc/config/s390/s390-c.cc
+++ b/gcc/config/s390/s390-c.cc
@@ -409,6 +409,7 @@ s390_cpu_cpp_builtins (cpp_reader *pfile)
     cpp_define (pfile, "__LONG_DOUBLE_128__");
   cl_target_option_save (&opts, &global_options, &global_options_set);
   s390_cpu_cpp_builtins_internal (pfile, &opts, NULL);
+  cpp_define (pfile, "__GCC_ASM_FLAG_OUTPUTS__");
 }
 
 #if S390_USE_TARGET_ATTRIBUTE
diff --git a/gcc/config/s390/s390.cc b/gcc/config/s390/s390.cc
index 61c5f88de8af..a19dd7849b84 100644
--- a/gcc/config/s390/s390.cc
+++ b/gcc/config/s390/s390.cc
@@ -1877,6 +1877,97 @@ s390_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
 	  *code = new_code;
 	}
     }
+  /* Remove UNSPEC_CC_TO_INT from connectives.  This happens for
+     checks against multiple condition codes. */
+  if (GET_CODE (*op0) == AND
+      && GET_CODE (XEXP (*op0, 0)) == UNSPEC
+      && XINT (XEXP (*op0, 0), 1) == UNSPEC_CC_TO_INT
+      && XVECLEN (XEXP (*op0, 0), 0) == 1
+      && REGNO (XVECEXP (XEXP (*op0, 0), 0, 0)) == CC_REGNUM
+      && CONST_INT_P (XEXP (*op0, 1))
+      && CONST_INT_P (*op1)
+      && INTVAL (XEXP (*op0, 1)) == -3
+      && *code == EQ)
+    {
+      if (INTVAL (*op1) == 0)
+	{
+	  /* case cc == 0 || cc = 2 => mask = 0xa */
+	  *op0 = XVECEXP (XEXP (*op0, 0), 0, 0);
+	  *op1 = gen_rtx_CONST_INT (VOIDmode, 0xa);
+	}
+      else if (INTVAL (*op1) == 1)
+	{
+	  /* case cc == 1 || cc == 3 => mask = 0x5 */
+	  *op0 = XVECEXP (XEXP (*op0, 0), 0, 0);
+	  *op1 = gen_rtx_CONST_INT (VOIDmode, 0x5);
+	}
+    }
+  if (GET_CODE (*op0) == PLUS
+      && GET_CODE (XEXP (*op0, 0)) == UNSPEC
+      && XINT (XEXP (*op0, 0), 1) == UNSPEC_CC_TO_INT
+      && XVECLEN (XEXP (*op0, 0), 0) == 1
+      && REGNO (XVECEXP (XEXP (*op0, 0), 0, 0)) == CC_REGNUM
+      && CONST_INT_P (XEXP (*op0, 1))
+      && CONST_INT_P (*op1)
+      && (*code == LEU || *code == GTU))
+    {
+      if (INTVAL (*op1) == 1)
+	{
+	  if (INTVAL (XEXP (*op0, 1)) == -1)
+	    {
+	      /* case cc == 1 || cc == 2 => mask = 0x6 */
+	      *op0 = XVECEXP (XEXP (*op0, 0), 0, 0);
+	      *op1 = gen_rtx_CONST_INT (VOIDmode, 0x6);
+	      *code = *code == GTU ? NE : EQ;
+	    }
+	  else if (INTVAL (XEXP (*op0, 1)) == -2)
+	    {
+	      /* case cc == 2 || cc == 3 => mask = 0x3 */
+	      *op0 = XVECEXP (XEXP (*op0, 0), 0, 0);
+	      *op1 = gen_rtx_CONST_INT (VOIDmode, 0x3);
+	      *code = *code == GTU ? NE : EQ;
+	    }
+	}
+      else if (INTVAL (*op1) == 2
+	       && INTVAL (XEXP (*op0, 1)) == -1)
+	{
+	  /* case cc == 1 || cc == 2 || cc == 3 => mask = 0x7 */
+	  *op0 = XVECEXP (XEXP (*op0, 0), 0, 0);
+	  *op1 = gen_rtx_CONST_INT (VOIDmode, 0x7);
+	  *code = *code == GTU ? NE : EQ;
+	}
+    }
+  else if (*code == LEU || *code == GTU)
+    {
+      if (GET_CODE (*op0) == UNSPEC
+	  && XINT (*op0, 1) == UNSPEC_CC_TO_INT
+	  && XVECLEN (*op0, 0) == 1
+	  && REGNO (XVECEXP (*op0, 0, 0)) == CC_REGNUM
+	  && CONST_INT_P (*op1))
+	{
+	  if (INTVAL (*op1) == 1)
+	    {
+	      /* case cc == 0 || cc == 1 => mask = 0xc */
+	      *op0 = XVECEXP (*op0, 0, 0);
+	      *op1 = gen_rtx_CONST_INT (VOIDmode, 0xc);
+	      *code = *code == GTU ? NE : EQ;
+	    }
+	  else if (INTVAL (*op1) == 2)
+	    {
+	      /* case cc == 0 || cc == 1 || cc == 2 => mask = 0xd */
+	      *op0 = XVECEXP (*op0, 0, 0);
+	      *op1 = gen_rtx_CONST_INT (VOIDmode, 0xd);
+	      *code = *code == GTU ? NE : EQ;
+	    }
+	  else if (INTVAL (*op1) == 3)
+	    {
+	      /* always true */
+	      *op0 = const0_rtx;
+	      *op1 = const0_rtx;
+	      *code = *code == GTU ? NE : EQ;
+	    }
+	}
+    }
 
   /* Simplify cascaded EQ, NE with const0_rtx.  */
   if ((*code == NE || *code == EQ)
@@ -17428,22 +17519,60 @@ static rtx_insn *
 s390_md_asm_adjust (vec<rtx> &outputs, vec<rtx> &inputs,
 		    vec<machine_mode> &input_modes,
 		    vec<const char *> &constraints, vec<rtx> & /*clobbers*/,
-		    HARD_REG_SET & /*clobbered_regs*/, location_t /*loc*/)
+		    HARD_REG_SET &clobbered_regs, location_t loc)
 {
-  if (!TARGET_VXE)
-    /* Long doubles are stored in FPR pairs - nothing to do.  */
-    return NULL;
 
   rtx_insn *after_md_seq = NULL, *after_md_end = NULL;
+  bool saw_cc = false;
 
   unsigned ninputs = inputs.length ();
   unsigned noutputs = outputs.length ();
   for (unsigned i = 0; i < noutputs; i++)
     {
+      const char *constraint = constraints[i];
+      if (strncmp(constraint, "=@cc", 4) == 0)
+	{
+	  if (constraint[4] != 0)
+	    {
+	      error_at (loc, "invalid cc output constraint: %qs", constraint);
+	      continue;
+	    }
+	  if (saw_cc)
+	    {
+	      error_at (loc, "multiple cc output constraints not supported");
+	      continue;
+	    }
+	  if (TEST_HARD_REG_BIT(clobbered_regs, CC_REGNUM))
+	    {
+	      error_at (loc, "%<asm%> specifier for cc output conflicts with %<asm%> clobber list");
+	      continue;
+	    }
+	  rtx dest = outputs[i];
+	  if (GET_MODE(dest) != SImode)
+	    {
+	      error ("invalid type for cc output constraint");
+	      continue;
+	    }
+	  saw_cc = true;
+	  constraints[i] = "=c";
+	  outputs[i] = gen_rtx_REG (CCRAWmode, CC_REGNUM);
+
+	  push_to_sequence2 (after_md_seq, after_md_end);
+	  emit_insn (gen_rtx_SET (dest,
+				  gen_rtx_UNSPEC (SImode,
+						  gen_rtvec (1, outputs[i]),
+						  UNSPEC_CC_TO_INT)));
+	  after_md_seq = get_insns ();
+	  after_md_end = get_last_insn ();
+	  end_sequence ();
+	  continue;
+	}
+      if (!TARGET_VXE)
+	/* Long doubles are stored in FPR pairs - nothing to do.  */
+	continue;
       if (GET_MODE (outputs[i]) != TFmode)
 	/* Not a long double - nothing to do.  */
 	continue;
-      const char *constraint = constraints[i];
       bool allows_mem, allows_reg, is_inout;
       bool ok = parse_output_constraint (&constraint, i, ninputs, noutputs,
 					 &allows_mem, &allows_reg, &is_inout);
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 3e53a217d837..e432b2f708d7 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -6948,7 +6948,7 @@
     [(set (match_operand:SI 0 "register_operand" "")
 	  (match_operator:SI 1 "s390_eqne_operator"
            [(match_operand 2 "cc_reg_operand")
-	    (match_operand 3 "const0_operand")]))
+	    (match_operand 3 "const_mask_operand")]))
      (clobber (reg:CC CC_REGNUM))])]
   ""
   "machine_mode mode = GET_MODE (operands[2]);
@@ -6957,15 +6957,15 @@
        rtx cond, ite;
 
        if (GET_CODE (operands[1]) == NE)
-	 cond = gen_rtx_NE (VOIDmode, operands[2], const0_rtx);
+	 cond = gen_rtx_NE (VOIDmode, operands[2], operands[3]);
        else
-	 cond = gen_rtx_EQ (VOIDmode, operands[2], const0_rtx);
+	 cond = gen_rtx_EQ (VOIDmode, operands[2], operands[3]);
        ite = gen_rtx_IF_THEN_ELSE (SImode, cond, const1_rtx, const0_rtx);
        emit_insn (gen_rtx_SET (operands[0], ite));
      }
    else
      {
-       if (mode != CCZ1mode)
+       if (mode != CCZ1mode || operands[3] != const0_rtx)
 	 FAIL;
        emit_insn (gen_sne (operands[0], operands[2]));
        if (GET_CODE (operands[1]) == EQ)
diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
index a3db9423ce66..1b1468fc1a5f 100644
--- a/gcc/doc/extend.texi
+++ b/gcc/doc/extend.texi
@@ -10788,6 +10788,11 @@ sign flag set
 ``not'' @var{flag}, or inverted versions of those above
 @end table
 
+@item s390
+The flag output constraint for s390 is @samp{=@@cc}.  Only one such
+constraint is allowed.  The variable has to be stored in a @samp{int}
+variable.
+
 @end table
 
 @anchor{InputOperands}
diff --git a/gcc/testsuite/gcc.target/s390/ccor.c b/gcc/testsuite/gcc.target/s390/ccor.c
new file mode 100644
index 000000000000..31f30f60314e
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/ccor.c
@@ -0,0 +1,88 @@
+/* { dg-do compile } */
+/* { dg-options "-O3 -march=zEC12 -mzarch" } */
+
+#define GENFUN1(C)                              \
+  int foo_ ##C(int x)                           \
+  {                                             \
+    int cc;					\
+    asm volatile ("ahi %[x],42\n"		\
+		  : [x] "+d"(x), "=@cc" (cc));	\
+    return cc == C ? 42 : 0;			\
+  }
+
+#define GENFUN2(C1,C2)                          \
+  int foo_ ##C1##C2(int x)                      \
+  {                                             \
+    int cc;					\
+    asm volatile ("ahi %[x],42\n"		\
+		  : [x] "+d"(x), "=@cc" (cc));	\
+    return cc == C1 || cc == C2 ? 42 : 0;	\
+  }
+
+#define GENFUN3(C1,C2,C3)                                               \
+  int foo_ ##C1##C2##C3(int x)                                          \
+  {                                                                     \
+    int cc;                                                             \
+    asm volatile ("ahi %[x],42\n"					\
+		  : [x] "+d"(x), "=@cc" (cc));				\
+    return cc == C1 || cc == C2 || cc == C3 ? 42 : 0;			\
+  }
+
+GENFUN1(0)
+
+/* { dg-final { scan-assembler {locrne} } } */
+
+GENFUN1(1)
+
+/* { dg-final { scan-assembler {locrnl} } } */
+
+GENFUN1(2)
+
+/* { dg-final { scan-assembler {locrnh} } } */
+
+GENFUN1(3)
+
+/* { dg-final { scan-assembler {locrno} } } */
+
+GENFUN2(0,1)
+
+/* { dg-final { scan-assembler {locrnle} } } */
+
+GENFUN2(0,2)
+
+/* { dg-final { scan-assembler {locrhe} } } */
+
+GENFUN2(0,3)
+
+/* currently unoptimized */
+
+GENFUN2(1,2)
+
+/* { dg-final { scan-assembler {locrnlh} } } */
+
+GENFUN2(1,3)
+
+/* { dg-final { scan-assembler {locrnhe} } } */
+
+GENFUN2(2,3)
+
+/* { dg-final { scan-assembler {locrle} } } */
+
+GENFUN3(0,1,2)
+
+/* { dg-final { scan-assembler {locrh} } } */
+
+GENFUN3(0,1,3)
+
+/* currently unoptimized */
+
+GENFUN3(0,2,3)
+
+/* currently unoptimized */
+
+GENFUN3(1,2,3)
+
+/* { dg-final { scan-assembler {locre} } } */
+
+/* for the unoptimized cases, we get an ipm */
+/* { dg-final { scan-assembler-times {ipm} 3 } } */
-- 
2.39.3


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] s390: implement flags output
  2023-11-15 13:15 [PATCH] s390: implement flags output Juergen Christ
@ 2023-11-23 14:36 ` Andreas Krebbel
  2023-11-28 22:45   ` Joseph Myers
  0 siblings, 1 reply; 3+ messages in thread
From: Andreas Krebbel @ 2023-11-23 14:36 UTC (permalink / raw)
  To: Juergen Christ, gcc-patches

On 11/15/23 14:15, Juergen Christ wrote:
> Implement flags output for inline assemblies.  Only use one output constraint
> that captures the whole condition code.  No breakout into different condition
> codes is allowed.  Also, only one condition code variable is allowed.
> 
> Add further logic to canonicalize various cases where we combine different
> cases of possible condition codes.
> 
> Bootstrapped and tested on s390.  OK for mainline?
> 
> gcc/ChangeLog:
> 
> 	* config/s390/s390-c.cc (s390_cpu_cpp_builtins): Define
> 	__GCC_ASM_FLAG_OUTPUTS__.
> 	* config/s390/s390.cc (s390_canonicalize_comparison): More
> 	UNSPEC_CC_TO_INT cases.
> 	(s390_md_asm_adjust): Implement flags output.
> 	* config/s390/s390.md (ccstore4): Allow mask operands.
> 	* doc/extend.texi: Document flags output.
> 
> gcc/testsuite/ChangeLog:
> 
> 	* gcc.target/s390/ccor.c: New test.
> 
> Signed-off-by: Juergen Christ <jchrist@linux.ibm.com>

Committed to mainline with a few minor formatting fixes. Thanks!

Andreas


^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: [PATCH] s390: implement flags output
  2023-11-23 14:36 ` Andreas Krebbel
@ 2023-11-28 22:45   ` Joseph Myers
  0 siblings, 0 replies; 3+ messages in thread
From: Joseph Myers @ 2023-11-28 22:45 UTC (permalink / raw)
  To: Andreas Krebbel; +Cc: Juergen Christ, gcc-patches

This has introduced an ICE building glibc for s390x-linux-gnu.

https://gcc.gnu.org/bugzilla/show_bug.cgi?id=112753

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2023-11-28 22:45 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-15 13:15 [PATCH] s390: implement flags output Juergen Christ
2023-11-23 14:36 ` Andreas Krebbel
2023-11-28 22:45   ` Joseph Myers

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).