Add some Processor specific instruction selections
authorMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 7 Apr 2006 08:55:07 +0000 (08:55 +0000)
committerMichael Beck <beck@ipd.info.uni-karlsruhe.de>
Fri, 7 Apr 2006 08:55:07 +0000 (08:55 +0000)
ir/be/ia32/bearch_ia32.c
ir/be/ia32/bearch_ia32.h
ir/be/ia32/bearch_ia32_t.h
ir/be/ia32/ia32_emitter.c
ir/be/ia32/ia32_spec.pl

index 88d53a1..ce5a9c0 100644 (file)
@@ -357,19 +357,33 @@ static void ia32_abi_epilogue(void *self, ir_node *bl, ir_node **mem, pmap *reg_
                curr_sp = be_new_IncSP(env->isa->sp, env->irg, bl, curr_sp, *mem, BE_STACK_FRAME_SIZE, be_stack_dir_shrink);
        }
        else {
-               ir_node *pop;
+               const ia32_isa_t *isa = (ia32_isa_t *)env->isa;
                ir_mode *mode_bp = env->isa->bp->reg_class->mode;
                int reg_size     = get_mode_size_bytes(env->isa->bp->reg_class->mode);
 
-               /* copy ebp to esp */
-               curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
+    if (ARCH_AMD(isa->opt_arch)) {
+                       ir_node *leave;
 
-               /* pop ebp */
-               pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem, mode_T);
-               set_ia32_flags(pop, arch_irn_flags_ignore);
-               curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, 0);
-               curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), 1);
-               *mem    = new_r_Proj(current_ir_graph, bl, pop, mode_M, 2);
+                       /* leave */
+                       leave = new_rd_ia32_Leave(NULL, env->irg, bl, curr_sp, *mem, mode_T);
+                       set_ia32_flags(leave, arch_irn_flags_ignore);
+                       curr_bp = new_r_Proj(current_ir_graph, bl, leave, mode_bp, 0);
+                       curr_sp = new_r_Proj(current_ir_graph, bl, leave, get_irn_mode(curr_sp), 1);
+                       *mem    = new_r_Proj(current_ir_graph, bl, leave, mode_M, 2);
+               }
+               else {
+                       ir_node *pop;
+
+                       /* copy ebp to esp */
+                       curr_sp = be_new_SetSP(env->isa->sp, env->irg, bl, curr_sp, curr_bp, *mem);
+
+                       /* pop ebp */
+                       pop = new_rd_ia32_Pop(NULL, env->irg, bl, curr_sp, *mem, mode_T);
+                       set_ia32_flags(pop, arch_irn_flags_ignore);
+                       curr_bp = new_r_Proj(current_ir_graph, bl, pop, mode_bp, 0);
+                       curr_sp = new_r_Proj(current_ir_graph, bl, pop, get_irn_mode(curr_sp), 1);
+                       *mem    = new_r_Proj(current_ir_graph, bl, pop, mode_M, 2);
+               }
                arch_set_irn_register(env->aenv, curr_sp, env->isa->sp);
                arch_set_irn_register(env->aenv, curr_bp, env->isa->bp);
        }
