Skip to content

Commit 9e61bea

Browse files
authored
[CIR] Add GEP flags to ptr stride op (#1863)
From the [comment](#1844 (comment)) on PR review #1844, it seems like we're missing the flags for GEP. I'm opening the PR to add the flags. The first commit is just a prototype to gather opinions and reviews to see if I'm heading to the right direction with this.
1 parent f8a64d4 commit 9e61bea

File tree

9 files changed

+109
-37
lines changed

9 files changed

+109
-37
lines changed

clang/include/clang/CIR/Dialect/Builder/CIRBaseBuilder.h

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -663,9 +663,11 @@ class CIRBaseBuilderTy : public mlir::OpBuilder {
663663
return cir::YieldOp::create(*this, loc, value);
664664
}
665665

666-
cir::PtrStrideOp createPtrStride(mlir::Location loc, mlir::Value base,
667-
mlir::Value stride) {
668-
return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride);
666+
cir::PtrStrideOp
667+
createPtrStride(mlir::Location loc, mlir::Value base, mlir::Value stride,
668+
std::optional<CIR_GEPNoWrapFlags> flags = std::nullopt) {
669+
return cir::PtrStrideOp::create(*this, loc, base.getType(), base, stride,
670+
flags.value_or(CIR_GEPNoWrapFlags::none));
669671
}
670672

671673
cir::CallOp createCallOp(mlir::Location loc,

clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,11 @@
1616
include "mlir/IR/EnumAttr.td"
1717
include "clang/CIR/Dialect/IR/CIRDialect.td"
1818

19+
class CIR_I32BitEnum<string name, string summary, list<BitEnumCaseBase> cases>
20+
: I32BitEnum<name, summary, cases> {
21+
let cppNamespace = "::cir";
22+
}
23+
1924
class CIR_I32EnumAttr<string name, string summary, list<I32EnumAttrCase> cases>
2025
: I32EnumAttr<name, summary, cases> {
2126
let cppNamespace = "::cir";

clang/include/clang/CIR/Dialect/IR/CIROps.td

Lines changed: 27 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -386,6 +386,24 @@ def CIR_PtrDiffOp : CIR_Op<"ptr_diff", [Pure, SameTypeOperands]> {
386386
//===----------------------------------------------------------------------===//
387387
// PtrStrideOp
388388
//===----------------------------------------------------------------------===//
389+
def CIR_GEPNone : I32BitEnumCaseNone<"none">;
390+
def CIR_GEPInboundsFlag : I32BitEnumCaseBit<"inboundsFlag", 0, "inbounds_flag">;
391+
def CIR_GEPNusw : I32BitEnumCaseBit<"nusw", 1>;
392+
def CIR_GEPNuw : I32BitEnumCaseBit<"nuw", 2>;
393+
def CIR_GEPInbounds
394+
: BitEnumCaseGroup<"inbounds", [CIR_GEPInboundsFlag, CIR_GEPNusw]>;
395+
396+
def CIR_GEPNoWrapFlags
397+
: CIR_I32BitEnum<"CIR_GEPNoWrapFlags", "::cir::CIR_GEPNoWrapFlags",
398+
[CIR_GEPNone, CIR_GEPInboundsFlag, CIR_GEPNusw, CIR_GEPNuw,
399+
CIR_GEPInbounds]> {
400+
let cppNamespace = "::cir";
401+
let printBitEnumPrimaryGroups = 1;
402+
}
403+
404+
def CIR_GEPNoWrapFlagsProp : EnumProp<CIR_GEPNoWrapFlags> {
405+
let defaultValue = interfaceType#"::none";
406+
}
389407

390408
def CIR_PtrStrideOp : CIR_Op<"ptr_stride",[
391409
Pure, AllTypesMatch<["base", "result"]>
@@ -397,19 +415,23 @@ def CIR_PtrStrideOp : CIR_Op<"ptr_stride",[
397415

398416
```mlir
399417
%3 = cir.const 0 : i32
418+
400419
%4 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32), !cir.ptr<i32>
420+
421+
%5 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32, inbounds), !cir.ptr<i32>
422+
423+
%6 = cir.ptr_stride(%2 : !cir.ptr<i32>, %3 : i32, inbounds|nuw), !cir.ptr<i32>
424+
401425
```
402426
}];
403427

404-
let arguments = (ins
405-
CIR_PointerType:$base,
406-
CIR_AnyFundamentalIntType:$stride
407-
);
428+
let arguments = (ins CIR_PointerType:$base, CIR_AnyFundamentalIntType:$stride,
429+
CIR_GEPNoWrapFlagsProp:$noWrapFlags);
408430

409431
let results = (outs CIR_PointerType:$result);
410432

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

415437
let extraClassDeclaration = [{

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2842,10 +2842,16 @@ mlir::Value CIRGenFunction::emitCheckedInBoundsGEP(
28422842
assert(IdxList.size() == 1 && "multi-index ptr arithmetic NYI");
28432843
mlir::Value GEPVal =
28442844
builder.create<cir::PtrStrideOp>(CGM.getLoc(Loc), PtrTy, Ptr, IdxList[0]);
2845-
28462845
// If the pointer overflow sanitizer isn't enabled, do nothing.
2847-
if (!SanOpts.has(SanitizerKind::PointerOverflow))
2848-
return GEPVal;
2846+
if (!SanOpts.has(SanitizerKind::PointerOverflow)) {
2847+
cir::CIR_GEPNoWrapFlags nwFlags = cir::CIR_GEPNoWrapFlags::inbounds;
2848+
if (!SignedIndices && !IsSubtraction)
2849+
nwFlags = nwFlags | cir::CIR_GEPNoWrapFlags::nuw;
2850+
return builder.create<cir::PtrStrideOp>(CGM.getLoc(Loc), PtrTy, Ptr,
2851+
IdxList[0], nwFlags);
2852+
}
2853+
2854+
return GEPVal;
28492855

28502856
// TODO(cir): the unreachable code below hides a substantial amount of code
28512857
// from the original codegen related with pointer overflow sanitizer.

clang/lib/CIR/Dialect/IR/CIRDialect.cpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
#include "clang/CIR/Dialect/IR/CIRTypes.h"
1818
#include "clang/CIR/Interfaces/CIRLoopOpInterface.h"
1919
#include "clang/CIR/MissingFeatures.h"
20+
#include "llvm/ADT/StringExtras.h"
2021
#include "llvm/ADT/TypeSwitch.h"
2122
#include "llvm/Support/ErrorHandling.h"
2223
#include "llvm/Support/LogicalResult.h"

clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp

Lines changed: 28 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,24 @@ void walkRegionSkipping(mlir::Region &region,
9292
});
9393
}
9494

95+
/// Convert from a CIR PtrStrideOp kind to an LLVM IR equivalent of GEP.
96+
mlir::LLVM::GEPNoWrapFlags
97+
convertPtrStrideKindToGEPFlags(cir::CIR_GEPNoWrapFlags flags) {
98+
using CIRFlags = cir::CIR_GEPNoWrapFlags;
99+
using LLVMFlags = mlir::LLVM::GEPNoWrapFlags;
100+
101+
LLVMFlags x = LLVMFlags::none;
102+
if ((flags & CIRFlags::inboundsFlag) == CIRFlags::inboundsFlag)
103+
x = x | LLVMFlags::inboundsFlag;
104+
if ((flags & CIRFlags::nusw) == CIRFlags::nusw)
105+
x = x | LLVMFlags::nusw;
106+
if ((flags & CIRFlags::inbounds) == CIRFlags::inbounds)
107+
x = x | LLVMFlags::inbounds;
108+
if ((flags & CIRFlags::nuw) == CIRFlags::nuw)
109+
x = x | LLVMFlags::nuw;
110+
return x;
111+
}
112+
95113
/// Convert from a CIR comparison kind to an LLVM IR integral comparison kind.
96114
mlir::LLVM::ICmpPredicate convertCmpKindToICmpPredicate(cir::CmpOpKind kind,
97115
bool isSigned) {
@@ -1023,9 +1041,9 @@ mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite(
10231041
isUnsigned = strideTy.isUnsigned();
10241042
index = promoteIndex(rewriter, index, *layoutWidth, isUnsigned);
10251043
}
1026-
10271044
rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(
1028-
ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index);
1045+
ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index,
1046+
convertPtrStrideKindToGEPFlags(adaptor.getNoWrapFlags()));
10291047
return mlir::success();
10301048
}
10311049

@@ -4299,14 +4317,14 @@ mlir::LogicalResult CIRToLLVMEhSetjmpOpLowering::matchAndRewrite(
42994317
return mlir::success();
43004318
}
43014319

4302-
StringRef fnName = "_setjmp";
4303-
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4304-
auto fnType = mlir::LLVM::LLVMFunctionType::get(returnType, llvmPtrTy,
4305-
/*isVarArg=*/false);
4306-
getOrCreateLLVMFuncOp(rewriter, op, fnName, fnType);
4307-
rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(op, returnType, fnName,
4308-
adaptor.getEnv());
4309-
return mlir::success();
4320+
StringRef fnName = "_setjmp";
4321+
auto llvmPtrTy = mlir::LLVM::LLVMPointerType::get(rewriter.getContext());
4322+
auto fnType = mlir::LLVM::LLVMFunctionType::get(returnType, llvmPtrTy,
4323+
/*isVarArg=*/false);
4324+
getOrCreateLLVMFuncOp(rewriter, op, fnName, fnType);
4325+
rewriter.replaceOpWithNewOp<mlir::LLVM::CallOp>(op, returnType, fnName,
4326+
adaptor.getEnv());
4327+
return mlir::success();
43104328
}
43114329

43124330
mlir::LogicalResult CIRToLLVMCatchParamOpLowering::matchAndRewrite(

clang/test/CIR/CodeGen/pointer-arith-ext.c

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,14 @@ void *f4(void *a, int b) { return a - b; }
3636
// CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
3737
// CIR: %[[STRIDE:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
3838
// CIR: %[[SUB:.*]] = cir.unary(minus, %[[STRIDE]]) : !s32i, !s32i
39-
// CIR: cir.ptr_stride %[[PTR]], %[[SUB]] : (!cir.ptr<!void>, !s32i) -> !cir.ptr<!void>
39+
// CIR: cir.ptr_stride inbounds %[[PTR]], %[[SUB]] : (!cir.ptr<!void>, !s32i) -> !cir.ptr<!void>
4040

4141
// LLVM-LABEL: f4
4242
// LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8
4343
// LLVM: %[[TOEXT:.*]] = load i32, ptr {{.*}}, align 4
4444
// LLVM: %[[STRIDE:.*]] = sext i32 %[[TOEXT]] to i64
4545
// LLVM: %[[SUB:.*]] = sub i64 0, %[[STRIDE]]
46-
// LLVM: getelementptr i8, ptr %[[PTR]], i64 %[[SUB]]
46+
// LLVM: getelementptr inbounds i8, ptr %[[PTR]], i64 %[[SUB]]
4747

4848
// Similar to f4, just make sure it does not crash.
4949
void *f4_1(void *a, int b) { return (a -= b); }
@@ -52,13 +52,13 @@ FP f5(FP a, int b) { return a + b; }
5252
// CIR-LABEL: f5
5353
// CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!cir.func<()>>>, !cir.ptr<!cir.func<()>>
5454
// CIR: %[[STRIDE:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
55-
// CIR: cir.ptr_stride %[[PTR]], %[[STRIDE]] : (!cir.ptr<!cir.func<()>>, !s32i) -> !cir.ptr<!cir.func<()>>
55+
// CIR: cir.ptr_stride inbounds %[[PTR]], %[[STRIDE]] : (!cir.ptr<!cir.func<()>>, !s32i) -> !cir.ptr<!cir.func<()>>
5656

5757
// LLVM-LABEL: f5
5858
// LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8
5959
// LLVM: %[[TOEXT:.*]] = load i32, ptr {{.*}}, align 4
6060
// LLVM: %[[STRIDE:.*]] = sext i32 %[[TOEXT]] to i64
61-
// LLVM: getelementptr i8, ptr %[[PTR]], i64 %[[STRIDE]]
61+
// LLVM: getelementptr inbounds i8, ptr %[[PTR]], i64 %[[STRIDE]]
6262

6363
// These test the same paths above, just make sure it does not crash.
6464
FP f5_1(FP a, int b) { return (a += b); }
@@ -70,14 +70,14 @@ FP f7(FP a, int b) { return a - b; }
7070
// CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!cir.func<()>>>, !cir.ptr<!cir.func<()>>
7171
// CIR: %[[STRIDE:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
7272
// CIR: %[[SUB:.*]] = cir.unary(minus, %[[STRIDE]]) : !s32i, !s32i
73-
// CIR: cir.ptr_stride %[[PTR]], %[[SUB]] : (!cir.ptr<!cir.func<()>>, !s32i) -> !cir.ptr<!cir.func<()>>
73+
// CIR: cir.ptr_stride inbounds %[[PTR]], %[[SUB]] : (!cir.ptr<!cir.func<()>>, !s32i) -> !cir.ptr<!cir.func<()>>
7474

7575
// LLVM-LABEL: f7
7676
// LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8
7777
// LLVM: %[[TOEXT:.*]] = load i32, ptr {{.*}}, align 4
7878
// LLVM: %[[STRIDE:.*]] = sext i32 %[[TOEXT]] to i64
7979
// LLVM: %[[SUB:.*]] = sub i64 0, %[[STRIDE]]
80-
// LLVM: getelementptr i8, ptr %[[PTR]], i64 %[[SUB]]
80+
// LLVM: getelementptr inbounds i8, ptr %[[PTR]], i64 %[[SUB]]
8181

8282
// Similar to f7, just make sure it does not crash.
8383
FP f7_1(FP a, int b) { return (a -= b); }
@@ -87,14 +87,14 @@ void f8(void *a, int b) { return *(id(a + b)); }
8787
// CIR-LABEL: f8
8888
// CIR: %[[PTR:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void>
8989
// CIR: %[[STRIDE:.*]] = cir.load{{.*}} {{.*}} : !cir.ptr<!s32i>, !s32i
90-
// CIR: cir.ptr_stride %[[PTR]], %[[STRIDE]] : (!cir.ptr<!void>, !s32i) -> !cir.ptr<!void>
90+
// CIR: cir.ptr_stride inbounds %[[PTR]], %[[STRIDE]] : (!cir.ptr<!void>, !s32i) -> !cir.ptr<!void>
9191
// CIR: cir.return
9292

9393
// LLVM-LABEL: f8
9494
// LLVM: %[[PTR:.*]] = load ptr, ptr {{.*}}, align 8
9595
// LLVM: %[[TOEXT:.*]] = load i32, ptr {{.*}}, align 4
9696
// LLVM: %[[STRIDE:.*]] = sext i32 %[[TOEXT]] to i64
97-
// LLVM: getelementptr i8, ptr %[[PTR]], i64 %[[STRIDE]]
97+
// LLVM: getelementptr inbounds i8, ptr %[[PTR]], i64 %[[STRIDE]]
9898
// LLVM: ret void
9999

100100
void f8_1(void *a, int b) { return a[b]; }
@@ -119,7 +119,8 @@ unsigned char *p(unsigned int x) {
119119

120120
// CIR-LABEL: @p
121121
// CIR: %[[SUB:.*]] = cir.binop(sub
122-
// CIR: cir.ptr_stride {{.*}}, %[[SUB]] : (!cir.ptr<!u8i>, !u32i) -> !cir.ptr<!u8i>
122+
// CIR: cir.ptr_stride inbounds|nuw {{.*}}, %[[SUB]] : (!cir.ptr<!u8i>, !u32i) -> !cir.ptr<!u8i>
123123

124124
// LLVM-LABEL: @p
125-
// LLVM: getelementptr i8, ptr {{.*}}
125+
// LLVM: getelementptr inbounds nuw i8, ptr {{.*}}
126+

clang/test/CIR/CodeGen/pointers.cpp

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,28 +5,28 @@
55
void foo(int *iptr, char *cptr, unsigned ustride) {
66
*(iptr + 2) = 1;
77
// CHECK: %[[#STRIDE:]] = cir.const #cir.int<2> : !s32i
8-
// CHECK: cir.ptr_stride %{{.+}}, %[[#STRIDE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
8+
// CHECK: cir.ptr_stride inbounds %{{.+}}, %[[#STRIDE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
99
*(cptr + 3) = 1;
1010
// CHECK: %[[#STRIDE:]] = cir.const #cir.int<3> : !s32i
11-
// CHECK: cir.ptr_stride %{{.+}}, %[[#STRIDE]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i>
11+
// CHECK: cir.ptr_stride inbounds %{{.+}}, %[[#STRIDE]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i>
1212
*(iptr - 2) = 1;
1313
// CHECK: %[[#STRIDE:]] = cir.const #cir.int<2> : !s32i
1414
// CHECK: %[[#NEGSTRIDE:]] = cir.unary(minus, %[[#STRIDE]]) : !s32i, !s32i
15-
// CHECK: cir.ptr_stride %{{.+}}, %[[#NEGSTRIDE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
15+
// CHECK: cir.ptr_stride inbounds %{{.+}}, %[[#NEGSTRIDE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
1616
*(cptr - 3) = 1;
1717
// CHECK: %[[#STRIDE:]] = cir.const #cir.int<3> : !s32i
1818
// CHECK: %[[#NEGSTRIDE:]] = cir.unary(minus, %[[#STRIDE]]) : !s32i, !s32i
19-
// CHECK: cir.ptr_stride %{{.+}}, %[[#NEGSTRIDE]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i>
19+
// CHECK: cir.ptr_stride inbounds %{{.+}}, %[[#NEGSTRIDE]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i>
2020
*(iptr + ustride) = 1;
2121
// CHECK: %[[#STRIDE:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!u32i>, !u32i
22-
// CHECK: cir.ptr_stride %{{.+}}, %[[#STRIDE]] : (!cir.ptr<!s32i>, !u32i) -> !cir.ptr<!s32i>
22+
// CHECK: cir.ptr_stride inbounds|nuw %{{.+}}, %[[#STRIDE]] : (!cir.ptr<!s32i>, !u32i) -> !cir.ptr<!s32i>
2323

2424
// Must convert unsigned stride to a signed one.
2525
*(iptr - ustride) = 1;
2626
// CHECK: %[[#STRIDE:]] = cir.load{{.*}} %{{.+}} : !cir.ptr<!u32i>, !u32i
2727
// CHECK: %[[#SIGNSTRIDE:]] = cir.cast(integral, %[[#STRIDE]] : !u32i), !s32i
2828
// CHECK: %[[#NEGSTRIDE:]] = cir.unary(minus, %[[#SIGNSTRIDE]]) : !s32i, !s32i
29-
// CHECK: cir.ptr_stride %{{.+}}, %[[#NEGSTRIDE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
29+
// CHECK: cir.ptr_stride inbounds %{{.+}}, %[[#NEGSTRIDE]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
3030
}
3131

3232
void testPointerSubscriptAccess(int *ptr) {

clang/test/CIR/IR/ptr_stride.cir

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@ module {
1010
%4 = cir.ptr_stride %2, %3 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
1111
cir.return
1212
}
13+
14+
cir.func @gepflags(%arg0: !cir.ptr<!s32i>, %arg1: !s32i) {
15+
%0 = cir.ptr_stride %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
16+
%1 = cir.ptr_stride nuw %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
17+
%2 = cir.ptr_stride inbounds|nuw %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
18+
%3 = cir.ptr_stride %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
19+
cir.return
20+
}
1321
}
1422

1523
// CHECK: cir.func @arraysubscript(%arg0: !s32i) {
@@ -20,3 +28,12 @@ module {
2028
// CHECK-NEXT: %4 = cir.ptr_stride %2, %3 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
2129
// CHECK-NEXT: cir.return
2230
// CHECK-NEXT: }
31+
32+
33+
// CHECK: cir.func @gepflags(%arg0: !cir.ptr<!s32i>, %arg1: !s32i) {
34+
// CHECK-NEXT: %0 = cir.ptr_stride %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
35+
// CHECK-NEXT: %1 = cir.ptr_stride nuw %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
36+
// CHECK-NEXT: %2 = cir.ptr_stride inbounds|nuw %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
37+
// CHECK-NEXT: %3 = cir.ptr_stride %arg0, %arg1 : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i>
38+
// CHECK-NEXT: cir.return
39+
// CHECK-NEXT: }

0 commit comments

Comments
 (0)