@@ -1166,11 +1166,8 @@ end
1166
1166
struct LoopInfo
1167
1167
header:: Int
1168
1168
latches:: Vector{Int}
1169
- # exiting::Vector{Int}
1170
- # exits::Vector{Int}
1171
1169
blocks:: Vector{Int}
1172
1170
end
1173
- # LoopInfo(header, latches, blocks) = LoopInfo(header, latches, Int[], Int[], blocks)
1174
1171
1175
1172
function construct_loopinfo (ir, domtree)
1176
1173
cfg = ir. cfg
@@ -1232,65 +1229,120 @@ function construct_loopinfo(ir, domtree)
1232
1229
end
1233
1230
1234
1231
1235
- function licm_pass! (ir, loops)
1232
+ function licm_pass! (ir:: IRCode , loops)
1236
1233
cfg = ir. cfg
1237
- ir = IncrementalCompact (ir)
1234
+
1238
1235
# 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}} ()
1240
1237
for (h, loop) in loops
1241
1238
# Find stmts that are invariant w.r.t this loop
1242
1239
invariant_stmts = Int[]
1243
-
1240
+
1244
1241
# TODO : Order to visit loops in: Innermost to outermost
1245
1242
for idx in loop. blocks
1246
1243
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 ]
1249
1246
if invariant_stmt (ir, loop, invariant_stmts, stmt)
1250
1247
# XXX : Need to account for, we either need
1251
1248
# to move the entire block or check ?reverse-dominance?
1252
1249
# if (x > 0)
1253
1250
# sqrt(x)
1254
- push! (invariant_stmts, i )
1251
+ push! (invariant_stmts, id )
1255
1252
end
1256
1253
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
1257
1273
end
1258
1274
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
1260
1284
header = cfg. blocks[loop. header]
1261
- predecessors = filter (bb-> bb ∉ loop. latches, header. preds)
1285
+ predecessors = filter (bb -> bb ∉ loop. latches, header. preds)
1286
+
1262
1287
@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]
1275
1303
else
1276
1304
return val
1277
1305
end
1278
1306
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
1283
1334
end
1335
+
1336
+ # XXX : How do we deal with implicit fallthrough?
1337
+ # Need to fixup the terminators. Maybe domsort will cure all things
1284
1338
end
1285
1339
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)
1289
1344
end
1290
1345
1291
- cfg (ir:: IRCode ) = ir. cfg
1292
- cfg (compact:: IncrementalCompact ) = cfg (compact. ir)
1293
-
1294
1346
function invariant_stmt (ir, loop, invariant_stmts, stmt)
1295
1347
if stmt isa Expr
1296
1348
return invariant_expr (ir, loop, invariant_stmts, stmt)
@@ -1303,7 +1355,7 @@ function invariant(ir, loop, invariant_stmts, stmt)
1303
1355
return true
1304
1356
elseif stmt isa SSAValue
1305
1357
id = stmt. id
1306
- bb = block_for_inst (cfg (ir) , id)
1358
+ bb = block_for_inst (ir . cfg , id)
1307
1359
if bb ∉ loop. blocks
1308
1360
return true
1309
1361
end
0 commit comments