@@ -288,6 +288,7 @@ void Dependences::addPrivatizationDependences() {
288288static __isl_give isl_union_flow *buildFlow (__isl_keep isl_union_map *Snk,
289289 __isl_keep isl_union_map *Src,
290290 __isl_keep isl_union_map *MaySrc,
291+ __isl_keep isl_union_map *Kill,
291292 __isl_keep isl_schedule *Schedule) {
292293 isl_union_access_info *AI;
293294
@@ -296,6 +297,8 @@ static __isl_give isl_union_flow *buildFlow(__isl_keep isl_union_map *Snk,
296297 AI = isl_union_access_info_set_may_source (AI, isl_union_map_copy (MaySrc));
297298 if (Src)
298299 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));
299302 AI = isl_union_access_info_set_schedule (AI, isl_schedule_copy (Schedule));
300303 auto Flow = isl_union_access_info_compute_flow (AI);
301304 LLVM_DEBUG (if (!Flow) dbgs ()
@@ -305,106 +308,6 @@ static __isl_give isl_union_flow *buildFlow(__isl_keep isl_union_map *Snk,
305308 return Flow;
306309}
307310
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-
408311void Dependences::calculateDependences (Scop &S) {
409312 isl_union_map *Read, *MustWrite, *MayWrite, *ReductionTagMap;
410313 isl_schedule *Schedule;
@@ -530,44 +433,43 @@ void Dependences::calculateDependences(Scop &S) {
530433 // }
531434 // }
532435
533- isl_union_flow *Flow = buildFlow (Write, Write, Read, Schedule);
436+ isl_union_flow *Flow = buildFlow (Write, Write, Read, nullptr , Schedule);
534437 StrictWAW = isl_union_flow_get_must_dependence (Flow);
535438 isl_union_flow_free (Flow);
536439
537440 if (OptAnalysisType == VALUE_BASED_ANALYSIS) {
538- Flow = buildFlow (Read, MustWrite, MayWrite, Schedule);
441+ Flow = buildFlow (Read, MustWrite, MayWrite, nullptr , Schedule);
539442 RAW = isl_union_flow_get_may_dependence (Flow);
540443 isl_union_flow_free (Flow);
541444
542- Flow = buildFlow (Write, MustWrite, MayWrite, Schedule);
445+ Flow = buildFlow (Write, MustWrite, MayWrite, nullptr , Schedule);
543446 WAW = isl_union_flow_get_may_dependence (Flow);
544447 isl_union_flow_free (Flow);
545448
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);
549454 } else {
550- isl_union_flow *Flow;
551-
552- Flow = buildFlow (Read, nullptr , Write, Schedule);
455+ Flow = buildFlow (Read, nullptr , Write, nullptr , Schedule);
553456 RAW = isl_union_flow_get_may_dependence (Flow);
554457 isl_union_flow_free (Flow);
555458
556- Flow = buildFlow (Write, nullptr , Read, Schedule);
459+ Flow = buildFlow (Write, nullptr , Read, nullptr , Schedule);
557460 WAR = isl_union_flow_get_may_dependence (Flow);
558461 isl_union_flow_free (Flow);
559462
560- Flow = buildFlow (Write, nullptr , Write, Schedule);
463+ Flow = buildFlow (Write, nullptr , Write, nullptr , Schedule);
561464 WAW = isl_union_flow_get_may_dependence (Flow);
562465 isl_union_flow_free (Flow);
563-
564- isl_union_map_free (Write);
565- isl_schedule_free (Schedule);
566466 }
567467
468+ isl_union_map_free (Write);
568469 isl_union_map_free (MustWrite);
569470 isl_union_map_free (MayWrite);
570471 isl_union_map_free (Read);
472+ isl_schedule_free (Schedule);
571473
572474 RAW = isl_union_map_coalesce (RAW);
573475 WAW = isl_union_map_coalesce (WAW);
0 commit comments