Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/mono.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEgor Bogatov <egorbo@gmail.com>2019-11-20 23:25:24 +0300
committerZoltan Varga <vargaz@gmail.com>2019-11-20 23:25:24 +0300
commit2c20649539ac16e069a65f2a750c793eb341e50f (patch)
tree6655a5d81138c3f055a974102c424587674c9adb
parent4961d411e7f6a425c4b7fad86b72f02947f9c817 (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.cpp3
-rw-r--r--mono/mini/mini-llvm-cpp.cpp22
-rw-r--r--mono/mini/mini-llvm-cpp.h3
-rw-r--r--mono/mini/mini-llvm.c17
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, "");