]> git.ipfire.org Git - thirdparty/gcc.git/blobdiff - gcc/rtl.h
Fix missed IPA-CP on by-ref argument directly passed through (PR 93429)
[thirdparty/gcc.git] / gcc / rtl.h
index f42d749511d8988b77f8f167c22c42ec0c2ef6d5..0872cc408eb177f42083204764e69b2268cf0840 100644 (file)
--- a/gcc/rtl.h
+++ b/gcc/rtl.h
@@ -1,5 +1,5 @@
 /* Register Transfer Language (RTL) definitions for GCC
-   Copyright (C) 1987-2018 Free Software Foundation, Inc.
+   Copyright (C) 1987-2020 Free Software Foundation, Inc.
 
 This file is part of GCC.
 
@@ -36,6 +36,8 @@ along with GCC; see the file COPYING3.  If not see
 
 #include "hard-reg-set.h"
 
+class predefined_function_abi;
+
 /* Value used by some passes to "recognize" noop moves as valid
  instructions.  */
 #define NOOP_MOVE_INSN_CODE    INT_MAX
@@ -145,8 +147,9 @@ struct addr_diff_vec_flags
 /* Structure used to describe the attributes of a MEM.  These are hashed
    so MEMs that the same attributes share a data structure.  This means
    they cannot be modified in place.  */
