""" LLVM pass that converts intrinsic into other math calls """ from __future__ import print_function, absolute_import from llvmlite import ir class _DivmodFixer(ir.Visitor): def visit_Instruction(self, instr): if instr.type == ir.IntType(64): if instr.opname in ['srem', 'urem', 'sdiv', 'udiv']: name = 'numba_{op}'.format(op=instr.opname) fn = self.module.globals.get(name) # Declare the function if it doesn't already exist if fn is None: opty = instr.type sdivfnty = ir.FunctionType(opty, [opty, opty]) fn = ir.Function(self.module, sdivfnty, name=name) # Replace the operation with a call to the builtin repl = ir.CallInstr(parent=instr.parent, func=fn, args=instr.operands, name=instr.name) instr.parent.replace(instr, repl) def fix_divmod(mod): """Replace division and reminder instructions to builtins calls """ _DivmodFixer().visit(mod) INTR_TO_CMATH = { "llvm.pow.f32": "powf", "llvm.pow.f64": "pow", "llvm.sin.f32": "sinf", "llvm.sin.f64": "sin", "llvm.cos.f32": "cosf", "llvm.cos.f64": "cos", "llvm.sqrt.f32": "sqrtf", "llvm.sqrt.f64": "sqrt", "llvm.exp.f32": "expf", "llvm.exp.f64": "exp", "llvm.log.f32": "logf", "llvm.log.f64": "log", "llvm.log10.f32": "log10f", "llvm.log10.f64": "log10", "llvm.fabs.f32": "fabsf", "llvm.fabs.f64": "fabs", "llvm.floor.f32": "floorf", "llvm.floor.f64": "floor", "llvm.ceil.f32": "ceilf", "llvm.ceil.f64": "ceil", "llvm.trunc.f32": "truncf", "llvm.trunc.f64": "trunc", } OTHER_CMATHS = ''' tan tanf sinh sinhf cosh coshf tanh tanhf asin asinf acos acosf atan atanf atan2 atan2f atan2_fixed asinh asinhf acosh acoshf atanh atanhf expm1 expm1f log1p log1pf log10 log10f fmod fmodf round roundf '''.split() INTR_MATH = frozenset(INTR_TO_CMATH.values()) | frozenset(OTHER_CMATHS)