const ir_node *node,
int pos)
{
- long node_pos = pos == -1 ? 0 : pos;
- ir_mode *mode = is_Block(node) ? NULL : get_irn_mode(node);
- (void) self;
+ ir_mode *mode = get_irn_mode(node);
+ long node_pos;
- if (is_Block(node) || mode == mode_X) {
+ (void)self;
+ if (mode == mode_X || is_Block(node)) {
return arch_no_register_req;
}
return arch_no_register_req;
}
+ node_pos = pos == -1 ? 0 : pos;
if (is_Proj(node)) {
- if(mode == mode_M)
- return arch_no_register_req;
-
- if(pos >= 0) {
+ if (mode == mode_M || pos >= 0) {
return arch_no_register_req;
}
if (is_ia32_irn(node)) {
const arch_register_req_t *req;
- if(pos >= 0)
+ if (pos >= 0)
req = get_ia32_in_req(node, pos);
else
req = get_ia32_out_req(node, node_pos);
/* unknowns should be transformed already */
assert(!is_Unknown(node));
-
return arch_no_register_req;
}
static void ia32_set_irn_reg(const void *self, ir_node *irn,
const arch_register_t *reg)
{
- int pos = 0;
+ int pos = 0;
(void) self;
if (get_irn_mode(irn) == mode_X) {
is_ia32_xStoreSimple(node) ||
is_ia32_vfst(node) ||
is_ia32_vfist(node) ||
+ is_ia32_vfisttp(node) ||
is_ia32_FnstCW(node));
#endif
}
}
-static const void *ia32_get_irn_ops(const arch_irn_handler_t *self,
- const ir_node *irn)
+static const void *ia32_get_irn_ops(const ir_node *irn)
{
- (void) self;
(void) irn;
return &ia32_irn_ops;
}
-const arch_irn_handler_t ia32_irn_handler = {
- ia32_get_irn_ops
-};
-
-const arch_irn_handler_t *ia32_get_irn_handler(const void *self)
+arch_get_irn_ops_t *ia32_get_irn_handler(const void *self)
{
(void) self;
- return &ia32_irn_handler;
+ return &ia32_get_irn_ops;
}
int ia32_to_appear_in_schedule(void *block_env, const ir_node *irn)
*/
static int ia32_is_psi_allowed(ir_node *sel, ir_node *phi_list, int i, int j)
{
- ir_node *phi;
-
- (void)sel;
- (void)i;
- (void)j;
+ ir_node *phi, *left;
+ ir_node *cmp = NULL;
+ ir_mode *cmp_mode;
+
+ if (ia32_cg_config.use_cmov) {
+ /* we can't handle psis with 64bit compares yet */
+ if (is_Proj(sel)) {
+ cmp = get_Proj_pred(sel);
+ if (is_Cmp(cmp)) {
+ left = get_Cmp_left(cmp);
+ cmp_mode = get_irn_mode(left);
+ if (!mode_is_float(cmp_mode) && get_mode_size_bits(cmp_mode) > 32)
+ return 0;
+ } else {
+ cmp = NULL;
+ }
+ }
- if(!ia32_cg_config.use_cmov) {
- /* TODO: we could still handle abs(x)... */
- return 0;
- }
+ if (ia32_cg_config.use_sse2 && cmp != NULL) {
+ pn_Cmp pn = get_Proj_proj(sel);
+ ir_node *cl = get_Cmp_left(cmp);
+ ir_node *cr = get_Cmp_right(cmp);
+
+ /* check the Phi nodes: no 64bit and no floating point cmov */
+ for (phi = phi_list; phi; phi = get_irn_link(phi)) {
+ ir_mode *mode = get_irn_mode(phi);
+
+ if (mode_is_float(mode)) {
+ /* check for Min, Max */
+ ir_node *t = get_Phi_pred(phi, i);
+ ir_node *f = get_Phi_pred(phi, j);
+ int res = 0;
+
+ /* SSE2 supports Min & Max */
+ if (pn == pn_Cmp_Lt || pn == pn_Cmp_Le || pn == pn_Cmp_Ge || pn == pn_Cmp_Gt) {
+ if (cl == t && cr == f) {
+ /* Psi(a <=/>= b, a, b) => MIN, MAX */
+ res = 1;
+ } else if (cl == f && cr == t) {
+ /* Psi(a <=/>= b, b, a) => MAX, MIN */
+ res = 1;
+ }
+ }
+ if (! res)
+ return 0;
+
+ } else if (get_mode_size_bits(mode) > 32)
+ return 0;
+ }
+ } else {
+ /* check the Phi nodes: no 64bit and no floating point cmov */
+ for (phi = phi_list; phi; phi = get_irn_link(phi)) {
+ ir_mode *mode = get_irn_mode(phi);
- /* we can't handle psis with 64bit compares yet */
- if(is_Proj(sel)) {
- ir_node *pred = get_Proj_pred(sel);
- if(is_Cmp(pred)) {
- ir_node *left = get_Cmp_left(pred);
- ir_mode *cmp_mode = get_irn_mode(left);
- if(!mode_is_float(cmp_mode) && get_mode_size_bits(cmp_mode) > 32)
- return 0;
+ if (mode_is_float(mode) || get_mode_size_bits(mode) > 32)
+ return 0;
+ }
}
- }
- /* check the Phi nodes */
- for (phi = phi_list; phi; phi = get_irn_link(phi)) {
- ir_mode *mode = get_irn_mode(phi);
+ return 1;
+ } else {
+ ir_node *cl, *cr;
+ pn_Cmp pn;
- if (mode_is_float(mode) || get_mode_size_bits(mode) > 32)
+ /* No cmov, only some special cases */
+ if (! is_Proj(sel))
+ return 0;
+ cmp = get_Proj_pred(sel);
+ if (! is_Cmp(cmp))
return 0;
- }
- return 1;
+ left = get_Cmp_left(cmp);
+ cmp_mode = get_irn_mode(left);
+
+ /* Now some supported cases here */
+ pn = get_Proj_proj(sel);
+ cl = get_Cmp_left(cmp);
+ cr = get_Cmp_right(cmp);
+
+ for (phi = phi_list; phi; phi = get_irn_link(phi)) {
+ ir_mode *mode = get_irn_mode(phi);
+ int res = 0;
+ ir_node *t, *f;
+
+ t = get_Phi_pred(phi, i);
+ f = get_Phi_pred(phi, j);
+
+ /* no floating point and no 64bit yet */
+ if (mode_is_float(mode) || get_mode_size_bits(mode) > 32)
+ return 0;
+
+ if (is_Const(t) && is_Const(f)) {
+ if ((is_Const_null(t) && is_Const_one(f)) || (is_Const_one(t) && is_Const_null(f))) {
+ /* always support Psi(x, C1, C2) */
+ res = 1;
+ }
+ } else if (pn == pn_Cmp_Lt || pn == pn_Cmp_Le || pn == pn_Cmp_Ge || pn == pn_Cmp_Gt) {
+ if (0) {
+#if 0
+ } else if (cl == t && cr == f) {
+ /* Psi(a <=/>= b, a, b) => Min, Max */
+ res = 1;
+ } else if (cl == f && cr == t) {
+ /* Psi(a <=/>= b, b, a) => Max, Min */
+ res = 1;
+#endif
+ } else if ((pn & pn_Cmp_Gt) && !mode_is_signed(mode) &&
+ is_Const(f) && is_Const_null(f) && is_Sub(t) &&
+ get_Sub_left(t) == cl && get_Sub_right(t) == cr) {
+ /* Psi(a >=u b, a - b, 0) unsigned Doz */
+ res = 1;
+ } else if ((pn & pn_Cmp_Lt) && !mode_is_signed(mode) &&
+ is_Const(t) && is_Const_null(t) && is_Sub(f) &&
+ get_Sub_left(f) == cl && get_Sub_right(f) == cr) {
+ /* Psi(a <=u b, 0, a - b) unsigned Doz */
+ res = 1;
+ } else if (is_Const(cr) && is_Const_null(cr)) {
+ if (cl == t && is_Minus(f) && get_Minus_op(f) == cl) {
+ /* Psi(a <=/>= 0 ? a : -a) Nabs/Abs */
+ res = 1;
+ } else if (cl == f && is_Minus(t) && get_Minus_op(t) == cl) {
+ /* Psi(a <=/>= 0 ? -a : a) Abs/Nabs */
+ res = 1;
+ }
+ }
+ }
+ if (! res)
+ return 0;
+ }
+ /* all checks passed */
+ return 1;
+ }
+ return 0;
}
/**