def frontend_looplift(self): """ Loop lifting analysis and transformation """ assert not self.lifted # Try loop lifting loop_flags = self.flags.copy() outer_flags = self.flags.copy() # Do not recursively loop lift outer_flags.unset('enable_looplift') loop_flags.unset('enable_looplift') if not self.flags.enable_pyobject_looplift: loop_flags.unset('enable_pyobject') def dispatcher_factory(loopbc): from . import dispatcher return dispatcher.LiftedLoop(loopbc, self.typingctx, self.targetctx, self.locals, loop_flags) entry, loops = looplifting.lift_loop(self.bc, dispatcher_factory) if loops: # Some loops were extracted if config.DEBUG_FRONTEND or config.DEBUG: print("Lifting loop", loops[0].get_source_location()) cres = compile_bytecode(self.typingctx, self.targetctx, entry, self.args, self.return_type, outer_flags, self.locals, lifted=tuple(loops), lifted_from=None, func_attr=self.func_attr) return cres
def compile_bytecode(typingctx, targetctx, bc, args, return_type, flags, locals, lifted=()): interp = translate_stage(bc) nargs = len(interp.argspec.args) if len(args) > nargs: raise TypeError("Too many argument types") status = _CompileStatus() status.can_fallback = flags.enable_pyobject status.fail_reason = None status.use_python_mode = flags.force_pyobject targetctx = targetctx.localized() if not status.use_python_mode: with _fallback_context(status): legalize_given_types(args, return_type) # Type inference typemap, return_type, calltypes = type_inference_stage(typingctx, interp, args, return_type, locals) if not status.use_python_mode: with _fallback_context(status): legalize_return_type(return_type, interp, targetctx) if status.use_python_mode and flags.enable_looplift: assert not lifted # Try loop lifting entry, loops = looplifting.lift_loop(bc) if not loops: # No extracted loops pass else: loopflags = flags.copy() # Do not recursively loop lift loopflags.unset('enable_looplift') loopdisp = looplifting.bind(loops, typingctx, targetctx, locals, loopflags) lifted = tuple(loopdisp) cres = compile_bytecode(typingctx, targetctx, entry, args, return_type, loopflags, locals, lifted=lifted) return cres._replace(lifted=lifted) if status.use_python_mode: # Object mode compilation func, fnptr, lmod, lfunc, fndesc = py_lowering_stage(targetctx, interp, flags.no_compile) typemap = defaultdict(lambda: types.pyobject) calltypes = defaultdict(lambda: types.pyobject) return_type = types.pyobject if len(args) != nargs: # append missing args = tuple(args) + (types.pyobject,) * (nargs - len(args)) else: # Native mode compilation func, fnptr, lmod, lfunc, fndesc = native_lowering_stage(targetctx, interp, typemap, return_type, calltypes, flags.no_compile) type_annotation = type_annotations.TypeAnnotation(interp=interp, typemap=typemap, calltypes=calltypes, lifted=lifted) if config.ANNOTATE: print("ANNOTATION".center(80, '-')) print(type_annotation) print('=' * 80) signature = typing.signature(return_type, *args) assert lfunc.module is lmod cr = compile_result(typing_context=typingctx, target_context=targetctx, entry_point=func, entry_point_addr=fnptr, typing_error=status.fail_reason, type_annotation=type_annotation, llvm_func=lfunc, llvm_module=lmod, signature=signature, objectmode=status.use_python_mode, lifted=lifted, fndesc=fndesc,) return cr
def _compile_core(typingctx, targetctx, bc, args, return_type, flags, locals, lifted, func_attr, status): ### Front-end: Analyze bytecode, generate Numba IR, infer types interp = translate_stage(bc) nargs = len(interp.argspec.args) if len(args) > nargs: raise TypeError("Too many argument types") if not status.use_python_mode: with _fallback_context(status): legalize_given_types(args, return_type) # Type inference typemap, return_type, calltypes = type_inference_stage( typingctx, interp, args, return_type, locals) if status.fail_reason is not None: warnings.warn_explicit( 'Function "%s" failed type inference: %s' % (func_attr.name, status.fail_reason), config.NumbaWarning, func_attr.filename, func_attr.lineno) if not status.use_python_mode: with _fallback_context(status): legalize_return_type(return_type, interp, targetctx) if status.fail_reason is not None: warnings.warn_explicit( 'Function "%s" has invalid return type: %s' % (func_attr.name, status.fail_reason), config.NumbaWarning, func_attr.filename, func_attr.lineno) if status.use_python_mode and flags.enable_looplift: assert not lifted # Try loop lifting loop_flags = flags.copy() outer_flags = flags.copy() # Do not recursively loop lift outer_flags.unset('enable_looplift') loop_flags.unset('enable_looplift') if not flags.enable_pyobject_looplift: loop_flags.unset('enable_pyobject') def dispatcher_factory(loopbc): from . import dispatcher return dispatcher.LiftedLoop(loopbc, typingctx, targetctx, locals, loop_flags) entry, loops = looplifting.lift_loop(bc, dispatcher_factory) if loops: # Some loops were extracted cres = compile_bytecode(typingctx, targetctx, entry, args, return_type, outer_flags, locals, lifted=tuple(loops), func_attr=func_attr) return cres if status.use_python_mode: # Fallback typing: everything is a python object typemap = defaultdict(lambda: types.pyobject) calltypes = defaultdict(lambda: types.pyobject) return_type = types.pyobject type_annotation = type_annotations.TypeAnnotation(interp=interp, typemap=typemap, calltypes=calltypes, lifted=lifted) if config.ANNOTATE: print("ANNOTATION".center(80, '-')) print(type_annotation) print('=' * 80) ### Back-end: Generate LLVM IR from Numba IR, compile to machine code if status.use_python_mode: # Object mode compilation func, lmod, lfunc, fndesc = py_lowering_stage(targetctx, interp, flags.no_compile) if len(args) != nargs: # append missing args = tuple(args) + (types.pyobject, ) * (nargs - len(args)) else: # Native mode compilation func, lmod, lfunc, fndesc = native_lowering_stage( targetctx, interp, typemap, return_type, calltypes, flags.no_compile) signature = typing.signature(return_type, *args) assert lfunc.module is lmod cr = compile_result( typing_context=typingctx, target_context=targetctx, entry_point=func, typing_error=status.fail_reason, type_annotation=type_annotation, llvm_func=lfunc, llvm_module=lmod, signature=signature, objectmode=status.use_python_mode, lifted=lifted, fndesc=fndesc, ) # Warn if compiled function in object mode and force_pyobject not set if status.use_python_mode and not flags.force_pyobject: warn_msg = ('Function "{name}" was compiled in object mode ' 'without forceobj=True').format(name=func_attr.name) if len(lifted) > 0: warn_msg += ', but has lifted loops.' warnings.warn_explicit(warn_msg, config.NumbaWarning, func_attr.filename, func_attr.lineno) return cr
def _compile_core(typingctx, targetctx, bc, args, return_type, flags, locals, lifted, func_attr, status): ### Front-end: Analyze bytecode, generate Numba IR, infer types interp = translate_stage(bc) nargs = len(interp.argspec.args) if len(args) > nargs: raise TypeError("Too many argument types") if not status.use_python_mode: with _fallback_context(status): legalize_given_types(args, return_type) # Type inference typemap, return_type, calltypes = type_inference_stage(typingctx, interp, args, return_type, locals) if status.fail_reason is not None: warnings.warn_explicit('Function "%s" failed type inference: %s' % (func_attr.name, status.fail_reason), config.NumbaWarning, func_attr.filename, func_attr.lineno) if not status.use_python_mode: with _fallback_context(status): legalize_return_type(return_type, interp, targetctx) if status.fail_reason is not None: warnings.warn_explicit('Function "%s" has invalid return type: %s' % (func_attr.name, status.fail_reason), config.NumbaWarning, func_attr.filename, func_attr.lineno) if status.use_python_mode and flags.enable_looplift: assert not lifted # Try loop lifting loop_flags = flags.copy() outer_flags = flags.copy() # Do not recursively loop lift outer_flags.unset('enable_looplift') loop_flags.unset('enable_looplift') if not flags.enable_pyobject_looplift: loop_flags.unset('enable_pyobject') def dispatcher_factory(loopbc): from . import dispatcher return dispatcher.LiftedLoop(loopbc, typingctx, targetctx, locals, loop_flags) entry, loops = looplifting.lift_loop(bc, dispatcher_factory) if loops: # Some loops were extracted cres = compile_bytecode(typingctx, targetctx, entry, args, return_type, outer_flags, locals, lifted=tuple(loops), func_attr=func_attr) return cres if status.use_python_mode: # Fallback typing: everything is a python object typemap = defaultdict(lambda: types.pyobject) calltypes = defaultdict(lambda: types.pyobject) return_type = types.pyobject type_annotation = type_annotations.TypeAnnotation(interp=interp, typemap=typemap, calltypes=calltypes, lifted=lifted) if config.ANNOTATE: print("ANNOTATION".center(80, '-')) print(type_annotation) print('=' * 80) ### Back-end: Generate LLVM IR from Numba IR, compile to machine code if status.use_python_mode: # Object mode compilation func, lmod, lfunc, fndesc = py_lowering_stage(targetctx, interp, flags.no_compile) if len(args) != nargs: # append missing args = tuple(args) + (types.pyobject,) * (nargs - len(args)) else: # Native mode compilation func, lmod, lfunc, fndesc = native_lowering_stage(targetctx, interp, typemap, return_type, calltypes, flags.no_compile) signature = typing.signature(return_type, *args) assert lfunc.module is lmod cr = compile_result(typing_context=typingctx, target_context=targetctx, entry_point=func, typing_error=status.fail_reason, type_annotation=type_annotation, llvm_func=lfunc, llvm_module=lmod, signature=signature, objectmode=status.use_python_mode, lifted=lifted, fndesc=fndesc,) # Warn if compiled function in object mode and force_pyobject not set if status.use_python_mode and not flags.force_pyobject: warn_msg = ('Function "{name}" was compiled in object mode ' 'without forceobj=True').format(name=func_attr.name) if len(lifted) > 0: warn_msg += ', but has lifted loops.' warnings.warn_explicit(warn_msg, config.NumbaWarning, func_attr.filename, func_attr.lineno) return cr
def compile_bytecode(typingctx, targetctx, bc, args, return_type, flags, locals, lifted=()): interp = translate_stage(bc) nargs = len(interp.argspec.args) if len(args) > nargs: raise TypeError("Too many argument types") status = _CompileStatus() status.can_fallback = flags.enable_pyobject status.fail_reason = None status.use_python_mode = flags.force_pyobject targetctx = targetctx.localized() targetctx.metadata['wraparound'] = not flags.no_wraparound if not status.use_python_mode: with _fallback_context(status): legalize_given_types(args, return_type) # Type inference typemap, return_type, calltypes = type_inference_stage(typingctx, interp, args, return_type, locals) if not status.use_python_mode: with _fallback_context(status): legalize_return_type(return_type, interp, targetctx) if status.use_python_mode and flags.enable_looplift: assert not lifted # Try loop lifting entry, loops = looplifting.lift_loop(bc) if not loops: # No extracted loops pass else: loopflags = flags.copy() # Do not recursively loop lift loopflags.unset('enable_looplift') loopdisp = looplifting.bind(loops, typingctx, targetctx, locals, loopflags) lifted = tuple(loopdisp) cres = compile_bytecode(typingctx, targetctx, entry, args, return_type, loopflags, locals, lifted=lifted) return cres._replace(lifted=lifted) if status.use_python_mode: # Object mode compilation func, fnptr, lmod, lfunc, fndesc = py_lowering_stage(targetctx, interp, flags.no_compile) typemap = defaultdict(lambda: types.pyobject) calltypes = defaultdict(lambda: types.pyobject) return_type = types.pyobject if len(args) != nargs: # append missing args = tuple(args) + (types.pyobject,) * (nargs - len(args)) else: # Native mode compilation func, fnptr, lmod, lfunc, fndesc = native_lowering_stage(targetctx, interp, typemap, return_type, calltypes, flags.no_compile) type_annotation = type_annotations.TypeAnnotation(interp=interp, typemap=typemap, calltypes=calltypes, lifted=lifted) if config.ANNOTATE: print("ANNOTATION".center(80, '-')) print(type_annotation) print('=' * 80) signature = typing.signature(return_type, *args) assert lfunc.module is lmod cr = compile_result(typing_context=typingctx, target_context=targetctx, entry_point=func, entry_point_addr=fnptr, typing_error=status.fail_reason, type_annotation=type_annotation, llvm_func=lfunc, llvm_module=lmod, signature=signature, objectmode=status.use_python_mode, lifted=lifted, fndesc=fndesc,) return cr