[mini] Simplify the way the JIT emits atomic opcodes.
authorAlex Rønne Petersen <alexrp@xamarin.com>
Tue, 1 Jul 2014 00:41:47 +0000 (02:41 +0200)
committerAlex Rønne Petersen <alexrp@xamarin.com>
Tue, 1 Jul 2014 19:53:56 +0000 (21:53 +0200)
* MONO_ARCH_HAVE_ATOMIC_* macros have been removed.
* Backends now report whether they support atomic opcodes via
  the mono_arch_opcode_supported () function.
* The default implementation of mono_arch_opcode_supported ()
  has been removed as almost all backends need to define one
  anyway.
* All old atomic_add_* opcodes have been removed. These were no
  longer being used but some backends still had code for them.
* atomic_add_new_* opcodes have been renamed to atomic_add_* as
  they are now the only atomic add opcodes.
* Itanium-specific atomic_add_imm_* opcodes have been moved to
  the __ia64__ section of mini-ops.h.
* Comments have been added to mini-ops.h explaining the precise
  semantics of the atomic opcodes.

The net result of this change is a simpler backend interface at
the cost of a slightly bigger binary.

26 files changed:
mono/mini/cpu-amd64.md
mono/mini/cpu-arm.md
mono/mini/cpu-arm64.md
mono/mini/cpu-ia64.md
mono/mini/cpu-ppc64.md
mono/mini/cpu-s390x.md
mono/mini/cpu-x86.md
mono/mini/method-to-ir.c
mono/mini/mini-amd64.c
mono/mini/mini-amd64.h
mono/mini/mini-arm.c
mono/mini/mini-arm.h
mono/mini/mini-ia64.c
mono/mini/mini-ia64.h
mono/mini/mini-llvm.c
mono/mini/mini-mips.c
mono/mini/mini-ops.h
mono/mini/mini-ppc.c
mono/mini/mini-ppc.h
mono/mini/mini-s390x.c
mono/mini/mini-s390x.h
mono/mini/mini-sparc.c
mono/mini/mini-x86.c
mono/mini/mini-x86.h
mono/mini/mini.c
mono/mini/mini.h

index b734d4c4fe710c668442e6a3106e8894a78e23ca..25fc6c15f00af74fa77024dac0ff9234c5e46d83 100644 (file)
@@ -298,10 +298,8 @@ tls_get_reg: dest:i src1:i len:32
 tls_set: src1:i len:16
 tls_set_reg: src1:i src2:i len:32
 atomic_add_i4: src1:b src2:i dest:i len:32
-atomic_add_new_i4: src1:b src2:i dest:i len:32
-atomic_exchange_i4: src1:b src2:i dest:a len:32
 atomic_add_i8: src1:b src2:i dest:i len:32
-atomic_add_new_i8: src1:b src2:i dest:i len:32
+atomic_exchange_i4: src1:b src2:i dest:a len:32
 atomic_exchange_i8: src1:b src2:i dest:a len:32
 atomic_cas_i4: src1:b src2:i src3:a dest:a len:24
 atomic_cas_i8: src1:b src2:i src3:a dest:a len:24
index 367cb5d4c5a6a54232a7f42839513002a7c29ccd..431936113c35613cc15904147fbc8904ab575fa4 100644 (file)
@@ -347,6 +347,6 @@ gc_liveness_use: len:0
 gc_spill_slot_liveness_def: len:0
 gc_param_slot_liveness_def: len:0
 
+atomic_add_i4: dest:i src1:i src2:i len:64
 atomic_exchange_i4: dest:i src1:i src2:i len:64
 atomic_cas_i4: dest:i src1:i src2:i src3:i len:64
-atomic_add_new_i4: dest:i src1:i src2:i len:64
index d57b6eeda2bf956c85d3f5b4c021ab5391c07655..7d9e40b22664406642de34d258df8576bec3941e 100644 (file)
@@ -414,8 +414,8 @@ arm64_cbzx: src1:i len:16
 arm64_cbnzw: src1:i len:16
 arm64_cbnzx: src1:i len:16
 
-atomic_add_new_i4: dest:i src1:i src2:i len:32
-atomic_add_new_i8: dest:i src1:i src2:i len:32
+atomic_add_i4: dest:i src1:i src2:i len:32
+atomic_add_i8: dest:i src1:i src2:i len:32
 atomic_exchange_i4: dest:i src1:i src2:i len:32
 atomic_exchange_i8: dest:i src1:i src2:i len:32
 atomic_cas_i4: dest:i src1:i src2:i src3:i len:32
index 5d4fec04432cc178c05a6fe646ac4e3213e8b1e0..0bae69301bd1ba0eab51d6cf33e51a0ce8cfd76c 100644 (file)
@@ -153,14 +153,12 @@ endfinally: len:96
 aot_const: dest:i len:48
 tls_get: dest:i len:48
 atomic_add_i4: src1:b src2:i dest:i len:48
-atomic_add_new_i4: src1:b src2:i dest:i len:48
-atomic_exchange_i4: src1:b src2:i dest:i len:48
 atomic_add_i8: src1:b src2:i dest:i len:48
