@@ -288,6 +288,7 @@ void Dependences::addPrivatizationDependences() {
288
288
static __isl_give isl_union_flow *buildFlow (__isl_keep isl_union_map *Snk,
289
289
__isl_keep isl_union_map *Src,
290
290
__isl_keep isl_union_map *MaySrc,
291
+ __isl_keep isl_union_map *Kill,
291
292
__isl_keep isl_schedule *Schedule) {
292
293
isl_union_access_info *AI;
293
294
@@ -296,6 +297,8 @@ static __isl_give isl_union_flow *buildFlow(__isl_keep isl_union_map *Snk,
296
297
AI = isl_union_access_info_set_may_source (AI, isl_union_map_copy (MaySrc));
297
298
if (Src)
298
299
AI = isl_union_access_info_set_must_source (AI, isl_union_map_copy (Src));
300
+ if (Kill)
301
+ AI = isl_union_access_info_set_kill (AI, isl_union_map_copy (Kill));
299
302
AI = isl_union_access_info_set_schedule (AI, isl_schedule_copy (Schedule));
300
303
auto Flow = isl_union_access_info_compute_flow (AI);
301
304
LLVM_DEBUG (if (!Flow) dbgs ()
@@ -305,106 +308,6 @@ static __isl_give isl_union_flow *buildFlow(__isl_keep isl_union_map *Snk,
305
308
return Flow;
306
309
}
307
310
308
- // / Compute exact WAR dependences
309
- // / We need exact WAR dependences. That is, if there are
310
- // / dependences of the form:
311
- // / must-W2 (sink) <- must-W1 (sink) <- R (source)
312
- // / We wish to generate *ONLY*:
313
- // / { R -> W1 },
314
- // / NOT:
315
- // / { R -> W2, R -> W1 }
316
- // /
317
- // / However, in the case of may-writes, we do *not* wish to allow
318
- // / may-writes to block must-writes. This makes sense, since perhaps the
319
- // / may-write will not happen. In that case, the exact dependence will
320
- // / be the (read -> must-write).
321
- // / Example:
322
- // / must-W2 (sink) <- may-W1 (sink) <- R (source)
323
- // / We wish to generate:
324
- // / { R-> W1, R -> W2 }
325
- // /
326
- // / We use the fact that may dependences are not allowed to flow
327
- // / through a must source. That way, reads will be stopped by intermediate
328
- // / must-writes.
329
- // / However, may-sources may not interfere with one another. Hence, reads
330
- // / will not block each other from generating dependences.
331
- // /
332
- // / Write (Sink) <- MustWrite (Must-Source) <- Read (MaySource) is
333
- // / present, then the dependence
334
- // / { Write <- Read }
335
- // / is not tracked.
336
- // /
337
- // / We would like to specify the Must-Write as kills, source as Read
338
- // / and sink as Write.
339
- // / ISL does not have the functionality currently to support "kills".
340
- // / Use the Must-Source as a way to specify "kills".
341
- // / The drawback is that we will have both
342
- // / { Write <- MustWrite, Write <- Read }
343
- // /
344
- // / We need to filter this to track only { Write <- Read }.
345
- // /
346
- // / Filtering { Write <- Read } from WAROverestimated:
347
- // / --------------------------------------------------
348
- // / isl_union_flow_get_full_may_dependence gives us dependences of the form
349
- // / WAROverestimated = { Read+MustWrite -> [Write -> MemoryAccess]}
350
- // /
351
- // / We need to intersect the domain with Read to get only
352
- // / Read dependences.
353
- // / Read = { Read -> MemoryAccess }
354
- // /
355
- // /
356
- // / 1. Construct:
357
- // / WARMemAccesses = { Read+Write -> [Read+Write -> MemoryAccess] }
358
- // / This takes a Read+Write from WAROverestimated and maps it to the
359
- // / corresponding wrapped memory access from WAROverestimated.
360
- // /
361
- // / 2. Apply WARMemAcesses to the domain of WAR Overestimated to give:
362
- // / WAR = { [Read+Write -> MemoryAccess] -> [Write -> MemoryAccess] }
363
- // /
364
- // / WAR is in a state where we can intersect with Read, since they
365
- // / have the same structure.
366
- // /
367
- // / 3. Intersect this with a wrapped Read. Read is wrapped
368
- // / to ensure the domains look the same.
369
- // / WAR = WAR \intersect (wrapped Read)
370
- // / WAR = { [Read -> MemoryAccesss] -> [Write -> MemoryAccess] }
371
- // /
372
- // / 4. Project out the memory access in the domain to get
373
- // / WAR = { Read -> Write }
374
- static isl_union_map *buildWAR (isl_union_map *Write, isl_union_map *MustWrite,
375
- isl_union_map *Read, isl_schedule *Schedule) {
376
- isl_union_flow *Flow = buildFlow (Write, MustWrite, Read, Schedule);
377
- auto *WAROverestimated = isl_union_flow_get_full_may_dependence (Flow);
378
-
379
- // 1. Constructing WARMemAccesses
380
- // WarMemAccesses = { Read+Write -> [Write -> MemAccess] }
381
- // Range factor of range product
382
- // { Read+Write -> MemAcesss }
383
- // Domain projection
384
- // { [Read+Write -> MemAccess] -> Read+Write }
385
- // Reverse
386
- // { Read+Write -> [Read+Write -> MemAccess] }
387
- auto WARMemAccesses =
388
- isl_union_map_range_factor_range (isl_union_map_copy (WAROverestimated));
389
- WARMemAccesses = isl_union_map_domain_map (WARMemAccesses);
390
- WARMemAccesses = isl_union_map_reverse (WARMemAccesses);
391
-
392
- // 2. Apply to get domain tagged with memory accesses
393
- isl_union_map *WAR =
394
- isl_union_map_apply_domain (WAROverestimated, WARMemAccesses);
395
-
396
- // 3. Intersect with Read to extract only reads
397
- auto ReadWrapped = isl_union_map_wrap (isl_union_map_copy (Read));
398
- WAR = isl_union_map_intersect_domain (WAR, ReadWrapped);
399
-
400
- // 4. Project out memory accesses to get usual style dependences
401
- WAR = isl_union_map_range_factor_domain (WAR);
402
- WAR = isl_union_map_domain_factor_domain (WAR);
403
-
404
- isl_union_flow_free (Flow);
405
- return WAR;
406
- }
407
-
408
311
void Dependences::calculateDependences (Scop &S) {
409
312
isl_union_map *Read, *MustWrite, *MayWrite, *ReductionTagMap;
410
313
isl_schedule *Schedule;
@@ -530,44 +433,43 @@ void Dependences::calculateDependences(Scop &S) {
530
433
// }
531
434
// }
532
435
533
- isl_union_flow *Flow = buildFlow (Write, Write, Read, Schedule);
436
+ isl_union_flow *Flow = buildFlow (Write, Write, Read, nullptr , Schedule);
534
437
StrictWAW = isl_union_flow_get_must_dependence (Flow);
535
438
isl_union_flow_free (Flow);
536
439
537
440
if (OptAnalysisType == VALUE_BASED_ANALYSIS) {
538
- Flow = buildFlow (Read, MustWrite, MayWrite, Schedule);
441
+ Flow = buildFlow (Read, MustWrite, MayWrite, nullptr , Schedule);
539
442
RAW = isl_union_flow_get_may_dependence (Flow);
540
443
isl_union_flow_free (Flow);
541
444
542
- Flow = buildFlow (Write, MustWrite, MayWrite, Schedule);
445
+ Flow = buildFlow (Write, MustWrite, MayWrite, nullptr , Schedule);
543
446
WAW = isl_union_flow_get_may_dependence (Flow);
544
447
isl_union_flow_free (Flow);
545
448
546
- WAR = buildWAR (Write, MustWrite, Read, Schedule);
547
- isl_union_map_free (Write);
548
- isl_schedule_free (Schedule);
449
+ // ISL now supports "kills" in approximate dataflow analysis, we can
450
+ // specify the MustWrite as kills, Read as source and Write as sink.
451
+ Flow = buildFlow (Write, nullptr , Read, MustWrite, Schedule);
452
+ WAR = isl_union_flow_get_may_dependence (Flow);
453
+ isl_union_flow_free (Flow);
549
454
} else {
550
- isl_union_flow *Flow;
551
-
552
- Flow = buildFlow (Read, nullptr , Write, Schedule);
455
+ Flow = buildFlow (Read, nullptr , Write, nullptr , Schedule);
553
456
RAW = isl_union_flow_get_may_dependence (Flow);
554
457
isl_union_flow_free (Flow);
555
458
556
- Flow = buildFlow (Write, nullptr , Read, Schedule);
459
+ Flow = buildFlow (Write, nullptr , Read, nullptr , Schedule);
557
460
WAR = isl_union_flow_get_may_dependence (Flow);
558
461
isl_union_flow_free (Flow);
559
462
560
- Flow = buildFlow (Write, nullptr , Write, Schedule);
463
+ Flow = buildFlow (Write, nullptr , Write, nullptr , Schedule);
561
464
WAW = isl_union_flow_get_may_dependence (Flow);
562
465
isl_union_flow_free (Flow);
563
-
564
- isl_union_map_free (Write);
565
- isl_schedule_free (Schedule);
566
466
}
567
467
468
+ isl_union_map_free (Write);
568
469
isl_union_map_free (MustWrite);
569
470
isl_union_map_free (MayWrite);
570
471
isl_union_map_free (Read);
472
+ isl_schedule_free (Schedule);
571
473
572
474
RAW = isl_union_map_coalesce (RAW);
573
475
WAW = isl_union_map_coalesce (WAW);
0 commit comments