S/390: Add loc patterns for QImode and HImode

Message ID 6897bb30-22b9-73e3-c945-7e058ba0c049@linux.ibm.com
State New
Headers show
Series
  • S/390: Add loc patterns for QImode and HImode
Related show

Commit Message

Robin Dapp Oct. 18, 2018, 9:04 a.m.
Hi,

this enables QImode and HImode for load on condition.  For SPEC2006 this
reduces code size overall, performance impact is negligible.

Regtested on s390x.

Regards
 Robin

--

gcc/ChangeLog:

2018-10-18  Robin Dapp  <rdapp@linux.ibm.com>

	* config/s390/s390.md: Add mov<mode>cc for QImode and HImode.

Comments

Robin Dapp Oct. 26, 2018, 3:33 p.m. | #1
Hi,

this is v2 of the patch with less quirky pattern syntax and two tests.

Regards
 Robin

--

gcc/ChangeLog:

2018-10-26  Robin Dapp  <rdapp@linux.ibm.com>

	* config/s390/s390.md: QImode and HImode for load on condition.

gcc/testsuite/ChangeLog:

2018-10-26  Robin Dapp  <rdapp@linux.ibm.com>

	* gcc.target/s390/ifcvt-one-insn-bool.c: New test.
	* gcc.target/s390/ifcvt-one-insn-char.c: New test.
diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index ba1fa0c6ff3..d62da92384d 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -6599,6 +6599,44 @@
 				     XEXP (operands[1], 1));
 })
 
+;;
+;; - We do not have instructions for QImode or HImode but still
+;;   enable load on condition/if conversion for them.
+(define_expand "mov<mode>cc"
+ [(set (match_operand:HQI 0 "nonimmediate_operand" "")
+	(if_then_else:HQI (match_operand 1 "comparison_operator" "")
+		(match_operand:HQI 2 "loc_operand" "")
+		(match_operand:HQI 3 "loc_operand" "")))]
+ "TARGET_Z196"
+{
+  /* Emit the comparison insn in case we do not already have a comparison
+     result. */
+  if (!s390_comparison (operands[1], VOIDmode))
+    operands[1] = s390_emit_compare (GET_CODE (operands[1]),
+			      XEXP (operands[1], 0),
+			      XEXP (operands[1], 1));
+
+  rtx then = operands[2];
+  rtx els = operands[3];
+
+  if ((!TARGET_Z13 && CONSTANT_P (then)) || MEM_P (then))
+	then = force_reg (<MODE>mode, then);
+  if ((!TARGET_Z13 && CONSTANT_P (els)) || MEM_P (els))
+	els = force_reg (<MODE>mode, els);
+
+  if (!CONSTANT_P (then))
+    then = simplify_gen_subreg (E_SImode, then, <MODE>mode, 0);
+  if (!CONSTANT_P (els))
+    els = simplify_gen_subreg (E_SImode, els, <MODE>mode, 0);
+
+  rtx tmp_target = gen_reg_rtx (E_SImode);
+  emit_insn (gen_movsicc (tmp_target, operands[1], then, els));
+  emit_move_insn (operands[0], gen_lowpart (<MODE>mode, tmp_target));
+  DONE;
+})
+
+
+
 ; locr, loc, stoc, locgr, locg, stocg, lochi, locghi
 (define_insn "*mov<mode>cc"
   [(set (match_operand:GPR 0 "nonimmediate_operand"   "=d,d,d,d,d,d,S,S")
diff --git a/gcc/testsuite/gcc.target/s390/ifcvt-one-insn-bool.c b/gcc/testsuite/gcc.target/s390/ifcvt-one-insn-bool.c
new file mode 100644
index 00000000000..0a96b71f458
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/ifcvt-one-insn-bool.c
@@ -0,0 +1,24 @@
+/* Check load on condition for bool.  */
+
+/* { dg-do compile { target { s390*-*-* } } } */
+/* { dg-options "-O2 -march=z13" } */
+
+/* { dg-final { scan-assembler "lochinh\t%r.?,1" } } */
+#include <stdbool.h>
+
+int foo (int *a, unsigned int n)
+{
+  int min = 999999;
+  bool bla = false;
+  for (int i = 0; i < n; i++)
+    {
+      if (a[i] < min)
+	{
+	  bla = true;
+	}
+    }
+
+  if (bla)
+    min += 1;
+  return min;
+}
diff --git a/gcc/testsuite/gcc.target/s390/ifcvt-one-insn-char.c b/gcc/testsuite/gcc.target/s390/ifcvt-one-insn-char.c
new file mode 100644
index 00000000000..9c3d041618b
--- /dev/null
+++ b/gcc/testsuite/gcc.target/s390/ifcvt-one-insn-char.c
@@ -0,0 +1,26 @@
+/* Check load on condition for global char.  */
+
+/* { dg-do compile { target { s390*-*-* } } } */
+/* { dg-options "-O2 -march=z13" } */
+
+/* { dg-final { scan-assembler "locrnh\t%r.?,%r.?" } } */
+#include <stdbool.h>
+
+char g = 42;
+
+int foo (int *a, unsigned int n)
+{
+  int min = 999999;
+  char bla = 3;
+  for (int i = 0; i < n; i++)
+    {
+      if (a[i] < min)
+	{
+	  bla = g;
+	}
+    }
+
+  if (bla == 42)
+    min += 1;
+  return min;
+}
Andreas Krebbel Oct. 27, 2018, 5:20 a.m. | #2
On 10/26/18 5:33 PM, Robin Dapp wrote:
> Hi,

> 

> this is v2 of the patch with less quirky pattern syntax and two tests.

> 

> Regards

>  Robin

> 

> --

> 

> gcc/ChangeLog:

> 

> 2018-10-26  Robin Dapp  <rdapp@linux.ibm.com>

> 

> 	* config/s390/s390.md: QImode and HImode for load on condition.

> 

> gcc/testsuite/ChangeLog:

> 

> 2018-10-26  Robin Dapp  <rdapp@linux.ibm.com>

> 

> 	* gcc.target/s390/ifcvt-one-insn-bool.c: New test.

> 	* gcc.target/s390/ifcvt-one-insn-char.c: New test.

> 


Ok. Thanks!

Andreas

Patch

diff --git a/gcc/config/s390/s390.md b/gcc/config/s390/s390.md
index 70a619f06f5..6c687a1416b 100644
--- a/gcc/config/s390/s390.md
+++ b/gcc/config/s390/s390.md
@@ -614,6 +614,9 @@ 
 (define_mode_iterator DD_DF [DF DD])
 (define_mode_iterator TD_TF [TF TD])
 
+(define_mode_iterator QHI [QI HI])
+(define_mode_attr qhi_si_offset [(QI "3") (HI "2")])
+
 ;; These mode iterators allow 31-bit and 64-bit GPR patterns to be generated
 ;; from the same template.
 (define_mode_iterator GPR [(DI "TARGET_ZARCH") SI])
@@ -6593,6 +6596,49 @@ 
 				     XEXP (operands[1], 1));
 })
 