-atomic_add_new_i8: src1:b src2:i dest:i len:48
-atomic_add_imm_new_i4: src1:b dest:i len:48
-atomic_add_imm_new_i8: src1:b dest:i len:48
+atomic_exchange_i4: src1:b src2:i dest:i len:48
 atomic_exchange_i8: src1:b src2:i dest:i len:48
 memory_barrier: len:48
+atomic_add_imm_i4: src1:b dest:i len:48
+atomic_add_imm_i8: src1:b dest:i len:48
 adc: dest:i src1:i src2:i len:48
 addcc: dest:i src1:i src2:i len:48
 subcc: dest:i src1:i src2:i len:48
index 889af55b4a20c48c9abb60afd2f6aa6219706c08..114bc3cf3b14228052d6b8dcfa07cf59ced16139 100644 (file)
@@ -380,8 +380,7 @@ vcall2_membase: src1:b len:16 clob:c
 
 jump_table: dest:i len:20
 
-atomic_add_new_i4: src1:b src2:i dest:i len:20
-atomic_add_new_i8: src1:b src2:i dest:i len:20
-
+atomic_add_i4: src1:b src2:i dest:i len:20
+atomic_add_i8: src1:b src2:i dest:i len:20
 atomic_cas_i4: src1:b src2:i src3:i dest:i len:38
 atomic_cas_i8: src1:b src2:i src3:i dest:i len:38
index 4bcfa33bafb2cd66d333fb7905f849918e1045c6..b3dce352ec640faff6fbb71abd21c2aeaab6042c 100644 (file)
@@ -56,8 +56,6 @@ and_imm: dest:i src1:i len:24
 aot_const: dest:i len:8
 atomic_add_i4: src1:b src2:i dest:i len:28
 atomic_add_i8: src1:b src2:i dest:i len:30
-atomic_add_new_i4: src1:b src2:i dest:i len:28
-atomic_add_new_i8: src1:b src2:i dest:i len:30
 atomic_exchange_i4: src1:b src2:i dest:i len:18
 atomic_exchange_i8: src1:b src2:i dest:i len:24
 br: len:6
index cc14b0dc15242e27aa0660633372f0ee2aed7479..24c354351e61d5d546b04db2fdc4499abbbc6874 100644 (file)
@@ -306,7 +306,6 @@ tls_get_reg: dest:i src1:i len:20
 tls_set: src1:i len:20
 tls_set_reg: src1:i src2:i len:20
 atomic_add_i4: src1:b src2:i dest:i len:16
-atomic_add_new_i4: src1:b src2:i dest:i len:16
 atomic_exchange_i4: src1:b src2:i dest:a len:24
 atomic_cas_i4: src1:b src2:i src3:a dest:a len:24
 memory_barrier: len:16
index 7ed3d639745a95a85fe49c65bbfd7a6163fa7884..01a7d1d50b2a1b588ecfee7f89e27ca1caa47cff 100644 (file)
@@ -5510,18 +5510,17 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                }
 #endif
 
-#ifdef MONO_ARCH_HAVE_ATOMIC_ADD
                if (strcmp (cmethod->name, "Increment") == 0) {
                        MonoInst *ins_iconst;
                        guint32 opcode = 0;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4) {
-                               opcode = OP_ATOMIC_ADD_NEW_I4;
-                               cfg->has_atomic_add_new_i4 = TRUE;
+                               opcode = OP_ATOMIC_ADD_I4;
+                               cfg->has_atomic_add_i4 = TRUE;
                        }
 #if SIZEOF_REGISTER == 8
                        else if (fsig->params [0]->type == MONO_TYPE_I8)
-                               opcode = OP_ATOMIC_ADD_NEW_I8;
+                               opcode = OP_ATOMIC_ADD_I8;
 #endif
                        if (opcode) {
                                if (!mono_arch_opcode_supported (opcode))
@@ -5536,7 +5535,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                ins->inst_basereg = args [0]->dreg;
                                ins->inst_offset = 0;
                                ins->sreg2 = ins_iconst->dreg;
-                               ins->type = (opcode == OP_ATOMIC_ADD_NEW_I4) ? STACK_I4 : STACK_I8;
+                               ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
                                MONO_ADD_INS (cfg->cbb, ins);
                        }
                } else if (strcmp (cmethod->name, "Decrement") == 0) {
@@ -5544,12 +5543,12 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        guint32 opcode = 0;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4) {
-                               opcode = OP_ATOMIC_ADD_NEW_I4;
-                               cfg->has_atomic_add_new_i4 = TRUE;
+                               opcode = OP_ATOMIC_ADD_I4;
+                               cfg->has_atomic_add_i4 = TRUE;
                        }
 #if SIZEOF_REGISTER == 8
                        else if (fsig->params [0]->type == MONO_TYPE_I8)
