1616#include " mlir/IR/BuiltinAttributes.h"
1717#include " mlir/IR/Operation.h"
1818#include " mlir/Target/LLVMIR/ModuleTranslation.h"
19+ #include " llvm/ADT/TypeSwitch.h"
20+ #include " llvm/IR/IRBuilder.h"
21+ #include " llvm/IR/Instructions.h"
22+ #include " llvm/IR/Type.h"
23+ #include " llvm/IR/Value.h"
1924
2025using namespace mlir ;
2126using namespace mlir ::ptr;
2227
2328namespace {
29+
30+ // / Converts ptr::AtomicOrdering to llvm::AtomicOrdering
31+ static llvm::AtomicOrdering
32+ convertAtomicOrdering (ptr::AtomicOrdering ordering) {
33+ switch (ordering) {
34+ case ptr::AtomicOrdering::not_atomic:
35+ return llvm::AtomicOrdering::NotAtomic;
36+ case ptr::AtomicOrdering::unordered:
37+ return llvm::AtomicOrdering::Unordered;
38+ case ptr::AtomicOrdering::monotonic:
39+ return llvm::AtomicOrdering::Monotonic;
40+ case ptr::AtomicOrdering::acquire:
41+ return llvm::AtomicOrdering::Acquire;
42+ case ptr::AtomicOrdering::release:
43+ return llvm::AtomicOrdering::Release;
44+ case ptr::AtomicOrdering::acq_rel:
45+ return llvm::AtomicOrdering::AcquireRelease;
46+ case ptr::AtomicOrdering::seq_cst:
47+ return llvm::AtomicOrdering::SequentiallyConsistent;
48+ }
49+ llvm_unreachable (" Unknown atomic ordering" );
50+ }
51+
52+ // / Convert ptr.ptr_add operation
53+ static LogicalResult
54+ convertPtrAddOp (PtrAddOp ptrAddOp, llvm::IRBuilderBase &builder,
55+ LLVM::ModuleTranslation &moduleTranslation) {
56+ llvm::Value *basePtr = moduleTranslation.lookupValue (ptrAddOp.getBase ());
57+ llvm::Value *offset = moduleTranslation.lookupValue (ptrAddOp.getOffset ());
58+
59+ if (!basePtr || !offset)
60+ return ptrAddOp.emitError (" Failed to lookup operands" );
61+
62+ // Create GEP instruction for pointer arithmetic
63+ llvm::GetElementPtrInst *gep = llvm::GetElementPtrInst::Create (
64+ builder.getInt8Ty (), basePtr, {offset}, " " , builder.GetInsertBlock ());
65+
66+ // Set the appropriate flags
67+ switch (ptrAddOp.getFlags ()) {
68+ case ptr::PtrAddFlags::none:
69+ break ;
70+ case ptr::PtrAddFlags::nusw:
71+ gep->setNoWrapFlags (llvm::GEPNoWrapFlags::noUnsignedSignedWrap ());
72+ break ;
73+ case ptr::PtrAddFlags::nuw:
74+ gep->setNoWrapFlags (llvm::GEPNoWrapFlags::noUnsignedWrap ());
75+ break ;
76+ case ptr::PtrAddFlags::inbounds:
77+ gep->setNoWrapFlags (llvm::GEPNoWrapFlags::inBounds ());
78+ break ;
79+ }
80+
81+ moduleTranslation.mapValue (ptrAddOp.getResult (), gep);
82+ return success ();
83+ }
84+
85+ // / Convert ptr.load operation
86+ static LogicalResult convertLoadOp (LoadOp loadOp, llvm::IRBuilderBase &builder,
87+ LLVM::ModuleTranslation &moduleTranslation) {
88+ llvm::Value *ptr = moduleTranslation.lookupValue (loadOp.getPtr ());
89+ if (!ptr)
90+ return loadOp.emitError (" Failed to lookup pointer operand" );
91+
92+ // Convert result type to LLVM type
93+ llvm::Type *resultType =
94+ moduleTranslation.convertType (loadOp.getValue ().getType ());
95+ if (!resultType)
96+ return loadOp.emitError (" Failed to convert result type" );
97+
98+ // Create the load instruction.
99+ llvm::LoadInst *loadInst = builder.CreateAlignedLoad (
100+ resultType, ptr, llvm::MaybeAlign (loadOp.getAlignment ().value_or (0 )),
101+ loadOp.getVolatile_ ());
102+
103+ // Set op flags and metadata.
104+ loadInst->setAtomic (convertAtomicOrdering (loadOp.getOrdering ()));
105+ // Set sync scope if specified
106+ if (loadOp.getSyncscope ().has_value ()) {
107+ llvm::LLVMContext &ctx = builder.getContext ();
108+ llvm::SyncScope::ID syncScope =
109+ ctx.getOrInsertSyncScopeID (loadOp.getSyncscope ().value ());
110+ loadInst->setSyncScopeID (syncScope);
111+ }
112+
113+ // Set metadata for nontemporal, invariant, and invariant_group
114+ if (loadOp.getNontemporal ()) {
115+ llvm::MDNode *nontemporalMD =
116+ llvm::MDNode::get (builder.getContext (),
117+ llvm::ConstantAsMetadata::get (builder.getInt32 (1 )));
118+ loadInst->setMetadata (llvm::LLVMContext::MD_nontemporal, nontemporalMD);
119+ }
120+
121+ if (loadOp.getInvariant ()) {
122+ llvm::MDNode *invariantMD = llvm::MDNode::get (builder.getContext (), {});
123+ loadInst->setMetadata (llvm::LLVMContext::MD_invariant_load, invariantMD);
124+ }
125+
126+ if (loadOp.getInvariantGroup ()) {
127+ llvm::MDNode *invariantGroupMD =
128+ llvm::MDNode::get (builder.getContext (), {});
129+ loadInst->setMetadata (llvm::LLVMContext::MD_invariant_group,
130+ invariantGroupMD);
131+ }
132+
133+ moduleTranslation.mapValue (loadOp.getResult (), loadInst);
134+ return success ();
135+ }
136+
137+ // / Convert ptr.store operation
138+ static LogicalResult
139+ convertStoreOp (StoreOp storeOp, llvm::IRBuilderBase &builder,
140+ LLVM::ModuleTranslation &moduleTranslation) {
141+ llvm::Value *value = moduleTranslation.lookupValue (storeOp.getValue ());
142+ llvm::Value *ptr = moduleTranslation.lookupValue (storeOp.getPtr ());
143+
144+ if (!value || !ptr)
145+ return storeOp.emitError (" Failed to lookup operands" );
146+
147+ // Create the store instruction.
148+ llvm::StoreInst *storeInst = builder.CreateAlignedStore (
149+ value, ptr, llvm::MaybeAlign (storeOp.getAlignment ().value_or (0 )),
150+ storeOp.getVolatile_ ());
151+
152+ // Set op flags and metadata.
153+ storeInst->setAtomic (convertAtomicOrdering (storeOp.getOrdering ()));
154+ // Set sync scope if specified
155+ if (storeOp.getSyncscope ().has_value ()) {
156+ llvm::LLVMContext &ctx = builder.getContext ();
157+ llvm::SyncScope::ID syncScope =
158+ ctx.getOrInsertSyncScopeID (storeOp.getSyncscope ().value ());
159+ storeInst->setSyncScopeID (syncScope);
160+ }
161+
162+ // Set metadata for nontemporal and invariant_group
163+ if (storeOp.getNontemporal ()) {
164+ llvm::MDNode *nontemporalMD =
165+ llvm::MDNode::get (builder.getContext (),
166+ llvm::ConstantAsMetadata::get (builder.getInt32 (1 )));
167+ storeInst->setMetadata (llvm::LLVMContext::MD_nontemporal, nontemporalMD);
168+ }
169+
170+ if (storeOp.getInvariantGroup ()) {
171+ llvm::MDNode *invariantGroupMD =
172+ llvm::MDNode::get (builder.getContext (), {});
173+ storeInst->setMetadata (llvm::LLVMContext::MD_invariant_group,
174+ invariantGroupMD);
175+ }
176+
177+ return success ();
178+ }
179+
180+ // / Convert ptr.type_offset operation
181+ static LogicalResult
182+ convertTypeOffsetOp (TypeOffsetOp typeOffsetOp, llvm::IRBuilderBase &builder,
183+ LLVM::ModuleTranslation &moduleTranslation) {
184+ // Convert the element type to LLVM type
185+ llvm::Type *elementType =
186+ moduleTranslation.convertType (typeOffsetOp.getElementType ());
187+ if (!elementType)
188+ return typeOffsetOp.emitError (" Failed to convert the element type" );
189+
190+ // Convert result type
191+ llvm::Type *resultType =
192+ moduleTranslation.convertType (typeOffsetOp.getResult ().getType ());
193+ if (!resultType)
194+ return typeOffsetOp.emitError (" Failed to convert the result type" );
195+
196+ // Use GEP with null pointer to compute type size/offset.
197+ llvm::Value *nullPtr = llvm::Constant::getNullValue (builder.getPtrTy (0 ));
198+ llvm::Value *offsetPtr =
199+ builder.CreateGEP (elementType, nullPtr, {builder.getInt32 (1 )});
200+ llvm::Value *offset = builder.CreatePtrToInt (offsetPtr, resultType);
201+
202+ moduleTranslation.mapValue (typeOffsetOp.getResult (), offset);
203+ return success ();
204+ }
205+
24206// / Implementation of the dialect interface that converts operations belonging
25207// / to the `ptr` dialect to LLVM IR.
26208class PtrDialectLLVMIRTranslationInterface
@@ -33,21 +215,33 @@ class PtrDialectLLVMIRTranslationInterface
33215 LogicalResult
34216 convertOperation (Operation *op, llvm::IRBuilderBase &builder,
35217 LLVM::ModuleTranslation &moduleTranslation) const final {
36- // Translation for ptr dialect operations to LLVM IR is currently
37- // unimplemented.
38- return op->emitError (" Translation for ptr dialect operations to LLVM IR is "
39- " not implemented." );
218+
219+ return llvm::TypeSwitch<Operation *, LogicalResult>(op)
220+ .Case <PtrAddOp>([&](PtrAddOp ptrAddOp) {
221+ return convertPtrAddOp (ptrAddOp, builder, moduleTranslation);
222+ })
223+ .Case <LoadOp>([&](LoadOp loadOp) {
224+ return convertLoadOp (loadOp, builder, moduleTranslation);
225+ })
226+ .Case <StoreOp>([&](StoreOp storeOp) {
227+ return convertStoreOp (storeOp, builder, moduleTranslation);
228+ })
229+ .Case <TypeOffsetOp>([&](TypeOffsetOp typeOffsetOp) {
230+ return convertTypeOffsetOp (typeOffsetOp, builder, moduleTranslation);
231+ })
232+ .Default ([&](Operation *op) {
233+ return op->emitError (" Translation for operation '" )
234+ << op->getName () << " ' is not implemented." ;
235+ });
40236 }
41237
42238 // / Attaches module-level metadata for functions marked as kernels.
43239 LogicalResult
44240 amendOperation (Operation *op, ArrayRef<llvm::Instruction *> instructions,
45241 NamedAttribute attribute,
46242 LLVM::ModuleTranslation &moduleTranslation) const final {
47- // Translation for ptr dialect operations to LLVM IR is currently
48- // unimplemented.
49- return op->emitError (" Translation for ptr dialect operations to LLVM IR is "
50- " not implemented." );
243+ // No special amendments needed for ptr dialect operations
244+ return success ();
51245 }
52246};
53247} // namespace
0 commit comments