Skip to content

Commit 1d8b0d4

Browse files
author
whitequark
committedMar 28, 2016
compiler: mark FFI functions as ModRef=Ref using TBAA metadata.
Fascinatingly, the fact that you can mark call instructions with !tbaa metadata is completely undocumented. Regardless, it is true: a !tbaa metadata for an "immutable" type will cause AliasAnalysis::getModRefBehavior to return OnlyReadsMemory for that call site. Don't bother marking loads with TBAA yet since we already place !load.invariant on them (which is as good as the TBAA "immutable" flag) and after that we're limited by lack of !nonnull anyway. Also, add TBAA analysis passes in our pipeline to actually engage it.
1 parent 418f0a5 commit 1d8b0d4

File tree

2 files changed

+22
-4
lines changed

2 files changed

+22
-4
lines changed
 

‎artiq/compiler/targets.py

+4
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,10 @@ def optimize(self, llmodule):
8989
llpassmgr = llvm.create_module_pass_manager()
9090
self.target_machine().target_data.add_pass(llpassmgr)
9191

92+
# Register our alias analysis passes.
93+
llpassmgr.add_basic_alias_analysis_pass()
94+
llpassmgr.add_type_based_alias_analysis_pass()
95+
9296
# Start by cleaning up after our codegen and exposing as much
9397
# information to LLVM as possible.
9498
llpassmgr.add_constant_merge_pass()

‎artiq/compiler/transforms/llvm_ir_generator.py

+18-4
Original file line numberDiff line numberDiff line change
@@ -181,6 +181,14 @@ def __init__(self, engine, module_name, target, function_map, object_map, type_m
181181
self.phis = []
182182
self.debug_info_emitter = DebugInfoEmitter(self.llmodule)
183183
self.empty_metadata = self.llmodule.add_metadata([])
184+
self.tbaa_tree = self.llmodule.add_metadata([
185+
ll.MetaDataString(self.llmodule, "ARTIQ TBAA")
186+
])
187+
self.tbaa_noalias_call = self.llmodule.add_metadata([
188+
ll.MetaDataString(self.llmodule, "non-aliasing function call"),
189+
self.tbaa_tree,
190+
ll.Constant(lli64, 1)
191+
])
184192

185193
def needs_sret(self, lltyp, may_be_large=True):
186194
if isinstance(lltyp, ll.VoidType):
@@ -1252,17 +1260,18 @@ def ret_error_handler(typ):
12521260
return llret
12531261

12541262
def process_Call(self, insn):
1255-
if types.is_rpc_function(insn.target_function().type):
1263+
functiontyp = insn.target_function().type
1264+
if types.is_rpc_function(functiontyp):
12561265
return self._build_rpc(insn.target_function().loc,
1257-
insn.target_function().type,
1266+
functiontyp,
12581267
insn.arguments(),
12591268
llnormalblock=None, llunwindblock=None)
1260-
elif types.is_c_function(insn.target_function().type):
1269+
elif types.is_c_function(functiontyp):
12611270
llfun, llargs = self._prepare_ffi_call(insn)
12621271
else:
12631272
llfun, llargs = self._prepare_closure_call(insn)
12641273

1265-
if self.has_sret(insn.target_function().type):
1274+
if self.has_sret(functiontyp):
12661275
llstackptr = self.llbuilder.call(self.llbuiltin("llvm.stacksave"), [])
12671276

12681277
llresultslot = self.llbuilder.alloca(llfun.type.pointee.args[0].pointee)
@@ -1276,6 +1285,11 @@ def process_Call(self, insn):
12761285
if insn.is_cold:
12771286
llcall.cconv = 'coldcc'
12781287

1288+
if types.is_c_function(functiontyp):
1289+
# All our global state is confined to our compilation unit,
1290+
# so by definition no FFI call can mutate it.
1291+
llcall.metadata['tbaa'] = self.tbaa_noalias_call
1292+
12791293
return llresult
12801294

12811295
def process_Invoke(self, insn):

0 commit comments

Comments
 (0)
Please sign in to comment.