-                               opcode = OP_ATOMIC_ADD_NEW_I8;
+                               opcode = OP_ATOMIC_ADD_I8;
 #endif
                        if (opcode) {
                                if (!mono_arch_opcode_supported (opcode))
@@ -5564,19 +5563,19 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                ins->inst_basereg = args [0]->dreg;
                                ins->inst_offset = 0;
                                ins->sreg2 = ins_iconst->dreg;
-                               ins->type = (opcode == OP_ATOMIC_ADD_NEW_I4) ? STACK_I4 : STACK_I8;
+                               ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
                                MONO_ADD_INS (cfg->cbb, ins);
                        }
                } else if (strcmp (cmethod->name, "Add") == 0) {
                        guint32 opcode = 0;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4) {
-                               opcode = OP_ATOMIC_ADD_NEW_I4;
-                               cfg->has_atomic_add_new_i4 = TRUE;
+                               opcode = OP_ATOMIC_ADD_I4;
+                               cfg->has_atomic_add_i4 = TRUE;
                        }
 #if SIZEOF_REGISTER == 8
                        else if (fsig->params [0]->type == MONO_TYPE_I8)
-                               opcode = OP_ATOMIC_ADD_NEW_I8;
+                               opcode = OP_ATOMIC_ADD_I8;
 #endif
                        if (opcode) {
                                if (!mono_arch_opcode_supported (opcode))
@@ -5586,13 +5585,11 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                                ins->inst_basereg = args [0]->dreg;
                                ins->inst_offset = 0;
                                ins->sreg2 = args [1]->dreg;
-                               ins->type = (opcode == OP_ATOMIC_ADD_NEW_I4) ? STACK_I4 : STACK_I8;
+                               ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
                                MONO_ADD_INS (cfg->cbb, ins);
                        }
                }
-#endif /* MONO_ARCH_HAVE_ATOMIC_ADD */
 
-#ifdef MONO_ARCH_HAVE_ATOMIC_EXCHANGE
                if (strcmp (cmethod->name, "Exchange") == 0) {
                        guint32 opcode;
                        gboolean is_ref = fsig->params [0]->type == MONO_TYPE_OBJECT;
@@ -5642,9 +5639,7 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        if (cfg->gen_write_barriers && is_ref)
                                emit_write_barrier (cfg, args [0], args [1]);
                }
-#endif /* MONO_ARCH_HAVE_ATOMIC_EXCHANGE */
-#ifdef MONO_ARCH_HAVE_ATOMIC_CAS
+
                if ((strcmp (cmethod->name, "CompareExchange") == 0)) {
                        int size = 0;
                        gboolean is_ref = mini_type_is_reference (cfg, fsig->params [1]);
@@ -5681,7 +5676,6 @@ mini_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                        if (cfg->gen_write_barriers && is_ref)
                                emit_write_barrier (cfg, args [0], args [1]);
                }
-#endif /* MONO_ARCH_HAVE_ATOMIC_CAS */
 
                if (strcmp (cmethod->name, "MemoryBarrier") == 0)
                        ins = emit_memory_barrier (cfg, FullBarrier);
index 38a7649bc2973622c74bcbd6b2f97f028cd4a076..ee2736786f30ae481c25548317e0991f1a23d3c1 100644 (file)
@@ -5635,25 +5635,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        int dreg = ins->dreg;
                        guint32 size = (ins->opcode == OP_ATOMIC_ADD_I4) ? 4 : 8;
 
-                       if (dreg == ins->inst_basereg)
-                               dreg = AMD64_R11;
-                       
-                       if (dreg != ins->sreg2)
-                               amd64_mov_reg_reg (code, ins->dreg, ins->sreg2, size);
-
-                       x86_prefix (code, X86_LOCK_PREFIX);
-                       amd64_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, dreg, size);
-
-                       if (dreg != ins->dreg)
-                               amd64_mov_reg_reg (code, ins->dreg, dreg, size);
-
-                       break;
-               }
-               case OP_ATOMIC_ADD_NEW_I4:
-               case OP_ATOMIC_ADD_NEW_I8: {
-                       int dreg = ins->dreg;
-                       guint32 size = (ins->opcode == OP_ATOMIC_ADD_NEW_I4) ? 4 : 8;
-
                        if ((dreg == ins->sreg2) || (dreg == ins->inst_basereg))
                                dreg = AMD64_R11;
 
@@ -8640,3 +8621,19 @@ mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
 }
 
 #endif
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       switch (opcode) {
+       case OP_ATOMIC_ADD_I4:
+       case OP_ATOMIC_ADD_I8:
+       case OP_ATOMIC_EXCHANGE_I4:
+       case OP_ATOMIC_EXCHANGE_I8:
+       case OP_ATOMIC_CAS_I4:
+       case OP_ATOMIC_CAS_I8:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
index 89009f38803976eb279399ff22e8208a886c4cc0..54105f836c8d4f812d98661d11d9f563699081b2 100644 (file)
@@ -337,9 +337,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
-#define MONO_ARCH_HAVE_ATOMIC_ADD 1
-#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
-#define MONO_ARCH_HAVE_ATOMIC_CAS 1
 #define MONO_ARCH_HAVE_FULL_AOT_TRAMPOLINES 1
 #define MONO_ARCH_HAVE_IMT 1
 #define MONO_ARCH_HAVE_TLS_GET (mono_amd64_have_tls_get ())
index 71ed6a53d2e027aa13dd3aa6463da58bc51e93b1..b83f3765fdb2f28f5006246bb0fc0590713d463c 100644 (file)
@@ -1980,7 +1980,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
                offset += size;
        }
 
