17#include "mlir/Dialect/LLVMIR/LLVMDialect.h"
19#include "mlir/IR/Matchers.h"
20#include "mlir/IR/PatternMatch.h"
21#include "mlir/IR/SymbolTable.h"
26#define GEN_PASS_DEF_RAISELLVMEXTPASS
27#include "Passes/Passes.h.inc"
33using namespace enzyme;
35struct RaiseLLVMExtPass
36 :
public enzyme::impl::RaiseLLVMExtPassBase<RaiseLLVMExtPass> {
37 using RaiseLLVMExtPassBase::RaiseLLVMExtPassBase;
39 void runOnOperation()
override {
42 SymbolTable::walkSymbolTables(
44 true, [&](Operation *st,
bool allUsesVisible) {
45 SymbolTable symtable(st);
47 auto name = StringAttr::get(&getContext(),
"__enzyme_ptr_size_hint");
48 auto uses = SymbolTable::getSymbolUses(name, st);
57 if (!uses || uses->empty())
60 auto fn = cast<FunctionOpInterface>(symtable.lookup(name));
61 if (!fn.isExternal()) {
63 fn.emitError() <<
"__enzyme_ptr_size_hint is not declared external";
67 for (
auto use : *uses) {
68 auto call = dyn_cast<LLVM::CallOp>(use.getUser());
71 use.getUser()->emitError()
72 <<
"user of __enzyme_ptr_size_hint is not a llvm.call";
76 auto args = call.getArgOperands();
77 if (args.size() < 2 || args.size() > 3) {
79 call.emitError() <<
"__enzyme_ptr_size_hint expects (ptr, size) "
80 "or (ptr, size, addrspace), got "
81 << args.size() <<
" arguments";
85 auto ptrTy = dyn_cast<LLVM::LLVMPointerType>(args[0].getType());
89 <<
"first argument of __enzyme_ptr_size_hint is not a "
94 OpBuilder builder(call);
107 if (args.size() == 3) {
109 if (!matchPattern(args[2], m_ConstantInt(&space))) {
111 call.emitError() <<
"address space argument of "
112 "__enzyme_ptr_size_hint is not a constant";
115 if (space.isNegative()) {
117 call.emitError() <<
"address space argument of "
118 "__enzyme_ptr_size_hint is negative: "
119 << space.getSExtValue();
122 if (space.getZExtValue() != ptrTy.getAddressSpace()) {
123 auto castTy = LLVM::LLVMPointerType::get(
124 &getContext(), (
unsigned)space.getZExtValue());
125 ptr = LLVM::AddrSpaceCastOp::create(builder, call.getLoc(),
130 llvm_ext::PtrSizeHintOp::create(builder, call.getLoc(), ptr,