67 SmallVector<Activity> inActivity(
68 uop.getActivity().template getAsValueRange<ActivityAttr>());
69 SmallVector<Activity> retActivity(
70 uop.getRetActivity().template getAsValueRange<ActivityAttr>());
71 SmallVector<Value> in_args = uop.getPrimalInputs();
82 SourceOp callerOp, FunctionOpInterface innerFnOp,
83 const SmallVector<MemoryEffects::EffectInstance> &innerEffects) {
84 SmallVector<MemoryEffects::EffectInstance> outerEffects;
85 for (
auto &eff : innerEffects) {
87 Value effVal = eff.getValue();
90 outerEffects.push_back(eff);
95 size_t primalArgPos = 0;
96 bool foundPrimal =
false;
97 if (
auto effBA = dyn_cast<BlockArgument>(effVal)) {
98 if (llvm::is_contained(innerFnOp.getArguments(), effBA)) {
100 primalArgPos = effBA.getArgNumber();
113 Value primalVal = callerOp.getPrimalInputs()[primalArgPos];
114 outerEffects.push_back(
123 (cast<ActivityAttr>(callerOp.getActivity()[primalArgPos]).getValue() ==
124 Activity::enzyme_dup) ||
125 (cast<ActivityAttr>(callerOp.getActivity()[primalArgPos]).getValue() ==
126 Activity::enzyme_dupnoneed);
130 for (
auto [idx, act] : llvm::enumerate(callerOp.getActivity())) {
131 auto iattr = cast<ActivityAttr>(act);
132 auto act_val = iattr.getValue();
135 if (idx == primalArgPos)
138 if (act_val == Activity::enzyme_dup ||
139 act_val == Activity::enzyme_dupnoneed) {
144 Value dVal = callerOp.getInputs()[gradArgPos];
146 if constexpr (std::is_same_v<SourceOp, ForwardDiffOp>) {
147 outerEffects.push_back(
151 dVal, MemoryEffects::Write::get(), eff.getResource()));
153 dVal, MemoryEffects::Read::get(), eff.getResource()));
165 SmallVector<SourceOp> &allDiffs) {
166 SmallVector<SourceOp, 2> prunedSources;
171 auto firstDiffOp = allDiffs[0];
172 for (
auto uop : allDiffs) {
174 auto diffArgs = uop.getShadows();
175 if constexpr (std::is_same_v<SourceOp, AutoDiffOp>) {
176 auto diffeRet = uop.getDifferentialReturns();
177 diffArgs.append(diffeRet.begin(), diffeRet.end());
180 bool definedBeforeFirst =
true;
182 for (
auto diffVal : diffArgs) {
183 if (
auto diffValOR = dyn_cast<OpResult>(diffVal)) {
185 auto parentOp = diffValOR.getOwner();
186 if (!parentOp->isBeforeInBlock(firstDiffOp.getOperation())) {
187 definedBeforeFirst =
false;
193 if (definedBeforeFirst) {
194 prunedSources.push_back(uop);
198 return prunedSources;
207 SmallVector<SourceOp> &prunedSources,
208 DenseMap<SourceOp, SmallVector<MemoryEffects::EffectInstance>>
210 llvm::DenseMap<FunctionOpInterface,
211 SmallVector<MemoryEffects::EffectInstance>>
220 if (callerEffectMap.empty()) {
222 return prunedSources;
225 SmallVector<SourceOp> legalMerge;
226 auto lastOp = prunedSources[0];
228 SmallVector<MemoryEffects::EffectInstance, 4> betweenEffects;
229 for (
auto candidateOp : prunedSources) {
232 for (Operation *curr = lastOp.getOperation();
233 curr != candidateOp.getOperation(); curr = curr->getNextNode()) {
234 auto currSourceOp = dyn_cast<SourceOp>(curr);
235 if (currSourceOp && callerEffectMap.contains(currSourceOp)) {
238 betweenEffects.append(callerEffectMap[currSourceOp]);
239 }
else if (
auto currFwdOp = dyn_cast<ForwardDiffOp>(curr)) {
241 auto fnOp = dyn_cast_or_null<FunctionOpInterface>(
242 symbolTable.lookupNearestSymbolFrom(currFwdOp,
243 currFwdOp.getFnAttr()));
247 if (!innerEffectCache.contains(fnOp)) {
253 currFwdOp, fnOp, innerEffectCache[fnOp]));
254 }
else if (
auto currBwdOp = dyn_cast<AutoDiffOp>(curr)) {
256 auto fnOp = dyn_cast_or_null<FunctionOpInterface>(
257 symbolTable.lookupNearestSymbolFrom(currBwdOp,
258 currBwdOp.getFnAttr()));
262 if (!innerEffectCache.contains(fnOp)) {
268 currBwdOp, fnOp, innerEffectCache[fnOp]));
273 SmallVector<MemoryEffects::EffectInstance> currOpEffects;
275 betweenEffects.append(currOpEffects);
283 bool foundConflict =
false;
284 for (
auto candidateEffect : callerEffectMap[candidateOp]) {
285 for (
auto prevEffect : betweenEffects) {
290 if ((isa<MemoryEffects::Write>(prevEffect.getEffect()) &&
291 isa<MemoryEffects::Read>(candidateEffect.getEffect())) ||
292 (isa<MemoryEffects::Read>(prevEffect.getEffect()) &&
293 isa<MemoryEffects::Write>(candidateEffect.getEffect())) ||
294 (isa<MemoryEffects::Write>(prevEffect.getEffect()) &&
295 isa<MemoryEffects::Write>(candidateEffect.getEffect()))) {
300 foundConflict =
true;
308 legalMerge.push_back(candidateOp);
311 lastOp = candidateOp;