Skip to content

Commit e8859b4

Browse files
EgorBovargaz
authored andcommitted
[llvm] Recognize GEP (mono/mono#17844)
* initial impl * improve jit * fix copy-paste * disable for non-netcore * clean up Commit migrated from mono/mono@2c20649
1 parent 20a1950 commit e8859b4

File tree

4 files changed

+41
-4
lines changed

4 files changed

+41
-4
lines changed

src/mono/mono/mini/llvm-jit.cpp

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,12 +297,13 @@ class MonoLLVMJIT {
297297
initializeScalarOpts(registry);
298298
initializeInstCombine(registry);
299299
initializeTarget(registry);
300+
initializeLoopIdiomRecognizeLegacyPassPass(registry);
300301
linkCoreCLRGC(); // Mono uses built-in "coreclr" GCStrategy
301302

302303
// FIXME: find optimal mono specific order of passes
303304
// see https://llvm.org/docs/Frontend/PerformanceTips.html#pass-ordering
304305
// the following order is based on a stripped version of "OPT -O2"
305-
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";
306+
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";
306307
const char *opts = g_getenv ("MONO_LLVM_OPT");
307308
if (opts == NULL)
308309
opts = default_opts;

src/mono/mono/mini/mini-llvm-cpp.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -297,6 +297,28 @@ mono_llvm_set_func_nonnull_arg (LLVMValueRef func, int argNo)
297297
unwrap<Function>(func)->addParamAttr (argNo, Attribute::NonNull);
298298
}
299299

300+
gboolean
301+
mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* gep_base, LLVMValueRef* gep_offset)
302+
{
303+
#ifdef ENABLE_NETCORE
304+
// Look for a pattern like this:
305+
// %1 = ptrtoint i8* %gep_base to i64
306+
// %2 = add i64 %1, %gep_offset
307+
if (Instruction *base_inst = dyn_cast<Instruction> (unwrap (base))) {
308+
if (base_inst->getOpcode () == Instruction::Add) {
309+
if (Instruction *base_ptr_ins = dyn_cast<Instruction> (base_inst->getOperand (0))) {
310+
if (base_ptr_ins->getOpcode () == Instruction::PtrToInt) {
311+
*gep_base = wrap (base_ptr_ins->getOperand (0));
312+
*gep_offset = wrap (base_inst->getOperand (1));
313+
return TRUE;
314+
}
315+
}
316+
}
317+
}
318+
#endif
319+
return FALSE;
320+
}
321+
300322
gboolean
301323
mono_llvm_is_nonnull (LLVMValueRef wrapped)
302324
{

src/mono/mono/mini/mini-llvm-cpp.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,9 @@ G_EXTERN_C _Unwind_Reason_Code mono_debug_personality (int a, _Unwind_Action b,
151151
void*
152152
mono_llvm_create_di_builder (LLVMModuleRef module);
153153

154+
gboolean
155+
mono_llvm_can_be_gep (LLVMValueRef base, LLVMValueRef* actual_base, LLVMValueRef* actual_offset);
156+
154157
void*
155158
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);
156159

src/mono/mono/mini/mini-llvm.c

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5762,7 +5762,12 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
57625762
base = lhs;
57635763

57645764
if (ins->inst_offset == 0) {
5765-
addr = base;
5765+
LLVMValueRef gep_base, gep_offset;
5766+
if (mono_llvm_can_be_gep (base, &gep_base, &gep_offset)) {
5767+
addr = LLVMBuildGEP (builder, convert (ctx, gep_base, LLVMPointerType (LLVMInt8Type (), 0)), &gep_offset, 1, "");
5768+
} else {
5769+
addr = base;
5770+
}
57665771
} else if (ins->inst_offset % size != 0) {
57675772
/* Unaligned load */
57685773
index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
@@ -5816,7 +5821,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
58165821
t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
58175822

58185823
base = values [ins->inst_destbasereg];
5819-
if (ins->inst_offset % size != 0) {
5824+
LLVMValueRef gep_base, gep_offset;
5825+
if (ins->inst_offset == 0 && mono_llvm_can_be_gep (base, &gep_base, &gep_offset)) {
5826+
addr = LLVMBuildGEP (builder, convert (ctx, gep_base, LLVMPointerType (LLVMInt8Type (), 0)), &gep_offset, 1, "");
5827+
} else if (ins->inst_offset % size != 0) {
58205828
/* Unaligned store */
58215829
index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
58225830
addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");
@@ -5846,7 +5854,10 @@ process_bb (EmitContext *ctx, MonoBasicBlock *bb)
58465854
t = load_store_to_llvm_type (ins->opcode, &size, &sext, &zext);
58475855

58485856
base = values [ins->inst_destbasereg];
5849-
if (ins->inst_offset % size != 0) {
5857+
LLVMValueRef gep_base, gep_offset;
5858+
if (ins->inst_offset == 0 && mono_llvm_can_be_gep (base, &gep_base, &gep_offset)) {
5859+
addr = LLVMBuildGEP (builder, convert (ctx, gep_base, LLVMPointerType (LLVMInt8Type (), 0)), &gep_offset, 1, "");
5860+
} else if (ins->inst_offset % size != 0) {
58505861
/* Unaligned store */
58515862
index = LLVMConstInt (LLVMInt32Type (), ins->inst_offset, FALSE);
58525863
addr = LLVMBuildGEP (builder, convert (ctx, base, LLVMPointerType (LLVMInt8Type (), 0)), &index, 1, "");

0 commit comments

Comments
 (0)