From patchwork Wed Dec 2 04:49:50 2020 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: Jeff Law X-Patchwork-Id: 1409296 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=gcc.gnu.org (client-ip=8.43.85.97; helo=sourceware.org; envelope-from=gcc-patches-bounces@gcc.gnu.org; receiver=) Authentication-Results: ozlabs.org; dmarc=pass (p=none dis=none) header.from=gcc.gnu.org Authentication-Results: ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=gcc.gnu.org header.i=@gcc.gnu.org header.a=rsa-sha256 header.s=default header.b=UjNDGdIB; dkim-atps=neutral Received: from sourceware.org (unknown [8.43.85.97]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 4Cm6303MrGz9sPB for ; Wed, 2 Dec 2020 15:50:02 +1100 (AEDT) Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id EF70F384B0C0; Wed, 2 Dec 2020 04:49:58 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org EF70F384B0C0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1606884599; bh=7Q1zmFNeM7tSs7u+LWGP/WLnXpz3Viw2/P3k0uccWHo=; h=Subject:To:Date:List-Id:List-Unsubscribe:List-Archive:List-Post: List-Help:List-Subscribe:From:Reply-To:From; b=UjNDGdIBxuc22cWnVoZHfgYIE9S9fr61nd4WX1Osnx76NN6zTpogBcVkYKKL3BqP7 h8DdvAbbUEV2HYs3shjdBsJDZeyCDShI3EXthLpYg44ClesWATSU04BnUagrpCi1kA pEI+zl4XkotWSMjhd9eypL+MSwn6RVmOfPzDehZQ= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [63.128.21.124]) by sourceware.org (Postfix) with ESMTP id B7A833857C66 for ; Wed, 2 Dec 2020 04:49:54 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org B7A833857C66 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-430-fiH4zYmMNcmG76cl_fUvAw-1; Tue, 01 Dec 2020 23:49:52 -0500 X-MC-Unique: fiH4zYmMNcmG76cl_fUvAw-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 54C2F1074645 for ; Wed, 2 Dec 2020 04:49:51 +0000 (UTC) Received: from localhost.localdomain (ovpn-112-145.phx2.redhat.com [10.3.112.145]) by smtp.corp.redhat.com (Postfix) with ESMTP id DA26B5C1B4 for ; Wed, 2 Dec 2020 04:49:50 +0000 (UTC) Subject: [committed] Use add/sub/neg insns to eliminate compare/test insns on H8 To: GCC Patches Message-ID: <6bf2525a-1c31-a27b-cd80-17749275c026@redhat.com> Date: Tue, 1 Dec 2020 21:49:50 -0700 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Thunderbird/78.4.0 MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Language: en-US X-Spam-Status: No, score=-12.0 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, KAM_NUMSUBJECT, RCVD_IN_DNSWL_NONE, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jeff Law via Gcc-patches From: Jeff Law Reply-To: Jeff Law Errors-To: gcc-patches-bounces@gcc.gnu.org Sender: "Gcc-patches" So this is the first in an unknown number of patches to start optimizing away unnecessary compares and test insns on the H8.    I originally had distinct insns for setting the flags and I still use those patches for comparison purposes, but this patch uses define_subst rather than creating distinct patterns. This particular patch enables using addition, subtraction and negation insns to remove redundant compare and test instructions.  It actually does a better job than we ever did with the old cc0 scheme.  It's got reasonable tests for add and subtract.  Negation is a bit tougher to build simple tests for, but I'm confident it works as instrumentation has shown it triggering. There is one case where I think this patch could regress the generated code.  Specifically it over-computes the size of an addition by +-4 by 2 bytes when the addition is not used for removing a compare/test insn.  As a result we could end up generating a longer branch than is strictly necessary.  If this turns out to be a problem, we can certainly account for that special case in the length computation if we need to. Naturally this does not trigger any regressions in the testsuite. Committed to the trunk. Jeff commit 7da97411b048cdd4e7941b311514f46ea53fe3a2 Author: Jeff Law Date: Tue Dec 1 21:48:10 2020 -0700 Use add/sub/neg insns to eliminate compare/test insns on H8 gcc/ * config/h8300/addsub.md (addqi3_clobber_flags): Rename to addqi3_flags and annotate with a for define_subst. (addhi3_h8sx_clobber_flags): Likewise. (subqi3_clobber_flags, sub3_clobber_flags): Likewise. (neg_clobber_flags): Similarly. (addsi3_clobber_flags): Similarly. Update last argument to output_plussi to distinguish when we need flags or do not need flags. (addhi3_clobber_flags): Similarly. Twiddle code for cases +-1, +-2 and +-4. * config/h8300/h8300.md: Define iterators, mode attributes and substitutions for use in compare/test elimination. * config/h8300/jumpcall.md (branch, branch_1): Use H8cc mode iterator to cover the different modes for the CC register. (branch_1_false): Likewise. gcc/testsuite * gcc.target/h8300/add.c: New test. * gcc.target/h8300/add-2.c: New test. * gcc.target/h8300/add-3.c: New test. * gcc.target/h8300/sub.c: New test. * gcc.target/h8300/sub-2.c: New test. * gcc.target/h8300/sub-3.c: New test. diff --git a/gcc/config/h8300/addsub.md b/gcc/config/h8300/addsub.md index d0877c008bf..3585bffa9fc 100644 --- a/gcc/config/h8300/addsub.md +++ b/gcc/config/h8300/addsub.md @@ -19,7 +19,7 @@ [(parallel [(set (match_dup 0) (plus:QI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addqi3_clobber_flags" +(define_insn "*addqi3_flags" [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") (plus:QI (match_operand:QI 1 "h8300_dst_operand" "%0") (match_operand:QI 2 "h8300_src_operand" "rQi"))) @@ -38,18 +38,41 @@ [(parallel [(set (match_dup 0) (plus:HI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addhi3_clobber_flags" +(define_insn "*addhi3_flags" [(set (match_operand:HI 0 "register_operand" "=r,r,r,r,r") (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0") - (match_operand:HI 2 "h8300_src_operand" "L,N,J,n,r"))) + (match_operand:HI 2 "h8300_src_operand" "M,O,J,n,r"))) (clobber (reg:CC CC_REG))] "reload_completed && !TARGET_H8300SX" - "@ - adds %2,%S0 - subs %G2,%S0 - add.b %t2,%t0 - add.w %T2,%T0 - add.w %T2,%T0" + "* + { + switch (which_alternative) + { + case 0: + return \"inc %T2,%T0\"; + case 1: + return \"dec %G2,%T0\"; + case 2: + return \"add.b %t2,%t0\"; + case 3: + { + /* If the constant is 4 or -4 and we do not need the + flags, then we can use adds/subs which is two bytes + shorter. */ + rtx x = XVECEXP (PATTERN (insn), 0, 1); + bool clobber = GET_CODE (x) == CLOBBER; + if (clobber && INTVAL (operands[2]) == 4) + return \"adds %2,%S0\"; + if (clobber && INTVAL (operands[2]) == -4) + return \"subs %G2,%S0\"; + return \"add.w %T2,%T0\"; + } + case 4: + return \"add.w %T2,%T0\"; + default: + gcc_unreachable (); + } + }" [(set_attr "length" "2,2,2,4,2")]) (define_insn_and_split "*addhi3_h8sx" @@ -62,7 +85,7 @@ [(parallel [(set (match_dup 0) (plus:HI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*addhi3_h8sx_clobber_flags" +(define_insn "*addhi3_h8sx_flags" [(set (match_operand:HI 0 "h8300_dst_operand" "=rU,rU,r,rQ") (plus:HI (match_operand:HI 1 "h8300_dst_operand" "%0,0,0,0") (match_operand:HI 2 "h8300_src_operand" "P3>X,P3" [(set (match_operand:SI 0 "h8300_dst_operand" "=rQ,rQ") (plus:SI (match_operand:SI 1 "h8300_dst_operand" "%0,0") (match_operand:SI 2 "h8300_src_operand" "i,rQ"))) (clobber (reg:CC CC_REG))] "reload_completed && h8300_operands_match_p (operands)" { - return output_plussi (operands, false); + rtx x = XVECEXP (PATTERN (insn), 0, 1); + return output_plussi (operands, GET_CODE (x) != CLOBBER); } [(set (attr "length") (symbol_ref "compute_plussi_length (operands, false)"))]) @@ -130,7 +154,7 @@ [(parallel [(set (match_dup 0) (minus:QI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*subqi3_clobber_flags" +(define_insn "*subqi3_flags" [(set (match_operand:QI 0 "h8300_dst_operand" "=rQ") (minus:QI (match_operand:QI 1 "h8300_dst_operand" "0") (match_operand:QI 2 "h8300_dst_operand" "rQ"))) @@ -149,7 +173,7 @@ [(parallel [(set (match_dup 0) (minus:HSI (match_dup 1) (match_dup 2))) (clobber (reg:CC CC_REG))])]) -(define_insn "*sub3_clobber_flags" +(define_insn "*sub3_flags" [(set (match_operand:HSI 0 "h8300_dst_operand" "=rQ,rQ") (minus:HSI (match_operand:HSI 1 "h8300_dst_operand" "0,0") (match_operand:HSI 2 "h8300_src_operand" "rQ,i"))) @@ -183,7 +207,7 @@ [(parallel [(set (match_dup 0) (neg:QHSI (match_dup 1))) (clobber (reg:CC CC_REG))])]) -(define_insn "*neg2_clobber_flags" +(define_insn "*neg2_flags" [(set (match_operand:QHSI 0 "h8300_dst_operand" "=rQ") (neg:QHSI (match_operand:QHSI 1 "h8300_dst_operand" "0"))) (clobber (reg:CC CC_REG))] diff --git a/gcc/config/h8300/h8300.md b/gcc/config/h8300/h8300.md index 7c9cc324f39..932f74eb88f 100644 --- a/gcc/config/h8300/h8300.md +++ b/gcc/config/h8300/h8300.md @@ -134,6 +134,39 @@ (define_attr "old_cc" "none,none_0hit,set_znv,set_zn,compare,clobber" (const_string "clobber")) +;; So the idea here is to define iterators and substitutions so that we +;; can easily modify the patterns with CC clobbers into a pattern +;; which sets appropriate condition codes + +;; The modes we're supporting. This is used when we want to generate +;; multiple patterns where only the mode differs from a single template +(define_mode_iterator H8cc [CC CCZN]) + +;; This is used to generate multiple define_substs from a single +;; template for the different variants we might have. +(define_mode_attr cc [(CC "cc") (CCZN "cczn")]) + +;; The primary substitution pattern. is used to create multiple +;; substitutions based on the CC bits that are set. +;; +;; The mode iterator sets the actual mode on the condition code +;; REG expression. +(define_subst "subst_" + [(set (match_operand 0 "") + (match_operand 1 "")) + (clobber (reg:CC CC_REG))] + "" + [(set (reg:H8cc CC_REG) + (compare:H8cc (match_dup 1) (const_int 0))) + (set (match_dup 0) (match_dup 1))]) + + +;; So when we see or in a define_insn pattern, we'll +;; apply the subst_cczn or subset_cc define_subst to generate a +;; new pattern that compare-elim can use +(define_subst_attr "cczn" "subst_cczn" "" "_cczn") +(define_subst_attr "cc" "subst_cc" "" "_cc") + ;; Type of delay slot. NONE means the instruction has no delay slot. ;; JUMP means it is an unconditional jump that (if short enough) ;; could be implemented using bra/s. diff --git a/gcc/config/h8300/jumpcall.md b/gcc/config/h8300/jumpcall.md index c07dbaf999c..49d1e4312ca 100644 --- a/gcc/config/h8300/jumpcall.md +++ b/gcc/config/h8300/jumpcall.md @@ -23,18 +23,18 @@ "" "#" "reload_completed" - [(set (reg:CC CC_REG) - (compare:CC (match_dup 1) (match_dup 2))) + [(set (reg:H8cc CC_REG) + (compare:H8cc (match_dup 1) (match_dup 2))) (set (pc) (if_then_else (match_op_dup 0 - [(reg:CC CC_REG) (const_int 0)]) + [(reg:H8cc CC_REG) (const_int 0)]) (label_ref (match_dup 3)) (pc)))] "") (define_insn "*branch_1" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(reg:CC CC_REG) (const_int 0)]) + [(reg:H8cc CC_REG) (const_int 0)]) (label_ref (match_operand 0 "" "")) (pc)))] "reload_completed" @@ -52,7 +52,7 @@ (define_insn "*branch_1_false" [(set (pc) (if_then_else (match_operator 1 "comparison_operator" - [(reg:CC CC_REG) (const_int 0)]) + [(reg:H8cc CC_REG) (const_int 0)]) (pc) (label_ref (match_operand 0 "" ""))))] "reload_completed" diff --git a/gcc/testsuite/gcc.target/h8300/add-2.c b/gcc/testsuite/gcc.target/h8300/add-2.c new file mode 100644 index 00000000000..27f9b2f0069 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/add-2.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-ms -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "add.c" diff --git a/gcc/testsuite/gcc.target/h8300/add-3.c b/gcc/testsuite/gcc.target/h8300/add-3.c new file mode 100644 index 00000000000..20de647c944 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/add-3.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-msx -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "add.c" diff --git a/gcc/testsuite/gcc.target/h8300/add.c b/gcc/testsuite/gcc.target/h8300/add.c new file mode 100644 index 00000000000..ebeea579f6b --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/add.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-mh -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned long ulong; + +volatile void abort (void); + + +#define ADD(T)\ +T addE##T (T x, T y) { T t = x + y ; if (t == 0) abort (); return t; } \ +T addNE##T (T x, T y) { T t = x + y ; if (t != 0) return t; abort (); } \ +T addGE##T (T x, T y) { T t = x + y ; if (t >= 0) abort (); return t; } \ +T addLT##T (T x, T y) { T t = x + y ; if (t < 0) abort (); return t; } + +#define ADDC(T,N)\ +T addEQ##N##T (T a) { T t = a + N; if (t == 0) abort (); return t; } \ +T addNE##N##T (T a) { T t = a + N; if (t != 0) return t; abort (); } \ +T addGE##N##T (T a) { T t = a + N; if (t >= 0) abort (); return t; } \ +T addLT##N##T (T a) { T t = a + N; if (t < 0) abort (); return t; } + +#define ADDNC(T,N)\ +T addEQN##N##T (T a) { T t = a + -N; if (t == 0) abort (); return t; } \ +T addNEN##N##T (T a) { T t = a + -N; if (t != 0) return t; abort (); } \ +T addGEN##N##T (T a) { T t = a + -N; if (t >= 0) abort (); return t; } \ +T addLTN##N##T (T a) { T t = a + -N; if (t < 0) abort (); return t; } + + +ADD (schar) +ADD (short) +ADD (long) +ADD (uchar) +ADD (ushort) +ADD (ulong) + + + +ADDC (schar,1) +ADDC (schar,2) +ADDC (schar,3) +ADDC (schar,4) +ADDC (schar,6) +ADDC (schar,8) +ADDNC (schar,1) +ADDNC (schar,2) +ADDNC (schar,3) +ADDNC (schar,4) +ADDNC (schar,6) +ADDNC (schar,8) + +ADDC (uchar,1) +ADDC (uchar,2) +ADDC (uchar,3) +ADDC (uchar,4) +ADDC (uchar,6) +ADDC (uchar,8) +ADDNC (uchar,1) +ADDNC (uchar,2) +ADDNC (uchar,3) +ADDNC (uchar,4) +ADDNC (uchar,6) +ADDNC (uchar,8) + +ADDC (short,1) +ADDC (short,2) +ADDC (short,3) +ADDC (short,4) +ADDC (short,6) +ADDC (short,8) +ADDNC (short,1) +ADDNC (short,2) +ADDNC (short,3) +ADDNC (short,4) +ADDNC (short,6) +ADDNC (short,8) + +ADDC (ushort,1) +ADDC (ushort,2) +ADDC (ushort,3) +ADDC (ushort,4) +ADDC (ushort,6) +ADDC (ushort,8) +ADDNC (ushort,1) +ADDNC (ushort,2) +ADDNC (ushort,3) +ADDNC (ushort,4) +ADDNC (ushort,6) +ADDNC (ushort,8) + +ADDC (long,1) +ADDC (long,2) +ADDC (long,3) +ADDC (long,4) +ADDC (long,6) +ADDC (long,8) +ADDNC (long,1) +ADDNC (long,2) +ADDNC (long,3) +ADDNC (long,4) +ADDNC (long,6) +ADDNC (long,8) + +ADDC (ulong,1) +ADDC (ulong,2) +ADDC (ulong,3) +ADDC (ulong,4) +ADDC (ulong,6) +ADDC (ulong,8) +ADDNC (ulong,1) +ADDNC (ulong,2) +ADDNC (ulong,3) +ADDNC (ulong,4) +ADDNC (ulong,6) +ADDNC (ulong,8) + diff --git a/gcc/testsuite/gcc.target/h8300/sub-2.c b/gcc/testsuite/gcc.target/h8300/sub-2.c new file mode 100644 index 00000000000..c2914bd1d97 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/sub-2.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-ms -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "sub.c" diff --git a/gcc/testsuite/gcc.target/h8300/sub-3.c b/gcc/testsuite/gcc.target/h8300/sub-3.c new file mode 100644 index 00000000000..72bcf04d156 --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/sub-3.c @@ -0,0 +1,5 @@ +/* { dg-do compile } */ +/* { dg-options "-msx -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +#include "sub.c" diff --git a/gcc/testsuite/gcc.target/h8300/sub.c b/gcc/testsuite/gcc.target/h8300/sub.c new file mode 100644 index 00000000000..66b63ab447d --- /dev/null +++ b/gcc/testsuite/gcc.target/h8300/sub.c @@ -0,0 +1,118 @@ +/* { dg-do compile } */ +/* { dg-options "-mh -mint32 -O2" } */ +/* { dg-final { scan-assembler-not "cmp" } } */ + +typedef unsigned char uchar; +typedef signed char schar; +typedef unsigned short ushort; +typedef unsigned long ulong; + +volatile void abort (void); + + +#define SUB(T)\ +T subE##T (T x, T y) { T t = x - y ; if (t == 0) abort (); return t; } \ +T subNE##T (T x, T y) { T t = x - y ; if (t != 0) return t; abort (); } \ +T subGE##T (T x, T y) { T t = x - y ; if (t >= 0) abort (); return t; } \ +T subLT##T (T x, T y) { T t = x - y ; if (t < 0) abort (); return t; } + +#define SUBC(T,N)\ +T subEQ##N##T (T a) { T t = a - N; if (t == 0) abort (); return t; } \ +T subNE##N##T (T a) { T t = a - N; if (t != 0) return t; abort (); } \ +T subGE##N##T (T a) { T t = a - N; if (t >= 0) abort (); return t; } \ +T subLT##N##T (T a) { T t = a - N; if (t < 0) abort (); return t; } + +#define SUBNC(T,N)\ +T subEQN##N##T (T a) { T t = a - -N; if (t == 0) abort (); return t; } \ +T subNEN##N##T (T a) { T t = a - -N; if (t != 0) return t; abort (); } \ +T subGEN##N##T (T a) { T t = a - -N; if (t >= 0) abort (); return t; } \ +T subLTN##N##T (T a) { T t = a - -N; if (t < 0) abort (); return t; } + + +SUB (schar) +SUB (short) +SUB (long) +SUB (uchar) +SUB (ushort) +SUB (ulong) + + + +SUBC (schar,1) +SUBC (schar,2) +SUBC (schar,3) +SUBC (schar,4) +SUBC (schar,6) +SUBC (schar,8) +SUBNC (schar,1) +SUBNC (schar,2) +SUBNC (schar,3) +SUBNC (schar,4) +SUBNC (schar,6) +SUBNC (schar,8) + +SUBC (uchar,1) +SUBC (uchar,2) +SUBC (uchar,3) +SUBC (uchar,4) +SUBC (uchar,6) +SUBC (uchar,8) +SUBNC (uchar,1) +SUBNC (uchar,2) +SUBNC (uchar,3) +SUBNC (uchar,4) +SUBNC (uchar,6) +SUBNC (uchar,8) + +SUBC (short,1) +SUBC (short,2) +SUBC (short,3) +SUBC (short,4) +SUBC (short,6) +SUBC (short,8) +SUBNC (short,1) +SUBNC (short,2) +SUBNC (short,3) +SUBNC (short,4) +SUBNC (short,6) +SUBNC (short,8) + +SUBC (ushort,1) +SUBC (ushort,2) +SUBC (ushort,3) +SUBC (ushort,4) +SUBC (ushort,6) +SUBC (ushort,8) +SUBNC (ushort,1) +SUBNC (ushort,2) +SUBNC (ushort,3) +SUBNC (ushort,4) +SUBNC (ushort,6) +SUBNC (ushort,8) + +SUBC (long,1) +SUBC (long,2) +SUBC (long,3) +SUBC (long,4) +SUBC (long,6) +SUBC (long,8) +SUBNC (long,1) +SUBNC (long,2) +SUBNC (long,3) +SUBNC (long,4) +SUBNC (long,6) +SUBNC (long,8) + +SUBC (ulong,1) +SUBC (ulong,2) +SUBC (ulong,3) +SUBC (ulong,4) +SUBC (ulong,6) +SUBC (ulong,8) +SUBNC (ulong,1) +SUBNC (ulong,2) +SUBNC (ulong,3) +SUBNC (ulong,4) +SUBNC (ulong,6) +SUBNC (ulong,8) +