Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h
Original file line number Diff line number Diff line change
Expand Up @@ -683,9 +683,9 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {

cir::PtrStrideOp
createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride,
std::optional<CIR_GEPNoWrapFlags> flags = std::nullopt) {
std::optional<GEPNoWrapFlags> flags = std::nullopt) {
return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride,
flags.value_or(CIR_GEPNoWrapFlags::none));
flags.value_or(GEPNoWrapFlags::none));
}

cir::CallOp createCallOp(mlir::Location loc,
Expand Down
53 changes: 31 additions & 22 deletions clang/include/clang/CIR/Dialect/IR/CIROps.td
Original file line number Diff line number Diff line change
Expand Up @@ -401,57 +401,66 @@ def CIR_PtrDiffOp : CIR_Op<"ptr_diff", [Pure, SameTypeOperands]> {
//===----------------------------------------------------------------------===//
// PtrStrideOp
//===----------------------------------------------------------------------===//

// These mirror the GEPNoWrapFlags in LLVM IR Dialect.
def CIR_GEPNone : I32BitEnumCaseNone<"none">;
def CIR_GEPInboundsFlag : I32BitEnumCaseBit<"inboundsFlag", 0, "inbounds_flag">;
def CIR_GEPNusw : I32BitEnumCaseBit<"nusw", 1>;
def CIR_GEPNuw : I32BitEnumCaseBit<"nuw", 2>;
def CIR_GEPInbounds
: BitEnumCaseGroup<"inbounds", [CIR_GEPInboundsFlag, CIR_GEPNusw]>;

def CIR_GEPNoWrapFlags
: CIR_I32BitEnum<"CIR_GEPNoWrapFlags", "::cir::CIR_GEPNoWrapFlags",
[CIR_GEPNone, CIR_GEPInboundsFlag, CIR_GEPNusw, CIR_GEPNuw,
CIR_GEPInbounds]> {
let cppNamespace = "::cir";
def CIR_GEPInbounds : BitEnumCaseGroup<"inbounds", [
CIR_GEPInboundsFlag, CIR_GEPNusw]>;

def CIR_GEPNoWrapFlags : CIR_I32BitEnum<"GEPNoWrapFlags", "no-wrap flags", [
CIR_GEPNone,
CIR_GEPInboundsFlag,
CIR_GEPNusw,
CIR_GEPNuw,
CIR_GEPInbounds
]> {
let printBitEnumPrimaryGroups = 1;
}

def CIR_GEPNoWrapFlagsProp : EnumProp<CIR_GEPNoWrapFlags> {
let defaultValue = interfaceType#"::none";
let defaultValue = enum.cppType # "::" # "none";
}

def CIR_PtrStrideOp : CIR_Op<"ptr_stride",[
Pure, AllTypesMatch<["base", "result"]>
]> {
let summary = "Pointer access with stride";
let description = [{
Given a base pointer as first operand, provides a new pointer after applying
a stride (second operand).

```mlir
%3 = cir.const 0 : i32

%4 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32), !cir.ptr<i32>
The `cir.ptr_stride` operation computes a new pointer from a base pointer
and an integer stride, similar to a single-index `getelementptr` in LLVM IR.
It moves the pointer by `stride * sizeof(element_type)` bytes.

%5 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32, inbounds), !cir.ptr<i32>
Optional no-wrap flags refine pointer arithmetic semantics, that mirror
LLVM's GEP no-wrap semantics.

%6 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32, inbounds|nuw), !cir.ptr<i32>
Example:

```mlir
%3 = cir.ptr_stride %1, %2 : (!cir.ptr<i32>, i32) ->!cir.ptr<i32>
%4 = cir.ptr_stride inbounds %1, %2 : (!cir.ptr<i32>, i32) -> !cir.ptr<i32>
%5 = cir.ptr_stride inbounds|nuw %1, %2 : (!cir.ptr<i32>, i32) -> !cir.ptr<i32>
```
}];

let arguments = (ins CIR_PointerType:$base, CIR_AnyFundamentalIntType:$stride,
CIR_GEPNoWrapFlagsProp:$noWrapFlags);
let arguments = (ins
CIR_PointerType:$base,
CIR_AnyFundamentalIntType:$stride,
CIR_GEPNoWrapFlagsProp:$noWrapFlags
);

let results = (outs CIR_PointerType:$result);

let assemblyFormat = [{
($noWrapFlags^)? $base`,` $stride `:` functional-type(operands, results) attr-dict
($noWrapFlags^)? $base`,` $stride `:` functional-type(operands, results)
attr-dict
}];

let extraClassDeclaration = [{
// Get type pointed by the base pointer.
mlir::Type getElementTy() {
mlir::Type getElementType() {
return getBase().getType().getPointee();
}
}];
Expand Down
4 changes: 2 additions & 2 deletions clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2850,9 +2850,9 @@ mlir::Value CIRGenFunction::emitCheckedInBoundsGEP(
builder.create<cir::PtrStrideOp>(CGM.getLoc(Loc), PtrTy, Ptr, IdxList[0]);
// If the pointer overflow sanitizer isn't enabled, do nothing.
if (!SanOpts.has(SanitizerKind::PointerOverflow)) {
cir::CIR_GEPNoWrapFlags nwFlags = cir::CIR_GEPNoWrapFlags::inbounds;
cir::GEPNoWrapFlags nwFlags = cir::GEPNoWrapFlags::inbounds;
if (!SignedIndices && !IsSubtraction)
nwFlags = nwFlags | cir::CIR_GEPNoWrapFlags::nuw;
nwFlags = nwFlags | cir::GEPNoWrapFlags::nuw;
return builder.create<cir::PtrStrideOp>(CGM.getLoc(Loc), PtrTy, Ptr,
IdxList[0], nwFlags);
}
Expand Down
8 changes: 3 additions & 5 deletions clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,17 +94,15 @@ void walkRegionSkipping(mlir::Region &region,

/// Convert from a CIR PtrStrideOp kind to an LLVM IR equivalent of GEP.
mlir::LLVM::GEPNoWrapFlags
convertPtrStrideKindToGEPFlags(cir::CIR_GEPNoWrapFlags flags) {
using CIRFlags = cir::CIR_GEPNoWrapFlags;
convertPtrStrideKindToGEPFlags(cir::GEPNoWrapFlags flags) {
using CIRFlags = cir::GEPNoWrapFlags;
using LLVMFlags = mlir::LLVM::GEPNoWrapFlags;

LLVMFlags x = LLVMFlags::none;
if ((flags & CIRFlags::inboundsFlag) == CIRFlags::inboundsFlag)
x = x | LLVMFlags::inboundsFlag;
if ((flags & CIRFlags::nusw) == CIRFlags::nusw)
x = x | LLVMFlags::nusw;
if ((flags & CIRFlags::inbounds) == CIRFlags::inbounds)
x = x | LLVMFlags::inbounds;
if ((flags & CIRFlags::nuw) == CIRFlags::nuw)
x = x | LLVMFlags::nuw;
return x;
Expand Down Expand Up @@ -1021,7 +1019,7 @@ mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
auto *tc = getTypeConverter();
const auto resultTy = tc->convertType(ptrStrideOp.getType());
auto elementTy =
convertTypeForMemory(*tc, dataLayout, ptrStrideOp.getElementTy());
convertTypeForMemory(*tc, dataLayout, ptrStrideOp.getElementType());
auto *ctx = elementTy.getContext();

// void and function types doesn't really have a layout to use in GEPs,
Expand Down
Loading