Better constant loading
authorDavid Schleef <ds@schleef.org>
Wed, 11 Aug 2010 05:16:50 +0000 (22:16 -0700)
committerDavid Schleef <ds@schleef.org>
Wed, 11 Aug 2010 05:16:50 +0000 (22:16 -0700)
orc/orccompiler.c
orc/orcprogram-sse.c
orc/orcprogram.h
orc/orcrules-sse.c

index 6980bb5..a7ecabf 100644 (file)
@@ -581,6 +581,11 @@ orc_compiler_get_temp_reg (OrcCompiler *compiler)
       compiler->alloc_regs[compiler->vars[j].alloc] = 1;
     }
   }
+  for(j=0;j<compiler->n_constants;j++){
+    if (compiler->constants[j].alloc_reg) {
+      compiler->alloc_regs[compiler->constants[j].alloc_reg] = 1;
+    }
+  }
 
   ORC_DEBUG("at insn %d", compiler->insn_index);
   for(j=0;j<8;j++){
@@ -924,6 +929,16 @@ orc_compiler_load_constant (OrcCompiler *compiler, int reg, int size,
 }
 
 int
+orc_compiler_get_temp_constant (OrcCompiler *compiler, int size, int value)
+{
+  int tmp;
+
+  tmp = orc_compiler_get_temp_reg (compiler);
+  orc_compiler_load_constant (compiler, tmp, size, value);
+  return tmp;
+}
+
+int
 orc_compiler_get_constant (OrcCompiler *compiler, int size, int value)
 {
   int i;
@@ -960,3 +975,44 @@ orc_compiler_get_constant (OrcCompiler *compiler, int size, int value)
   return tmp;
 }
 
+int
+orc_compiler_get_constant_reg (OrcCompiler *compiler)
+{
+  int j;
+
+  for(j=0;j<ORC_N_REGS;j++){
+    compiler->alloc_regs[j] = 0;
+  }
+  for(j=0;j<ORC_N_COMPILER_VARIABLES;j++){
+    if (!compiler->vars[j].alloc) continue;
+
+    ORC_DEBUG("var %d: %d  %d %d", j, compiler->vars[j].alloc,
+        compiler->vars[j].first_use,
+        compiler->vars[j].last_use);
+
+    if (compiler->vars[j].first_use == -1) {
+      compiler->alloc_regs[compiler->vars[j].alloc] = 1;
+    } else if (compiler->vars[j].last_use != -1) {
+      compiler->alloc_regs[compiler->vars[j].alloc] = 1;
+    }
+  }
+  for(j=0;j<compiler->n_constants;j++){
+    if (compiler->constants[j].alloc_reg) {
+      compiler->alloc_regs[compiler->constants[j].alloc_reg] = 1;
+    }
+  }
+
+  for(j=0;j<8;j++){
+    ORC_DEBUG("xmm%d: %d %d", j, compiler->valid_regs[ORC_VEC_REG_BASE + j],
+        compiler->alloc_regs[ORC_VEC_REG_BASE + j]);
+  }
+
+  for(j=compiler->min_temp_reg;j<ORC_VEC_REG_BASE+16;j++){
+    if (compiler->valid_regs[j] && !compiler->alloc_regs[j]) {
+      return j;
+    }
+  }
+
+  return 0;
+}
+
index 3d5bc5e..0024f0b 100644 (file)
@@ -306,17 +306,20 @@ sse_load_constant (OrcCompiler *compiler, int reg, int size, int value)
     value |= (value << 16);
   }
 
+  ORC_ASM_CODE(compiler, "# loading constant %d 0x%08x\n", value, value);
   if (value == 0) {
     orc_sse_emit_pxor(compiler, reg, reg);
     return;
   }
   if (value == 0xffffffff) {
     orc_sse_emit_pcmpeqb (compiler, reg, reg);
+    return;
   }
   if (compiler->target_flags & ORC_TARGET_SSE_SSSE3) {
     if (value == 0x01010101) {
       orc_sse_emit_pcmpeqb (compiler, reg, reg);
       orc_sse_emit_pabsb (compiler, reg, reg);
+      return;
     }
   }
 
@@ -375,7 +378,7 @@ sse_load_constants_outer (OrcCompiler *compiler)
       case ORC_VAR_TYPE_DEST:
         break;
       case ORC_VAR_TYPE_ACCUMULATOR:
-        orc_sse_emit_660f (compiler, "pxor", 0xef,
+        orc_sse_emit_pxor (compiler,
             compiler->vars[i].alloc, compiler->vars[i].alloc);
         break;
       case ORC_VAR_TYPE_TEMP:
@@ -388,6 +391,18 @@ sse_load_constants_outer (OrcCompiler *compiler)
 
   orc_sse_emit_invariants (compiler);
 
+  /* FIXME move to a better place */
+  for(i=0;i<compiler->n_constants;i++){
+    compiler->constants[i].alloc_reg =
+      orc_compiler_get_constant_reg (compiler);
+  }
+
+  for(i=0;i<compiler->n_constants;i++){
+    if (compiler->constants[i].alloc_reg) {
+      sse_load_constant (compiler, compiler->constants[i].alloc_reg,
+          4, compiler->constants[i].value);
+    }
+  }
 }
 
 void
@@ -619,6 +634,15 @@ orc_compiler_sse_assemble (OrcCompiler *compiler)
 
   compiler->vars[align_var].is_aligned = FALSE;
 
+  {
+    orc_sse_emit_loop (compiler, 0, 0);
+
+    compiler->codeptr = compiler->program->code;
+    free (compiler->asm_code);
+    compiler->asm_code = NULL;
+    compiler->asm_code_len = 0;
+  }
+
   orc_x86_emit_prologue (compiler);
 
 #ifndef MMX
