diff --git a/enzyme/Enzyme/MLIR/Analysis/ActivityAnnotations.cpp b/enzyme/Enzyme/MLIR/Analysis/ActivityAnnotations.cpp index dd860cf02ec3..d0fb9e339f46 100644 --- a/enzyme/Enzyme/MLIR/Analysis/ActivityAnnotations.cpp +++ b/enzyme/Enzyme/MLIR/Analysis/ActivityAnnotations.cpp @@ -1,5 +1,6 @@ #include "ActivityAnnotations.h" #include "AliasAnalysis.h" +#include "Dialect/Dialect.h" #include "Dialect/Ops.h" #include "Lattice.h" @@ -17,10 +18,6 @@ using namespace mlir; -static StringRef getActivityAnnotationAttrName() { return "activedeps"; } -static StringRef getPointerSummaryAttrName() { return "p2psummary"; } -static StringRef getReturnOriginsAttrName() { return "returnorigins"; } - template void printSetLattice(const enzyme::SparseSetLattice &setLattice, raw_ostream &os) { @@ -184,8 +181,8 @@ void enzyme::ForwardActivityAnnotationAnalysis::visitExternalCall( if (auto callee = SymbolTable::lookupNearestSymbolFrom( call, symbol.getLeafReference())) { - if (auto returnOriginsAttr = - callee->getAttrOfType(getReturnOriginsAttrName())) { + if (auto returnOriginsAttr = callee->getAttrOfType( + EnzymeDialect::getSparseActivityAnnotationAttrName())) { SmallVector returnOrigins; deserializeReturnOrigins(returnOriginsAttr, returnOrigins); return processCallToSummarizedFunc(call, returnOrigins, operands, @@ -286,8 +283,8 @@ void enzyme::BackwardActivityAnnotationAnalysis::visitExternalCall( if (auto callee = SymbolTable::lookupNearestSymbolFrom( call, symbol.getLeafReference())) { - if (auto returnOriginsAttr = - callee->getAttrOfType(getReturnOriginsAttrName())) { + if (auto returnOriginsAttr = callee->getAttrOfType( + EnzymeDialect::getSparseActivityAnnotationAttrName())) { SmallVector returnOrigins; deserializeReturnOrigins(returnOriginsAttr, returnOrigins); return processCallToSummarizedFunc(call, returnOrigins, operands, @@ -513,7 +510,7 @@ void enzyme::DenseActivityAnnotationAnalysis::visitCallControlFlowTransfer( if (auto callee = SymbolTable::lookupNearestSymbolFrom( call, symbol.getLeafReference())) { if (auto summaryAttr = callee->getAttrOfType( - getActivityAnnotationAttrName())) { + EnzymeDialect::getDenseActivityAnnotationAttrName())) { DenseMap summary; deserializePointsTo(summaryAttr, summary); return processCallToSummarizedFunc(call, summary, before, after); @@ -634,7 +631,7 @@ void enzyme::DenseBackwardActivityAnnotationAnalysis:: if (auto callee = SymbolTable::lookupNearestSymbolFrom( call, symbol.getLeafReference())) { if (auto summaryAttr = callee->getAttrOfType( - getActivityAnnotationAttrName())) { + EnzymeDialect::getDenseActivityAnnotationAttrName())) { DenseMap summary; deserializePointsTo(summaryAttr, summary); return processCallToSummarizedFunc(call, summary, after, before); @@ -859,8 +856,9 @@ void enzyme::runActivityAnnotations(FunctionOpInterface callee) { reverseToposortCallgraph(callee, &symbolTable, sorted); raw_ostream &os = llvm::outs(); + StringRef pointerSummaryName = EnzymeDialect::getPointerSummaryAttrName(); for (CallableOpInterface node : sorted) { - if (!node.getCallableRegion() || node->hasAttr(getPointerSummaryAttrName())) + if (!node.getCallableRegion() || node->hasAttr(pointerSummaryName)) continue; auto funcOp = cast(node.getOperation()); os << "[ata] processing function @" << funcOp.getName() << "\n"; @@ -887,7 +885,7 @@ void enzyme::runActivityAnnotations(FunctionOpInterface callee) { // Create the overall summary by joining sets at all return sites. enzyme::PointsToSets p2sets(nullptr); - enzyme::ForwardOriginsMap voMap(nullptr); + enzyme::ForwardOriginsMap forwardOriginsMap(nullptr); size_t numResults = node.getResultTypes().size(); SmallVector returnOperandOrigins( numResults, ForwardOriginsLattice(nullptr)); @@ -900,7 +898,7 @@ void enzyme::runActivityAnnotations(FunctionOpInterface callee) { auto *returnOrigins = solver.lookupState(&op); if (returnOrigins) - (void)voMap.join(*returnOrigins); + (void)forwardOriginsMap.join(*returnOrigins); for (OpOperand &operand : op.getOpOperands()) { (void)returnAliasClasses[operand.getOperandNumber()].join( @@ -918,37 +916,39 @@ void enzyme::runActivityAnnotations(FunctionOpInterface callee) { // os << "[debug] backward state for arg " << arg.getArgNumber() << ": " // << *backwardState << "\n"; // } + SmallVector aliasAttributes(returnAliasClasses.size()); + llvm::transform(returnAliasClasses, aliasAttributes.begin(), + [&](enzyme::AliasClassLattice lattice) { + return lattice.serialize(node.getContext()); + }); + node->setAttr(EnzymeDialect::getAliasSummaryAttrName(), + ArrayAttr::get(node.getContext(), aliasAttributes)); - for (auto lattice : returnAliasClasses) { - os << "[debug] return alias class: " << lattice << "\n"; - } - - node->setAttr(getPointerSummaryAttrName(), - p2sets.serialize(node.getContext())); + node->setAttr(pointerSummaryName, p2sets.serialize(node.getContext())); os << "[ata] p2p summary:\n"; - if (node->getAttrOfType(getPointerSummaryAttrName()).size() == - 0) { + if (node->getAttrOfType(pointerSummaryName).size() == 0) { os << " \n"; } - for (ArrayAttr pair : - node->getAttrOfType(getPointerSummaryAttrName()) - .getAsRange()) { + for (ArrayAttr pair : node->getAttrOfType(pointerSummaryName) + .getAsRange()) { os << " " << pair[0] << " -> " << pair[1] << "\n"; } - node->setAttr(getActivityAnnotationAttrName(), - voMap.serialize(node.getContext())); + node->setAttr(EnzymeDialect::getDenseActivityAnnotationAttrName(), + forwardOriginsMap.serialize(node.getContext())); os << "[ata] forward value origins:\n"; for (ArrayAttr pair : - node->getAttrOfType(getActivityAnnotationAttrName()) + node->getAttrOfType( + EnzymeDialect::getDenseActivityAnnotationAttrName()) .getAsRange()) { os << " " << pair[0] << " originates from " << pair[1] << "\n"; } - auto *backwardOriginMap = + auto *backwardOriginsMap = solver.getOrCreateState( &node.getCallableRegion()->front().front()); - Attribute backwardOrigins = backwardOriginMap->serialize(node.getContext()); + Attribute backwardOrigins = + backwardOriginsMap->serialize(node.getContext()); os << "[ata] backward value origins:\n"; for (ArrayAttr pair : cast(backwardOrigins).getAsRange()) { @@ -965,22 +965,42 @@ void enzyme::runActivityAnnotations(FunctionOpInterface callee) { return lattice.serialize(ctx); }); node->setAttr( - getReturnOriginsAttrName(), + EnzymeDialect::getSparseActivityAnnotationAttrName(), ArrayAttr::get(node.getContext(), serializedReturnOperandOrigins)); - os << "[ata] return origins: " << node->getAttr(getReturnOriginsAttrName()) + os << "[ata] return origins: " + << node->getAttr(EnzymeDialect::getSparseActivityAnnotationAttrName()) << "\n"; node.getCallableRegion()->walk([&](Operation *op) { if (op->hasAttr("tag")) { for (OpResult result : op->getResults()) { - auto *sources = - solver.getOrCreateState(result); - auto *sinks = - solver.getOrCreateState(result); - os << op->getAttr("tag") << "(#" << result.getResultNumber() - << ") sources:\n" - << *sources << "sinks:\n" - << *sinks << "\n"; + auto *aliasClasses = + solver.getOrCreateState(result); + if (aliasClasses->isUndefined()) { + // Not a pointer, check the sources and sinks from the sparse state + auto *sources = + solver.getOrCreateState(result); + auto *sinks = + solver.getOrCreateState(result); + os << op->getAttr("tag") << "(#" << result.getResultNumber() + << ")\n" + << " sources: " << sources->serialize(ctx) << "\n" + << " sinks: " << sinks->serialize(ctx) << "\n"; + } else { + // Is a pointer, see the origins of whatever it points to + ForwardOriginsLattice sources(result, ValueOriginSet()); + BackwardOriginsLattice sinks(result, ValueOriginSet()); + traversePointsToSets( + aliasClasses->getAliasClassesObject(), p2sets, + [&](DistinctAttr aliasClass) { + (void)sources.merge(forwardOriginsMap.getOrigins(aliasClass)); + (void)sinks.merge(backwardOriginsMap->getOrigins(aliasClass)); + }); + os << op->getAttr("tag") << "(#" << result.getResultNumber() + << ")\n" + << " sources: " << sources.serialize(ctx) << "\n" + << " sinks: " << sinks.serialize(ctx) << "\n"; + } } } }); diff --git a/enzyme/Enzyme/MLIR/Analysis/AliasAnalysis.cpp b/enzyme/Enzyme/MLIR/Analysis/AliasAnalysis.cpp index 91219e736520..4d2731caadf3 100644 --- a/enzyme/Enzyme/MLIR/Analysis/AliasAnalysis.cpp +++ b/enzyme/Enzyme/MLIR/Analysis/AliasAnalysis.cpp @@ -24,6 +24,7 @@ // //===----------------------------------------------------------------------===// #include "AliasAnalysis.h" +#include "Dialect/Dialect.h" #include "Dialect/Ops.h" #include "mlir/Analysis/AliasAnalysis.h" @@ -629,7 +630,8 @@ void enzyme::PointsToPointerAnalysis::visitCallControlFlowTransfer( // into pointers that are non-arguments. if (auto callee = SymbolTable::lookupNearestSymbolFrom( call, symbol.getLeafReference())) { - if (auto summaryAttr = callee->getAttrOfType("p2psummary")) { + if (auto summaryAttr = callee->getAttrOfType( + EnzymeDialect::getPointerSummaryAttrName())) { DenseMap summary; deserializePointsTo(summaryAttr, summary); return processCallToSummarizedFunc(call, summary, after); @@ -1127,6 +1129,28 @@ void enzyme::AliasAnalysis::visitOperation( } } +static void +deserializeAliasSummary(ArrayAttr summary, + SmallVectorImpl &out) { + for (Attribute element : summary) { + if (auto strAttr = dyn_cast(element)) { + if (strAttr.getValue() == "") { + out.push_back(enzyme::AliasClassSet::getUnknown()); + } else { + assert(strAttr.getValue() == ""); + out.push_back(enzyme::AliasClassSet::getUndefined()); + } + } else { + enzyme::AliasClassSet aliasClasses; + for (DistinctAttr aliasClass : + cast(element).getAsRange()) { + (void)aliasClasses.insert({aliasClass}); + } + out.push_back(aliasClasses); + } + } +} + void enzyme::AliasAnalysis::visitExternalCall( CallOpInterface call, ArrayRef operands, ArrayRef results) { @@ -1155,6 +1179,42 @@ void enzyme::AliasAnalysis::visitExternalCall( if (!callee) return markResultsUnknown(); + if (auto aliasSummaryAttr = callee->getAttrOfType( + EnzymeDialect::getAliasSummaryAttrName())) { + // The summary tells us what operands may alias with what results + SmallVector aliasSummary; + deserializeAliasSummary(aliasSummaryAttr, aliasSummary); + + assert(results.size() == aliasSummary.size()); + for (auto &&[i, resultSummary] : llvm::enumerate(aliasSummary)) { + // Would be nice to zip over results and aliasSummary, but requires + // capture of structured binding (may require a newer clang version) + AliasClassLattice *result = results[i]; + ChangeResult changed = ChangeResult::NoChange; + if (resultSummary.isUndefined()) + continue; + if (resultSummary.isUnknown()) + changed |= result->markUnknown(); + else { + changed |= resultSummary.foreachElement( + [&](DistinctAttr aliasClass, AliasClassSet::State state) { + assert(state == AliasClassSet::State::Defined); + if (auto pseudoClass = dyn_cast( + aliasClass.getReferencedAttr())) { + assert( + pseudoClass.getDepth() == 0 && + "sparse alias summaries for depth > 0 not yet implemented"); + return result->join(*operands[pseudoClass.getArgNumber()]); + } else { + return result->insert({aliasClass}); + } + }); + } + propagateIfChanged(result, changed); + } + return; + } + // Collect alias classes that can be read through the arguments. std::optional argModRef = getFunctionArgModRef(callee); std::optional otherModRef = getFunctionOtherModRef(callee); diff --git a/enzyme/Enzyme/MLIR/Dialect/Dialect.td b/enzyme/Enzyme/MLIR/Dialect/Dialect.td index 24ed91fa4427..59fc21277dfb 100644 --- a/enzyme/Enzyme/MLIR/Dialect/Dialect.td +++ b/enzyme/Enzyme/MLIR/Dialect/Dialect.td @@ -22,6 +22,14 @@ def Enzyme_Dialect : Dialect { let cppNamespace = "::mlir::enzyme"; let useDefaultAttributePrinterParser = 1; let useDefaultTypePrinterParser = 1; + + let extraClassDeclaration = [{ + /// Names of analysis summary attributes + static StringRef getPointerSummaryAttrName() { return "enzyme.p2p"; } + static StringRef getAliasSummaryAttrName() { return "enzyme.alias"; } + static StringRef getDenseActivityAnnotationAttrName() { return "enzyme.denseactive"; } + static StringRef getSparseActivityAnnotationAttrName() { return "enzyme.sparseactive"; } + }]; } //===----------------------------------------------------------------------===// diff --git a/enzyme/test/MLIR/ActivityAnalysis/Summaries/basic.mlir b/enzyme/test/MLIR/ActivityAnalysis/Summaries/basic.mlir index 231a77a2f07b..809e50e77e46 100644 --- a/enzyme/test/MLIR/ActivityAnalysis/Summaries/basic.mlir +++ b/enzyme/test/MLIR/ActivityAnalysis/Summaries/basic.mlir @@ -1,12 +1,9 @@ // RUN: %eopt --print-activity-analysis='use-annotations' --split-input-file %s | FileCheck %s // CHECK-LABEL: processing function @sparse_callee -// CHECK: "fadd"(#0) sources: -// CHECK: size: 1: -// CHECK: #enzyme.argorigin<@sparse_callee(0)> -// CHECK: sinks: -// CHECK: size: 1: -// CHECK: #enzyme.retorigin<@sparse_callee(1)> +// CHECK: "fadd"(#0) +// CHECK: sources: [#enzyme.argorigin<@sparse_callee(0)>] +// CHECK: sinks: [#enzyme.retorigin<@sparse_callee(1)>] func.func @sparse_callee(%arg0: f64) -> (f64, f64) { %zero = llvm.mlir.constant (0.0) : f64 %0 = llvm.fadd %arg0, %arg0 {tag = "fadd"} : f64 @@ -14,12 +11,9 @@ func.func @sparse_callee(%arg0: f64) -> (f64, f64) { } // CHECK-LABEL: processing function @sparse_caller -// CHECK: "fmul"(#0) sources: -// CHECK: size: 1: -// CHECK: #enzyme.argorigin<@sparse_caller(1)> -// CHECK: sinks: -// CHECK: size: 1: -// CHECK: #enzyme.retorigin<@sparse_caller(0)> +// CHECK: "fmul"(#0) +// CHECK: sources: [#enzyme.argorigin<@sparse_caller(1)>] +// CHECK: sinks: [#enzyme.retorigin<@sparse_caller(0)>] func.func @sparse_caller(%unused: i64, %arg0: f64) -> f64 { %0 = llvm.fmul %arg0, %arg0 {tag = "fmul"} : f64 %zero, %1 = call @sparse_callee(%0) : (f64) -> (f64, f64) @@ -31,13 +25,17 @@ func.func @sparse_caller(%unused: i64, %arg0: f64) -> f64 { func.func @aliased_callee(%arg0: !llvm.ptr) -> !llvm.ptr { %c0 = llvm.mlir.constant (0) : i64 %0 = llvm.getelementptr inbounds %arg0[%c0] : (!llvm.ptr, i64) -> !llvm.ptr, f64 - return %arg0 : !llvm.ptr + return %0 : !llvm.ptr } // Test propagation of aliasing through function calls +// CHECK-LABEL: processing function @loadstore +// CHECK: "alloca"(#0) +// CHECK: sources: [#enzyme.argorigin<@loadstore(0)>] +// CHECK: sinks: [#enzyme.retorigin<@loadstore(0)>] func.func @loadstore(%arg0: f64) -> f64 { %c1 = llvm.mlir.constant (1) : i64 - %ptr = llvm.alloca %c1 x f64 : (i64) -> !llvm.ptr + %ptr = llvm.alloca %c1 x f64 {tag = "alloca"} : (i64) -> !llvm.ptr %ptr2 = call @aliased_callee(%ptr) : (!llvm.ptr) -> !llvm.ptr llvm.store %arg0, %ptr2 : f64, !llvm.ptr %0 = llvm.load %ptr : !llvm.ptr -> f64 @@ -55,6 +53,16 @@ func.func @returnptr(%arg0: f64) -> !llvm.ptr { return %ptr : !llvm.ptr } +// CHECK-LABEL: processing function @loadstore +// CHECK: "loaded"(#0) +// CHECK: sources: [#enzyme.argorigin<@loadstore(0)>] +// CHECK: sinks: [#enzyme.retorigin<@loadstore(0)>] +func.func @loadstore(%arg0: f64) -> f64 { + %ptr = call @returnptr(%arg0) : (f64) -> !llvm.ptr + %val = llvm.load %ptr {tag = "loaded"} : !llvm.ptr -> f64 + return %val : f64 +} + // ----- // CHECK-LABEL: processing function @load_nested @@ -71,12 +79,17 @@ func.func @load_nested(%arg0: !llvm.ptr, %arg1: !llvm.ptr) { // means we need to union the origins of %alloc with everything %alloc points to // (%inner in this case) // CHECK-LABEL: processing function @pass_pointer_to -// CHECK: forward value origins: -// CHECK: distinct[0]<#enzyme.pseudoclass<@pass_pointer_to(2, 0)>> originates from [#enzyme.argorigin<@pass_pointer_to(0)>, #enzyme.argorigin<@pass_pointer_to(1)>, #enzyme.argorigin<@pass_pointer_to(2)>] +// CHECK: "val"(#0) +// CHECK: sources: [#enzyme.argorigin<@pass_pointer_to(0)>] +// CHECK: sinks: [#enzyme.argorigin<@pass_pointer_to(1)>, #enzyme.argorigin<@pass_pointer_to(2)>] +// CHECK: "inner"(#0) +// CHECK: sources: [#enzyme.argorigin<@pass_pointer_to(0)>, #enzyme.argorigin<@pass_pointer_to(1)>] +// CHECK: sinks: [#enzyme.argorigin<@pass_pointer_to(1)>, #enzyme.argorigin<@pass_pointer_to(2)>] func.func @pass_pointer_to(%arg0: f64, %alloc: !llvm.ptr, %out: !llvm.ptr) { %one = llvm.mlir.constant (1) : i64 - %inner = llvm.load %alloc : !llvm.ptr -> !llvm.ptr - llvm.store %arg0, %inner : f64, !llvm.ptr + %val = llvm.fmul %arg0, %arg0 {tag = "val"} : f64 + %inner = llvm.load %alloc {tag = "inner"} : !llvm.ptr -> !llvm.ptr + llvm.store %val, %inner : f64, !llvm.ptr func.call @load_nested(%alloc, %out) : (!llvm.ptr, !llvm.ptr) -> () return } @@ -88,9 +101,13 @@ func.func @callee(%val: f64, %out: !llvm.ptr) { return } -// Test backward summary propagation to scalar arguments +// CHECK-LABEL: processing function @caller +// CHECK: "square"(#0) +// CHECK: sources: [#enzyme.argorigin<@caller(1)>] +// CHECK: sinks: [#enzyme.argorigin<@caller(2)>] func.func @caller(%unused: i32, %val: f64, %out: !llvm.ptr) { - call @callee(%val, %out) : (f64, !llvm.ptr) -> () + %square = llvm.fmul %val, %val {tag = "square"} : f64 + call @callee(%square, %out) : (f64, !llvm.ptr) -> () return } diff --git a/enzyme/test/MLIR/AliasAnalysis/Summaries/parent_nodes.mlir b/enzyme/test/MLIR/AliasAnalysis/Summaries/parent_nodes.mlir index c3064a1ac293..52f5b7f9fd49 100644 --- a/enzyme/test/MLIR/AliasAnalysis/Summaries/parent_nodes.mlir +++ b/enzyme/test/MLIR/AliasAnalysis/Summaries/parent_nodes.mlir @@ -48,7 +48,7 @@ llvm.func local_unnamed_addr @calloc(i64 {llvm.noundef}, i64 {llvm.noundef}) -> llvm.func local_unnamed_addr @free(!llvm.ptr {llvm.allocptr, llvm.nocapture, llvm.noundef}) attributes {frame_pointer = #llvm.framePointerKind<"non-leaf">, memory = #llvm.memory_effects, passthrough = ["mustprogress", "nounwind", "willreturn", ["allockind", "4"], ["alloc-family", "malloc"], ["approx-func-fp-math", "true"], ["no-infs-fp-math", "true"], ["no-nans-fp-math", "true"], ["no-signed-zeros-fp-math", "true"], ["no-trapping-math", "true"], ["stack-protector-buffer-size", "8"], ["target-cpu", "apple-m1"], ["unsafe-fp-math", "true"]], sym_visibility = "private", target_cpu = "apple-m1", target_features = #llvm.target_features<["+aes", "+complxnum", "+crc", "+dotprod", "+fp-armv8", "+fp16fml", "+fullfp16", "+jsconv", "+lse", "+neon", "+ras", "+rcpc", "+rdm", "+sha2", "+sha3", "+v8.1a", "+v8.2a", "+v8.3a", "+v8.4a", "+v8.5a", "+v8a", "+zcm", "+zcz"]>} llvm.func @euler_angles_to_rotation_matrix(!llvm.ptr, !llvm.ptr) attributes { - p2psummary = [ + enzyme.p2p = [ [distinct[30]<#enzyme.pseudoclass<@euler_angles_to_rotation_matrix(1, 0)>>, [distinct[31]<#enzyme.pseudoclass<@euler_angles_to_rotation_matrix(1, 1)>>, distinct[32]<"fresh-euler_angles_malloc">]], [distinct[32]<"fresh-euler_angles_malloc">, []], [distinct[33]<"fresh-malloc_RX">, []], @@ -56,32 +56,32 @@ llvm.func @euler_angles_to_rotation_matrix(!llvm.ptr, !llvm.ptr) attributes { [distinct[35]<"fresh-malloc_RZ">, []], [distinct[36]<"fresh-malloc_tmp">, []] ], - activedeps = [ + enzyme.denseactive = [ [distinct[31]<#enzyme.pseudoclass<@euler_angles_to_rotation_matrix(1, 1)>>, [#enzyme.argorigin<@euler_angles_to_rotation_matrix(0)>, #enzyme.argorigin<@euler_angles_to_rotation_matrix(1)>]] ] } llvm.func @angle_axis_to_rotation_matrix(!llvm.ptr, !llvm.ptr) attributes { - p2psummary = [[distinct[40]<#enzyme.pseudoclass<@angle_axis_to_rotation_matrix(1, 0)>>, [distinct[41]<#enzyme.pseudoclass<@angle_axis_to_rotation_matrix(1, 1)>>]]], - activedeps = [[distinct[41]<#enzyme.pseudoclass<@angle_axis_to_rotation_matrix(1, 1)>>, [#enzyme.argorigin<@angle_axis_to_rotation_matrix(0)>, #enzyme.argorigin<@angle_axis_to_rotation_matrix(1)>]]] + enzyme.p2p = [[distinct[40]<#enzyme.pseudoclass<@angle_axis_to_rotation_matrix(1, 0)>>, [distinct[41]<#enzyme.pseudoclass<@angle_axis_to_rotation_matrix(1, 1)>>]]], + enzyme.denseactive = [[distinct[41]<#enzyme.pseudoclass<@angle_axis_to_rotation_matrix(1, 1)>>, [#enzyme.argorigin<@angle_axis_to_rotation_matrix(0)>, #enzyme.argorigin<@angle_axis_to_rotation_matrix(1)>]]] } llvm.func @relatives_to_absolutes(i32, !llvm.ptr, !llvm.ptr, !llvm.ptr) attributes { - p2psummary = [ + enzyme.p2p = [ [distinct[50]<#enzyme.pseudoclass<@relatives_to_absolutes(1, 0)>>, [distinct[51]<#enzyme.pseudoclass<@relatives_to_absolutes(1, 1)>>]], [distinct[52]<#enzyme.pseudoclass<@relatives_to_absolutes(3, 0)>>, [distinct[53]<#enzyme.pseudoclass<@relatives_to_absolutes(3, 1)>>, distinct[54]<"fresh-rta1">, distinct[55]<"fresh-rta2">]], [distinct[54]<"fresh-rta1">, []], [distinct[55]<"fresh-rta2">, []] ], - activedeps = [[distinct[53]<#enzyme.pseudoclass<@relatives_to_absolutes(3, 1)>>, [#enzyme.argorigin<@relatives_to_absolutes(1)>, #enzyme.argorigin<@relatives_to_absolutes(3)>]]] + enzyme.denseactive = [[distinct[53]<#enzyme.pseudoclass<@relatives_to_absolutes(3, 1)>>, [#enzyme.argorigin<@relatives_to_absolutes(1)>, #enzyme.argorigin<@relatives_to_absolutes(3)>]]] } llvm.func @to_pose_params(i32, !llvm.ptr, !llvm.ptr, !llvm.ptr) attributes { - p2psummary = [ + enzyme.p2p = [ [distinct[60]<#enzyme.pseudoclass<@to_pose_params(3, 0)>>, [distinct[61]<#enzyme.pseudoclass<@to_pose_params(3, 1)>>, distinct[62]<"fresh-pose_params_data">]], [distinct[62]<"fresh-pose_params_data">, []] ], - activedeps = [ + enzyme.denseactive = [ [distinct[61]<#enzyme.pseudoclass<@to_pose_params(3, 1)>>, [#enzyme.argorigin<@to_pose_params(1)>, #enzyme.argorigin<@to_pose_params(3)>]] ] }