diff options
author | Egor Bogatov <egorbo@gmail.com> | 2019-11-20 23:25:24 +0300 |
---|---|---|
committer | Zoltan Varga <vargaz@gmail.com> | 2019-11-20 23:25:24 +0300 |
commit | 2c20649539ac16e069a65f2a750c793eb341e50f (patch) | |
tree | 6655a5d81138c3f055a974102c424587674c9adb | |
parent | 4961d411e7f6a425c4b7fad86b72f02947f9c817 (diff) |
[llvm] Recognize GEP (#17844)
* initial impl
* improve jit
* fix copy-paste
* disable for non-netcore
* clean up
-rw-r--r-- | mono/mini/llvm-jit.cpp | 3 | ||||
-rw-r--r-- | mono/mini/mini-llvm-cpp.cpp | 22 | ||||
-rw-r--r-- | mono/mini/mini-llvm-cpp.h | 3 | ||||
-rw-r--r-- | mono/mini/mini-llvm.c | 17 |
4 files changed, 41 insertions, 4 deletions
diff --git a/mono/mini/llvm-jit.cpp b/mono/mini/llvm-jit.cpp index ecd63cbe5c2..85c9ee92107 100644 --- a/mono/mini/llvm-jit.cpp +++ b/mono/mini/llvm-jit.cpp @@ -297,12 +297,13 @@ public: initializeScalarOpts(registry); initializeInstCombine(registry); initializeTarget(registry); + initializeLoopIdiomRecognizeLegacyPassPass(registry); linkCoreCLRGC(); // Mono uses built-in "coreclr" GCStrategy // FIXME: find optimal mono specific order of passes // see https://llvm.org/docs/Frontend/PerformanceTips.html#pass-ordering // the following order is based on a stripped version of "OPT -O2" - const char *default_opts = " -simplifycfg -sroa -lower-expect -instcombine -licm -simplifycfg -lcssa -indvars -loop-deletion -gvn -memcpyopt -sccp -bdce -instcombine -dse -simplifycfg -enable-implicit-null-checks"; + const char *default_opts = " -simplifycfg -sroa -lower-expect -instcombine -loop-rotate -licm -simplifycfg -lcssa -loop-idiom -indvars -loop-deletion -gvn -memcpyopt -sccp -bdce -instcombine -dse -simplifycfg -enable-implicit-null-checks"; const char *opts = g_getenv ("MONO_LLVM_OPT"); if (opts == NULL) opts = default_opts; diff --git a/mono/mini/mini-llvm-cpp.cpp b/mono/mini/mini-llvm-cpp.cpp index c4523ee0b7a..3c95c3e5c79 100644 --- a/mono/mini/mini-llvm-cpp.cpp +++ b/mono/mini/mini-llvm-cpp.cpp @@ -298,6 +298,28 @@ mono_llvm_set_func_nonnull_arg (LLVMValueRef func, int argNo) } gboolean +mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* gep_base, LLVMValueRef* gep_offset) +{ +#ifdef ENABLE_NETCORE + // Look for a pattern like this: + // %1 = ptrtoint i8* %gep_base to i64 + // %2 = add i64 %1, %gep_offset + if (Instruction *base_inst = dyn_cast<Instruction> (unwrap (base))) { + if (base_inst->getOpcode () == Instruction::Add) { + if (Instruction *base_ptr_ins = dyn_cast<Instruction> (base_inst->getOperand (0))) { + if (base_ptr_ins->getOpcode () == Instruction::PtrToInt) { + *gep_base = wrap (base_ptr_ins->getOperand (0)); + *gep_offset = wrap (base_inst->getOperand (1)); + return TRUE; + } + } + } + } +#endif + return FALSE; +} + +gboolean mono_llvm_is_nonnull (LLVMValueRef wrapped) { // Argument to function diff --git a/mono/mini/mini-llvm-cpp.h b/mono/mini/mini-llvm-cpp.h index b2aa9392e4a..ef56a6f3790 100644 --- a/mono/mini/mini-llvm-cpp.h +++ b/mono/mini/mini-llvm-cpp.h @@ -151,6 +151,9 @@ G_EXTERN_C _Unwind_Reason_Code mono_debug_personality (int a, _Unwind_Action b, void* mono_llvm_create_di_builder (LLVMModuleRef module); +gboolean +mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* actual_base, LLVMValueRef* actual_offset); + void* mono_llvm_di_create_function (void *di_builder, void *cu, LLVMValueRef func, const char *name, const char *mangled_name, const char *dir, const char *file, int line); diff --git a/mono/mini/mini-llvm.c b/mono/mini/mini-llvm.c index 88e1d2ab2be..7edd0cd2197 100644 --- a/mono/mini/mini-llvm.c +++ b/mono/mini/mini-llvm.c @@ -5762,7 +5762,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) base = lhs; if (ins->inst_offset == 0) { - addr = base; + LLVMValueRef gep_base, gep_offset; + if (mono_llvm_can_be_gep (base, &gep_base, &gep_offset)) { + addr = LLVMBuildGEP (builder, convert (ctx, gep_base, LLVMPointerType (LLVMInt8Type (), 0)), &gep_offset, 1, ""); + } else { + addr = base; + } } else if (ins->inst_offset % size != 0) { /* Unaligned load */ index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE); @@ -5816,7 +5821,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext); base = values [ins->inst_destbasereg]; - if (ins->inst_offset % size != 0) { + LLVMValueRef gep_base, gep_offset; + if (ins->inst_offset == 0 && mono_llvm_can_be_gep (base, &gep_base, &gep_offset)) { + addr = LLVMBuildGEP (builder, convert (ctx, gep_base, LLVMPointerType (LLVMInt8Type (), 0)), &gep_offset, 1, ""); + } else if (ins->inst_offset % size != 0) { /* Unaligned store */ index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, ""); @@ -5846,7 +5854,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb) t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext); base = values [ins->inst_destbasereg]; - if (ins->inst_offset % size != 0) { + LLVMValueRef gep_base, gep_offset; + if (ins->inst_offset == 0 && mono_llvm_can_be_gep (base, &gep_base, &gep_offset)) { + addr = LLVMBuildGEP (builder, convert (ctx, gep_base, LLVMPointerType (LLVMInt8Type (), 0)), &gep_offset, 1, ""); + } else if (ins->inst_offset % size != 0) { /* Unaligned store */ index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE); addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, ""); |