Merge Fix: Spills have ProjMs now
authorAndreas Zwinkau <zwinkau@kit.edu>
Fri, 24 Jun 2011 15:33:47 +0000 (17:33 +0200)
committerAndreas Zwinkau <zwinkau@kit.edu>
Fri, 24 Jun 2011 15:35:02 +0000 (17:35 +0200)
1  2 
ir/be/ia32/ia32_emitter.c

@@@ -557,8 -557,8 +557,8 @@@ void ia32_emit_am(const ir_node *node
        int        offs      = get_ia32_am_offs_int(node);
        ir_node   *base      = get_irn_n(node, n_ia32_base);
        int        has_base  = !is_ia32_NoReg_GP(base);
 -      ir_node   *index     = get_irn_n(node, n_ia32_index);
 -      int        has_index = !is_ia32_NoReg_GP(index);
 +      ir_node   *idx       = get_irn_n(node, n_ia32_index);
 +      int        has_index = !is_ia32_NoReg_GP(idx);
  
        /* just to be sure... */
        assert(!is_ia32_use_frame(node) || get_ia32_frame_ent(node) != NULL);
@@@ -675,9 -675,6 +675,9 @@@ static void ia32_emitf(const ir_node *n
  end_of_mods:
  
                switch (*fmt++) {
 +                      arch_register_t const *reg;
 +                      ir_node         const *imm;
 +
                        case '%':
                                be_emit_char('%');
                                break;
@@@ -691,13 -688,17 +691,13 @@@ emit_AM
                                                ia32_emit_am(node);
                                                break;
  
 -                                      case 'R': {
 -                                              const arch_register_t *reg = va_arg(ap, const arch_register_t*);
 +                                      case 'R':
 +                                              reg = va_arg(ap, const arch_register_t*);
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
                                                        goto emit_AM;
                                                } else {
 -                                                      if (mod & EMIT_ALTERNATE_AM)
 -                                                              be_emit_char('*');
 -                                                      emit_register(reg, NULL);
 +                                                      goto emit_R;
                                                }
 -                                              break;
 -                                      }
  
                                        case 'S':
                                                if (get_ia32_op_type(node) == ia32_AddrModeS) {
                                                        assert(get_ia32_op_type(node) == ia32_Normal);
                                                        goto emit_S;
                                                }
 -                                              break;
  
                                        default: goto unknown;
                                }
                                break;
                        }
  
 -                      case 'D': {
 -                              unsigned               pos;
 -                              const arch_register_t *reg;
 -
 +                      case 'D':
                                if (*fmt < '0' || '9' <= *fmt)
                                        goto unknown;
 -
 -                              pos = *fmt++ - '0';
 -                              reg = get_out_reg(node, pos);
 -                              emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
 -                              break;
 -                      }
 +                              reg = get_out_reg(node, *fmt++ - '0');
 +                              goto emit_R;
  
                        case 'I':
 +                              imm = node;
 +emit_I:
                                if (!(mod & EMIT_ALTERNATE_AM))
                                        be_emit_char('$');
 -                              emit_ia32_Immediate_no_prefix(node);
 +                              emit_ia32_Immediate_no_prefix(imm);
                                break;
  
                        case 'L':
                                ia32_emit_cfop_target(node);
                                break;
  
 -                      case 'M': {
 +                      case 'M':
                                ia32_emit_mode_suffix_mode(get_ia32_ls_mode(node));
                                break;
 -                      }
  
                        case 'P': {
                                ia32_condition_code_t cc = va_arg(ap, ia32_condition_code_t);
                                break;
                        }
  
 -                      case 'R': {
 -                              const arch_register_t *reg = va_arg(ap, const arch_register_t*);
 +                      case 'R':
 +                              reg = va_arg(ap, const arch_register_t*);
 +emit_R:
 +                              if (mod & EMIT_ALTERNATE_AM)
 +                                      be_emit_char('*');
                                if (mod & EMIT_HIGH_REG) {
                                        emit_8bit_register_high(reg);
                                } else if (mod & EMIT_LOW_REG) {
                                        emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
                                }
                                break;
 -                      }
  
  emit_S:
                        case 'S': {
 -                              unsigned       pos;
 -                              const ir_node *in;
 +                              unsigned pos;
  
                                if (*fmt < '0' || '9' <= *fmt)
                                        goto unknown;
  
                                pos = *fmt++ - '0';
 -                              in  = get_irn_n(node, pos);
 -                              if (is_ia32_Immediate(in)) {
 -                                      if (!(mod & EMIT_ALTERNATE_AM))
 -                                              be_emit_char('$');
 -                                      emit_ia32_Immediate_no_prefix(in);
 +                              imm = get_irn_n(node, pos);
 +                              if (is_ia32_Immediate(imm)) {
 +                                      goto emit_I;
                                } else {
 -                                      const arch_register_t *reg;
 -
 -                                      if (mod & EMIT_ALTERNATE_AM)
 -                                              be_emit_char('*');
                                        reg = get_in_reg(node, pos);
 -                                      emit_register(reg, mod & EMIT_RESPECT_LS ? get_ia32_ls_mode(node) : NULL);
 +                                      goto emit_R;
                                }
 -                              break;
                        }
  
                        case 's': {
@@@ -899,11 -913,11 +899,11 @@@ static ir_node *find_original_value(ir_
                        return find_original_value(get_irn_n(pred, get_Proj_proj(node) + 1));
                } else if (is_ia32_Load(pred)) {
                        return find_original_value(get_irn_n(pred, n_ia32_Load_mem));
+               } else if (is_ia32_Store(pred)) {
+                       return find_original_value(get_irn_n(pred, n_ia32_Store_val));
                } else {
                        return node;
                }
-       } else if (is_ia32_Store(node)) {
-               return find_original_value(get_irn_n(node, n_ia32_Store_val));
        } else if (is_Phi(node)) {
                int i, arity;
                arity = get_irn_arity(node);
@@@ -1120,16 -1134,127 +1120,16 @@@ static void emit_ia32_CMovcc(const ir_n
        ia32_emitf(node, "\tcmov%P %#AR, %#R\n", cc, in_true, out);
  }
  
 -
 -/* jump table entry (target and corresponding number) */
 -typedef struct branch_t {
 -      ir_node *target;
 -      int      value;
 -} branch_t;
 -
 -/* jump table for switch generation */
 -typedef struct jmp_tbl_t {
 -      ir_node  *defProj;                 /**< default target */
 -      long      min_value;               /**< smallest switch case */
 -      long      max_value;               /**< largest switch case */
 -      long      num_branches;            /**< number of jumps */
 -      char      label[SNPRINTF_BUF_LEN]; /**< label of the jump table */
 -      branch_t *branches;                /**< jump array */
 -} jmp_tbl_t;
 -
 -/**
 - * Compare two variables of type branch_t. Used to sort all switch cases
 - */
 -static int ia32_cmp_branch_t(const void *a, const void *b)
 -{
 -      branch_t *b1 = (branch_t *)a;
 -      branch_t *b2 = (branch_t *)b;
 -
 -      if (b1->value <= b2->value)
 -              return -1;
 -      else
 -              return 1;
 -}
 -
 -static void generate_jump_table(jmp_tbl_t *tbl, const ir_node *node)
 -{
 -      int                 i;
 -      long                default_pn = get_ia32_default_pn(node);
 -      ir_node            *proj;
 -      const ir_edge_t    *edge;
 -
 -      /* fill the table structure */
 -      get_unique_label(tbl->label, SNPRINTF_BUF_LEN, "TBL_");
 -      tbl->defProj      = NULL;
 -      tbl->num_branches = get_irn_n_edges(node) - 1;
 -      tbl->branches     = XMALLOCNZ(branch_t, tbl->num_branches);
 -      tbl->min_value    = LONG_MAX;
 -      tbl->max_value    = LONG_MIN;
 -
 -      i = 0;
 -      /* go over all proj's and collect them */
 -      foreach_out_edge(node, edge) {
 -              long pn;
 -              proj = get_edge_src_irn(edge);
 -              assert(is_Proj(proj) && "Only proj allowed at SwitchJmp");
 -
 -              pn = get_Proj_proj(proj);
 -
 -              /* check for default proj */
 -              if (pn == default_pn) {
 -                      assert(tbl->defProj == NULL && "found two default Projs at SwitchJmp");
 -                      tbl->defProj = proj;
 -              } else {
 -                      tbl->min_value = pn < tbl->min_value ? pn : tbl->min_value;
 -                      tbl->max_value = pn > tbl->max_value ? pn : tbl->max_value;
 -
 -                      /* create branch entry */
 -                      tbl->branches[i].target = proj;
 -                      tbl->branches[i].value  = pn;
 -                      ++i;
 -              }
 -
 -      }
 -      assert(i == tbl->num_branches);
 -
 -      /* sort the branches by their number */
 -      qsort(tbl->branches, tbl->num_branches, sizeof(tbl->branches[0]), ia32_cmp_branch_t);
 -}
 -
  /**
 - * Emits code for a SwitchJmp (creates a jump table if
 - * possible otherwise a cmp-jmp cascade). Port from
 - * cggg ia32 backend
 + * Emits code for a SwitchJmp
   */
  static void emit_ia32_SwitchJmp(const ir_node *node)
  {
 -      unsigned long       interval;
 -      int                 last_value, i;
 -      jmp_tbl_t           tbl;
 -
 -      /* fill the table structure */
 -      generate_jump_table(&tbl, node);
 -
 -      /* two-complement's magic make this work without overflow */
 -      interval = tbl.max_value - tbl.min_value;
 -
 -      /* emit the table */
 -      ia32_emitf(node,        "\tcmpl $%u, %S0\n", interval);
 -      ia32_emitf(tbl.defProj, "\tja %L\n");
 -
 -      if (tbl.num_branches > 1) {
 -              /* create table */
 -              ia32_emitf(node, "\tjmp *%s(,%S0,4)\n", tbl.label);
 -
 -              be_gas_emit_switch_section(GAS_SECTION_RODATA);
 -              ia32_emitf(NULL, "\t.align 4\n");
 -              ia32_emitf(NULL, "%s:\n", tbl.label);
 +      ir_entity *jump_table = get_ia32_am_sc(node);
 +      long       default_pn = get_ia32_default_pn(node);
  
 -              last_value = tbl.branches[0].value;
 -              for (i = 0; i != tbl.num_branches; ++i) {
 -                      while (last_value != tbl.branches[i].value) {
 -                              ia32_emitf(tbl.defProj, ".long %L\n");
 -                              ++last_value;
 -                      }
 -                      ia32_emitf(tbl.branches[i].target, ".long %L\n");
 -                      ++last_value;
 -              }
 -              be_gas_emit_switch_section(GAS_SECTION_TEXT);
 -      } else {
 -              /* one jump is enough */
 -              ia32_emitf(tbl.branches[0].target, "\tjmp %L\n");
 -      }
 -
 -      free(tbl.branches);
 +      ia32_emitf(node, "\tjmp %*AM\n");
 +      emit_jump_table(node, default_pn, jump_table, get_cfop_target_block);
  }
  
  /**
@@@ -1370,8 -1495,8 +1370,8 @@@ static void emit_ia32_Conv_FP2FP(const 
   */
  static void emit_ia32_Conv_I2I(const ir_node *node)
  {
 -      ir_mode *smaller_mode = get_ia32_ls_mode(node);
 -      int      signed_mode  = mode_is_signed(smaller_mode);
 +      ir_mode    *smaller_mode = get_ia32_ls_mode(node);
 +      int         signed_mode  = mode_is_signed(smaller_mode);
        const char *sign_suffix;
  
        assert(!mode_is_float(smaller_mode));
@@@ -1799,10 -1924,10 +1799,10 @@@ static int should_align_block(const ir_
   */
  static void ia32_emit_block_header(ir_node *block)
  {
 -      ir_graph     *irg = current_ir_graph;
 +      ir_graph     *irg        = current_ir_graph;
        int           need_label = block_needs_label(block);
 -      int           i, arity;
 -      ir_exec_freq *exec_freq = be_get_irg_exec_freq(irg);
 +      ir_exec_freq *exec_freq  = be_get_irg_exec_freq(irg);
 +      int           arity;
  
        if (block == get_irg_end_block(irg))
                return;
        if (arity <= 0) {
                be_emit_cstring(" none");
        } else {
 +              int i;
                for (i = 0; i < arity; ++i) {
                        ir_node *predblock = get_Block_cfgpred_block(block, i);
                        be_emit_irprintf(" %d", get_irn_node_nr(predblock));
@@@ -1982,14 -2106,14 +1982,14 @@@ void ia32_gen_routine(ir_graph *irg
           Those are ascending with ascending addresses. */
        qsort(exc_list, ARR_LEN(exc_list), sizeof(exc_list[0]), cmp_exc_entry);
        {
 -              size_t i;
 +              size_t e;
  
 -              for (i = 0; i < ARR_LEN(exc_list); ++i) {
 +              for (e = 0; e < ARR_LEN(exc_list); ++e) {
                        be_emit_cstring("\t.long ");
 -                      ia32_emit_exc_label(exc_list[i].exc_instr);
 +                      ia32_emit_exc_label(exc_list[e].exc_instr);
                        be_emit_char('\n');
                        be_emit_cstring("\t.long ");
 -                      be_gas_emit_block_name(exc_list[i].block);
 +                      be_gas_emit_block_name(exc_list[e].block);
                        be_emit_char('\n');
                }
        }
@@@ -2195,8 -2319,8 +2195,8 @@@ static void bemit_mod_am(unsigned reg, 
        int        offs      = get_ia32_am_offs_int(node);
        ir_node   *base      = get_irn_n(node, n_ia32_base);
        int        has_base  = !is_ia32_NoReg_GP(base);
 -      ir_node   *index     = get_irn_n(node, n_ia32_index);
 -      int        has_index = !is_ia32_NoReg_GP(index);
 +      ir_node   *idx       = get_irn_n(node, n_ia32_index);
 +      int        has_index = !is_ia32_NoReg_GP(idx);
        unsigned   modrm     = 0;
        unsigned   sib       = 0;
        unsigned   emitoffs  = 0;
  
        /* Determine if we need a SIB byte. */
        if (has_index) {
 -              const arch_register_t *reg_index = arch_get_irn_register(index);
 +              const arch_register_t *reg_index = arch_get_irn_register(idx);
                int                    scale     = get_ia32_am_scale(node);
                assert(scale < 4);
                /* R/M set to ESP means SIB in 32bit mode. */
@@@ -3054,8 -3178,8 +3054,8 @@@ static void bemit_load(const ir_node *n
        if (out->index == REG_GP_EAX) {
                ir_node   *base      = get_irn_n(node, n_ia32_base);
                int        has_base  = !is_ia32_NoReg_GP(base);
 -              ir_node   *index     = get_irn_n(node, n_ia32_index);
 -              int        has_index = !is_ia32_NoReg_GP(index);
 +              ir_node   *idx       = get_irn_n(node, n_ia32_index);
 +              int        has_index = !is_ia32_NoReg_GP(idx);
                if (!has_base && !has_index) {
                        ir_entity *ent  = get_ia32_am_sc(node);
                        int        offs = get_ia32_am_offs_int(node);
@@@ -3099,8 -3223,8 +3099,8 @@@ static void bemit_store(const ir_node *
                if (in->index == REG_GP_EAX) {
                        ir_node   *base      = get_irn_n(node, n_ia32_base);
                        int        has_base  = !is_ia32_NoReg_GP(base);
 -                      ir_node   *index     = get_irn_n(node, n_ia32_index);
 -                      int        has_index = !is_ia32_NoReg_GP(index);
 +                      ir_node   *idx       = get_irn_n(node, n_ia32_index);
 +                      int        has_index = !is_ia32_NoReg_GP(idx);
                        if (!has_base && !has_index) {
                                ir_entity *ent  = get_ia32_am_sc(node);
                                int        offs = get_ia32_am_offs_int(node);
@@@ -3291,13 -3415,63 +3291,13 @@@ static void bemit_ia32_jcc(const ir_nod
  
  static void bemit_switchjmp(const ir_node *node)
  {
 -      unsigned long          interval;
 -      int                    last_value;
 -      int                    i;
 -      jmp_tbl_t              tbl;
 -      const arch_register_t *in;
 -
 -      /* fill the table structure */
 -      generate_jump_table(&tbl, node);
 -
 -      /* two-complement's magic make this work without overflow */
 -      interval = tbl.max_value - tbl.min_value;
 +      ir_entity *jump_table = get_ia32_am_sc(node);
 +      long       default_pn = get_ia32_default_pn(node);
  
 -      in = get_in_reg(node, 0);
 -      /* emit the table */
 -      if (get_signed_imm_size(interval) == 1) {
 -              bemit8(0x83); // cmpl $imm8, %in
 -              bemit_modru(in, 7);
 -              bemit8(interval);
 -      } else {
 -              bemit8(0x81); // cmpl $imm32, %in
 -              bemit_modru(in, 7);
 -              bemit32(interval);
 -      }
 -      bemit8(0x0F); // ja tbl.defProj
 -      bemit8(0x87);
 -      ia32_emitf(tbl.defProj, ".long %L - . - 4\n");
 -
 -      if (tbl.num_branches > 1) {
 -              /* create table */
 -              bemit8(0xFF); // jmp *tbl.label(,%in,4)
 -              bemit8(MOD_IND | ENC_REG(4) | ENC_RM(0x04));
 -              bemit8(ENC_SIB(2, reg_gp_map[in->index], 0x05));
 -              be_emit_irprintf("\t.long %s\n", tbl.label);
 -
 -              be_gas_emit_switch_section(GAS_SECTION_RODATA);
 -              be_emit_cstring(".align 4\n");
 -              be_emit_irprintf("%s:\n", tbl.label);
 -
 -              last_value = tbl.branches[0].value;
 -              for (i = 0; i != tbl.num_branches; ++i) {
 -                      while (last_value != tbl.branches[i].value) {
 -                              ia32_emitf(tbl.defProj, ".long %L\n");
 -                              ++last_value;
 -                      }
 -                      ia32_emitf(tbl.branches[i].target, ".long %L\n");
 -                      ++last_value;
 -              }
 -              be_gas_emit_switch_section(GAS_SECTION_TEXT);
 -      } else {
 -              /* one jump is enough */
 -              panic("switch only has one case");
 -              //ia32_emitf(tbl.branches[0].target, "\tjmp %L\n");
 -      }
 -
 -      be_emit_write_line();
 +      bemit8(0xFF); // jmp *tbl.label(,%in,4)
 +      bemit_mod_am(0x05, node);
  
 -      free(tbl.branches);
 +      emit_jump_table(node, default_pn, jump_table, get_cfop_target_block);
  }
  
  /**