]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
[committed] Support uaddv and usubv on the H8
authorJeff Law <jlaw@ventanamicro.com>
Sun, 10 Dec 2023 17:41:05 +0000 (10:41 -0700)
committerJeff Law <jlaw@ventanamicro.com>
Sun, 10 Dec 2023 17:41:05 +0000 (10:41 -0700)
This patch adds uaddv/usubv support on the H8 port to speed up those pesky
builtin-overflow tests.  It's a variant of something I'd been running for a
while -- the major change between the old approach I'd been using and this
patch is this version does not expose the CC register until after reload to be
consistent with the rest of the H8 port.

The general approach is to first clear the GPR that's going to hold the
overflow status, perform the arithmetic operation (add/sub), then use addx to
move the overflow indicator (in the C bit) into the GPR holding the overflow
status.

That's a significant improvement over the mess of logicals that's generated by
the generic code.

Handling signed overflow is possible and something I'll probably port to this
scheme at some point.  It's a bit more complex because we can't trivially move
the bit from CCR into the right position in a GPR and other quirks of the H8.

This has been regression tested on the H8 without problems.  Pushing to the
trunk.

gcc/
* config/h8300/addsub.md (uaddv<mode>4, usubv<mode>4): New expanders.
(uaddv): New define_insn_and_split plus post-reload pattern.

gcc/config/h8300/addsub.md

index b1eb0d2018807c284dc0a63d3474873e4142ac67..32eba9df67aa8829d63ddc0c351be24ce9cf7210 100644 (file)
   "reload_completed"
   "xor.w\\t#32768,%e0"
   [(set_attr "length" "4")])
+
+(define_expand "uaddv<mode>4"
+  [(set (match_operand:QHSI 0 "register_operand" "")
+       (plus:QHSI (match_operand:QHSI 1 "register_operand" "")
+                  (match_operand:QHSI 2 "register_operand" "")))
+   (set (pc)
+       (if_then_else (ltu (match_dup 0) (match_dup 1))
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
+  "")
+
+(define_insn_and_split "*uaddv"
+  [(set (match_operand:QHSI2 3 "register_operand" "=&r")
+       (ltu:QHSI2 (plus:QHSI (match_operand:QHSI 1 "register_operand" "%0")
+                          (match_operand:QHSI 2 "register_operand" "r"))
+               (match_dup 1)))
+   (set (match_operand:QHSI 0 "register_operand" "=r")
+       (plus:QHSI (match_dup 1) (match_dup 2)))]
+  ""
+  "#"
+  "&& reload_completed"
+  [(parallel [(set (match_dup 3) (ltu:QHSI2 (plus:QHSI (match_dup 1) (match_dup 2))
+                                         (match_dup 1)))
+             (set (match_dup 0) (plus:QHSI (match_dup 1) (match_dup 2)))
+             (clobber (reg:CC CC_REG))])])
+
+(define_insn "*uaddv"
+  [(set (match_operand:QHSI2 3 "register_operand" "=&r")
+       (ltu:QHSI2 (plus:QHSI (match_operand:QHSI 1 "register_operand" "%0")
+                            (match_operand:QHSI 2 "register_operand" "r"))
+               (match_dup 1)))
+   (set (match_operand:QHSI 0 "register_operand" "=r")
+       (plus (match_dup 1) (match_dup 2)))
+   (clobber (reg:CC CC_REG))]
+  ""
+{
+  if (E_<QHSI2:MODE>mode == E_QImode)
+    {
+      if (E_<QHSI:MODE>mode == E_QImode)
+       return "sub.b\t%X3,%X3\;add.b\t%X2,%X0\;addx\t%X3,%X3";
+      else if (E_<QHSI:MODE>mode == E_HImode)
+       return "sub.b\t%X3,%X3\;add.w\t%T2,%T0\;addx\t%X3,%X3";
+      else if (E_<QHSI:MODE>mode == E_SImode)
+       return "sub.b\t%X3,%X3\;add.l\t%S2,%S0\;addx\t%X3,%X3";
+    }
+  else if (E_<QHSI2:MODE>mode == E_HImode)
+    {
+      if (E_<QHSI:MODE>mode == E_QImode)
+       return "sub.w\t%T3,%T3\;add.b\t%X2,%X0\;addx\t%X3,%X3";
+      else if (E_<QHSI:MODE>mode == E_HImode)
+       return "sub.w\t%T3,%T3\;add.w\t%T2,%T0\;addx\t%X3,%X3";
+      else if (E_<QHSI:MODE>mode == E_SImode)
+       return "sub.w\t%T3,%T3\;add.l\t%S2,%S0\;addx\t%X3,%X3";
+    }
+  else if (E_<QHSI2:MODE>mode == E_SImode)
+    {
+      if (E_<QHSI:MODE>mode == E_QImode)
+       return "sub.l\t%S3,%S3\;add.b\t%X2,%X0\;addx\t%X3,%X3";
+      else if (E_<QHSI:MODE>mode == E_HImode)
+       return "sub.l\t%S3,%S3\;add.w\t%T2,%T0\;addx\t%X3,%X3";
+      else if (E_<QHSI:MODE>mode == E_SImode)
+       return "sub.l\t%S3,%S3\;add.l\t%S2,%S0\;addx\t%X3,%X3";
+    }
+  else
+    gcc_unreachable ();
+}
+  [(set_attr "length" "6")])
+
+(define_expand "usubv<mode>4"
+  [(set (match_operand:QHSI 0 "register_operand" "")
+       (minus:QHSI (match_operand:QHSI 1 "register_operand" "")
+                   (match_operand:QHSI 2 "register_operand" "")))
+   (set (pc)
+       (if_then_else (ltu (match_dup 1) (match_dup 2))
+                     (label_ref (match_operand 3 ""))
+                     (pc)))]
+  "")