index 97ea55c..5586534 100644 (file)
@@ -648,7 +648,10 @@ int orc_program_allocate_register (OrcProgram *program, int is_data);
 void orc_compiler_allocate_codemem (OrcCompiler *compiler);
 int orc_compiler_label_new (OrcCompiler *compiler);
 int orc_compiler_get_constant (OrcCompiler *compiler, int size, int value);
+int orc_compiler_get_temp_constant (OrcCompiler *compiler, int size, int value);
 int orc_compiler_get_temp_reg (OrcCompiler *compiler);
+int orc_compiler_get_constant_reg (OrcCompiler *compiler);
+
 
 const char *orc_program_get_asm_code (OrcProgram *program);
 const char *orc_target_get_asm_preamble (const char *target);
index b709a4b..4e8c63b 100644 (file)
@@ -46,6 +46,8 @@ sse_rule_loadpX (OrcCompiler *compiler, void *user, OrcInstruction *insn)
 #endif
   } else if (src->vartype == ORC_VAR_TYPE_CONST) {
     sse_load_constant (compiler, dest->alloc, src->size, src->value);
+  } else {
+    ORC_ASSERT(0);
   }
 }
 
@@ -515,7 +517,7 @@ sse_rule_signX_ssse3 (OrcCompiler *p, void *user, OrcInstruction *insn)
   int type = ORC_PTR_TO_INT(user);
   int tmpc;
 
-  tmpc = orc_compiler_get_constant (p, 1<<type, 1);
+  tmpc = orc_compiler_get_temp_constant (p, 1<<type, 1);
   if (src == dest) {
     orc_sse_emit_660f (p, names[type], codes[type], src, tmpc);
     orc_sse_emit_movdqa (p, tmpc, dest);
@@ -960,7 +962,7 @@ sse_rule_div255w (OrcCompiler *p, void *user, OrcInstruction *insn)
   if (src != dest) {
     orc_sse_emit_movdqa (p, src, dest);
   }
-  tmp = orc_compiler_get_constant (p, 2, 0x0080);
+  tmp = orc_compiler_get_temp_constant (p, 2, 0x0080);
   orc_sse_emit_paddw (p, tmp, dest);
   orc_sse_emit_movdqa (p, dest, tmp);
   orc_sse_emit_psrlw (p, 8, tmp);
@@ -1755,11 +1757,12 @@ sse_rule_maxul_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
   int src = p->vars[insn->src_args[1]].alloc;
   int dest = p->vars[insn->dest_args[0]].alloc;
-  int tmp;
+  int tmp = orc_compiler_get_temp_reg (p);
+  int tmpc;
 
-  tmp = orc_compiler_get_constant (p, 4, 0x80000000);
-  orc_sse_emit_pxor(p, tmp, src);
-  orc_sse_emit_pxor(p, tmp, dest);
+  tmpc = orc_compiler_get_constant (p, 4, 0x80000000);
+  orc_sse_emit_pxor(p, tmpc, src);
+  orc_sse_emit_pxor(p, tmpc, dest);
 
   orc_sse_emit_movdqa (p, dest, tmp);
   orc_sse_emit_pcmpgtd (p, src, tmp);
@@ -1767,9 +1770,8 @@ sse_rule_maxul_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_sse_emit_pandn (p, src, tmp);
   orc_sse_emit_por (p, tmp, dest);
 
-  tmp = orc_compiler_get_constant (p, 4, 0x80000000);
-  orc_sse_emit_pxor(p, tmp, src);
-  orc_sse_emit_pxor(p, tmp, dest);
+  orc_sse_emit_pxor(p, tmpc, src);
+  orc_sse_emit_pxor(p, tmpc, dest);
 }
 
 static void
@@ -1777,11 +1779,12 @@ sse_rule_minul_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
 {
   int src = p->vars[insn->src_args[1]].alloc;
   int dest = p->vars[insn->dest_args[0]].alloc;
-  int tmp;
+  int tmp = orc_compiler_get_temp_reg (p);
+  int tmpc;
 
-  tmp = orc_compiler_get_constant (p, 4, 0x80000000);
-  orc_sse_emit_pxor(p, tmp, src);
-  orc_sse_emit_pxor(p, tmp, dest);
+  tmpc = orc_compiler_get_constant (p, 4, 0x80000000);
+  orc_sse_emit_pxor(p, tmpc, src);
+  orc_sse_emit_pxor(p, tmpc, dest);
 
   orc_sse_emit_movdqa (p, src, tmp);
   orc_sse_emit_pcmpgtd (p, dest, tmp);
@@ -1789,9 +1792,8 @@ sse_rule_minul_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
   orc_sse_emit_pandn (p, src, tmp);
   orc_sse_emit_por (p, tmp, dest);
 
-  tmp = orc_compiler_get_constant (p, 4, 0x80000000);
-  orc_sse_emit_pxor(p, tmp, src);
-  orc_sse_emit_pxor(p, tmp, dest);
+  orc_sse_emit_pxor(p, tmpc, src);
+  orc_sse_emit_pxor(p, tmpc, dest);
 }
 
 static void
@@ -1917,7 +1919,7 @@ sse_rule_subssl_slow (OrcCompiler *p, void *user, OrcInstruction *insn)
   int tmp2 = orc_compiler_get_temp_reg (p);
   int tmp3 = orc_compiler_get_temp_reg (p);
 
-  tmp = orc_compiler_get_constant (p, 4, 0xffffffff);
+  tmp = orc_compiler_get_temp_constant (p, 4, 0xffffffff);
   orc_sse_emit_pxor (p, src, tmp);
   orc_sse_emit_movdqa (p, tmp, tmp2);
   orc_sse_emit_por (p, dest, tmp);