Skip to content

Commit 0ca76a7

Browse files
committed
Refactor for modularity
1 parent 77acdbd commit 0ca76a7

17 files changed

+7968
-7791
lines changed

src/numba/openmp/__init__.py

Lines changed: 54 additions & 7791 deletions
Large diffs are not rendered by default.

src/numba/openmp/analysis.py

Lines changed: 252 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,252 @@
1+
from numba.core import ir, types, typing
2+
from numba.core.analysis import _fix_loop_exit, compute_cfg_from_blocks
3+
from numba.core.ir_utils import visit_vars
4+
from numba.extending import overload, intrinsic
5+
6+
7+
def remove_ssa(var_name, scope, loc):
8+
# Get the base name of a variable, removing the SSA extension.
9+
var = ir.Var(scope, var_name, loc)
10+
return var.unversioned_name
11+
12+
13+
def user_defined_var(var):
14+
if not isinstance(var, str):
15+
return False
16+
return not var.startswith("$")
17+
18+
19+
def is_dsa(name):
20+
return (
21+
name
22+
in [
23+
"QUAL.OMP.FIRSTPRIVATE",
24+
"QUAL.OMP.PRIVATE",
25+
"QUAL.OMP.SHARED",
26+
"QUAL.OMP.LASTPRIVATE",
27+
"QUAL.OMP.TARGET.IMPLICIT",
28+
]
29+
or name.startswith("QUAL.OMP.REDUCTION")
30+
or name.startswith("QUAL.OMP.MAP")
31+
)
32+
33+
34+
def is_private(x):
35+
return x in [
36+
"QUAL.OMP.PRIVATE",
37+
"QUAL.OMP.FIRSTPRIVATE",
38+
"QUAL.OMP.LASTPRIVATE",
39+
"QUAL.OMP.TARGET.IMPLICIT",
40+
]
41+
42+
43+
def is_internal_var(var):
44+
# Determine if a var is a Python var or an internal Numba var.
45+
if var.is_temp:
46+
return True
47+
return var.unversioned_name != var.name
48+
49+
50+
def has_user_defined_var(the_set):
51+
for x in the_set:
52+
if user_defined_var(x):
53+
return True
54+
return False
55+
56+
57+
def get_user_defined_var(the_set):
58+
ret = set()
59+
for x in the_set:
60+
if user_defined_var(x):
61+
ret.add(x)
62+
return ret
63+
64+
65+
def get_enclosing_region(func_ir, cur_block):
66+
if not hasattr(func_ir, "openmp_enclosing"):
67+
func_ir.openmp_enclosing = {}
68+
if cur_block in func_ir.openmp_enclosing:
69+
return func_ir.openmp_enclosing[cur_block]
70+
else:
71+
return None
72+
73+
74+
def add_enclosing_region(func_ir, blocks, openmp_node):
75+
if not hasattr(func_ir, "openmp_enclosing"):
76+
func_ir.openmp_enclosing = {}
77+
if not hasattr(func_ir, "openmp_regions"):
78+
func_ir.openmp_regions = {}
79+
func_ir.openmp_regions[openmp_node] = sorted(blocks)
80+
for b in blocks:
81+
if b not in func_ir.openmp_enclosing:
82+
func_ir.openmp_enclosing[b] = []
83+
func_ir.openmp_enclosing[b].append(openmp_node)
84+
85+
86+
def filter_nested_loops(cfg, loops):
87+
blocks_in_loop = set()
88+
# get loop bodies
89+
for loop in loops.values():
90+
insiders = set(loop.body) | set(loop.entries) | set(loop.exits)
91+
insiders.discard(loop.header)
92+
blocks_in_loop |= insiders
93+
# find loop that is not part of other loops
94+
for loop in loops.values():
95+
if loop.header not in blocks_in_loop:
96+
yield _fix_loop_exit(cfg, loop)
97+
98+
99+
def remove_privatized(x):
100+
if isinstance(x, ir.Var):
101+
x = x.name
102+
103+
if isinstance(x, str) and x.endswith("%privatized"):
104+
return x[: len(x) - len("%privatized")]
105+
else:
106+
return x
107+
108+
109+
def get_var_from_enclosing(enclosing_regions, var):
110+
if not enclosing_regions:
111+
return None
112+
if len(enclosing_regions) == 0:
113+
return None
114+
return enclosing_regions[-1].get_var_dsa(var)
115+
116+
117+
def remove_indirections(clause):
118+
try:
119+
while len(clause) == 1 and isinstance(clause[0], list):
120+
clause = clause[0]
121+
except:
122+
pass
123+
return clause
124+
125+
126+
def add_tags_to_enclosing(func_ir, cur_block, tags):
127+
enclosing_region = get_enclosing_region(func_ir, cur_block)
128+
if enclosing_region:
129+
for region in enclosing_region:
130+
for tag in tags:
131+
region.add_tag(tag)
132+
133+
134+
def get_blocks_between_start_end(blocks, start_block, end_block):
135+
cfg = compute_cfg_from_blocks(blocks)
136+
blocks_in_region = [start_block]
137+
138+
def add_in_region(cfg, blk, blocks_in_region, end_block):
139+
"""For each successor in the CFG of the block we're currently
140+
adding to blocks_in_region, add that successor to
141+
blocks_in_region if it isn't the end_block. Then,
142+
recursively call this routine for the added block to add
143+
its successors.
144+
"""
145+
for out_blk, _ in cfg.successors(blk):
146+
if out_blk != end_block and out_blk not in blocks_in_region:
147+
blocks_in_region.append(out_blk)
148+
add_in_region(cfg, out_blk, blocks_in_region, end_block)
149+
150+
# Calculate all the Numba IR blocks in the target region.
151+
add_in_region(cfg, start_block, blocks_in_region, end_block)
152+
return blocks_in_region
153+
154+
155+
@intrinsic
156+
def get_itercount(typingctx, it):
157+
if isinstance(it, types.RangeIteratorType):
158+
sig = typing.signature(it.yield_type, it)
159+
160+
def codegen(context, builder, signature, args):
161+
assert len(args) == 1
162+
val = args[0]
163+
pair = context.make_helper(builder, it, val)
164+
return builder.load(pair.count)
165+
166+
return sig, codegen
167+
168+
169+
def remove_all_privatized(x):
170+
new_x = None
171+
while new_x != x:
172+
new_x = x
173+
x = remove_privatized(new_x)
174+
175+
return new_x
176+
177+
178+
def typemap_lookup(typemap, x):
179+
orig_x = x
180+
if isinstance(x, ir.Var):
181+
x = x.name
182+
183+
while True:
184+
if x in typemap:
185+
return typemap[x]
186+
new_x = remove_privatized(x)
187+
if new_x == x:
188+
break
189+
else:
190+
x = new_x
191+
192+
tkeys = typemap.keys()
193+
194+
# Get basename (without privatized)
195+
x = remove_all_privatized(x)
196+
197+
potential_keys = list(filter(lambda y: y.startswith(x), tkeys))
198+
199+
for pkey in potential_keys:
200+
pkey_base = remove_all_privatized(pkey)
201+
if pkey_base == x:
202+
return typemap[pkey]
203+
204+
raise KeyError(f"{orig_x} and all of its non-privatized names not found in typemap")
205+
206+
207+
def is_target_tag(x):
208+
ret = x.startswith("DIR.OMP.TARGET") and x not in [
209+
"DIR.OMP.TARGET.DATA",
210+
"DIR.OMP.TARGET.ENTER.DATA",
211+
"DIR.OMP.TARGET.EXIT.DATA",
212+
]
213+
return ret
214+
215+
216+
def is_target_arg(name):
217+
return (
218+
name in ["QUAL.OMP.FIRSTPRIVATE", "QUAL.OMP.TARGET.IMPLICIT"]
219+
or name.startswith("QUAL.OMP.MAP")
220+
or name.startswith("QUAL.OMP.REDUCTION")
221+
)
222+
223+
224+
def in_openmp_region(builder):
225+
if hasattr(builder, "_lowerer_push_alloca_callbacks"):
226+
return builder._lowerer_push_alloca_callbacks > 0
227+
else:
228+
return False
229+
230+
231+
def get_name_var_table(blocks):
232+
"""create a mapping from variable names to their ir.Var objects"""
233+
234+
def get_name_var_visit(var, namevar):
235+
namevar[var.name] = var
236+
return var
237+
238+
namevar = {}
239+
visit_vars(blocks, get_name_var_visit, namevar)
240+
return namevar
241+
242+
243+
def is_pointer_target_arg(name, typ):
244+
if name.startswith("QUAL.OMP.REDUCTION"):
245+
return True
246+
if name.startswith("QUAL.OMP.MAP"):
247+
return True
248+
if name in ["QUAL.OMP.TARGET.IMPLICIT"]:
249+
if isinstance(typ, types.npytypes.Array):
250+
return True
251+
252+
return False

0 commit comments

Comments
 (0)