[clang] [CIR] Add cir.ptr_mask (PR #224143)

Adam Smith via cfe-commits cfe-commits at lists.llvm.org
Wed Sep 16 14:58:48 PDT 2026


================
@@ -1938,6 +1938,27 @@ mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
   return mlir::success();
 }
 
+mlir::LogicalResult CIRToLLVMPtrMaskOpLowering::matchAndRewrite(
+    cir::PtrMaskOp op, OpAdaptor adaptor,
+    mlir::ConversionPatternRewriter &rewriter) const {
+  const mlir::Type resultTy = getTypeConverter()->convertType(op.getType());
+
+  // llvm.ptrmask requires the mask to be exactly the pointer index width, so
+  // resize it.
+  std::optional<uint64_t> indexWidth =
+      dataLayout.getTypeIndexBitwidth(adaptor.getPtr().getType());
+  assert(indexWidth && "!llvm.ptr always has an index width");
+
+  auto cirMaskTy = mlir::cast<cir::IntType>(op.getMask().getType());
+  mlir::Value mask = getLLVMIntCast(
----------------
adams381 wrote:

The quantity `llvm.ptrmask` is verified against is the pointer index width rather than the pointer size, and CIR keeps those apart already: `PointerType::getIndexBitwidth` returns the spec's index and falls back to the size only when the index is unspecified.  They differ for `__ptr32` on x86-64, which is the address-space-271 module in the lowering test.

A verifier could get at that, since CIRGen attaches a DLTI spec and the verifier could walk up to the module.  What puts me off is that op validity would then depend on a module attribute, so the same `cir.ptr_mask` would verify or not depending on whether a layout is attached.  Plenty of hand-written CIR has none, including the round-trip test in this PR.

On the cost/benefit: for the producer this exists for, the resize never fires.  Classic builds the mask at `IntPtrTy` in `emitRoundPointerUpToAlignment`, the x86-64 `va_arg` expansion will do the same, and `getLLVMIntCast` hands back the operand untouched when the widths already match.  So it costs three lines and buys correct IR rather than a verifier failure if a later producer does not know the target's index width.  `cir.ptr_stride` also takes any fundamental integer and resizes it through `convertToIndexTy`, so tightening `ptr_mask` alone would make it the stricter of the two.

That is reasoning rather than strong conviction.  If you would rather the op demanded the mask at index width, I would put the check in the lowering as an `errorNYI` instead of the verifier, for the module-attribute reason.  Do you think the tighter contract is worth making every producer know the target's index width?

https://github.com/llvm/llvm-project/pull/224143


More information about the cfe-commits mailing list