Skip to content

Commit 1fe83fe

Browse files
committed
attempt at creating a new BB
1 parent 7e22f7e commit 1fe83fe

File tree

2 files changed

+94
-35
lines changed

2 files changed

+94
-35
lines changed

base/compiler/ssair/ir.jl

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -486,6 +486,13 @@ function insert_node!(ir::IRCode, pos::Int, @nospecialize(typ), @nospecialize(va
486486
return SSAValue(length(ir.stmts) + node.idx)
487487
end
488488

489+
function copy_inst!(ir::IRCode, to::Int, inst::Instruction, attach_after::Bool=false)
490+
node = add!(ir.new_nodes, to, attach_after)
491+
node[] = inst
492+
return SSAValue(length(ir.stmts) + node.idx)
493+
end
494+
495+
489496
# For bootstrapping
490497
function my_sortperm(v)
491498
p = Vector{Int}(undef, length(v))

base/compiler/ssair/passes.jl

Lines changed: 87 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1166,11 +1166,8 @@ end
11661166
struct LoopInfo
11671167
header::Int
11681168
latches::Vector{Int}
1169-
# exiting::Vector{Int}
1170-
# exits::Vector{Int}
11711169
blocks::Vector{Int}
11721170
end
1173-
# LoopInfo(header, latches, blocks) = LoopInfo(header, latches, Int[], Int[], blocks)
11741171

11751172
function construct_loopinfo(ir, domtree)
11761173
cfg = ir.cfg
@@ -1232,65 +1229,120 @@ function construct_loopinfo(ir, domtree)
12321229
end
12331230

12341231

1235-
function licm_pass!(ir, loops)
1232+
function licm_pass!(ir::IRCode, loops)
12361233
cfg = ir.cfg
1237-
ir = IncrementalCompact(ir)
1234+
12381235
# TODO: Processing order, we should proceess innermost to outermost loops,
1239-
# but we need to maintain LoopInfo under CFG changes.
1236+
staged_blocks = IdDict{Int, Vector{Int}}()
12401237
for (h, loop) in loops
12411238
# Find stmts that are invariant w.r.t this loop
12421239
invariant_stmts = Int[]
1243-
1240+
12441241
# TODO: Order to visit loops in: Innermost to outermost
12451242
for idx in loop.blocks
12461243
bb = cfg.blocks[idx]
1247-
for i in bb.stmts
1248-
stmt = ir[i]
1244+
for id in bb.stmts
1245+
stmt = ir.stmts[id][:inst]
12491246
if invariant_stmt(ir, loop, invariant_stmts, stmt)
12501247
# XXX: Need to account for, we either need
12511248
# to move the entire block or check ?reverse-dominance?
12521249
# if (x > 0)
12531250
# sqrt(x)
1254-
push!(invariant_stmts, i)
1251+
push!(invariant_stmts, id)
12551252
end
12561253
end
1254+
1255+
# Move stmts as far as possible
1256+
if haskey(staged_blocks, idx)
1257+
staged_stmts = staged_blocks[idx]
1258+
new_staged_stmts = Int[]
1259+
for (i, id) in enumerate(staged_stmts)
1260+
stmt = ir.stmts[id]
1261+
if invariant_stmt(ir, loop, invariant_stmts, stmt)
1262+
# XXX: Need to account for, we either need
1263+
# to move the entire block or check ?reverse-dominance?
1264+
# if (x > 0)
1265+
# sqrt(x)
1266+
push!(invariant_stmts, id)
1267+
else
1268+
push!(new_staged_stmts, id)
1269+
end
1270+
end
1271+
staged_blocks[idx] = new_staged_stmts
1272+
end
12571273
end
12581274

1259-
# XXX: Need to insert pre-header instead of dumping into predecessor
1275+
# isempty(invariant_stmts) && continue
1276+
staged_blocks[h] = invariant_stmts
1277+
end
1278+
1279+
# Now we no longer need a correct loop info / domtree and we can take the sledgehammer to the CFG/IR
1280+
irstream = ir.stmts
1281+
valmap = IdDict{Int, Int}()
1282+
for (h, loop) in loops
1283+
# Non-loop predecessors
12601284
header = cfg.blocks[loop.header]
1261-
predecessors = filter(bb->bb loop.latches, header.preds)
1285+
predecessors = filter(bb -> bb loop.latches, header.preds)
1286+
12621287
@assert length(predecessors) == 1
1263-
# FIXME: Need to insert pre-header instead
1264-
pre_header = predecessors[1]
1265-
1266-
1267-
insertion_point = SSAValue(last(cfg.blocks[pre_header].stmts))
1268-
valmap = IdDict{SSAValue, Core.Compiler.AnySSAValue}()
1269-
typesmap = types(ir)
1270-
for idx in invariant_stmts
1271-
stmt = ir[idx]
1272-
new_stmt = Core.Compiler.ssamap(stmt) do val
1273-
if haskey(valmap, val)
1274-
return valmap[val]
1288+
# XXX: If predecessors are more than one we might need to move PhiNodes
1289+
entry_bb = first(predecessors)
1290+
1291+
insertion_point = last(cfg.blocks[entry_bb].stmts)
1292+
# Copy invariant stmts to new BB
1293+
# start = length(irstream) + 1
1294+
for id in staged_blocks[h]
1295+
inst = irstream[id]
1296+
ssaval = copy_inst!(ir, insertion_point, inst, true)
1297+
inst[:inst] = ssaval
1298+
1299+
# Fixup SSAValue's
1300+
ir[ssaval] = Core.Compiler.ssamap(ir[ssaval]) do val
1301+
if haskey(valmap, val.id)
1302+
return valmap[val.id]
12751303
else
12761304
return val
12771305
end
12781306
end
1279-
typ = typesmap[idx]
1280-
new_ssaval = insert_node!(ir, insertion_point, typ, stmt) # XXX: lineinfo
1281-
ir[idx] = new_ssaval
1282-
valmap[SSAValue(idx)] = new_ssaval
1307+
1308+
valmap[id] = ssaval.id # record new SSAValue id
1309+
end
1310+
insert_node!(ir, insertion_point, Nothing, GotoNode(h), true)
1311+
1312+
# Insert pre-header into CFG
1313+
# push!(cfg.blocks, BasicBlock(StmtRange(start, length(irstream)), predecessors, Int[loop.header]))
1314+
push!(cfg.blocks, BasicBlock(StmtRange(-1, 0), predecessors, Int[loop.header]))
1315+
pre_header = length(cfg.blocks)
1316+
cfg.blocks[loop.header] = BasicBlock(header.stmts, [pre_header, loop.latches...], header.succs)
1317+
1318+
for pred in predecessors
1319+
bb = cfg.blocks[loop.header]
1320+
succs = map(bb->bb == loop.header ? pre_header : bb, bb.succs)
1321+
cfg.blocks[loop.header] = BasicBlock(bb.stmts, bb.preds, succs)
1322+
end
1323+
1324+
# CFG now looks right, time to fixup the terminators and phi nodes
1325+
for id in header.stmts
1326+
node = irstream[id]
1327+
stmt = node[:inst]
1328+
if stmt isa PhiNode
1329+
edges = Any[bb == entry_bb ? pre_header : bb for bb in stmt.edges]
1330+
node[:inst] = PhiNode(edges, stmt.values)
1331+
else
1332+
break
1333+
end
12831334
end
1335+
1336+
# XXX: How do we deal with implicit fallthrough?
1337+
# Need to fixup the terminators. Maybe domsort will cure all things
12841338
end
12851339

1286-
# Just run through the iterator without any processing
1287-
Core.Compiler.foreach(x -> nothing, ir) # x isa Pair{Int, Any}
1288-
return Core.Compiler.finish(ir)
1340+
# XXX: The cfg stmt ranges are all wrong
1341+
# Now domsort the IR so that everything is neat and tidy.
1342+
domtree = construct_domtree(cfg)
1343+
return domsort_ssa!(ir, domtree)
12891344
end
12901345

1291-
cfg(ir::IRCode) = ir.cfg
1292-
cfg(compact::IncrementalCompact) = cfg(compact.ir)
1293-
12941346
function invariant_stmt(ir, loop, invariant_stmts, stmt)
12951347
if stmt isa Expr
12961348
return invariant_expr(ir, loop, invariant_stmts, stmt)
@@ -1303,7 +1355,7 @@ function invariant(ir, loop, invariant_stmts, stmt)
13031355
return true
13041356
elseif stmt isa SSAValue
13051357
id = stmt.id
1306-
bb = block_for_inst(cfg(ir), id)
1358+
bb = block_for_inst(ir.cfg, id)
13071359
if bb loop.blocks
13081360
return true
13091361
end

0 commit comments

Comments
 (0)