diff --git a/artiq/compiler/targets.py b/artiq/compiler/targets.py index 42f5551b0..34f85d85f 100644 --- a/artiq/compiler/targets.py +++ b/artiq/compiler/targets.py @@ -89,6 +89,10 @@ class Target: llpassmgr = llvm.create_module_pass_manager() self.target_machine().target_data.add_pass(llpassmgr) + # Register our alias analysis passes. + llpassmgr.add_basic_alias_analysis_pass() + llpassmgr.add_type_based_alias_analysis_pass() + # Start by cleaning up after our codegen and exposing as much # information to LLVM as possible. llpassmgr.add_constant_merge_pass() diff --git a/artiq/compiler/transforms/llvm_ir_generator.py b/artiq/compiler/transforms/llvm_ir_generator.py index fcb3b5d85..5ae0c3faa 100644 --- a/artiq/compiler/transforms/llvm_ir_generator.py +++ b/artiq/compiler/transforms/llvm_ir_generator.py @@ -181,6 +181,14 @@ class LLVMIRGenerator: self.phis = [] self.debug_info_emitter = DebugInfoEmitter(self.llmodule) self.empty_metadata = self.llmodule.add_metadata([]) + self.tbaa_tree = self.llmodule.add_metadata([ + ll.MetaDataString(self.llmodule, "ARTIQ TBAA") + ]) + self.tbaa_noalias_call = self.llmodule.add_metadata([ + ll.MetaDataString(self.llmodule, "non-aliasing function call"), + self.tbaa_tree, + ll.Constant(lli64, 1) + ]) def needs_sret(self, lltyp, may_be_large=True): if isinstance(lltyp, ll.VoidType): @@ -1252,17 +1260,18 @@ class LLVMIRGenerator: return llret def process_Call(self, insn): - if types.is_rpc_function(insn.target_function().type): + functiontyp = insn.target_function().type + if types.is_rpc_function(functiontyp): return self._build_rpc(insn.target_function().loc, - insn.target_function().type, + functiontyp, insn.arguments(), llnormalblock=None, llunwindblock=None) - elif types.is_c_function(insn.target_function().type): + elif types.is_c_function(functiontyp): llfun, llargs = self._prepare_ffi_call(insn) else: llfun, llargs = self._prepare_closure_call(insn) - if self.has_sret(insn.target_function().type): + if self.has_sret(functiontyp): llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), []) llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee) @@ -1276,6 +1285,11 @@ class LLVMIRGenerator: if insn.is_cold: llcall.cconv = 'coldcc' + if types.is_c_function(functiontyp): + # All our global state is confined to our compilation unit, + # so by definition no FFI call can mutate it. + llcall.metadata['tbaa'] = self.tbaa_noalias_call + return llresult def process_Invoke(self, insn):