+;;
+;; - Allow QImode and HImode
+(define_expand "mov<mode>cc"
+ [(set (match_dup 4) (match_operand:QHI 2 "nonimmediate_operand" ""))
+ (set (match_dup 5) (match_operand:QHI 3 "loc_operand" ""))
+ (set (match_dup 6) (if_then_else:SI (match_operand 1 "comparison_operator" "")
+		     (match_dup 4) (match_dup 5)))
+ (set (match_operand:QHI 0 "nonimmediate_operand" "") (subreg:QHI (match_dup 6) <QHI:qhi_si_offset>))]
+ "TARGET_Z196"
+{
+  operands[4] = gen_reg_rtx (E_SImode);
+  operands[5] = gen_reg_rtx (E_SImode);
+  operands[6] = gen_reg_rtx (E_SImode);
+
+  if (!CONSTANT_P (operands[2]) && !MEM_P (operands[2]))
+    {
+      operands[2] = simplify_gen_subreg (E_SImode, operands[2], <MODE>mode, 0);
+    }
+  else if (MEM_P (operands[2]))
+    {
+      rtx tmp = gen_reg_rtx (E_SImode);
+      if (<MODE>mode == E_QImode)
+	emit_insn (gen_zero_extendqisi2 (tmp, operands[2]));
+      else if (<MODE>mode == E_HImode)
+	emit_insn (gen_zero_extendhisi2 (tmp, operands[2]));
+      operands[2] = tmp;
+    }
+
+  if (!CONSTANT_P (operands[3]) && !MEM_P (operands[3]))
+    {
+      operands[3] = simplify_gen_subreg (E_SImode, operands[3], <MODE>mode, 0);
+    }
+
+  /* Emit the comparison insn in case we do not already have a comparison
+     result. */
+  if (!s390_comparison (operands[1], VOIDmode))
+    operands[1] = s390_emit_compare (GET_CODE (operands[1]),
+			      XEXP (operands[1], 0),
+			      XEXP (operands[1], 1));
+})
+
+
+
 ; locr, loc, stoc, locgr, locg, stocg, lochi, locghi
 (define_insn "*mov<mode>cc"
   [(set (match_operand:GPR 0 "nonimmediate_operand"   "=d,d,d,d,d,d,S,S")