@@ -899,6 +913,7 @@ static ia32_isa_t ia32_isa_template = {
        NULL,                    /* types */
        NULL,                    /* tv_ents */
        (0 |
+       IA32_OPT_INCDEC    |     /* optimize add 1, sub 1 into inc/dec               default: on  */
        IA32_OPT_DOAM      |     /* optimize address mode                            default: on  */
        IA32_OPT_PLACECNST |     /* place constants immediately before instructions, default: on  */
        IA32_OPT_IMMOPS    |     /* operations can use immediates,                   default: on  */
@@ -930,6 +945,16 @@ static void *ia32_init(FILE *file_handle) {
        ia32_create_opcodes();
        ia32_register_copy_attr_func();
 
+       if ((ARCH_INTEL(isa->arch) && isa->arch < arch_pentium_4) ||
+           (ARCH_AMD(isa->arch) && isa->arch < arch_athlon))
+               /* no SSE2 for these cpu's */
+               isa->fp_kind = fp_x87;
+
+       if (ARCH_INTEL(isa->opt_arch) && isa->opt_arch >= arch_pentium_4) {
+               /* Pentium 4 don't like inc and dec instructions */
+               isa->opt &= ~IA32_OPT_INCDEC;
+       }
+
        isa->regs_16bit = pmap_create();
        isa->regs_8bit  = pmap_create();
        isa->types      = pmap_create();
@@ -1217,7 +1242,6 @@ static const lc_opt_table_entry_t ia32_options[] = {
        LC_OPT_ENT_ENUM_INT("arch",   "select the instruction architecture", &arch_var),
        LC_OPT_ENT_ENUM_INT("opt",    "optimize for instruction architecture", &opt_arch_var),
        LC_OPT_ENT_ENUM_INT("fpunit", "select the floating point unit", &fp_unit_var),
-       LC_OPT_ENT_BIT("incdec", "optimize for inc/dec", &ia32_isa_template.opt, IA32_OPT_INCDEC),
        LC_OPT_ENT_NEGBIT("noaddrmode", "do not use address mode", &ia32_isa_template.opt, IA32_OPT_DOAM),
        LC_OPT_ENT_NEGBIT("noplacecnst", "do not place constants", &ia32_isa_template.opt, IA32_OPT_PLACECNST),
        LC_OPT_ENT_NEGBIT("noimmop", "no operations with immediates", &ia32_isa_template.opt, IA32_OPT_IMMOPS),
index bacfa03..05a9cba 100644 (file)
@@ -4,10 +4,6 @@
 #include "pset.h"
 #include "../bearch.h"
 
-#define FP_USED(cg)  ((cg)->used_fp = (cg)->fp_kind)
-#define USE_SSE2(cg) ((cg)->fp_kind == fp_sse2)
-#define USE_x87(cg)  ((cg)->fp_kind == fp_x87)
-
 extern const arch_isa_if_t ia32_isa_if;
 
 #endif /* _BEARCH_IA32_H_ */
index 32c4705..7ce596b 100644 (file)
@@ -29,7 +29,10 @@ typedef enum _ia32_optimize_t {
        IA32_OPT_EXTBB     = 16,  /**< do extended basic block scheduling */
 } ia32_optimize_t;
 
-/** architectures */
+/**
+ * Architectures. Clustered for easier macro implementation,
+ * do not change.
+ */
 typedef enum cpu_support {
        arch_i386,          /**< i386 */
        arch_i486,          /**< i486 */
@@ -47,6 +50,15 @@ typedef enum cpu_support {
        arch_opteron,       /**< Opteron */
 } cpu_support;
 
+/** checks for l <= x <= h */
+#define _IN_RANGE(x, l, h)     ((unsigned)((x) - (l)) <= (unsigned)((h) - (l)))
+
+/** returns true if it's Intel architecture */
+#define ARCH_INTEL(x)          _IN_RANGE((x), arch_i386, arch_core)
+
+/** returns true if it's AMD architecture */
+#define ARCH_AMD(x)                    _IN_RANGE((x), arch_k6, arch_opteron)
+
 /** floating point support */
 typedef enum fp_support {
        fp_none,  /**< no floating point instructions are used */
@@ -54,6 +66,15 @@ typedef enum fp_support {
        fp_sse2   /**< use SSE2 instructions */
 } fp_support;
 
+/** Sets the used flag to the current floating point architecture. */
+#define FP_USED(cg)  ((cg)->used_fp = (cg)->fp_kind)
+
+/** Returns non-zero if the current floating point architecture is SSE2. */
+#define USE_SSE2(cg) ((cg)->fp_kind == fp_sse2)
+
+/** Returns non-zero if the current floating point architecture is x87. */
+#define USE_x87(cg)  ((cg)->fp_kind == fp_x87)
+
 typedef struct _ia32_isa_t ia32_isa_t;
 
 /**
index 0153117..ec363f3 100644 (file)
@@ -1396,6 +1396,36 @@ static void emit_be_Perm(const ir_node *irn, ia32_emit_env_t *emit_env) {
        IA32_DO_EMIT(irn);
 }
 
+/**
+ * Emits code for Constant loading.
+ */
+static void emit_ia32_Const(const ir_node *n, ia32_emit_env_t *env) {
+  FILE *F = env->out;
+  char cmd_buf[256], cmnt_buf[256];
+  const lc_arg_env_t *arg_env = ia32_get_arg_env();
+
+  if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) {
+               const char *instr = "xor";
+               if (env->isa->opt_arch == arch_pentium_4) {
+                       /* P4 prefers sub r, r, others xor r, r */
+                       instr = "sub";
+               }
+    lc_esnprintf(arg_env, cmd_buf, 256, "%s %1D, %1D ", instr, n, n);
+    lc_esnprintf(arg_env, cmnt_buf, 256, "/* optimized mov 0 to register */");
+  }
+  else {
+    if (get_ia32_op_type(n) == ia32_SymConst) {
+      lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, OFFSET FLAT:%C ", n, n);
+      lc_esnprintf(arg_env, cmnt_buf, 256, "/* Move address of SymConst into register */");
+    }
+               else {
+                               lc_esnprintf(arg_env, cmd_buf, 256, "mov %1D, %C ", n, n);
+                               lc_esnprintf(arg_env, cmnt_buf, 256, "/* Mov Const into register */");
+               }
+  }
+  lc_efprintf(arg_env, F, "\t%-35s %-60s /* %+F (%+G) */\n", cmd_buf, cmnt_buf, n, n);
+}
+
 
 
 /***********************************************************************************
@@ -1437,6 +1467,7 @@ static void ia32_register_emitters(void) {
        IA32_EMIT(Conv_FP2FP);
        IA32_EMIT(Conv_I2I);
        IA32_EMIT(Conv_I2I8Bit);
+       IA32_EMIT(Const);
 
        /* benode emitter */
        BE_EMIT(Call);
index d7cdf3e..e892c06 100644 (file)
@@ -414,19 +414,6 @@ $comment_string = "/*";
   "comment"   => "represents an integer constant",
   "cmp_attr"  => "  return ia32_compare_immop_attr(attr_a, attr_b);\n",
   "reg_req"   => { "out" => [ "gp" ] },
-  "emit"      =>
-'  if (get_ia32_Immop_tarval(n) == get_tarval_null(get_irn_mode(n))) {
-4.   sub %D1, %D1 /* optimized mov 0 to register */
-  }
-  else {
-    if (get_ia32_op_type(n) == ia32_SymConst) {
-6.    mov %D1, OFFSET FLAT:%C /* Move address of SymConst into register */
-    }
-       else {
-6.    mov %D1, %C /* Mov Const into register */
-       }
-  }
-',
 },
 
 "Cdq" => {
@@ -501,8 +488,8 @@ $comment_string = "/*";
 
 "Leave" => {
   "comment"   => "destroy stack frame",
-  "reg_req"   => { "in" => [ "esp", "ebp" ], "out" => [ "esp" ] },
-  "emit"      => '. leave /* Enter */'
+  "reg_req"   => { "in" => [ "esp", "ebp" ], "out" => [ "ebp", "esp" ] },
+  "emit"      => '. leave /* Leave */'
 },
 
 #-----------------------------------------------------------------------------#