-       if (cfg->has_atomic_exchange_i4 || cfg->has_atomic_cas_i4 || cfg->has_atomic_add_new_i4) {
+       if (cfg->has_atomic_exchange_i4 || cfg->has_atomic_cas_i4 || cfg->has_atomic_add_i4) {
                /* Allocate a temporary used by the atomic ops */
                size = 4;
                align = 4;
@@ -4174,7 +4174,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        break;
                case OP_ATOMIC_EXCHANGE_I4:
                case OP_ATOMIC_CAS_I4:
-               case OP_ATOMIC_ADD_NEW_I4: {
+               case OP_ATOMIC_ADD_I4: {
                        int tmpreg;
                        guint8 *buf [16];
 
@@ -4217,7 +4217,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                                arm_patch (buf [2], buf [0]);
                                arm_patch (buf [1], code);
                                break;
-                       case OP_ATOMIC_ADD_NEW_I4:
+                       case OP_ATOMIC_ADD_I4:
                                buf [0] = code;
                                ARM_DMB (code, ARM_DMB_SY);
                                ARM_LDREX_REG (code, ARMREG_LR, ins->sreg1);
@@ -7220,9 +7220,9 @@ gboolean
 mono_arch_opcode_supported (int opcode)
 {
        switch (opcode) {
+       case OP_ATOMIC_ADD_I4:
        case OP_ATOMIC_EXCHANGE_I4:
        case OP_ATOMIC_CAS_I4:
-       case OP_ATOMIC_ADD_NEW_I4:
                return v7_supported;
        default:
                return FALSE;
index 131d43300166f748532ccb0c60dd987131906671..5c9350c05d3eb86a283f05aad61269838d453ca9 100644 (file)
@@ -274,10 +274,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_HAVE_OP_TAIL_CALL 1
 #endif
 #define MONO_ARCH_HAVE_DUMMY_INIT 1
-#define MONO_ARCH_HAVE_OPCODE_SUPPORTED 1
-#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
-#define MONO_ARCH_HAVE_ATOMIC_CAS 1
-#define MONO_ARCH_HAVE_ATOMIC_ADD 1
 
 #if defined(__native_client__)
 #undef MONO_ARCH_SOFT_DEBUG_SUPPORTED
index 17cc1f9f2f7f50c8ce62031fde85e2ef3bc19bfb..b701631a9674351b74eddb0c16bbb6be0736d727 100644 (file)
@@ -1487,10 +1487,10 @@ mono_arch_lowering_pass (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_LOADR8_MEMBASE:
                case OP_ATOMIC_EXCHANGE_I4:
                case OP_ATOMIC_EXCHANGE_I8:
-               case OP_ATOMIC_ADD_NEW_I4:
-               case OP_ATOMIC_ADD_NEW_I8:
-               case OP_ATOMIC_ADD_IMM_NEW_I4:
-               case OP_ATOMIC_ADD_IMM_NEW_I8:
+               case OP_ATOMIC_ADD_I4:
+               case OP_ATOMIC_ADD_I8:
+               case OP_ATOMIC_ADD_IMM_I4:
+               case OP_ATOMIC_ADD_IMM_I8:
                        /* There are no membase instructions on ia64 */
                        if (ins->inst_offset == 0) {
                                break;
@@ -2934,12 +2934,12 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_MEMORY_BARRIER:
                        ia64_mf (code);
                        break;
-               case OP_ATOMIC_ADD_IMM_NEW_I4:
+               case OP_ATOMIC_ADD_IMM_I4:
                        g_assert (ins->inst_offset == 0);
                        ia64_fetchadd4_acq_hint (code, ins->dreg, ins->inst_basereg, ins->inst_imm, 0);
                        ia64_adds_imm (code, ins->dreg, ins->inst_imm, ins->dreg);
                        break;
-               case OP_ATOMIC_ADD_IMM_NEW_I8:
+               case OP_ATOMIC_ADD_IMM_I8:
                        g_assert (ins->inst_offset == 0);
                        ia64_fetchadd8_acq_hint (code, ins->dreg, ins->inst_basereg, ins->inst_imm, 0);
                        ia64_adds_imm (code, ins->dreg, ins->inst_imm, ins->dreg);
@@ -2951,7 +2951,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_ATOMIC_EXCHANGE_I8:
                        ia64_xchg8_hint (code, ins->dreg, ins->inst_basereg, ins->sreg2, 0);
                        break;
-               case OP_ATOMIC_ADD_NEW_I4: {
+               case OP_ATOMIC_ADD_I4: {
                        guint8 *label, *buf;
 
                        /* From libatomic_ops */
@@ -2971,7 +2971,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        ia64_add (code, ins->dreg, GP_SCRATCH_REG, ins->sreg2);
                        break;
                }
-               case OP_ATOMIC_ADD_NEW_I8: {
+               case OP_ATOMIC_ADD_I8: {
                        guint8 *label, *buf;
 
                        /* From libatomic_ops */
@@ -4669,9 +4669,9 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho
                        guint32 opcode;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4)
-                               opcode = OP_ATOMIC_ADD_IMM_NEW_I4;
+                               opcode = OP_ATOMIC_ADD_IMM_I4;
                        else if (fsig->params [0]->type == MONO_TYPE_I8)
-                               opcode = OP_ATOMIC_ADD_IMM_NEW_I8;
+                               opcode = OP_ATOMIC_ADD_IMM_I8;
                        else
                                g_assert_not_reached ();
                        MONO_INST_NEW (cfg, ins, opcode);
@@ -4684,9 +4684,9 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho
                        guint32 opcode;
 
                        if (fsig->params [0]->type == MONO_TYPE_I4)
-                               opcode = OP_ATOMIC_ADD_IMM_NEW_I4;
+                               opcode = OP_ATOMIC_ADD_IMM_I4;
                        else if (fsig->params [0]->type == MONO_TYPE_I8)
-                               opcode = OP_ATOMIC_ADD_IMM_NEW_I8;
+                               opcode = OP_ATOMIC_ADD_IMM_I8;
                        else
                                g_assert_not_reached ();
                        MONO_INST_NEW (cfg, ins, opcode);
@@ -4708,9 +4708,9 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho
 
                        if (is_imm) {
                                if (fsig->params [0]->type == MONO_TYPE_I4)
-                                       opcode = OP_ATOMIC_ADD_IMM_NEW_I4;
+                                       opcode = OP_ATOMIC_ADD_IMM_I4;
                                else if (fsig->params [0]->type == MONO_TYPE_I8)
-                                       opcode = OP_ATOMIC_ADD_IMM_NEW_I8;
+                                       opcode = OP_ATOMIC_ADD_IMM_I8;
                                else
                                        g_assert_not_reached ();
 
@@ -4719,12 +4719,12 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho
                                ins->inst_basereg = args [0]->dreg;
                                ins->inst_offset = 0;
                                ins->inst_imm = imm;
-                               ins->type = (opcode == OP_ATOMIC_ADD_IMM_NEW_I4) ? STACK_I4 : STACK_I8;
+                               ins->type = (opcode == OP_ATOMIC_ADD_IMM_I4) ? STACK_I4 : STACK_I8;
                        } else {
                                if (fsig->params [0]->type == MONO_TYPE_I4)
-                                       opcode = OP_ATOMIC_ADD_NEW_I4;
+                                       opcode = OP_ATOMIC_ADD_I4;
                                else if (fsig->params [0]->type == MONO_TYPE_I8)
-                                       opcode = OP_ATOMIC_ADD_NEW_I8;
+                                       opcode = OP_ATOMIC_ADD_I8;
                                else
                                        g_assert_not_reached ();
 
@@ -4733,7 +4733,7 @@ mono_arch_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMetho
                                ins->inst_basereg = args [0]->dreg;
                                ins->inst_offset = 0;
                                ins->sreg2 = args [1]->dreg;
-                               ins->type = (opcode == OP_ATOMIC_ADD_NEW_I4) ? STACK_I4 : STACK_I8;
+                               ins->type = (opcode == OP_ATOMIC_ADD_I4) ? STACK_I4 : STACK_I8;
                        }
                        MONO_ADD_INS (cfg->cbb, ins);
                }
@@ -4754,3 +4754,17 @@ mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
        /* FIXME: implement */
        g_assert_not_reached ();
 }
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       switch (opcode) {
+       case OP_ATOMIC_ADD_I4:
+       case OP_ATOMIC_ADD_I8:
+       case OP_ATOMIC_EXCHANGE_I4:
+       case OP_ATOMIC_EXCHANGE_I8:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
index 4d4f1df44317af2ca40fe79bc3e1d48c4bded62e..c2171bce428d66e9b7863fd648e6738e4b3a4017 100644 (file)
@@ -114,7 +114,6 @@ unw_dyn_region_info_t* mono_ia64_create_unwind_region (Ia64CodegenState *code);
 #define MONO_ARCH_HAVE_INVALIDATE_METHOD 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
 #define MONO_ARCH_HAVE_SAVE_UNWIND_INFO 1
-#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
 #define MONO_ARCH_HAVE_IMT 1
 #define MONO_ARCH_HAVE_GENERALIZED_IMT_THUNK 1
 #define MONO_ARCH_THIS_AS_FIRST_ARG 1
index c6f04b8073acb2eb2d7bc0de089c2255d8e2b1ae..df6de20bab48786bcf4caed9ec1b139896289f9c 100644 (file)
@@ -3328,12 +3328,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                        values [ins->dreg] = mono_llvm_build_atomic_rmw (builder, LLVM_ATOMICRMW_OP_XCHG, args [0], args [1]);
                        break;
                }
-               case OP_ATOMIC_ADD_NEW_I4:
-               case OP_ATOMIC_ADD_NEW_I8: {
+               case OP_ATOMIC_ADD_I4:
+               case OP_ATOMIC_ADD_I8: {
                        LLVMValueRef args [2];
                        LLVMTypeRef t;
                                
-                       if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+                       if (ins->opcode == OP_ATOMIC_ADD_I4)
                                t = LLVMInt32Type ();
                        else
                                t = LLVMInt64Type ();
index 235fd33a449b15e2c2d8b4e2f8c0f2f900d8871b..ed56ee380dbdb77003257d2b7970589eb1c40c3e 100644 (file)
@@ -6142,3 +6142,9 @@ mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
 }
 
 #endif /* MONO_ARCH_SOFT_DEBUG_SUPPORTED */
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       return FALSE;
+}
index b1a31ee16d760a892f4782aa404a173625e0442f..e667a4c08f5050f328c1637ebfe03f84674cd5a8 100644 (file)
@@ -847,32 +847,36 @@ MINI_OP(OP_XMOVE,   "xmove", XREG, XREG, NONE)
 MINI_OP(OP_XZERO,   "xzero", XREG, NONE, NONE)
 MINI_OP(OP_XPHI,       "xphi", XREG, NONE, NONE)
 
-/* Atomic specific
-
-       Note, OP_ATOMIC_ADD_IMM_NEW_I4 and
-       OP_ATOMIC_ADD_NEW_I4 returns the new
-       value compared to OP_ATOMIC_ADD_I4 that
-       returns the old value.
-
-       OP_ATOMIC_ADD_NEW_I4 is used by
-       Interlocked::Increment and Interlocked:Decrement
-       and atomic_add_i4 by Interlocked::Add
+/*
+ * These are used for efficient implementation of the
+ * methods on the System.Threading.Interlocked class
+ * on architectures that support it. This is checked
+ * via mono_arch_opcode_supported ().
+ *
+ * Note that while the 32-bit variants are used on
+ * both 32-bit and 64-bit systems, the 64-bit variants
+ * are only used if the system is 64-bit. If that is
+ * not the case, the fallback code in the runtime is
+ * used instead. This is done because decomposing the
+ * 64-bit variants to instructions operating on 32-bit
+ * registers is very complicated on some architectures.
+ *
+ * The memory_barrier instruction translates to a full
+ * acquire/release barrier. Such a memory barrier is
+ * implied at the beginning and end of all other atomic
+ * operations, such that they ensure sequential
+ * consistency.
+ *
+ * All of these return the new value at the given
+ * memory location after performing the operation.
 */
 MINI_OP(OP_ATOMIC_ADD_I4, "atomic_add_i4", IREG, IREG, IREG)
-MINI_OP(OP_ATOMIC_ADD_NEW_I4, "atomic_add_new_i4", IREG, IREG, IREG)
-MINI_OP(OP_ATOMIC_ADD_IMM_I4, "atomic_add_imm_i4", IREG, IREG, NONE)
-MINI_OP(OP_ATOMIC_ADD_IMM_NEW_I4, "atomic_add_imm_new_i4", IREG, IREG, NONE)
-MINI_OP(OP_ATOMIC_EXCHANGE_I4, "atomic_exchange_i4", IREG, IREG, IREG)
-
 MINI_OP(OP_ATOMIC_ADD_I8, "atomic_add_i8", IREG, IREG, IREG)
-MINI_OP(OP_ATOMIC_ADD_NEW_I8, "atomic_add_new_i8", IREG, IREG, IREG)
-MINI_OP(OP_ATOMIC_ADD_IMM_I8, "atomic_add_imm_i8", IREG, IREG, NONE)
-MINI_OP(OP_ATOMIC_ADD_IMM_NEW_I8, "atomic_add_imm_new_i8", IREG, IREG, NONE)
+MINI_OP(OP_ATOMIC_EXCHANGE_I4, "atomic_exchange_i4", IREG, IREG, IREG)
 MINI_OP(OP_ATOMIC_EXCHANGE_I8, "atomic_exchange_i8", IREG, IREG, IREG)
-MINI_OP(OP_MEMORY_BARRIER, "memory_barrier", NONE, NONE, NONE)
-
 MINI_OP3(OP_ATOMIC_CAS_I4, "atomic_cas_i4", IREG, IREG, IREG, IREG)
 MINI_OP3(OP_ATOMIC_CAS_I8, "atomic_cas_i8", IREG, IREG, IREG, IREG)
+MINI_OP(OP_MEMORY_BARRIER, "memory_barrier", NONE, NONE, NONE)
 
 /* Conditional move opcodes.
  * Must be in the same order as the matching CEE_B... opcodes
@@ -1077,6 +1081,9 @@ MINI_OP(OP_S390_ISUB_OVF_UN,    "s390_int_sub_ovf_un", IREG, IREG, IREG)
 #endif
 
 #if defined(__ia64__)
+MINI_OP(OP_ATOMIC_ADD_IMM_I4, "atomic_add_imm_i4", IREG, IREG, NONE)
+MINI_OP(OP_ATOMIC_ADD_IMM_I8, "atomic_add_imm_i8", IREG, IREG, NONE)
+
 MINI_OP(OP_IA64_LOAD,          "ia64_load", NONE, NONE, NONE)
 MINI_OP(OP_IA64_LOADI1,        "ia64_loadi1", NONE, NONE, NONE)
 MINI_OP(OP_IA64_LOADU1,        "ia64_loadu1", NONE, NONE, NONE)
index d2a7aec7cd7373b9ca668f044e158a33502e63ea..16f34d1c00d84845426ca22da6f591c288c77e8f 100644 (file)
@@ -4384,17 +4384,17 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        else
                                ppc_mr (code, ins->dreg, ins->sreg1);
                        break;
-               case OP_ATOMIC_ADD_NEW_I4:
-               case OP_ATOMIC_ADD_NEW_I8: {
+               case OP_ATOMIC_ADD_I4:
+               case OP_ATOMIC_ADD_I8: {
                        guint8 *loop = code, *branch;
                        g_assert (ins->inst_offset == 0);
                        ppc_sync (code);
-                       if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+                       if (ins->opcode == OP_ATOMIC_ADD_I4)
                                ppc_lwarx (code, ppc_r0, 0, ins->inst_basereg);
                        else
                                ppc_ldarx (code, ppc_r0, 0, ins->inst_basereg);
                        ppc_add (code, ppc_r0, ppc_r0, ins->sreg2);
-                       if (ins->opcode == OP_ATOMIC_ADD_NEW_I4)
+                       if (ins->opcode == OP_ATOMIC_ADD_I4)
                                ppc_stwcxd (code, ppc_r0, 0, ins->inst_basereg);
                        else
                                ppc_stdcxd (code, ppc_r0, 0, ins->inst_basereg);
@@ -5945,3 +5945,19 @@ mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
 }
 
 #endif
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       switch (opcode) {
+       case OP_ATOMIC_CAS_I4:
+#ifdef TARGET_POWERPC64
+       case OP_ATOMIC_ADD_I4: /* Yes, really - see cpu-ppc(64).md. */
+       case OP_ATOMIC_ADD_I8:
+       case OP_ATOMIC_CAS_I8:
+#endif
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
index 13b6adb5376fccf0bc1957d16eb5fdc27b8de21c..a0b81e3da435f2a878478820a85692d93c674df6 100644 (file)
@@ -68,7 +68,6 @@ typedef struct MonoCompileArch {
 #ifdef __mono_ppc64__
 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS
 #define MONO_ARCH_NO_EMULATE_LONG_MUL_OPTS
-#define MONO_ARCH_HAVE_ATOMIC_ADD 1
 #define PPC_USES_FUNCTION_DESCRIPTOR
 
 #ifndef __mono_ilp32__
@@ -95,7 +94,6 @@ typedef struct MonoCompileArch {
 #define MONO_ARCH_EMULATE_LCONV_TO_R8_UN 1
 #define MONO_ARCH_EMULATE_FREM 1
 #define MONO_ARCH_BIGMUL_INTRINS 1
-#define MONO_ARCH_HAVE_ATOMIC_CAS 1
 
 /* Parameters used by the register allocator */
 #define MONO_ARCH_CALLEE_REGS ((0xff << ppc_r3) | (1 << ppc_r11) | (1 << ppc_r12))
index fbc6278a34239e379a26c97c0751bcfa055b63ed..8c3819b4668bd3a980ae53949bc7576a3c998bdb 100644 (file)
@@ -4529,15 +4529,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        s390_lgr (code, ins->dreg, s390_r1);
                }
                        break;  
-               case OP_ATOMIC_ADD_NEW_I8: {
-                       s390_lgr (code, s390_r1, ins->sreg2);
-                       s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
-                       s390_agr (code, s390_r1, s390_r0);
-                       s390_csg (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
-                       s390_jnz (code, -10);
-                       s390_lgr (code, ins->dreg, s390_r1);
-               }
-                       break;  
                case OP_ATOMIC_EXCHANGE_I8: {
                        s390_lg  (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
                        s390_csg (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
@@ -4554,15 +4545,6 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                        s390_lgfr(code, ins->dreg, s390_r1);
                }
                        break;  
-               case OP_ATOMIC_ADD_NEW_I4: {
-                       s390_lgfr(code, s390_r1, ins->sreg2);
-                       s390_lgf (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
-                       s390_agr (code, s390_r1, s390_r0);
-                       s390_cs  (code, s390_r0, s390_r1, ins->inst_basereg, ins->inst_offset);
-                       s390_jnz (code, -9);
-                       s390_lgfr(code, ins->dreg, s390_r1);
-               }
-                       break;  
                case OP_ATOMIC_EXCHANGE_I4: {
                        s390_l   (code, s390_r0, 0, ins->inst_basereg, ins->inst_offset);
                        s390_cs  (code, s390_r0, ins->sreg2, ins->inst_basereg, ins->inst_offset);
@@ -6138,3 +6120,17 @@ mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
 /*========================= End of Function ========================*/
 
 #endif
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       switch (opcode) {
+       case OP_ATOMIC_ADD_I4:
+       case OP_ATOMIC_ADD_I8:
+       case OP_ATOMIC_EXCHANGE_I4:
+       case OP_ATOMIC_EXCHANGE_I8:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
index 8ca5fb27ad29937182d013f1f838007ed13f0521..b03a1f4cc793f6acfccae34f41186382f336d39e 100644 (file)
@@ -45,8 +45,6 @@ typedef struct
 #define MONO_ARCH_NO_EMULATE_LONG_SHIFT_OPS            1
 #define MONO_ARCH_HAVE_IS_INT_OVERFLOW                 1
 #define MONO_ARCH_NEED_DIV_CHECK                       1
-#define MONO_ARCH_HAVE_ATOMIC_ADD                      1
-#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE                         1
 #define MONO_ARCH_SIGNAL_STACK_SIZE                    256*1024
 #define MONO_ARCH_HAVE_DECOMPOSE_OPTS                  1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE      1
index ec65fb5c6b9abf2b5f4d6d986f1f0995b5842a57..3b95fd970336c9f187ef0e05f7f563b96acc9190 100644 (file)
@@ -4430,3 +4430,9 @@ mono_arch_context_get_int_reg (MonoContext *ctx, int reg)
        /* FIXME: implement */
        g_assert_not_reached ();
 }
+
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       return FALSE;
+}
index 3de9b0be1a226801938979a57a19bb9a0c8bae13..0a52a720d18de916ed80458558c4f149d93fc0d6 100644 (file)
@@ -1065,7 +1065,7 @@ mono_arch_allocate_vars (MonoCompile *cfg)
        cfg->frame_reg = X86_EBP;
        offset = 0;
 
-       if (cfg->has_atomic_add_new_i4 || cfg->has_atomic_exchange_i4) {
+       if (cfg->has_atomic_add_i4 || cfg->has_atomic_exchange_i4) {
                /* The opcode implementations use callee-saved regs as scratch regs by pushing and pop-ing them, but that is not async safe */
                cfg->used_int_regs |= (1 << X86_EBX) | (1 << X86_EDI) | (1 << X86_ESI);
        }
@@ -4372,28 +4372,7 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
                case OP_ATOMIC_ADD_I4: {
                        int dreg = ins->dreg;
 
-                       if (dreg == ins->inst_basereg) {
-                               x86_push_reg (code, ins->sreg2);
-                               dreg = ins->sreg2;
-                       } 
-                       
-                       if (dreg != ins->sreg2)
-                               x86_mov_reg_reg (code, ins->dreg, ins->sreg2, 4);
-
-                       x86_prefix (code, X86_LOCK_PREFIX);
-                       x86_xadd_membase_reg (code, ins->inst_basereg, ins->inst_offset, dreg, 4);
-
-                       if (dreg != ins->dreg) {
-                               x86_mov_reg_reg (code, ins->dreg, dreg, 4);
-                               x86_pop_reg (code, dreg);
-                       }
-
-                       break;
-               }
-               case OP_ATOMIC_ADD_NEW_I4: {
-                       int dreg = ins->dreg;
-
-                       g_assert (cfg->has_atomic_add_new_i4);
+                       g_assert (cfg->has_atomic_add_i4);
 
                        /* hack: limit in regalloc, dreg != sreg1 && dreg != sreg2 */
                        if (ins->sreg2 == dreg) {
@@ -6849,6 +6828,19 @@ mono_arch_init_lmf_ext (MonoLMFExt *ext, gpointer prev_lmf)
 
 #endif
 
+gboolean
+mono_arch_opcode_supported (int opcode)
+{
+       switch (opcode) {
+       case OP_ATOMIC_ADD_I4:
+       case OP_ATOMIC_EXCHANGE_I4:
+       case OP_ATOMIC_CAS_I4:
+               return TRUE;
+       default:
+               return FALSE;
+       }
+}
+
 #if defined(ENABLE_GSHAREDVT)
 
 #include "../../../mono-extensions/mono/mini/mini-x86-gsharedvt.c"
index 2f7eaca37b6ac519649f4011229dc0e4aa454e6b..c0c57b121f7d6d3d556c1a0c6bbd537033fc4db0 100644 (file)
@@ -211,9 +211,6 @@ typedef struct {
 #define MONO_ARCH_NEED_GOT_VAR 1
 #define MONO_ARCH_ENABLE_MONO_LMF_VAR 1
 #define MONO_ARCH_HAVE_CREATE_DELEGATE_TRAMPOLINE 1
-#define MONO_ARCH_HAVE_ATOMIC_ADD 1
-#define MONO_ARCH_HAVE_ATOMIC_EXCHANGE 1
-#define MONO_ARCH_HAVE_ATOMIC_CAS 1
 #define MONO_ARCH_HAVE_IMT 1
 #define MONO_ARCH_HAVE_TLS_GET (mono_x86_have_tls_get ())
 #define MONO_ARCH_IMT_REG X86_EDX
index 4d4c39c2f2aaaeb2280ca0711c62abb057f422ad..6a2249fff058be8e29532a2d2e338583d2556fc0 100644 (file)
@@ -7959,16 +7959,6 @@ mono_arch_get_gsharedvt_trampoline (MonoTrampInfo **info, gboolean aot)
 
 #endif
 
-#ifndef MONO_ARCH_HAVE_OPCODE_SUPPORTED
-
-gboolean
-mono_arch_opcode_supported (int opcode)
-{
-       return TRUE;
-}
-
-#endif
-
 #if defined(MONO_ARCH_GSHAREDVT_SUPPORTED) && !defined(ENABLE_GSHAREDVT)
 
 gboolean
index 76cbdf32022f906d8c4fb701b8cc443cb3d2aa68..ad7c3d8794d0ef9ff68c6219b056760421e0f4b6 100644 (file)
@@ -1491,7 +1491,7 @@ typedef struct {
        guint            soft_breakpoints : 1;
        guint            arch_eh_jit_info : 1;
        guint            has_indirection : 1;
-       guint            has_atomic_add_new_i4 : 1;
+       guint            has_atomic_add_i4 : 1;
        guint            has_atomic_exchange_i4 : 1;
        guint            has_atomic_cas_i4 : 1;
        guint            check_pinvoke_callconv : 1;