#include "bitset.h"
#include "obst.h"
#include "raw_bitset.h"
+#include "irop_t.h"
#include "be_types.h"
#include "beinfo.h"
extern const arch_register_req_t *arch_no_register_req;
/**
- * Format a register requirements information into a string.
- * @param buf The string where to put it to.
- * @param len The size of @p buf.
+ * Print information about a register requirement in human readable form
+ * @param F output stream/file
* @param req The requirements structure to format.
- * @return A pointer to buf.
*/
-extern char *arch_register_req_format(char *buf, size_t len, const arch_register_req_t *req, const ir_node *node);
+void arch_dump_register_req(FILE *F, const arch_register_req_t *req,
+ const ir_node *node);
+
+void arch_dump_register_reqs(FILE *F, const ir_node *node);
+void arch_dump_reqs_and_registers(FILE *F, const ir_node *node);
/**
- * Certain node classes which are relevant for the register allocator.
+ * Node classification. Mainly used for statistics.
*/
typedef enum arch_irn_class_t {
- arch_irn_class_spill = 1 << 0,
- arch_irn_class_reload = 1 << 1,
- arch_irn_class_remat = 1 << 2,
- arch_irn_class_copy = 1 << 3,
- arch_irn_class_perm = 1 << 4,
- arch_irn_class_branch = 1 << 5
+ arch_irn_class_spill = 1 << 0,
+ arch_irn_class_reload = 1 << 1,
+ arch_irn_class_remat = 1 << 2,
+ arch_irn_class_copy = 1 << 3,
+ arch_irn_class_perm = 1 << 4
} arch_irn_class_t;
void arch_set_frame_offset(ir_node *irn, int bias);
/**
* Get the register requirements for a node.
+ * @note Deprecated API! Preferably use
+ * arch_get_in_register_req and
+ * arch_get_out_register_req.
+ *
* @param irn The node.
* @param pos The position of the operand you're interested in.
* @return A pointer to the register requirements. If NULL is returned, the
*/
const arch_register_req_t *arch_get_register_req(const ir_node *irn, int pos);
-#define arch_get_register_req_out(irn) arch_get_register_req(irn, -1)
-
/**
* Put all registers which shall not be ignored by the register
* allocator in a bit set.
struct arch_register_t {
const char *name; /**< The name of the register. */
const arch_register_class_t *reg_class; /**< The class the register belongs to. */
- unsigned index; /**< The index of the register in the class. */
- arch_register_type_t type; /**< The type of the register. */
+ unsigned index; /**< The index of the register in the class. */
+ arch_register_type_t type; /**< The type of the register. */
+ const arch_register_req_t *single_req;
};
static inline const arch_register_class_t *
return reg->name;
}
-#define arch_register_get_class(reg) _arch_register_get_class(reg)
-#define arch_register_get_index(reg) _arch_register_get_index(reg)
-#define arch_register_get_name(reg) _arch_register_get_name(reg)
+#define arch_register_get_class(reg) _arch_register_get_class(reg)
+#define arch_register_get_index(reg) _arch_register_get_index(reg)
+#define arch_register_get_name(reg) _arch_register_get_name(reg)
/**
* Convenience macro to check for register type.
* Like general purpose or floating point.
*/
struct arch_register_class_t {
- unsigned index; /**< index of this register class */
- const char *name; /**< The name of the register class.*/
- unsigned n_regs; /**< Number of registers in this
- class. */
- ir_mode *mode; /**< The mode of the register class.*/
- const arch_register_t *regs; /**< The array of registers. */
- arch_register_class_flags_t flags; /**< register class flags. */
+ unsigned index; /**< index of this register class */
+ const char *name; /**< The name of the register class.*/
+ unsigned n_regs; /**< Number of registers in this
+ class. */
+ ir_mode *mode; /**< The mode of the register class.*/
+ const arch_register_t *regs; /**< The array of registers. */
+ arch_register_class_flags_t flags; /**< register class flags. */
+ const arch_register_req_t *class_req;
};
/** return the number of registers in this register class */
* Expresses requirements to register allocation for an operand.
*/
struct arch_register_req_t {
- arch_register_req_type_t type; /**< The type of the constraint. */
+ arch_register_req_type_t type; /**< The type of the constraint. */
const arch_register_class_t *cls; /**< The register class this constraint belongs to. */
const unsigned *limited; /**< allowed register bitset */
/**
* Get the register requirements for a given operand.
- * @param self The self pointer.
* @param irn The node.
- * @param pos The operand's position (0..n for the input operands).
+ * @param pos The operand's position
* @return The register requirements for the selected operand.
* The pointer returned is never NULL.
*/
- const arch_register_req_t *(*get_irn_reg_req)(const ir_node *irn, int pos);
+ const arch_register_req_t *(*get_irn_reg_req_in)(const ir_node *irn, int pos);
/**
* Classify the node.
/**
* Get the entity on the stack frame this node depends on.
- * @param self The this pointer.
* @param irn The node in question.
* @return The entity on the stack frame or NULL, if the node does not have a
* stack frame entity.
/**
* Set the entity on the stack frame this node depends on.
- * @param self The this pointer.
* @param irn The node in question.
* @param ent The entity to set
*/
/**
* Set the offset of a node carrying an entity on the stack frame.
- * @param self The this pointer.
* @param irn The node.
* @param offset The offset of the node's stack frame entity.
*/
* A positive value stands for an expanding stack area, a negative value for
* a shrinking one.
*
- * @param self The this pointer
* @param irn The node
* @return 0 if the stackpointer is not modified with a constant
* value, otherwise the increment/decrement value
* Returns an inverse operation which yields the i-th argument
* of the given node as result.
*
- * @param self The this pointer.
* @param irn The original operation
* @param i Index of the argument we want the inverse operation to yield
* @param inverse struct to be filled with the resulting inverse op
/**
* Get the estimated cycle count for @p irn.
*
- * @param self The this pointer.
* @param irn The node.
*
* @return The estimated cycle count for this operation
/**
* Asks the backend whether operand @p i of @p irn can be loaded form memory internally
*
- * @param self The this pointer.
* @param irn The node.
* @param i Index of the argument we would like to know whether @p irn can load it form memory internally
*
/**
* Ask the backend to assimilate @p reload of operand @p i into @p irn.
*
- * @param self The this pointer.
* @param irn The node.
* @param spill The spill.
* @param i The position of the reload.
* Get the the number of register classes in the isa.
* @return The number of register classes.
*/
- unsigned (*get_n_reg_class)(const void *self);
+ unsigned (*get_n_reg_class)(void);
/**
* Get the i-th register class.
* @param i The number of the register class.
* @return The register class.
*/
- const arch_register_class_t *(*get_reg_class)(const void *self, unsigned i);
+ const arch_register_class_t *(*get_reg_class)(unsigned i);
/**
* Get the register class which shall be used to store a value of a given mode.
* @param mode The mode in question.
* @return A register class which can hold values of the given mode.
*/
- const arch_register_class_t *(*get_reg_class_for_mode)(const void *self, const ir_mode *mode);
+ const arch_register_class_t *(*get_reg_class_for_mode)(const ir_mode *mode);
/**
* Get the ABI restrictions for procedure calls.
* @param cls The register class.
* @return The alignment in bytes.
*/
- int (*get_reg_class_alignment)(const void *self, const arch_register_class_t *cls);
+ int (*get_reg_class_alignment)(const arch_register_class_t *cls);
/**
* A "static" function, returns the frontend settings
* NULL
* };
*/
- const be_execution_unit_t ***(*get_allowed_execution_units)(const void *self, const ir_node *irn);
+ const be_execution_unit_t ***(*get_allowed_execution_units)(const ir_node *irn);
/**
* Return the abstract machine for this isa.
/**
* mark node as rematerialized
*/
- void (*mark_remat)(const void *self, ir_node *node);
+ void (*mark_remat)(ir_node *node);
/**
* parse an assembler constraint part and set flags according to its nature
* advances the *c pointer to point to the last parsed character (so if you
* parse a single character don't advance c)
*/
- asm_constraint_flags_t (*parse_asm_constraint)(const void *self, const char **c);
+ asm_constraint_flags_t (*parse_asm_constraint)(const char **c);
/**
* returns true if the string is a valid clobbered (register) in this
* backend
*/
- int (*is_valid_clobber)(const void *self, const char *clobber);
+ int (*is_valid_clobber)(const char *clobber);
};
#define arch_env_done(env) ((env)->impl->done(env))
#define arch_env_handle_intrinsics(env) \
do { if((env)->impl->handle_intrinsics != NULL) (env)->impl->handle_intrinsics(); } while(0)
-#define arch_env_get_n_reg_class(env) ((env)->impl->get_n_reg_class(env))
-#define arch_env_get_reg_class(env,i) ((env)->impl->get_reg_class(env, i))
-#define arch_env_get_reg_class_for_mode(env,mode) ((env)->impl->get_reg_class_for_mode((env), (mode)))
+#define arch_env_get_n_reg_class(env) ((env)->impl->get_n_reg_class())
+#define arch_env_get_reg_class(env,i) ((env)->impl->get_reg_class(i))
+#define arch_env_get_reg_class_for_mode(env,mode) ((env)->impl->get_reg_class_for_mode((mode)))
#define arch_env_get_call_abi(env,tp,abi) ((env)->impl->get_call_abi((env), (tp), (abi)))
#define arch_env_get_code_generator_if(env) ((env)->impl->get_code_generator_if((env)))
#define arch_env_get_list_sched_selector(env,selector) ((env)->impl->get_list_sched_selector((env), (selector)))
#define arch_env_get_ilp_sched_selector(env) ((env)->impl->get_ilp_sched_selector(env))
-#define arch_env_get_reg_class_alignment(env,cls) ((env)->impl->get_reg_class_alignment((env), (cls)))
+#define arch_env_get_reg_class_alignment(env,cls) ((env)->impl->get_reg_class_alignment((cls)))
#define arch_env_get_params(env) ((env)->impl->get_params())
-#define arch_env_get_allowed_execution_units(env,irn) ((env)->impl->get_allowed_execution_units((env), (irn)))
+#define arch_env_get_allowed_execution_units(env,irn) ((env)->impl->get_allowed_execution_units((irn)))
#define arch_env_get_machine(env) ((env)->impl->get_machine(env))
#define arch_env_get_backend_irg_list(env,irgs) ((env)->impl->get_backend_irg_list((env), (irgs)))
-#define arch_env_parse_asm_constraint(env,c) ((env)->impl->parse_asm_constraint((env), (c))
-#define arch_env_is_valid_clobber(env,clobber) ((env)->impl->is_valid_clobber((env), (clobber))
+#define arch_env_parse_asm_constraint(env,c) ((env)->impl->parse_asm_constraint((c))
+#define arch_env_is_valid_clobber(env,clobber) ((env)->impl->is_valid_clobber((clobber))
#define arch_env_mark_remat(env,node) \
- do { if ((env)->impl->mark_remat != NULL) (env)->impl->mark_remat((env), (node)); } while(0)
+ do { if ((env)->impl->mark_remat != NULL) (env)->impl->mark_remat((node)); } while(0)
/**
* ISA base class.
static inline unsigned arch_irn_get_n_outs(const ir_node *node)
{
backend_info_t *info = be_get_info(node);
+ if (info->out_infos == NULL)
+ return 0;
+
return ARR_LEN(info->out_infos);
}
+static inline const arch_irn_ops_t *get_irn_ops_simple(const ir_node *node)
+{
+ const ir_op *ops = get_irn_op(node);
+ const arch_irn_ops_t *be_ops = get_op_ops(ops)->be_ops;
+ assert(!is_Proj(node));
+ return be_ops;
+}
+
+static inline const arch_register_req_t *arch_get_register_req_out(
+ const ir_node *irn)
+{
+ int pos = 0;
+ backend_info_t *info;
+
+ if (is_Proj(irn)) {
+ pos = get_Proj_proj(irn);
+ irn = get_Proj_pred(irn);
+ } else if (get_irn_mode(irn) == mode_T) {
+ /* TODO: find out who does this and fix the caller! */
+ return arch_no_register_req;
+ }
+ info = be_get_info(irn);
+ if (info->out_infos == NULL)
+ return arch_no_register_req;
+
+ return info->out_infos[pos].req;
+}
+
+static inline bool arch_irn_is_ignore(const ir_node *irn)
+{
+ const arch_register_req_t *req = arch_get_register_req_out(irn);
+ return !!(req->type & arch_register_req_type_ignore);
+}
+
static inline bool arch_irn_consider_in_reg_alloc(
const arch_register_class_t *cls, const ir_node *node)
{
!(req->type & arch_register_req_type_ignore);
}
-static inline bool arch_irn_is_ignore(const ir_node *irn)
+/**
+ * Get register constraints for an operand at position @p
+ */
+static inline const arch_register_req_t *arch_get_in_register_req(
+ const ir_node *node, int pos)
{
- const arch_register_req_t *req = arch_get_register_req_out(irn);
- return !!(req->type & arch_register_req_type_ignore);
+ const arch_irn_ops_t *ops = get_irn_ops_simple(node);
+ return ops->get_irn_reg_req_in(node, pos);
+}
+
+/**
+ * Get register constraint for a produced result (the @p pos result)
+ */
+static inline const arch_register_req_t *arch_get_out_register_req(
+ const ir_node *node, int pos)
+{
+ const backend_info_t *info = be_get_info(node);
+ if (info->out_infos == NULL)
+ return arch_no_register_req;
+ return info->out_infos[pos].req;
+}
+
+static inline void arch_set_out_register_req(ir_node *node, int pos,
+ const arch_register_req_t *req)
+{
+ backend_info_t *info = be_get_info(node);
+ assert(pos < (int) arch_irn_get_n_outs(node));
+ info->out_infos[pos].req = req;
}
-#endif /* FIRM_BE_BEARCH_H */
+#endif