In amd64 when i8const are use with values within the first 32 bits
instructions and registers used can be optimized to their 32 bit
versions.
Setting MONO_DEBUG=single-imm-size variable disables such optimizations
and guarantee that the the generated native code size is independent
of the i8const values.
return code [0] == 0xe8;
}
return code [0] == 0xe8;
}
+static inline gboolean
+amd64_use_imm32 (gint64 val)
+{
+ if (mini_get_debug_options()->single_imm_size)
+ return FALSE;
+
+ return amd64_is_imm32 (val);
+}
+
#ifdef __native_client_codegen__
/* Keep track of instruction "depth", that is, the level of sub-instruction */
#ifdef __native_client_codegen__
/* Keep track of instruction "depth", that is, the level of sub-instruction */
break;
case OP_COMPARE_IMM:
case OP_LCOMPARE_IMM:
break;
case OP_COMPARE_IMM:
case OP_LCOMPARE_IMM:
- if (!amd64_is_imm32 (ins->inst_imm)) {
+ if (!amd64_use_imm32 (ins->inst_imm)) {
NEW_INS (cfg, ins, temp, OP_I8CONST);
temp->inst_c0 = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
NEW_INS (cfg, ins, temp, OP_I8CONST);
temp->inst_c0 = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
#ifndef __native_client_codegen__
/* Don't generate memindex opcodes (to simplify */
/* read sandboxing) */
#ifndef __native_client_codegen__
/* Don't generate memindex opcodes (to simplify */
/* read sandboxing) */
- if (!amd64_is_imm32 (ins->inst_offset)) {
+ if (!amd64_use_imm32 (ins->inst_offset)) {
NEW_INS (cfg, ins, temp, OP_I8CONST);
temp->inst_c0 = ins->inst_offset;
temp->dreg = mono_alloc_ireg (cfg);
NEW_INS (cfg, ins, temp, OP_I8CONST);
temp->inst_c0 = ins->inst_offset;
temp->dreg = mono_alloc_ireg (cfg);
case OP_STORE_MEMBASE_IMM:
#endif
case OP_STOREI8_MEMBASE_IMM:
case OP_STORE_MEMBASE_IMM:
#endif
case OP_STOREI8_MEMBASE_IMM:
- if (!amd64_is_imm32 (ins->inst_imm)) {
+ if (!amd64_use_imm32 (ins->inst_imm)) {
NEW_INS (cfg, ins, temp, OP_I8CONST);
temp->inst_c0 = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
NEW_INS (cfg, ins, temp, OP_I8CONST);
temp->inst_c0 = ins->inst_imm;
temp->dreg = mono_alloc_ireg (cfg);
#endif
case OP_LOADI8_MEM:
// FIXME: Decompose this earlier
#endif
case OP_LOADI8_MEM:
// FIXME: Decompose this earlier
- if (amd64_is_imm32 (ins->inst_imm))
+ if (amd64_use_imm32 (ins->inst_imm))
amd64_mov_reg_mem (code, ins->dreg, ins->inst_imm, 8);
else {
amd64_mov_reg_mem (code, ins->dreg, ins->inst_imm, 8);
else {
- amd64_mov_reg_imm (code, ins->dreg, ins->inst_imm);
+ amd64_mov_reg_imm_size (code, ins->dreg, ins->inst_imm, sizeof(gpointer));
amd64_mov_reg_membase (code, ins->dreg, ins->dreg, 0, 8);
}
break;
amd64_mov_reg_membase (code, ins->dreg, ins->dreg, 0, 8);
}
break;
break;
case OP_LOADU4_MEM:
// FIXME: Decompose this earlier
break;
case OP_LOADU4_MEM:
// FIXME: Decompose this earlier
- if (amd64_is_imm32 (ins->inst_imm))
+ if (amd64_use_imm32 (ins->inst_imm))
amd64_mov_reg_mem (code, ins->dreg, ins->inst_imm, 4);
else {
amd64_mov_reg_mem (code, ins->dreg, ins->inst_imm, 4);
else {
- amd64_mov_reg_imm (code, ins->dreg, ins->inst_imm);
+ amd64_mov_reg_imm_size (code, ins->dreg, ins->inst_imm, sizeof(gpointer));
amd64_mov_reg_membase (code, ins->dreg, ins->dreg, 0, 4);
}
break;
amd64_mov_reg_membase (code, ins->dreg, ins->dreg, 0, 4);
}
break;
case OP_ICONST:
case OP_I8CONST:
case OP_ICONST:
case OP_I8CONST:
- if ((((guint64)ins->inst_c0) >> 32) == 0)
+ if (amd64_use_imm32 (ins->inst_c0))
amd64_mov_reg_imm_size (code, ins->dreg, ins->inst_c0, 4);
else
amd64_mov_reg_imm_size (code, ins->dreg, ins->inst_c0, 8);
amd64_mov_reg_imm_size (code, ins->dreg, ins->inst_c0, 4);
else
amd64_mov_reg_imm_size (code, ins->dreg, ins->inst_c0, 8);
gboolean
mono_arch_is_inst_imm (gint64 imm)
{
gboolean
mono_arch_is_inst_imm (gint64 imm)
{
- return amd64_is_imm32 (imm);
+ return amd64_use_imm32 (imm);
if (item->is_equals) {
if (item->check_target_idx) {
if (!item->compare_done) {
if (item->is_equals) {
if (item->check_target_idx) {
if (!item->compare_done) {
- if (amd64_is_imm32 (item->key))
+ if (amd64_use_imm32 ((gint64)item->key))
item->chunk_size += CMP_SIZE;
else
item->chunk_size += MOV_REG_IMM_SIZE + CMP_REG_REG_SIZE;
item->chunk_size += CMP_SIZE;
else
item->chunk_size += MOV_REG_IMM_SIZE + CMP_REG_REG_SIZE;
- if (amd64_is_imm32 (item->key))
+ if (amd64_use_imm32 ((gint64)item->key))
item->chunk_size += CMP_SIZE;
else
item->chunk_size += MOV_REG_IMM_SIZE + CMP_REG_REG_SIZE;
item->chunk_size += CMP_SIZE;
else
item->chunk_size += MOV_REG_IMM_SIZE + CMP_REG_REG_SIZE;
if (item->check_target_idx || fail_case) {
if (!item->compare_done || fail_case) {
if (item->check_target_idx || fail_case) {
if (!item->compare_done || fail_case) {
- if (amd64_is_imm32 (item->key))
+ if (amd64_use_imm32 ((gint64)item->key))
amd64_alu_reg_imm_size (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)(gssize)item->key, sizeof(gpointer));
else {
amd64_alu_reg_imm_size (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)(gssize)item->key, sizeof(gpointer));
else {
- amd64_mov_reg_imm (code, MONO_ARCH_IMT_SCRATCH_REG, item->key);
+ amd64_mov_reg_imm_size (code, MONO_ARCH_IMT_SCRATCH_REG, item->key, sizeof(gpointer));
amd64_alu_reg_reg (code, X86_CMP, MONO_ARCH_IMT_REG, MONO_ARCH_IMT_SCRATCH_REG);
}
}
amd64_alu_reg_reg (code, X86_CMP, MONO_ARCH_IMT_REG, MONO_ARCH_IMT_SCRATCH_REG);
}
}
- if (amd64_is_imm32 (item->key))
+ if (amd64_use_imm32 ((gint64)item->key))
amd64_alu_reg_imm_size (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)(gssize)item->key, sizeof (gpointer));
else {
amd64_alu_reg_imm_size (code, X86_CMP, MONO_ARCH_IMT_REG, (guint32)(gssize)item->key, sizeof (gpointer));
else {
- amd64_mov_reg_imm (code, MONO_ARCH_IMT_SCRATCH_REG, item->key);
+ amd64_mov_reg_imm_size (code, MONO_ARCH_IMT_SCRATCH_REG, item->key, sizeof (gpointer));
amd64_alu_reg_reg (code, X86_CMP, MONO_ARCH_IMT_REG, MONO_ARCH_IMT_SCRATCH_REG);
}
item->jmp_code = code;
amd64_alu_reg_reg (code, X86_CMP, MONO_ARCH_IMT_REG, MONO_ARCH_IMT_SCRATCH_REG);
}
item->jmp_code = code;
debug_options.gen_sdb_seq_points = TRUE;
else if (!strcmp (arg, "gen-compact-seq-points"))
debug_options.gen_seq_points_compact_data = TRUE;
debug_options.gen_sdb_seq_points = TRUE;
else if (!strcmp (arg, "gen-compact-seq-points"))
debug_options.gen_seq_points_compact_data = TRUE;
+ else if (!strcmp (arg, "single-imm-size"))
+ debug_options.single_imm_size = TRUE;
else if (!strcmp (arg, "init-stacks"))
debug_options.init_stacks = TRUE;
else if (!strcmp (arg, "casts"))
else if (!strcmp (arg, "init-stacks"))
debug_options.init_stacks = TRUE;
else if (!strcmp (arg, "casts"))
*/
gboolean gen_sdb_seq_points;
gboolean gen_seq_points_compact_data;
*/
gboolean gen_sdb_seq_points;
gboolean gen_seq_points_compact_data;
+ /*
+ * Setting single_imm_size should guarantee that each time managed code is compiled
+ * the same instructions and registers are used, regardless of the size of used values.
+ */
+ gboolean single_imm_size;
gboolean explicit_null_checks;
/*
* Fill stack frames with 0x2a in method prologs. This helps with the
gboolean explicit_null_checks;
/*
* Fill stack frames with 0x2a in method prologs. This helps with the