[NDS32] Refine bit-wise operation and shift patterns.
authorKito Cheng <kito.cheng@gmail.com>
Thu, 5 Apr 2018 02:51:45 +0000 (02:51 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Thu, 5 Apr 2018 02:51:45 +0000 (02:51 +0000)
gcc/
* config/nds32/iterators.md (shift_rotate): New code iterator.
(shift): New code attribute.
* config/nds32/nds32-md-auxiliary.c (nds32_expand_constant): New.
* config/nds32/nds32-protos.h (nds32_expand_constant): Declare.
* config/nds32/nds32.c (nds32_print_operand): Deal with more cases.
* config/nds32/nds32.md (addsi3, *add_srli): Refine implementation for
bit-wise operations.
(andsi3, *andsi3): Ditto.
(iorsi3, *iorsi3, *or_slli, *or_srli): Ditto.
(xorsi3, *xorsi3, *xor_slli, *xor_srli): Ditto.
(<shift>si3, *ashlsi3, *ashrsi3, *lshrsi3, *rotrsi3): Ditto.
* config/nds32/predicates.md (nds32_rimm5u_operand, nds32_and_operand,
nds32_ior_operand, nds32_xor_operand): New predicates.

Co-Authored-By: Chung-Ju Wu <jasonwucj@gmail.com>
From-SVN: r259117

gcc/ChangeLog
gcc/config/nds32/iterators.md
gcc/config/nds32/nds32-md-auxiliary.c
gcc/config/nds32/nds32-protos.h
gcc/config/nds32/nds32.c
gcc/config/nds32/nds32.md
gcc/config/nds32/predicates.md

index da7eed2401960981e423d6af81feb0703ae585f7..19ea1ab7f628e077e8085efe32c04418edcce331 100644 (file)
@@ -1,3 +1,20 @@
+2018-04-05  Kito Cheng  <kito.cheng@gmail.com>
+           Chung-Ju Wu  <jasonwucj@gmail.com>
+
+       * config/nds32/iterators.md (shift_rotate): New code iterator.
+       (shift): New code attribute.
+       * config/nds32/nds32-md-auxiliary.c (nds32_expand_constant): New.
+       * config/nds32/nds32-protos.h (nds32_expand_constant): Declare.
+       * config/nds32/nds32.c (nds32_print_operand): Deal with more cases.
+       * config/nds32/nds32.md (addsi3, *add_srli): Refine implementation for
+       bit-wise operations.
+       (andsi3, *andsi3): Ditto.
+       (iorsi3, *iorsi3, *or_slli, *or_srli): Ditto.
+       (xorsi3, *xorsi3, *xor_slli, *xor_srli): Ditto.
+       (<shift>si3, *ashlsi3, *ashrsi3, *lshrsi3, *rotrsi3): Ditto.
+       * config/nds32/predicates.md (nds32_rimm5u_operand, nds32_and_operand,
+       nds32_ior_operand, nds32_xor_operand): New predicates.
+
 2018-04-05  Chung-Ju Wu  <jasonwucj@gmail.com>
 
        * config/nds32/nds32.md (add<mode>3, sub<mode>3): Rename to ...
index c587921a39dee895a70c8fc2b9daaa63c77c2885..e0798ff812f7a384ebd37fceea6a46ce9129d81e 100644 (file)
 ;; Code iterators.
 ;;----------------------------------------------------------------------------
 
+;; shifts
+(define_code_iterator shift_rotate [ashift ashiftrt lshiftrt rotatert])
 
 ;;----------------------------------------------------------------------------
 ;; Code attributes.
 ;;----------------------------------------------------------------------------
 
+;; shifts
+(define_code_attr shift
+  [(ashift "ashl") (ashiftrt "ashr") (lshiftrt "lshr") (rotatert "rotr")])
+
 
 ;;----------------------------------------------------------------------------
index f707f19853027cb6c030deca95087de8db9ec42c..607bcc212113b1dc2a0d6532c15816b542d156ca 100644 (file)
@@ -2111,3 +2111,49 @@ nds32_long_call_p (rtx symbol)
 {
   return TARGET_CMODEL_LARGE;
 }
+
+void
+nds32_expand_constant (machine_mode mode, HOST_WIDE_INT val,
+                      rtx target, rtx source)
+{
+  rtx temp = gen_reg_rtx (mode);
+  int clear_sign_bit_copies = 0;
+  int clear_zero_bit_copies = 0;
+  unsigned HOST_WIDE_INT remainder = val & 0xffffffffUL;
+
+  /* Count number of leading zeros.  */
+  clear_sign_bit_copies =  __builtin_clz (remainder);
+  /* Count number of trailing zeros.  */
+  clear_zero_bit_copies = __builtin_ctz (remainder);
+
+  HOST_WIDE_INT sign_shift_mask = ((0xffffffffUL
+                                   << (32 - clear_sign_bit_copies))
+                                  & 0xffffffffUL);
+  HOST_WIDE_INT zero_shift_mask = (1 << clear_zero_bit_copies) - 1;
+
+  if (clear_sign_bit_copies > 0 && clear_sign_bit_copies < 17
+      && (remainder | sign_shift_mask) == 0xffffffffUL)
+    {
+      /* Transfer AND to two shifts, example:
+        a = b & 0x7fffffff => (b << 1) >> 1 */
+      rtx shift = GEN_INT (clear_sign_bit_copies);
+
+      emit_insn (gen_ashlsi3 (temp, source, shift));
+      emit_insn (gen_lshrsi3 (target, temp, shift));
+    }
+  else if (clear_zero_bit_copies > 0 && clear_sign_bit_copies < 17
+          && (remainder | zero_shift_mask) == 0xffffffffUL)
+    {
+      /* Transfer AND to two shifts, example:
+        a = b & 0xfff00000 => (b >> 20) << 20 */
+      rtx shift = GEN_INT (clear_zero_bit_copies);
+
+      emit_insn (gen_lshrsi3 (temp, source, shift));
+      emit_insn (gen_ashlsi3 (target, temp, shift));
+    }
+  else
+    {
+      emit_move_insn (temp, GEN_INT (val));
+      emit_move_insn (target, gen_rtx_fmt_ee (AND, mode, source, temp));
+    }
+}
index 97aad41840b5fe9ca67a15ebcfeffff9a7d5b994..42f8dd9d762ca8b27714a7f183724bb9f6a80db9 100644 (file)
@@ -154,6 +154,11 @@ extern const char *nds32_output_cbranchsi4_greater_less_zero (rtx_insn *, rtx *)
 extern const char *nds32_output_stack_push (rtx);
 extern const char *nds32_output_stack_pop (rtx);
 
+/* Auxiliary functions to split large constant RTX pattern.  */
+
+extern void nds32_expand_constant (machine_mode,
+                                  HOST_WIDE_INT, rtx, rtx);
+
 /* Auxiliary functions to check using return with null epilogue.  */
 
 extern int nds32_can_use_return_insn (void);
index 829e097eae2ea161178f6bbf36c1233523360e05..74ff621664f0440efb43556bac06127bcea59bed 100644 (file)
@@ -2402,6 +2402,8 @@ nds32_asm_globalize_label (FILE *stream, const char *name)
 static void
 nds32_print_operand (FILE *stream, rtx x, int code)
 {
+  HOST_WIDE_INT one_position;
+  HOST_WIDE_INT zero_position;
   int op_value;
 
   switch (code)
@@ -2410,6 +2412,26 @@ nds32_print_operand (FILE *stream, rtx x, int code)
       /* Do nothing special.  */
       break;
 
+    case 'b':
+      /* Use exact_log2() to search the 0-bit position.  */
+      gcc_assert (CONST_INT_P (x));
+      zero_position = exact_log2 (~UINTVAL (x) & GET_MODE_MASK (SImode));
+      gcc_assert (zero_position != -1);
+      fprintf (stream, HOST_WIDE_INT_PRINT_DEC, zero_position);
+
+      /* No need to handle following process, so return immediately.  */
+      return;
+
+    case 'B':
+      /* Use exact_log2() to search the 1-bit position.  */
+      gcc_assert (CONST_INT_P (x));
+      one_position = exact_log2 (UINTVAL (x) & GET_MODE_MASK (SImode));
+      gcc_assert (one_position != -1);
+      fprintf (stream, HOST_WIDE_INT_PRINT_DEC, one_position);
+
+      /* No need to handle following process, so return immediately.  */
+      return;
+
     case 'V':
       /* 'x' is supposed to be CONST_INT, get the value.  */
       gcc_assert (CONST_INT_P (x));
index 95345ff7af8434fe2d9dba44e4fb22c4b3289154..b7c82b6979870177820c10e5f7fe0b38e7cb270d 100644 (file)
 (define_insn "addsi3"
   [(set (match_operand:SI 0 "register_operand"               "=   d,   l,   d,   l, d, l,   k,   l,    r, r")
        (plus:SI (match_operand:SI 1 "register_operand"      "%   0,   l,   0,   l, 0, l,   0,   k,    r, r")
-                (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,IU06, Is15, r")))]
+                (match_operand:SI 2 "nds32_rimm15s_operand" " In05,In03,Iu05,Iu03, r, l,Is10,Iu06, Is15, r")))]
   ""
 {
   switch (which_alternative)
    (set_attr "length"       "4")])
 
 (define_insn "*add_srli"
-  [(set (match_operand:SI 0 "register_operand"                        "=   r")
-       (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"  "    r")
-                             (match_operand:SI 2 "immediate_operand" " Iu05"))
-                (match_operand:SI 3 "register_operand"               "    r")))]
+  [(set (match_operand:SI 0 "register_operand"                          "=   r")
+       (plus:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
+                             (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
+                (match_operand:SI 3 "register_operand"                 "    r")))]
   "TARGET_ISA_V3"
   "add_srli\t%0, %3, %1, %2"
   [(set_attr "type" "alu_shift")
    (set_attr "length" "4")]
 )
 
-(define_insn "andsi3"
-  [(set (match_operand:SI 0 "register_operand"         "=w, r,    l,    l,    l,    l,    l,    l,    r,   r,     r,    r,    r")
-       (and:SI (match_operand:SI 1 "register_operand" "%0, r,    l,    l,    l,    l,    0,    0,    r,   r,     r,    r,    r")
-               (match_operand:SI 2 "general_operand"  " w, r, Izeb, Izeh, Ixls, Ix11, Ibms, Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
+(define_expand "andsi3"
+  [(set (match_operand:SI 0 "register_operand" "")
+       (and:SI (match_operand:SI 1 "register_operand" "")
+               (match_operand:SI 2 "nds32_reg_constant_operand" "")))]
+  ""
+{
+  if (CONST_INT_P (operands[2])
+      && !nds32_and_operand (operands[2], SImode))
+    {
+      nds32_expand_constant (SImode, INTVAL (operands[2]),
+                            operands[0], operands[1]);
+      DONE;
+    }
+})
+
+(define_insn "*andsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=l, r,   l,   l,   l,   l,   l,   l,    r,   r,     r,    r,    r")
+       (and:SI (match_operand:SI 1 "register_operand"  "%0, r,   l,   l,   l,   l,   0,   0,    r,   r,     r,    r,    r")
+               (match_operand:SI 2 "nds32_and_operand" " l, r,Izeb,Izeh,Ixls,Ix11,Ibms,Ifex, Izeb, Izeh, Iu15, Ii15, Ic15")))]
   ""
 {
   HOST_WIDE_INT mask = INTVAL (operands[2]);
-  int zero_position;
 
   /* 16-bit andi instructions:
      andi Rt3,Ra3,0xff   -> zeb33  Rt3,Ra3
     case 5:
       return "x11b33\t%0, %1";
     case 6:
-      operands[2] = GEN_INT (floor_log2 (mask));
-      return "bmski33\t%0, %2";
+      return "bmski33\t%0, %B2";
     case 7:
       operands[2] = GEN_INT (floor_log2 (mask + 1) - 1);
       return "fexti33\t%0, %2";
       operands[2] = GEN_INT (~mask);
       return "bitci\t%0, %1, %2";
     case 12:
-      /* If we reach this alternative,
-         it must pass the nds32_can_use_bclr_p() test,
-         so that we can guarantee there is only one 0-bit
-         within the immediate value.  */
-      for (zero_position = 31; zero_position >= 0; zero_position--)
-       {
-         if ((INTVAL (operands[2]) & (1 << zero_position)) == 0)
-           {
-             /* Found the 0-bit position.  */
-             operands[2] = GEN_INT (zero_position);
-             break;
-           }
-       }
-      return "bclr\t%0, %1, %2";
+      return "bclr\t%0, %1, %b2";
 
     default:
       gcc_unreachable ();
 
 ;; For V3/V3M ISA, we have 'or33' instruction.
 ;; So we can identify 'or Rt3,Rt3,Ra3' case and set its length to be 2.
-(define_insn "iorsi3"
-  [(set (match_operand:SI 0 "register_operand"         "=w, r,    r,    r")
-       (ior:SI (match_operand:SI 1 "register_operand" "%0, r,    r,    r")
-               (match_operand:SI 2 "general_operand"  " w, r, Iu15, Ie15")))]
+
+(define_expand "iorsi3"
+  [(set (match_operand:SI 0 "register_operand"         "")
+       (ior:SI (match_operand:SI 1 "register_operand" "")
+               (match_operand:SI 2 "general_operand"  "")))]
   ""
 {
-  int one_position;
-
-  switch (which_alternative)
-    {
-    case 0:
-      return "or33\t%0, %2";
-    case 1:
-      return "or\t%0, %1, %2";
-    case 2:
-      return "ori\t%0, %1, %2";
-    case 3:
-      /* If we reach this alternative,
-         it must pass the nds32_can_use_bset_p() test,
-         so that we can guarantee there is only one 1-bit
-         within the immediate value.  */
-      /* Use exact_log2() to search the 1-bit position.  */
-      one_position = exact_log2 (INTVAL (operands[2]));
-      operands[2] = GEN_INT (one_position);
-      return "bset\t%0, %1, %2";
+  if (!nds32_ior_operand (operands[2], SImode))
+    operands[2] = force_reg (SImode, operands[2]);
+})
 
-    default:
-      gcc_unreachable ();
-    }
-}
-  [(set_attr "type"   "alu,alu,alu,alu")
-   (set_attr "length" "  2,  4,  4,  4")])
+(define_insn "*iorsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=l, r,    r,    r")
+       (ior:SI (match_operand:SI 1 "register_operand"  "%0, r,    r,    r")
+               (match_operand:SI 2 "nds32_ior_operand" " l, r, Iu15, Ie15")))]
+  ""
+  "@
+   or33\t%0, %2
+   or\t%0, %1, %2
+   ori\t%0, %1, %2
+   bset\t%0, %1, %B2"
+  [(set_attr "type"    "alu,alu,alu,alu")
+   (set_attr "length"  "  2,  4,  4,  4")
+   (set_attr "feature" "v3m, v1, v1,pe1")])
 
 (define_insn "*or_slli"
-  [(set (match_operand:SI 0 "register_operand"                     "=   r")
-       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand"  "    r")
-                          (match_operand:SI 2 "immediate_operand" " Iu05"))
-               (match_operand:SI 3 "register_operand"             "    r")))]
+  [(set (match_operand:SI 0 "register_operand"                       "=   r")
+       (ior:SI (ashift:SI (match_operand:SI 1 "register_operand"    "    r")
+                          (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
+               (match_operand:SI 3 "register_operand"               "    r")))]
   "TARGET_ISA_V3"
   "or_slli\t%0, %3, %1, %2"
   [(set_attr "type" "alu_shift")
    (set_attr "length"       "4")])
 
 (define_insn "*or_srli"
-  [(set (match_operand:SI 0 "register_operand"                       "=   r")
-       (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"  "    r")
-                            (match_operand:SI 2 "immediate_operand" " Iu05"))
-               (match_operand:SI 3 "register_operand"               "    r")))]
+  [(set (match_operand:SI 0 "register_operand"                         "=   r")
+       (ior:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
+                            (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
+               (match_operand:SI 3 "register_operand"                 "    r")))]
   "TARGET_ISA_V3"
   "or_srli\t%0, %3, %1, %2"
   [(set_attr "type" "alu_shift")
 
 ;; For V3/V3M ISA, we have 'xor33' instruction.
 ;; So we can identify 'xor Rt3,Rt3,Ra3' case and set its length to be 2.
-(define_insn "xorsi3"
-  [(set (match_operand:SI 0 "register_operand"         "=w, r,    r,    r")
-       (xor:SI (match_operand:SI 1 "register_operand" "%0, r,    r,    r")
-               (match_operand:SI 2 "general_operand"  " w, r, Iu15, It15")))]
+
+(define_expand "xorsi3"
+  [(set (match_operand:SI 0 "register_operand"         "")
+       (xor:SI (match_operand:SI 1 "register_operand" "")
+               (match_operand:SI 2 "general_operand"  "")))]
   ""
 {
-  int one_position;
-
-  switch (which_alternative)
-    {
-    case 0:
-      return "xor33\t%0, %2";
-    case 1:
-      return "xor\t%0, %1, %2";
-    case 2:
-      return "xori\t%0, %1, %2";
-    case 3:
-      /* If we reach this alternative,
-         it must pass the nds32_can_use_btgl_p() test,
-         so that we can guarantee there is only one 1-bit
-         within the immediate value.  */
-      /* Use exact_log2() to search the 1-bit position.  */
-      one_position = exact_log2 (INTVAL (operands[2]));
-      operands[2] = GEN_INT (one_position);
-      return "btgl\t%0, %1, %2";
+  if (!nds32_xor_operand (operands[2], SImode))
+    operands[2] = force_reg (SImode, operands[2]);
+})
 
-    default:
-      gcc_unreachable ();
-    }
-}
+(define_insn "*xorsi3"
+  [(set (match_operand:SI 0 "register_operand"          "=l, r,    r,    r")
+       (xor:SI (match_operand:SI 1 "register_operand"  "%0, r,    r,    r")
+               (match_operand:SI 2 "nds32_xor_operand" " l, r, Iu15, It15")))]
+  ""
+  "@
+   xor33\t%0, %2
+   xor\t%0, %1, %2
+   xori\t%0, %1, %2
+   btgl\t%0, %1, %B2"
   [(set_attr "type"    "alu,alu,alu,alu")
    (set_attr "length"  "  2,  4,  4,  4")
    (set_attr "feature" "v3m, v1, v1,pe1")])
 (define_insn "*xor_slli"
   [(set (match_operand:SI 0 "register_operand"                     "=   r")
        (xor:SI (ashift:SI (match_operand:SI 1 "register_operand"  "    r")
-                          (match_operand:SI 2 "immediate_operand" " Iu05"))
+                          (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
                (match_operand:SI 3 "register_operand"             "    r")))]
   "TARGET_ISA_V3"
   "xor_slli\t%0, %3, %1, %2"
    (set_attr "length"       "4")])
 
 (define_insn "*xor_srli"
-  [(set (match_operand:SI 0 "register_operand"                       "=   r")
-       (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"  "    r")
-                            (match_operand:SI 2 "immediate_operand" " Iu05"))
-               (match_operand:SI 3 "register_operand"               "    r")))]
+  [(set (match_operand:SI 0 "register_operand"                         "=   r")
+       (xor:SI (lshiftrt:SI (match_operand:SI 1 "register_operand"    "    r")
+                            (match_operand:SI 2 "nds32_imm5u_operand" " Iu05"))
+               (match_operand:SI 3 "register_operand"                 "    r")))]
   "TARGET_ISA_V3"
   "xor_srli\t%0, %3, %1, %2"
   [(set_attr "type" "alu_shift")
 
 ;; Rotate Right Instructions.
 
-(define_insn "rotrsi3"
-  [(set (match_operand:SI 0 "register_operand"                 "=   r, r")
-         (rotatert:SI (match_operand:SI 1 "register_operand"  "    r, r")
-                      (match_operand:SI 2 "nonmemory_operand" " Iu05, r")))]
+(define_insn "*rotrsi3"
+  [(set (match_operand:SI 0 "register_operand"                    "=   r, r")
+         (rotatert:SI (match_operand:SI 1 "register_operand"     "    r, r")
+                      (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, r")))]
   ""
   "@
    rotri\t%0, %1, %2
 
 ;; Shift instructions.
 
-(define_insn "ashlsi3"
-  [(set (match_operand:SI 0 "register_operand"             "=   l,    r, r")
-       (ashift:SI (match_operand:SI 1 "register_operand"  "    l,    r, r")
-                  (match_operand:SI 2 "nonmemory_operand" " Iu03, Iu05, r")))]
+(define_expand "<shift>si3"
+  [(set (match_operand:SI 0 "register_operand"                      "")
+       (shift_rotate:SI (match_operand:SI 1 "register_operand"     "")
+                        (match_operand:SI 2 "nds32_rimm5u_operand" "")))]
+  ""
+{
+  if (operands[2] == const0_rtx)
+    {
+      emit_move_insn (operands[0], operands[1]);
+      DONE;
+    }
+})
+
+(define_insn "*ashlsi3"
+  [(set (match_operand:SI 0 "register_operand"                "=   l,    r, r")
+       (ashift:SI (match_operand:SI 1 "register_operand"     "    l,    r, r")
+                  (match_operand:SI 2 "nds32_rimm5u_operand" " Iu03, Iu05, r")))]
   ""
   "@
    slli333\t%0, %1, %2
   [(set_attr "type"    "  alu,  alu,  alu")
    (set_attr "subtype" "shift,shift,shift")
    (set_attr "length"  "    2,    4,    4")])
-(define_insn "ashrsi3"
-  [(set (match_operand:SI 0 "register_operand"               "=   d,    r, r")
-       (ashiftrt:SI (match_operand:SI 1 "register_operand"  "    0,    r, r")
-                    (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))]
+
+(define_insn "*ashrsi3"
+  [(set (match_operand:SI 0 "register_operand"                  "=   d,    r, r")
+       (ashiftrt:SI (match_operand:SI 1 "register_operand"     "    0,    r, r")
+                    (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
   ""
   "@
    srai45\t%0, %2
    (set_attr "subtype" "shift,shift,shift")
    (set_attr "length"  "    2,    4,    4")])
 
-(define_insn "lshrsi3"
-  [(set (match_operand:SI 0 "register_operand"               "=   d,    r, r")
-       (lshiftrt:SI (match_operand:SI 1 "register_operand"  "    0,    r, r")
-                    (match_operand:SI 2 "nonmemory_operand" " Iu05, Iu05, r")))]
+(define_insn "*lshrsi3"
+  [(set (match_operand:SI 0 "register_operand"                  "=   d,    r, r")
+       (lshiftrt:SI (match_operand:SI 1 "register_operand"     "    0,    r, r")
+                    (match_operand:SI 2 "nds32_rimm5u_operand" " Iu05, Iu05, r")))]
   ""
   "@
    srli45\t%0, %2
index 7cf4635e1cf971342289f7865d9122a16f0cbdbd..066ec3471eab0a427d508ce6fe006abc9dda4171 100644 (file)
   (and (match_operand 0 "const_int_operand")
        (match_test "satisfies_constraint_Iu05 (op)")))
 
+(define_predicate "nds32_rimm5u_operand"
+  (ior (match_operand 0 "register_operand")
+       (match_operand 0 "nds32_imm5u_operand")))
+
 (define_predicate "nds32_move_operand"
   (and (match_operand 0 "general_operand")
        (not (match_code "high,const,symbol_ref,label_ref")))
   return true;
 })
 
+(define_predicate "nds32_and_operand"
+  (match_operand 0 "nds32_reg_constant_operand")
+{
+  return REG_P (op)
+        || GET_CODE (op) == SUBREG
+        || satisfies_constraint_Izeb (op)
+        || satisfies_constraint_Izeh (op)
+        || satisfies_constraint_Ixls (op)
+        || satisfies_constraint_Ix11 (op)
+        || satisfies_constraint_Ibms (op)
+        || satisfies_constraint_Ifex (op)
+        || satisfies_constraint_Iu15 (op)
+        || satisfies_constraint_Ii15 (op)
+        || satisfies_constraint_Ic15 (op);
+})
+
+(define_predicate "nds32_ior_operand"
+  (match_operand 0 "nds32_reg_constant_operand")
+{
+  return REG_P (op)
+        || GET_CODE (op) == SUBREG
+        || satisfies_constraint_Iu15 (op)
+        || satisfies_constraint_Ie15 (op);
+})
+
+(define_predicate "nds32_xor_operand"
+  (match_operand 0 "nds32_reg_constant_operand")
+{
+  return REG_P (op)
+        || GET_CODE (op) == SUBREG
+        || satisfies_constraint_Iu15 (op)
+        || satisfies_constraint_It15 (op);
+})
+
 (define_predicate "nds32_general_register_operand"
   (match_code "reg,subreg")
 {