public inbox for gcc-cvs@sourceware.org
help / color / mirror / Atom feed
* [gcc r14-5081] [committed] Improve H8 sequences for single bit sign extractions
@ 2023-11-02 13:33 Jeff Law
  0 siblings, 0 replies; only message in thread
From: Jeff Law @ 2023-11-02 13:33 UTC (permalink / raw)
  To: gcc-cvs

https://gcc.gnu.org/g:0f9f3fc885a1f830ff09a095e8c14919c2796a9d

commit r14-5081-g0f9f3fc885a1f830ff09a095e8c14919c2796a9d
Author: Jeff Law <jlaw@ventanamicro.com>
Date:   Thu Nov 2 07:25:39 2023 -0600

    [committed] Improve H8 sequences for single bit sign extractions
    
    Spurred by Roger's recent work on ARC, this patch improves the code we
    generation for single bit sign extractions.
    
    The basic idea is to get the bit we want into C, the use a subx;ext.w;ext.l
    sequence to sign extend it in a GPR.
    
    For bits 0..15 we can use a bld instruction to get the bit we want into C.  For
    bits 16..31, we can move the high word into the low word, then use bld.
    There's a couple special cases where we can shift the bit we want from the high
    word into C which is an instruction smaller.
    
    Not surprisingly most cases seen in newlib and the test suite are extractions
    from the low byte, HImode sign bit and top two bits of SImode.
    
    Regression tested on the H8 with no regressions.  Installing on the trunk.
    
    gcc/
            * config/h8300/combiner.md: Add new patterns for single bit
            sign extractions.

Diff:
---
 gcc/config/h8300/combiner.md | 91 ++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 91 insertions(+)

diff --git a/gcc/config/h8300/combiner.md b/gcc/config/h8300/combiner.md
index fd5cf2f4af4a..2f7faf77c930 100644
--- a/gcc/config/h8300/combiner.md
+++ b/gcc/config/h8300/combiner.md
@@ -1268,3 +1268,94 @@
 ;; 		      (label_ref (match_dup 1))
 ;; 		      (pc)))]
 ;;   "")
+
+;; Various ways to extract a single bit bitfield and sign extend it
+;;
+;; Testing showed this only triggering with SImode, probably because
+;; of how insv/extv are defined.
+(define_insn_and_split ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sign_extract:SI (match_operand:QHSI 1 "register_operand" "0")
+			 (const_int 1)
+			 (match_operand 2 "immediate_operand")))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 0)
+		   (sign_extract:SI (match_dup 1) (const_int 1) (match_dup 2)))
+	      (clobber (reg:CC CC_REG))])])
+
+(define_insn ""
+  [(set (match_operand:SI 0 "register_operand" "=r")
+	(sign_extract:SI (match_operand:QHSI 1 "register_operand" "0")
+			 (const_int 1)
+			 (match_operand 2 "immediate_operand")))
+   (clobber (reg:CC CC_REG))]
+  ""
+{
+  int position = INTVAL (operands[2]);
+
+  /* For bit position 31, 30, left shift the bit we want into C.  */
+  bool bit_in_c = false;
+  if (position == 31)
+    {
+      output_asm_insn ("shll.l\t%0", operands);
+      bit_in_c = true;
+    }
+  else if (position == 30 && TARGET_H8300S)
+    {
+      output_asm_insn ("shll.l\t#2,%0", operands);
+      bit_in_c = true;
+    }
+
+  /* Similar for positions 16, 17, but with a right shift into C.  */
+  else if (position == 16)
+    {
+      output_asm_insn ("shlr.w\t%e0", operands);
+      bit_in_c = true;
+    }
+  else if (position == 17 && TARGET_H8300S)
+    {
+      output_asm_insn ("shlr.w\t#2,%e0", operands);
+      bit_in_c = true;
+    }
+
+
+  /* For all the other cases in the upper 16 bits, move the upper 16
+     bits into the lower 16 bits, then use the standard sequence for
+     extracting one of the low 16 bits.  */
+  else if (position >= 16)
+    {
+      output_asm_insn ("mov.w\t%e1,%f0", operands);
+
+      /* We'll use the standard sequences for the low word now.  */
+      position %= 16;
+    }
+
+  /* Same size/speed as the general sequence, but slightly faster
+     to simulate.  */
+  if (position == 0)
+    return "and.l\t#1,%0\;neg.l\t%0";
+
+  rtx xoperands[3];
+  xoperands[0] = operands[0];
+  xoperands[1] = operands[1];
+  xoperands[2] = GEN_INT (position);
+
+  /* If the bit we want is not already in C, get it there  */
+  if (!bit_in_c)
+    {
+      if (position >= 8)
+	{
+	  xoperands[2] = GEN_INT (position % 8);
+	  output_asm_insn ("bld\t%2,%t1", xoperands);
+	}
+      else
+	output_asm_insn ("bld\t%2,%s1", xoperands);
+    }
+
+  /* Now the bit we want is in C, emit the generalized sequence
+     to get that bit into the destination, properly extended.  */
+  return "subx\t%s0,%s0\;exts.w %T0\;exts.l %0";
+}
+  [(set_attr "length" "10")])

^ permalink raw reply	[flat|nested] only message in thread

only message in thread, other threads:[~2023-11-02 13:33 UTC | newest]

Thread overview: (only message) (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2023-11-02 13:33 [gcc r14-5081] [committed] Improve H8 sequences for single bit sign extractions Jeff Law

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).