From bf8693bb806be4192810b740c08300876d76cb34 Mon Sep 17 00:00:00 2001 From: Siu Kwan Lam Date: Wed, 14 Aug 2013 17:45:38 -0500 Subject: [PATCH] disable float div/mod test temporarily --- llvm/core.py | 3 + llvm/llrt.py | 77 ++++++++ llvm/llrt/llrt_x86.ll | 371 +++++++++++++++++++++++++++++++++++++++ llvm/llrt/llrt_x86_64.ll | 371 +++++++++++++++++++++++++++++++++++++++ llvm/test_llvmpy.py | 42 ++++- 5 files changed, 858 insertions(+), 6 deletions(-) create mode 100644 llvm/llrt.py create mode 100644 llvm/llrt/llrt_x86.ll create mode 100644 llvm/llrt/llrt_x86_64.ll diff --git a/llvm/core.py b/llvm/core.py index 945dd86..c4fe560 100644 --- a/llvm/core.py +++ b/llvm/core.py @@ -1848,6 +1848,9 @@ class Instruction(User): def erase_from_parent(self): return self._ptr.eraseFromParent() + def replace_all_uses_with(self, inst): + self._ptr.replaceAllUsesWith(inst) + class CallOrInvokeInstruction(Instruction): _type_ = api.llvm.CallInst, api.llvm.InvokeInst diff --git a/llvm/llrt.py b/llvm/llrt.py new file mode 100644 index 0000000..b80914e --- /dev/null +++ b/llvm/llrt.py @@ -0,0 +1,77 @@ +import os +import llvm.core as lc +import llvm.passes as lp +import llvm.ee as le + +def replace_divmod64(lfunc): + '''Replaces all 64-bit integer division (sdiv, udiv) and modulo (srem, urem) + ''' + int64 = lc.Type.int(64) + int64ptr = lc.Type.pointer(lc.Type.int(64)) + + functy = lc.Type.function(int64, [int64, int64]) + udiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_udiv64') + sdiv64 = lfunc.module.get_or_insert_function(functy, '__llrt_sdiv64') + umod64 = lfunc.module.get_or_insert_function(functy, '__llrt_umod64') + smod64 = lfunc.module.get_or_insert_function(functy, '__llrt_smod64') + + builder = lc.Builder.new(lfunc.entry_basic_block) + for bb in lfunc.basic_blocks: + for inst in bb.instructions: + if inst.opcode_name == 'sdiv' and inst.type == int64: + _replace_with(builder, inst, sdiv64) + elif inst.opcode_name == 'udiv' and inst.type == int64: + _replace_with(builder, inst, udiv64) + elif inst.opcode_name == 'srem' and inst.type == int64: + _replace_with(builder, inst, smod64) + elif inst.opcode_name == 'urem' and inst.type == int64: + _replace_with(builder, inst, umod64) + +def _replace_with(builder, inst, func): + '''Replace instruction with a call to the function with the same operands + as arguments. + ''' + builder.position_before(inst) + replacement = builder.call(func, inst.operands) + inst.replace_all_uses_with(replacement._ptr) + inst.erase_from_parent() + +def load(arch): + '''Load the LLRT module corresponding to the given architecture + Creates a new module and optimizes it using the information from + the host machine. + ''' + path = os.path.join(os.path.dirname(__file__), 'llrt', 'llrt_%s.ll' % arch) + with open(path) as fin: + lib = lc.Module.from_assembly(fin) + + # run passes to optimize + tm = le.TargetMachine.new() + pms = lp.build_pass_managers(tm, opt=3, fpm=False) + pms.pm.run(lib) + return lib + +class LLRT(object): + def __init__(self): + arch = le.get_default_triple().split('-', 1)[0] + self.module = load(arch) + self.engine = le.EngineBuilder.new(self.module).opt(3).create() + self.installed_symbols = set() + + def install_symbols(self): + '''Bind all the external symbols to the global symbol map. + Any future reference to these symbols will be automatically resolved + by LLVM. + ''' + for lfunc in self.module.functions: + if lfunc.linkage == lc.LINKAGE_EXTERNAL: + mangled = '__llrt_' + lfunc.name + self.installed_symbols.add(mangled) + ptr = self.engine.get_pointer_to_function(lfunc) + le.dylib_add_symbol(mangled, ptr) + + def uninstall_symbols(self): + for sym in self.installed_symbols: + le.dylib_add_symbol(sym, 0) + + diff --git a/llvm/llrt/llrt_x86.ll b/llvm/llrt/llrt_x86.ll new file mode 100644 index 0000000..5096214 --- /dev/null +++ b/llvm/llrt/llrt_x86.ll @@ -0,0 +1,371 @@ +; ModuleID = 'udivmod64_x86.bc' +target datalayout = "e-p:32:32:32-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-f32:32:32-f64:32:64-v64:64:64-v128:128:128-a0:0:64-f80:128:128-n8:16:32-S128" + +%struct.div_state_ = type { i64, i64 } + +define i64 @udivmod64(i64 %dividend, i64 %divisor, i64* %remainder) nounwind ssp { + %1 = alloca i64, align 4 + %2 = alloca i64, align 8 + %3 = alloca i64, align 8 + %4 = alloca i64*, align 4 + %state = alloca %struct.div_state_, align 4 + %quotient = alloca i64, align 8 + %i = alloca i32, align 4 + %skipahead = alloca i32, align 4 + store i64 %dividend, i64* %2, align 8 + store i64 %divisor, i64* %3, align 8 + store i64* %remainder, i64** %4, align 4 + %5 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 0 + store i64 0, i64* %5, align 4 + %6 = getelementptr inbounds %struct.div_state_* %state, i32 0, i32 1 + %7 = load i64* %2, align 8 + store i64 %7, i64* %6, align 4 + store i64 0, i64* %quotient, align 8 + %8 = load i64* %3, align 8 + %9 = icmp eq i64 %8, 0 + br i1 %9, label %10, label %11 + +;