LLVM: Make Buffer.Memmove intrinsic (mono/mono#16610)
authorEgor Bogatov <egorbo@gmail.com>
Sat, 31 Aug 2019 23:42:44 +0000 (02:42 +0300)
committerZoltan Varga <vargaz@gmail.com>
Sat, 31 Aug 2019 23:42:44 +0000 (19:42 -0400)
* Add memmove intrinsic

* Fix typo

* Add -lower-expect

Commit migrated from https://github.com/mono/mono/commit/6327274b54cca5ad11207c79f5a611ca1623c60f

src/mono/mono/mini/intrinsics.c
src/mono/mono/mini/llvm-jit.cpp
src/mono/mono/mini/mini-llvm.c
src/mono/mono/mini/mini-ops.h

index 2b1ced9..8eeb551 100644 (file)
@@ -222,6 +222,17 @@ llvm_emit_inst_for_method (MonoCompile *cfg, MonoMethod *cmethod, MonoMethodSign
                }
        }
 
+       if (in_corlib && !strcmp (m_class_get_name (cmethod->klass), "Buffer")) {
+               if (!strcmp (cmethod->name, "Memmove") && fsig->param_count == 3 && fsig->params [0]->type == MONO_TYPE_PTR && fsig->params [1]->type == MONO_TYPE_PTR) {
+                       opcode = OP_MEMMOVE;
+                       MONO_INST_NEW (cfg, ins, opcode);
+                       ins->sreg1 = args [0]->dreg; // i1* dst
+                       ins->sreg2 = args [1]->dreg; // i1* src
+                       ins->sreg3 = args [2]->dreg; // i32/i64 len
+                       MONO_ADD_INS (cfg->cbb, ins);
+               }
+       }
+
        return ins;
 }
 
index 2fa9c60..4a36413 100644 (file)
@@ -289,7 +289,7 @@ public:
                if (opts == NULL) {
                        // FIXME: find optimal mono specific order of passes
                        // see https://llvm.org/docs/Frontend/PerformanceTips.html#pass-ordering
-                       opts = " -simplifycfg -sroa -instcombine -gvn";
+                       opts = " -simplifycfg -sroa -lower-expect -instcombine -gvn";
                }
 
                char **args = g_strsplit (opts, " ", -1);
index 58c29e0..f15b320 100644 (file)
@@ -278,6 +278,7 @@ static LLVMRealPredicate fpcond_to_llvm_cond [] = {
 typedef enum {
        INTRINS_MEMSET,
        INTRINS_MEMCPY,
+       INTRINS_MEMMOVE,
        INTRINS_SADD_OVF_I32,
        INTRINS_UADD_OVF_I32,
        INTRINS_SSUB_OVF_I32,
@@ -5901,6 +5902,20 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
                                set_nonnull_load_flag (values [ins->dreg]);
                        break;
                }
+               case OP_MEMMOVE: {
+                       int argn = 0;
+                       LLVMValueRef args [5];
+                       args [argn++] = convert (ctx, values [ins->sreg1], LLVMPointerType (LLVMInt8Type (), 0));
+                       args [argn++] = convert (ctx, values [ins->sreg2], LLVMPointerType (LLVMInt8Type (), 0));
+                       args [argn++] = convert (ctx, values [ins->sreg3], LLVMInt64Type ());
+#if LLVM_API_VERSION < 900
+                       args [argn++] = LLVMConstInt (LLVMInt32Type (), 1, FALSE); // alignment
+#endif
+                       args [argn++] = LLVMConstInt (LLVMInt1Type (), 0, FALSE);  // is_volatile
+
+                       LLVMBuildCall (builder, get_intrins (ctx, INTRINS_MEMMOVE), args, argn, "");
+                       break;
+               }
                case OP_NOT_REACHED:
                        LLVMBuildUnreachable (builder);
                        has_terminator = TRUE;
@@ -8522,6 +8537,7 @@ typedef struct {
 static IntrinsicDesc intrinsics[] = {
        {INTRINS_MEMSET, "llvm.memset.p0i8.i32"},
        {INTRINS_MEMCPY, "llvm.memcpy.p0i8.p0i8.i32"},
+       {INTRINS_MEMMOVE, "llvm.memmove.p0i8.p0i8.i64"},
        {INTRINS_SADD_OVF_I32, "llvm.sadd.with.overflow.i32"},
        {INTRINS_UADD_OVF_I32, "llvm.uadd.with.overflow.i32"},
        {INTRINS_SSUB_OVF_I32, "llvm.ssub.with.overflow.i32"},
@@ -8664,6 +8680,17 @@ add_intrinsic (LLVMModuleRef module, int id)
 #endif
                break;
        }
+       case INTRINS_MEMMOVE: {
+#if LLVM_API_VERSION >= 900
+               /* No alignment argument */
+               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt64Type (), LLVMInt1Type () };
+               AddFunc (module, name, LLVMVoidType (), params, 4);
+#else
+               LLVMTypeRef params [] = { LLVMPointerType (LLVMInt8Type (), 0), LLVMPointerType (LLVMInt8Type (), 0), LLVMInt64Type (), LLVMInt32Type (), LLVMInt1Type () };
+               AddFunc (module, name, LLVMVoidType (), params, 5);
+#endif
+               break;
+       }
        case INTRINS_SADD_OVF_I32:
        case INTRINS_UADD_OVF_I32:
        case INTRINS_SSUB_OVF_I32:
index 1696889..8d8425a 100644 (file)
@@ -755,6 +755,8 @@ MINI_OP(OP_MEMSET, "memset", NONE, NONE, NONE)
 MINI_OP(OP_SAVE_LMF, "save_lmf", NONE, NONE, NONE)
 MINI_OP(OP_RESTORE_LMF, "restore_lmf", NONE, NONE, NONE)
 
+MINI_OP3(OP_MEMMOVE, "memmove", NONE, IREG, IREG, IREG)
+
 /* write barrier */
 MINI_OP(OP_CARD_TABLE_WBARRIER, "card_table_wbarrier", NONE, IREG, IREG)