-struct GTY(()) mem_attrs
+class GTY(()) mem_attrs
 {
+public:
   mem_attrs ();
 
   /* The expression that the MEM accesses, or null if not known.
@@ -187,7 +190,8 @@ struct GTY(()) mem_attrs
    object in the low part of a 4-byte register, the OFFSET field
    will be -3 rather than 0.  */
 
-struct GTY((for_user)) reg_attrs {
+class GTY((for_user)) reg_attrs {
+public:
   tree decl;                   /* decl corresponding to REG.  */
   poly_int64 offset;           /* Offset from start of DECL.  */
 };
@@ -208,7 +212,7 @@ union rtunion
   tree rt_tree;
   basic_block rt_bb;
   mem_attrs *rt_mem;
-  struct constant_descriptor_rtx *rt_constant;
+  class constant_descriptor_rtx *rt_constant;
   struct dw_cfi_node *rt_cfi;
 };
 
@@ -327,6 +331,7 @@ struct GTY((desc("0"), tag("0"),
      1 in a MEM if it cannot trap.
      1 in a CALL_INSN logically equivalent to
        ECF_LOOPING_CONST_OR_PURE and DECL_LOOPING_CONST_OR_PURE_P.
+     1 in a VALUE is SP_DERIVED_VALUE_P in cselib.c.
      Dumped as "/c" in RTL dumps.  */
   unsigned int call : 1;
   /* 1 in a REG, MEM, or CONCAT if the value is set at most once, anywhere.
@@ -449,8 +454,9 @@ struct GTY((desc("0"), tag("0"),
 
 /* A node for constructing singly-linked lists of rtx.  */
 
-class GTY(()) rtx_expr_list : public rtx_def
+struct GTY(()) rtx_expr_list : public rtx_def
 {
+private:
   /* No extra fields, but adds invariant: (GET_CODE (X) == EXPR_LIST).  */
 
 public:
@@ -469,8 +475,9 @@ is_a_helper <rtx_expr_list *>::test (rtx rt)
   return rt->code == EXPR_LIST;
 }
 
-class GTY(()) rtx_insn_list : public rtx_def
+struct GTY(()) rtx_insn_list : public rtx_def
 {
+private:
   /* No extra fields, but adds invariant: (GET_CODE (X) == INSN_LIST).
 
      This is an instance of:
@@ -501,8 +508,9 @@ is_a_helper <rtx_insn_list *>::test (rtx rt)
 /* A node with invariant GET_CODE (X) == SEQUENCE i.e. a vector of rtx,
    typically (but not always) of rtx_insn *, used in the late passes.  */
 
-class GTY(()) rtx_sequence : public rtx_def
+struct GTY(()) rtx_sequence : public rtx_def
 {
+private:
   /* No extra fields, but adds invariant: (GET_CODE (X) == SEQUENCE).  */
 
 public:
@@ -533,7 +541,7 @@ is_a_helper <const rtx_sequence *>::test (const_rtx rt)
   return rt->code == SEQUENCE;
 }
 
-class GTY(()) rtx_insn : public rtx_def
+struct GTY(()) rtx_insn : public rtx_def
 {
 public:
   /* No extra fields, but adds the invariant:
@@ -567,7 +575,7 @@ public:
 
 /* Subclasses of rtx_insn.  */
 
-class GTY(()) rtx_debug_insn : public rtx_insn
+struct GTY(()) rtx_debug_insn : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        DEBUG_INSN_P (X) aka (GET_CODE (X) == DEBUG_INSN)
@@ -578,7 +586,7 @@ class GTY(()) rtx_debug_insn : public rtx_insn
      from rtl.def.  */
 };
 
-class GTY(()) rtx_nonjump_insn : public rtx_insn
+struct GTY(()) rtx_nonjump_insn : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        NONJUMP_INSN_P (X) aka (GET_CODE (X) == INSN)
@@ -589,7 +597,7 @@ class GTY(()) rtx_nonjump_insn : public rtx_insn
      from rtl.def.  */
 };
 
-class GTY(()) rtx_jump_insn : public rtx_insn
+struct GTY(()) rtx_jump_insn : public rtx_insn
 {
 public:
   /* No extra fields, but adds the invariant:
@@ -616,7 +624,7 @@ public:
   inline void set_jump_target (rtx_code_label *);
 };
 
-class GTY(()) rtx_call_insn : public rtx_insn
+struct GTY(()) rtx_call_insn : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        CALL_P (X) aka (GET_CODE (X) == CALL_INSN)
@@ -629,7 +637,7 @@ class GTY(()) rtx_call_insn : public rtx_insn
      from rtl.def.  */
 };
 
-class GTY(()) rtx_jump_table_data : public rtx_insn
+struct GTY(()) rtx_jump_table_data : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        JUMP_TABLE_DATA_P (X) aka (GET_CODE (INSN) == JUMP_TABLE_DATA)
@@ -640,8 +648,6 @@ class GTY(()) rtx_jump_table_data : public rtx_insn
        DEF_RTL_EXPR(JUMP_TABLE_DATA, "jump_table_data", "uuBe0000", RTX_INSN)
      from rtl.def.  */
 
-public:
-
   /* This can be either:
 
        (a) a table of absolute jumps, in which case PATTERN (this) is an
@@ -657,7 +663,7 @@ public:
   inline scalar_int_mode get_data_mode () const;
 };
 
-class GTY(()) rtx_barrier : public rtx_insn
+struct GTY(()) rtx_barrier : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        BARRIER_P (X) aka (GET_CODE (X) == BARRIER)
@@ -668,7 +674,7 @@ class GTY(()) rtx_barrier : public rtx_insn
      from rtl.def.  */
 };
 
-class GTY(()) rtx_code_label : public rtx_insn
+struct GTY(()) rtx_code_label : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        LABEL_P (X) aka (GET_CODE (X) == CODE_LABEL)
@@ -679,7 +685,7 @@ class GTY(()) rtx_code_label : public rtx_insn
      from rtl.def.  */
 };
 
-class GTY(()) rtx_note : public rtx_insn
+struct GTY(()) rtx_note : public rtx_insn
 {
   /* No extra fields, but adds the invariant:
        NOTE_P(X) aka (GET_CODE (X) == NOTE)
@@ -840,7 +846,7 @@ struct GTY(()) rtvec_def {
 #define DEBUG_INSN_P(X) (GET_CODE (X) == DEBUG_INSN)
 
 /* Predicate yielding nonzero iff X is an insn that is not a debug insn.  */
-#define NONDEBUG_INSN_P(X) (INSN_P (X) && !DEBUG_INSN_P (X))
+#define NONDEBUG_INSN_P(X) (NONJUMP_INSN_P (X) || JUMP_P (X) || CALL_P (X))
 
 /* Nonzero if DEBUG_MARKER_INSN_P may possibly hold.  */
 #define MAY_HAVE_DEBUG_MARKER_INSNS debug_nonbind_markers_p
@@ -851,8 +857,7 @@ struct GTY(()) rtvec_def {
   (MAY_HAVE_DEBUG_MARKER_INSNS || MAY_HAVE_DEBUG_BIND_INSNS)
 
 /* Predicate yielding nonzero iff X is a real insn.  */
-#define INSN_P(X) \
-  (NONJUMP_INSN_P (X) || DEBUG_INSN_P (X) || JUMP_P (X) || CALL_P (X))
+#define INSN_P(X) (NONDEBUG_INSN_P (X) || DEBUG_INSN_P (X))
 
 /* Predicate yielding nonzero iff X is a note insn.  */
 #define NOTE_P(X) (GET_CODE (X) == NOTE)
@@ -1053,6 +1058,10 @@ is_a_helper <rtx_note *>::test (rtx_insn *insn)
 #define CONSTANT_P(X)   \
   (GET_RTX_CLASS (GET_CODE (X)) == RTX_CONST_OBJ)
 
+/* 1 if X is a LABEL_REF.  */
+#define LABEL_REF_P(X)  \
+  (GET_CODE (X) == LABEL_REF)
+
 /* 1 if X can be used to represent an object.  */
 #define OBJECT_P(X)                                                    \
   ((GET_RTX_CLASS (GET_CODE (X)) & RTX_OBJ_MASK) == RTX_OBJ_RESULT)
@@ -1624,12 +1633,18 @@ extern const char * const reg_note_name[];
 #define GET_REG_NOTE_NAME(MODE) (reg_note_name[(int) (MODE)])
 
 /* This field is only present on CALL_INSNs.  It holds a chain of EXPR_LIST of
-   USE and CLOBBER expressions.
+   USE, CLOBBER and SET expressions.
      USE expressions list the registers filled with arguments that
    are passed to the function.
      CLOBBER expressions document the registers explicitly clobbered
    by this CALL_INSN.
-     Pseudo registers can not be mentioned in this list.  */
+     SET expressions say that the return value of the call (the SET_DEST)
+   is equivalent to a value available before the call (the SET_SRC).
+   This kind of SET is used when the return value is predictable in
+   advance.  It is purely an optimisation hint; unlike USEs and CLOBBERs,
+   it does not affect register liveness.
+
+     Pseudo registers cannot be mentioned in this list.  */
 #define CALL_INSN_FUNCTION_USAGE(INSN) XEXP(INSN, 7)
 
 /* The label-number of a code-label.  The assembler label
@@ -2093,7 +2108,8 @@ costs_add_n_insns (struct full_rtx_costs *c, int n)
    inner_mode == the mode of the SUBREG_REG
    offset     == the SUBREG_BYTE
    outer_mode == the mode of the SUBREG itself.  */
-struct subreg_shape {
+class subreg_shape {
+public:
   subreg_shape (machine_mode, poly_uint16, machine_mode);
   bool operator == (const subreg_shape &) const;
   bool operator != (const subreg_shape &) const;
@@ -2393,12 +2409,30 @@ extern int rtx_cost (rtx, machine_mode, enum rtx_code, int, bool);
 extern int address_cost (rtx, machine_mode, addr_space_t, bool);
 extern void get_full_rtx_cost (rtx, machine_mode, enum rtx_code, int,
                               struct full_rtx_costs *);
+extern bool native_encode_rtx (machine_mode, rtx, vec<target_unit> &,
+                              unsigned int, unsigned int);
+extern rtx native_decode_rtx (machine_mode, vec<target_unit>,
+                             unsigned int);
+extern rtx native_decode_vector_rtx (machine_mode, vec<target_unit>,
+                                    unsigned int, unsigned int, unsigned int);
 extern poly_uint64 subreg_lsb (const_rtx);
-extern poly_uint64 subreg_lsb_1 (machine_mode, machine_mode, poly_uint64);
+extern poly_uint64 subreg_size_lsb (poly_uint64, poly_uint64, poly_uint64);
 extern poly_uint64 subreg_size_offset_from_lsb (poly_uint64, poly_uint64,
                                                poly_uint64);
 extern bool read_modify_subreg_p (const_rtx);
 
+/* Given a subreg's OUTER_MODE, INNER_MODE, and SUBREG_BYTE, return the
+   bit offset at which the subreg begins (counting from the least significant
+   bit of the operand).  */
+
+inline poly_uint64
+subreg_lsb_1 (machine_mode outer_mode, machine_mode inner_mode,
+             poly_uint64 subreg_byte)
+{
+  return subreg_size_lsb (GET_MODE_SIZE (outer_mode),
+                         GET_MODE_SIZE (inner_mode), subreg_byte);
+}
+
 /* Return the subreg byte offset for a subreg whose outer mode is
    OUTER_MODE, whose inner mode is INNER_MODE, and where there are
    LSB_SHIFT *bits* between the lsb of the outer value and the lsb of
@@ -2646,7 +2680,7 @@ do {                                                                      \
 
 /* For a SET rtx, SET_DEST is the place that is set
    and SET_SRC is the value it is set to.  */
-#define SET_DEST(RTX) XC3EXP (RTX, 0, SET, CLOBBER, CLOBBER_HIGH)
+#define SET_DEST(RTX) XC2EXP (RTX, 0, SET, CLOBBER)
 #define SET_SRC(RTX) XCEXP (RTX, 1, SET)
 #define SET_IS_RETURN_P(RTX)                                           \
   (RTL_FLAG_CHECK1 ("SET_IS_RETURN_P", (RTX), SET)->jump)
@@ -2926,6 +2960,15 @@ extern HOST_WIDE_INT get_stack_check_protect (void);
 
 /* In rtl.c */
 extern rtx rtx_alloc (RTX_CODE CXX_MEM_STAT_INFO);
+inline rtx
+rtx_init (rtx rt, RTX_CODE code)
+{
+  memset (rt, 0, RTX_HDR_SIZE);
+  PUT_CODE (rt, code);
+  return rt;
+}
+#define rtx_alloca(code) \
+  rtx_init ((rtx) alloca (RTX_CODE_SIZE ((code))), (code))
 extern rtx rtx_alloc_stat_v (RTX_CODE MEM_STAT_DECL, int);
 #define rtx_alloc_v(c, SZ) rtx_alloc_stat_v (c MEM_STAT_INFO, SZ)
 #define const_wide_int_alloc(NWORDS)                           \
@@ -3310,6 +3353,15 @@ extern enum rtx_code unsigned_condition (enum rtx_code);
 extern enum rtx_code signed_condition (enum rtx_code);
 extern void mark_jump_label (rtx, rtx_insn *, int);
 
+/* Return true if integer comparison operator CODE interprets its operands
+   as unsigned.  */
+
+inline bool
+unsigned_condition_p (enum rtx_code code)
+{
+  return unsigned_condition (code) == code;
+}
+
 /* In jump.c */
 extern rtx_insn *delete_related_insns (rtx);
 
@@ -3362,7 +3414,7 @@ extern bool val_signbit_known_clear_p (machine_mode,
 
 /* In reginfo.c  */
 extern machine_mode choose_hard_reg_mode (unsigned int, unsigned int,
-                                              bool);
+                                         const predefined_function_abi *);
 extern const HARD_REG_SET &simplifiable_subregs (const subreg_shape &);
 
 /* In emit-rtl.c  */
@@ -3376,6 +3428,8 @@ extern void set_insn_deleted (rtx_insn *);
 extern rtx single_set_2 (const rtx_insn *, const_rtx);
 extern bool contains_symbol_ref_p (const_rtx);
 extern bool contains_symbolic_reference_p (const_rtx);
+extern bool contains_constant_pool_address_p (const_rtx);
+extern void add_auto_inc_notes (rtx_insn *, rtx);
 
 /* Handle the cheap and common cases inline for performance.  */
 
@@ -3397,7 +3451,8 @@ extern bool nonzero_address_p (const_rtx);
 extern int rtx_unstable_p (const_rtx);
 extern bool rtx_varies_p (const_rtx, bool);
 extern bool rtx_addr_varies_p (const_rtx, bool);
-extern rtx get_call_rtx_from (rtx);
+extern rtx get_call_rtx_from (const rtx_insn *);
+extern tree get_call_fndecl (const rtx_insn *);
 extern HOST_WIDE_INT get_integer_term (const_rtx);
 extern rtx get_related_value (const_rtx);
 extern bool offset_within_block_p (const_rtx, HOST_WIDE_INT);
@@ -3426,7 +3481,10 @@ extern void record_hard_reg_sets (rtx, const_rtx, void *);
 extern void record_hard_reg_uses (rtx *, void *);
 extern void find_all_hard_regs (const_rtx, HARD_REG_SET *);
 extern void find_all_hard_reg_sets (const rtx_insn *, HARD_REG_SET *, bool);
-extern void note_stores (const_rtx, void (*) (rtx, const_rtx, void *), void *);
+extern void note_pattern_stores (const_rtx,
+                                void (*) (rtx, const_rtx, void *), void *);
+extern void note_stores (const rtx_insn *,
+                        void (*) (rtx, const_rtx, void *), void *);
 extern void note_uses (rtx *, void (*) (rtx *, void *), void *);
 extern int dead_or_set_p (const rtx_insn *, const_rtx);
 extern int dead_or_set_regno_p (const rtx_insn *, unsigned int);
@@ -3443,7 +3501,7 @@ extern void add_args_size_note (rtx_insn *, poly_int64);
 extern void add_shallow_copy_of_reg_note (rtx_insn *, rtx);
 extern rtx duplicate_reg_note (rtx);
 extern void remove_note (rtx_insn *, const_rtx);
-extern bool remove_reg_equal_equiv_notes (rtx_insn *);
+extern bool remove_reg_equal_equiv_notes (rtx_insn *, bool = false);
 extern void remove_reg_equal_equiv_notes_for_regno (unsigned int);
 extern int side_effects_p (const_rtx);
 extern int volatile_refs_p (const_rtx);
@@ -3458,12 +3516,12 @@ extern bool insn_nothrow_p (const_rtx);
 extern bool can_nonlocal_goto (const rtx_insn *);
 extern void copy_reg_eh_region_note_forward (rtx, rtx_insn *, rtx);
 extern void copy_reg_eh_region_note_backward (rtx, rtx_insn *, rtx);
-extern int inequality_comparisons_p (const_rtx);
 extern rtx replace_rtx (rtx, rtx, rtx, bool = false);
 extern void replace_label (rtx *, rtx, rtx, bool);
 extern void replace_label_in_insn (rtx_insn *, rtx_insn *, rtx_insn *, bool);
 extern bool rtx_referenced_p (const_rtx, const_rtx);
 extern bool tablejump_p (const rtx_insn *, rtx_insn **, rtx_jump_table_data **);
+extern rtx tablejump_casesi_pattern (const rtx_insn *insn);
 extern int computed_jump_p (const rtx_insn *);
 extern bool tls_referenced_p (const_rtx);
 extern bool contains_mem_rtx_p (rtx x);
@@ -3699,7 +3757,7 @@ struct GTY(()) target_rtl {
   rtx x_static_reg_base_value[FIRST_PSEUDO_REGISTER];
 
   /* The default memory attributes for each mode.  */
-  struct mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
+  class mem_attrs *x_mode_mem_attrs[(int) MAX_MACHINE_MODE];
 
   /* Track if RTL has been initialized.  */
   bool target_specific_initialized;
@@ -3733,10 +3791,10 @@ extern struct target_rtl *this_target_rtl;
 
 #ifndef GENERATOR_FILE
 /* Return the attributes of a MEM rtx.  */
-static inline const struct mem_attrs *
+static inline const class mem_attrs *
 get_mem_attrs (const_rtx x)
 {
-  struct mem_attrs *attrs;
+  class mem_attrs *attrs;
 
   attrs = MEM_ATTRS (x);
   if (!attrs)
@@ -3769,7 +3827,10 @@ gen_rtx_INSN (machine_mode mode, rtx_insn *prev_insn, rtx_insn *next_insn,
 extern rtx gen_rtx_CONST_INT (machine_mode, HOST_WIDE_INT);
 extern rtx gen_rtx_CONST_VECTOR (machine_mode, rtvec);
 extern void set_mode_and_regno (rtx, machine_mode, unsigned int);
+extern rtx init_raw_REG (rtx, machine_mode, unsigned int);
 extern rtx gen_raw_REG (machine_mode, unsigned int);
+#define alloca_raw_REG(mode, regno) \
+  init_raw_REG (rtx_alloca (REG), (mode), (regno))
 extern rtx gen_rtx_REG (machine_mode, unsigned int);
 extern rtx gen_rtx_SUBREG (machine_mode, rtx, poly_uint64);
 extern rtx gen_rtx_MEM (machine_mode, rtx);
@@ -4026,9 +4087,24 @@ extern void expand_null_return (void);
 extern void expand_naked_return (void);
 extern void emit_jump (rtx);
 
+/* Memory operation built-ins differ by return value.  Mapping
+   of the enum values is following:
+   - RETURN_BEGIN - return destination, e.g. memcpy
+   - RETURN_END - return destination + n, e.g. mempcpy
+   - RETURN_END_MINUS_ONE - return a pointer to the terminating
+    null byte of the string, e.g. strcpy
+*/
+
+enum memop_ret
+{
+  RETURN_BEGIN,
+  RETURN_END,
+  RETURN_END_MINUS_ONE
+};
+
 /* In expr.c */
 extern rtx move_by_pieces (rtx, rtx, unsigned HOST_WIDE_INT,
-                          unsigned int, int);
+                          unsigned int, memop_ret);
 extern poly_int64 find_args_size_adjust (rtx_insn *);
 extern poly_int64 fixup_args_size_notes (rtx_insn *, rtx_insn *, poly_int64);
 
@@ -4043,6 +4119,9 @@ extern void init_lower_subreg (void);
 /* In gcse.c */
 extern bool can_copy_p (machine_mode);
 extern bool can_assign_to_reg_without_clobbers_p (rtx, machine_mode);
+extern rtx_insn *prepare_copy_insn (rtx, rtx);
+
+/* In cprop.c */
 extern rtx fis_get_condition (rtx_insn *);
 
 /* In ira.c */
@@ -4242,7 +4321,6 @@ extern void vt_equate_reg_base_value (const_rtx, const_rtx);
 extern bool memory_modified_in_insn_p (const_rtx, const_rtx);
 extern bool may_be_sp_based_p (rtx);
 extern rtx gen_hard_reg_clobber (machine_mode, unsigned int);
-extern rtx gen_hard_reg_clobber_high (machine_mode, unsigned int);
 extern rtx get_reg_known_value (unsigned int);
 extern bool get_reg_known_equiv_p (unsigned int);
 extern rtx get_reg_base_value (unsigned int);
@@ -4297,6 +4375,7 @@ extern void insn_locations_init (void);
 extern void insn_locations_finalize (void);
 extern void set_curr_insn_location (location_t);
 extern location_t curr_insn_location (void);
+extern void set_insn_locations (rtx_insn *, location_t);
 
 /* rtl-error.c */
 extern void _fatal_insn_not_found (const_rtx, const char *, int, const char *)
@@ -4316,14 +4395,11 @@ extern tree GTY(()) global_regs_decl[FIRST_PSEUDO_REGISTER];
    Available only for functions that has been already assembled.  */
 
 struct GTY(()) cgraph_rtl_info {
-   unsigned int preferred_incoming_stack_boundary;
+  unsigned int preferred_incoming_stack_boundary;
 
-  /* Call unsaved hard registers really used by the corresponding
-     function (including ones used by functions called by the
-     function).  */
+  /* Which registers the function clobbers, either directly or by
+     calling another function.  */
   HARD_REG_SET function_used_regs;
-  /* Set if function_used_regs is valid.  */
-  unsigned function_used_regs_valid: 1;
 };
 
 /* If loads from memories of mode MODE always sign or zero extend,
@@ -4355,6 +4431,26 @@ strip_offset_and_add (rtx x, poly_int64_pod *offset)
   return x;
 }
 
+/* Return true if X is an operation that always operates on the full
+   registers for WORD_REGISTER_OPERATIONS architectures.  */
+
+inline bool
+word_register_operation_p (const_rtx x)
+{
+  switch (GET_CODE (x))
+    {
+    case CONST_INT:
+    case ROTATE:
+    case ROTATERT:
+    case SIGN_EXTRACT:
+    case ZERO_EXTRACT:
+      return false;
+    
+    default:
+      return true;
+    }
+}
+    
 /* gtype-desc.c.  */
 extern void gt_ggc_mx (rtx &);
 extern void gt_pch_nx (rtx &);