https://github.com/erichkeane created https://github.com/llvm/llvm-project/pull/172897
This is a refactor/upstream/etc of: https://github.com/llvm/clangir/pull/1748 This modifies our array-index operations to use a specific operation (GetElementOp). According to the original patch commit message, this replaces nearly 50% of ptr_stride operations in single source tests! >From 485d2be6d88705a007b1e2542d003f0614e6aedf Mon Sep 17 00:00:00 2001 From: erichkeane <[email protected]> Date: Thu, 18 Dec 2025 08:31:42 -0800 Subject: [PATCH] [CIR] Add 'get element' for array index ops This is a refactor/upstream/etc of: https://github.com/llvm/clangir/pull/1748 This modifies our array-index operations to use a specific operation (GetElementOp). According to the original patch commit message, this replaces nearly 50% of ptr_stride operations in single source tests! --- clang/include/clang/CIR/Dialect/IR/CIROps.td | 63 +++++++++ clang/lib/CIR/CodeGen/CIRGenBuilder.cpp | 12 ++ clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 11 ++ .../CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp | 123 +++++++++++++----- clang/test/CIR/CodeGen/array.cpp | 36 ++--- clang/test/CIR/CodeGen/binassign.c | 8 +- clang/test/CIR/CodeGen/complex.cpp | 6 +- clang/test/CIR/CodeGen/union.c | 12 +- .../CIR/CodeGenBuiltins/builtin-constant-p.c | 3 +- clang/test/CIR/CodeGenOpenACC/combined-copy.c | 5 +- clang/test/CIR/Lowering/array.cpp | 12 +- 11 files changed, 203 insertions(+), 88 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 0e91d008dc52d..8808ab3d73752 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -2694,6 +2694,69 @@ def CIR_GetMemberOp : CIR_Op<"get_member"> { let hasVerifier = 1; } +//===----------------------------------------------------------------------===// + + +// GetElementOp + + +//===----------------------------------------------------------------------===// + + + + + +def CIR_GetElementOp : CIR_Op<"get_element"> { + let summary = "Get the address of an array element"; + + let description = [{ + The `cir.get_element` operation gets the address of a particular element + from the `base` array. + + It expects a pointer to the `base` array and the `index` of the element. + + Example: + ```mlir + // Suppose we have a array. + !s32i = !cir.int<s, 32> + !arr_ty = !cir.array<!s32i x 4> + + // Get the address of the element at index 1. + %elem_1 = cir.get_element %0[1] : (!cir.ptr<!array_ty>, !s32i) -> !cir.ptr<!s32i> + + // Get the address of the element at index %i. + %i = ... + %elem_i = cir.get_element %0[%i] : (!cir.ptr<!array_ty>, !s32i) -> !cir.ptr<!s32i> + + ``` + }]; + + let arguments = (ins + Arg<CIR_PtrToArray, "the base address of the array ">:$base, + Arg<CIR_AnyFundamentalIntType, "the index of the element">:$index + ); + + let results = (outs CIR_PointerType:$result); + + let assemblyFormat = [{ + $base `[` $index `]` `:` `(` qualified(type($base)) `,` qualified(type($index)) `)` + `->` qualified(type($result)) attr-dict + }]; + + let extraClassDeclaration = [{ + // Get the type of the element of the array. + mlir::Type getElementType() { + return getType().getPointee(); + } + + cir::PointerType getBaseType() { + return mlir::cast<cir::PointerType>(getBase().getType()); + } + }]; + + let hasVerifier = 1; +} + //===----------------------------------------------------------------------===// // FuncOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp index 42df10b2fbf4b..4d87bda7b3647 100644 --- a/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.cpp @@ -36,6 +36,18 @@ mlir::Value CIRGenBuilderTy::getArrayElement(mlir::Location arrayLocBegin, mlir::Value arrayPtr, mlir::Type eltTy, mlir::Value idx, bool shouldDecay) { + auto arrayPtrTy = mlir::dyn_cast<cir::PointerType>(arrayPtr.getType()); + assert(arrayPtrTy && "expected pointer type"); + // If the array pointer is not decayed, emit a GetElementOp. + auto arrayTy = mlir::dyn_cast<cir::ArrayType>(arrayPtrTy.getPointee()); + + if (shouldDecay && arrayTy && arrayTy == eltTy) { + auto eltPtrTy = + getPointerTo(arrayTy.getElementType(), arrayPtrTy.getAddrSpace()); + return cir::GetElementOp::create(arrayLocEnd, eltPtrTy, arrayPtr, idx); + } + + // If we don't have sufficient type information, emit a PtrStrideOp. mlir::Value basePtr = arrayPtr; if (shouldDecay) basePtr = maybeBuildArrayDecay(arrayLocBegin, arrayPtr, eltTy); diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 95fc3afffb156..2866dfeacab13 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -2537,6 +2537,17 @@ LogicalResult cir::GetMemberOp::verify() { return mlir::success(); } +//===----------------------------------------------------------------------===// +// GetElementOp Definitions +//===----------------------------------------------------------------------===// + +LogicalResult cir::GetElementOp::verify() { + auto arrayTy = mlir::cast<cir::ArrayType>(getBaseType().getPointee()); + if (getElementType() != arrayTy.getElementType()) + return emitError() << "element type mismatch"; + return mlir::success(); +} + //===----------------------------------------------------------------------===// // VecCreateOp //===----------------------------------------------------------------------===// diff --git a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp index 7d854997848aa..9558942df992d 100644 --- a/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp +++ b/clang/lib/CIR/Lowering/DirectToLLVM/LowerToLLVM.cpp @@ -1357,6 +1357,55 @@ mlir::LogicalResult CIRToLLVMCastOpLowering::matchAndRewrite( return mlir::success(); } +static mlir::Value convertToIndexTy(mlir::ConversionPatternRewriter &rewriter, + mlir::ModuleOp mod, mlir::Value index, + mlir::Type baseTy, cir::IntType strideTy) { + mlir::Operation *indexOp = index.getDefiningOp(); + if (!indexOp) + return index; + + auto indexType = mlir::cast<mlir::IntegerType>(index.getType()); + mlir::DataLayout llvmLayout(mod); + std::optional<uint64_t> layoutWidth = llvmLayout.getTypeIndexBitwidth(baseTy); + + // If there is no change in width, don't do anything. + if (!layoutWidth || *layoutWidth == indexType.getWidth()) + return index; + + // If the index comes from a subtraction, make sure the extension happens + // before it. To achieve that, look at unary minus, which already got + // lowered to "sub 0, x". + auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp); + bool rewriteSub = false; + if (sub) { + if (auto lhsConst = dyn_cast<mlir::LLVM::ConstantOp>( + sub.getOperand(0).getDefiningOp())) { + auto lhsConstInt = mlir::dyn_cast<mlir::IntegerAttr>(lhsConst.getValue()); + if (lhsConstInt && lhsConstInt.getValue() == 0) { + index = sub.getOperand(1); + rewriteSub = true; + } + } + } + + auto llvmDstType = rewriter.getIntegerType(*layoutWidth); + bool isUnsigned = strideTy && strideTy.isUnsigned(); + index = getLLVMIntCast(rewriter, index, llvmDstType, isUnsigned, + indexType.getWidth(), *layoutWidth); + + if (rewriteSub) { + index = mlir::LLVM::SubOp::create( + rewriter, index.getLoc(), + mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(), + index.getType(), 0), + index); + // TODO: ensure sub is trivially dead now. + rewriter.eraseOp(sub); + } + + return index; +} + mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite( cir::PtrStrideOp ptrStrideOp, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { @@ -1366,7 +1415,6 @@ mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite( mlir::Type elementTy = convertTypeForMemory(*tc, dataLayout, ptrStrideOp.getElementType()); - mlir::MLIRContext *ctx = elementTy.getContext(); // void and function types doesn't really have a layout to use in GEPs, // make it i8 instead. @@ -1376,45 +1424,52 @@ mlir::LogicalResult CIRToLLVMPtrStrideOpLowering::matchAndRewrite( mlir::IntegerType::Signless); // Zero-extend, sign-extend or trunc the pointer value. mlir::Value index = adaptor.getStride(); - const unsigned width = - mlir::cast<mlir::IntegerType>(index.getType()).getWidth(); - const std::optional<std::uint64_t> layoutWidth = - dataLayout.getTypeIndexBitwidth(adaptor.getBase().getType()); - - mlir::Operation *indexOp = index.getDefiningOp(); - if (indexOp && layoutWidth && width != *layoutWidth) { - // If the index comes from a subtraction, make sure the extension happens - // before it. To achieve that, look at unary minus, which already got - // lowered to "sub 0, x". - const auto sub = dyn_cast<mlir::LLVM::SubOp>(indexOp); - auto unary = ptrStrideOp.getStride().getDefiningOp<cir::UnaryOp>(); - bool rewriteSub = - unary && unary.getKind() == cir::UnaryOpKind::Minus && sub; - if (rewriteSub) - index = indexOp->getOperand(1); - - // Handle the cast - const auto llvmDstType = mlir::IntegerType::get(ctx, *layoutWidth); - index = getLLVMIntCast(rewriter, index, llvmDstType, - ptrStrideOp.getStride().getType().isUnsigned(), - width, *layoutWidth); - - // Rewrite the sub in front of extensions/trunc - if (rewriteSub) { - index = mlir::LLVM::SubOp::create( - rewriter, index.getLoc(), index.getType(), - mlir::LLVM::ConstantOp::create(rewriter, index.getLoc(), - index.getType(), 0), - index); - rewriter.eraseOp(sub); - } - } + index = convertToIndexTy( + rewriter, ptrStrideOp->getParentOfType<mlir::ModuleOp>(), index, + adaptor.getBase().getType(), + dyn_cast<cir::IntType>(ptrStrideOp.getOperand(1).getType())); rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>( ptrStrideOp, resultTy, elementTy, adaptor.getBase(), index); return mlir::success(); } +mlir::LogicalResult CIRToLLVMGetElementOpLowering::matchAndRewrite( + cir::GetElementOp op, OpAdaptor adaptor, + mlir::ConversionPatternRewriter &rewriter) const { + if (auto arrayTy = + mlir::dyn_cast<cir::ArrayType>(op.getBaseType().getPointee())) { + const mlir::TypeConverter *converter = getTypeConverter(); + const mlir::Type llArrayTy = converter->convertType(arrayTy); + const mlir::Type llResultTy = converter->convertType(op.getType()); + mlir::Type elementTy = + convertTypeForMemory(*converter, dataLayout, op.getElementType()); + + // void and function types don't really have a layout to use in GEPs, + // make it i8 instead. + if (mlir::isa<mlir::LLVM::LLVMVoidType>(elementTy) || + mlir::isa<mlir::LLVM::LLVMFunctionType>(elementTy)) + elementTy = rewriter.getIntegerType(8); + + mlir::Value index = adaptor.getIndex(); + index = + convertToIndexTy(rewriter, op->getParentOfType<mlir::ModuleOp>(), index, + adaptor.getBase().getType(), + dyn_cast<cir::IntType>(op.getOperand(1).getType())); + + // Since the base address is a pointer to an aggregate, the first + // offset is always zero. The second offset tell us which member it + // will access. + std::array<mlir::LLVM::GEPArg, 2> offset{0, index}; + rewriter.replaceOpWithNewOp<mlir::LLVM::GEPOp>(op, llResultTy, llArrayTy, + adaptor.getBase(), offset); + return mlir::success(); + } + + op.emitError() << "NYI: GetElementOp lowering to LLVM for non-array"; + return mlir::failure(); +} + mlir::LogicalResult CIRToLLVMBaseClassAddrOpLowering::matchAndRewrite( cir::BaseClassAddrOp baseClassOp, OpAdaptor adaptor, mlir::ConversionPatternRewriter &rewriter) const { diff --git a/clang/test/CIR/CodeGen/array.cpp b/clang/test/CIR/CodeGen/array.cpp index 5e873810d494b..b5f2e906e620d 100644 --- a/clang/test/CIR/CodeGen/array.cpp +++ b/clang/test/CIR/CodeGen/array.cpp @@ -113,13 +113,11 @@ void func() { // CIR: %[[INIT:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e", init] // CIR: %[[INIT_2:.*]] = cir.alloca !s32i, !cir.ptr<!s32i>, ["e2", init] // CIR: %[[IDX:.*]] = cir.const #cir.int<0> : !s32i -// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 10>> -> !cir.ptr<!s32i> -// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[IDX]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ELE_PTR:.*]] = cir.get_element %[[ARR]][%[[IDX]]] : (!cir.ptr<!cir.array<!s32i x 10>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[TMP:.*]] = cir.load{{.*}} %[[ELE_PTR]] : !cir.ptr<!s32i>, !s32i // CIR" cir.store %[[TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i> // CIR: %[[IDX:.*]] = cir.const #cir.int<1> : !s32i -// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 10>> -> !cir.ptr<!s32i> -// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[IDX]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ELE_PTR:.*]] = cir.get_element %[[ARR]][%[[IDX]]] : (!cir.ptr<!cir.array<!s32i x 10>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[TMP:.*]] = cir.load{{.*}} %[[ELE_PTR]] : !cir.ptr<!s32i>, !s32i // CIR" cir.store %[[TMP]], %[[INIT_2]] : !s32i, !cir.ptr<!s32i> @@ -127,12 +125,10 @@ void func() { // LLVM-NEXT: %[[ARR:.*]] = alloca [10 x i32], i64 1, align 16 // LLVM-NEXT: %[[INIT:.*]] = alloca i32, i64 1, align 4 // LLVM-NEXT: %[[INIT_2:.*]] = alloca i32, i64 1, align 4 -// LLVM-NEXT: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0 -// LLVM-NEXT: %[[ELE_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 0 +// LLVM-NEXT: %[[ELE_PTR:.*]] = getelementptr [10 x i32], ptr %[[ARR]], i32 0, i64 0 // LLVM-NEXT: %[[TMP_1:.*]] = load i32, ptr %[[ELE_PTR]], align 16 // LLVM-NEXT: store i32 %[[TMP_1]], ptr %[[INIT]], align 4 -// LLVM-NEXT: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0 -// LLVM-NEXT: %[[ELE_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1 +// LLVM-NEXT: %[[ELE_PTR:.*]] = getelementptr [10 x i32], ptr %[[ARR]], i32 0, i64 1 // LLVM-NEXT: %[[TMP_2:.*]] = load i32, ptr %[[ELE_PTR]], align 4 // LLVM-NEXT: store i32 %[[TMP_2]], ptr %[[INIT_2]], align 4 @@ -176,8 +172,7 @@ void func3() { // CIR: %[[IDX_V:.*]] = cir.const #cir.int<1> : !s32i // CIR: cir.store{{.*}} %[[IDX_V]], %[[IDX]] : !s32i, !cir.ptr<!s32i> // CIR: %[[TMP_IDX:.*]] = cir.load{{.*}} %[[IDX]] : !cir.ptr<!s32i>, !s32i -// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 2>> -> !cir.ptr<!s32i> -// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[TMP_IDX]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ELE_PTR:.*]] = cir.get_element %[[ARR]][%[[TMP_IDX]]] : (!cir.ptr<!cir.array<!s32i x 2>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[ELE_TMP:.*]] = cir.load{{.*}} %[[ELE_PTR]] : !cir.ptr<!s32i>, !s32i // CIR: cir.store{{.*}} %[[ELE_TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i> @@ -188,9 +183,8 @@ void func3() { // LLVM: store [2 x i32] [i32 5, i32 6], ptr %[[ARR]], align 4 // LLVM: store i32 1, ptr %[[IDX]], align 4 // LLVM: %[[TMP1:.*]] = load i32, ptr %[[IDX]], align 4 -// LLVM: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR]], i32 0 // LLVM: %[[IDX_I64:.*]] = sext i32 %[[TMP1]] to i64 -// LLVM: %[[ELE:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 %[[IDX_I64]] +// LLVM: %[[ELE:.*]] = getelementptr [2 x i32], ptr %[[ARR]], i32 0, i64 %[[IDX_I64]] // LLVM: %[[TMP2:.*]] = load i32, ptr %[[ELE]], align 4 // LLVM: store i32 %[[TMP2]], ptr %[[INIT]], align 4 @@ -216,10 +210,8 @@ void func4() { // CIR: cir.store{{.*}} %[[CONST]], %[[ARR]] : !cir.array<!cir.array<!s32i x 1> x 2>, !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>> // CIR: %[[IDX:.*]] = cir.const #cir.int<0> : !s32i // CIR: %[[IDX_1:.*]] = cir.const #cir.int<1> : !s32i -// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>> -> !cir.ptr<!cir.array<!s32i x 1>> -// CIR: %[[ARR_1:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[IDX_1]] : (!cir.ptr<!cir.array<!s32i x 1>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 1>> -// CIR: %[[ARR_1_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR_1]] : !cir.ptr<!cir.array<!s32i x 1>> -> !cir.ptr<!s32i> -// CIR: %[[ELE_0:.*]] = cir.ptr_stride %[[ARR_1_PTR]], %[[IDX]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ARR_1:.*]] = cir.get_element %[[ARR]][%[[IDX_1]]] : (!cir.ptr<!cir.array<!cir.array<!s32i x 1> x 2>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 1>> +// CIR: %[[ELE_0:.*]] = cir.get_element %[[ARR_1]][%[[IDX]]] : (!cir.ptr<!cir.array<!s32i x 1>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[TMP:.*]] = cir.load{{.*}} %[[ELE_0]] : !cir.ptr<!s32i>, !s32i // CIR: cir.store{{.*}} %[[TMP]], %[[INIT]] : !s32i, !cir.ptr<!s32i> @@ -227,10 +219,8 @@ void func4() { // LLVM: %[[ARR:.*]] = alloca [2 x [1 x i32]], i64 1, align 4 // LLVM: %[[INIT:.*]] = alloca i32, i64 1, align 4 // LLVM: store [2 x [1 x i32]] {{\[}}[1 x i32] [i32 5], [1 x i32] [i32 6]], ptr %[[ARR]], align 4 -// LLVM: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR]], i32 0 -// LLVM: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1 -// LLVM: %[[ARR_1_0:.*]] = getelementptr i32, ptr %[[ARR_1]], i32 0 -// LLVM: %[[ELE_PTR:.*]] = getelementptr i32, ptr %[[ARR_1_0]], i64 0 +// LLVM: %[[ARR_1:.*]] = getelementptr [2 x [1 x i32]], ptr %[[ARR]], i32 0, i64 1 +// LLVM: %[[ELE_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_1]], i32 0, i64 0 // LLVM: %[[TMP:.*]] = load i32, ptr %[[ELE_PTR]], align 4 // LLVM: store i32 %[[TMP]], ptr %[[INIT]], align 4 @@ -367,8 +357,7 @@ void func9(int arr[10][5]) { // CIR: %[[IDX_1:.*]] = cir.const #cir.int<1> : !s32i // CIR: %[[TMP_1:.*]] = cir.load{{.*}} %[[ARR]] : !cir.ptr<!cir.ptr<!cir.array<!s32i x 5>>>, !cir.ptr<!cir.array<!s32i x 5>> // CIR: %[[ARR_1:.*]] = cir.ptr_stride %[[TMP_1]], %[[IDX_1]] : (!cir.ptr<!cir.array<!s32i x 5>>, !s32i) -> !cir.ptr<!cir.array<!s32i x 5>> -// CIR: %[[ARR_1_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR_1]] : !cir.ptr<!cir.array<!s32i x 5>> -> !cir.ptr<!s32i> -// CIR: %[[ARR_1_2:.*]] = cir.ptr_stride %[[ARR_1_PTR]], %[[IDX]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ARR_1_2:.*]] = cir.get_element %[[ARR_1]][%[[IDX]]] : (!cir.ptr<!cir.array<!s32i x 5>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[TMP_2:.*]] = cir.load{{.*}} %[[ARR_1_2]] : !cir.ptr<!s32i>, !s32i // CIR: cir.store{{.*}} %[[TMP_2]], %[[INIT]] : !s32i, !cir.ptr<!s32i> @@ -378,8 +367,7 @@ void func9(int arr[10][5]) { // LLVM: store ptr %[[ARG]], ptr %[[ARR]], align 8 // LLVM: %[[TMP_1:.*]] = load ptr, ptr %[[ARR]], align 8 // LLVM: %[[ARR_1:.*]] = getelementptr [5 x i32], ptr %[[TMP_1]], i64 1 -// LLVM: %[[ARR_1_PTR:.*]] = getelementptr i32, ptr %[[ARR_1]], i32 0 -// LLVM: %[[ARR_1_2:.*]] = getelementptr i32, ptr %[[ARR_1_PTR]], i64 2 +// LLVM: %[[ARR_1_2:.*]] = getelementptr [5 x i32], ptr %[[ARR_1]], i32 0, i64 2 // LLVM: %[[TMP_2:.*]] = load i32, ptr %[[ARR_1_2]], align 4 // LLVM: store i32 %[[TMP_2]], ptr %[[INIT]], align 4 diff --git a/clang/test/CIR/CodeGen/binassign.c b/clang/test/CIR/CodeGen/binassign.c index 4520063c56ee6..3368a6915de52 100644 --- a/clang/test/CIR/CodeGen/binassign.c +++ b/clang/test/CIR/CodeGen/binassign.c @@ -125,8 +125,7 @@ int ignore_result_assign() { // CIR: %[[VAL_0:.*]] = cir.const #cir.int<0> : !s32i // CIR: %[[VAL_5:.*]] = cir.const #cir.int<5> : !s32i // CIR: cir.store{{.*}} %[[VAL_5]], %[[I]] : !s32i, !cir.ptr<!s32i> -// CIR: %[[ARR_DECAY:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 10>> -> !cir.ptr<!s32i> -// CIR: %[[ARR_ELEM:.*]] = cir.ptr_stride %[[ARR_DECAY]], %[[VAL_5]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ARR_ELEM:.*]] = cir.get_element %[[ARR]][%[[VAL_5]]] : (!cir.ptr<!cir.array<!s32i x 10>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[ARR_LOAD:.*]] = cir.load{{.*}} %[[ARR_ELEM]] : !cir.ptr<!s32i>, !s32i // CIR: cir.store{{.*}} %[[ARR_LOAD]], %[[J]] : !s32i, !cir.ptr<!s32i> // CIR: %[[NULL:.*]] = cir.const #cir.ptr<null> : !cir.ptr<!s32i> @@ -157,9 +156,8 @@ int ignore_result_assign() { // LLVM: store i32 123, ptr %[[I_PTR]] // LLVM: store i32 123, ptr %[[J_PTR]] // LLVM: store i32 5, ptr %[[I_PTR]] -// LLVM: %[[GEP1:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i32 0 -// LLVM: %[[GEP2:.*]] = getelementptr i32, ptr %[[GEP1]], i64 5 -// LLVM: %[[ARR_VAL:.*]] = load i32, ptr %[[GEP2]] +// LLVM: %[[GEP:.*]] = getelementptr [10 x i32], ptr %[[ARR_PTR]], i32 0, i64 5 +// LLVM: %[[ARR_VAL:.*]] = load i32, ptr %[[GEP]] // LLVM: store i32 %[[ARR_VAL]], ptr %[[J_PTR]] // LLVM: store ptr null, ptr %[[Q_PTR]] // LLVM: br label diff --git a/clang/test/CIR/CodeGen/complex.cpp b/clang/test/CIR/CodeGen/complex.cpp index 82c9f2d7aaf26..97ce1a5dc1f6d 100644 --- a/clang/test/CIR/CodeGen/complex.cpp +++ b/clang/test/CIR/CodeGen/complex.cpp @@ -612,15 +612,13 @@ void foo24() { // CIR: %[[ARR:.*]] = cir.alloca !cir.array<!cir.complex<!s32i> x 2>, !cir.ptr<!cir.array<!cir.complex<!s32i> x 2>>, ["arr"] // CIR: %[[RESULT:.*]] = cir.alloca !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>>, ["r", init] // CIR: %[[IDX:.*]] = cir.const #cir.int<1> : !s32i -// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!cir.complex<!s32i> x 2>> -> !cir.ptr<!cir.complex<!s32i>> -// CIR: %[[RESULT_VAL:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[IDX]] : (!cir.ptr<!cir.complex<!s32i>>, !s32i) -> !cir.ptr<!cir.complex<!s32i>> +// CIR: %[[RESULT_VAL:.*]] = cir.get_element %[[ARR]][%[[IDX]]] : (!cir.ptr<!cir.array<!cir.complex<!s32i> x 2>>, !s32i) -> !cir.ptr<!cir.complex<!s32i>> // CIR: %[[TMP:.*]] = cir.load{{.*}} %[[RESULT_VAL]] : !cir.ptr<!cir.complex<!s32i>>, !cir.complex<!s32i> // CIR: cir.store{{.*}} %[[TMP]], %[[RESULT]] : !cir.complex<!s32i>, !cir.ptr<!cir.complex<!s32i>> // LLVM: %[[ARR:.*]] = alloca [2 x { i32, i32 }], i64 1, align 16 // LLVM: %[[RESULT:.*]] = alloca { i32, i32 }, i64 1, align 4 -// LLVM: %[[ARR_PTR:.*]] = getelementptr { i32, i32 }, ptr %[[ARR]], i32 0 -// LLVM: %[[RESULT_VAL:.*]] = getelementptr { i32, i32 }, ptr %[[ARR_PTR]], i64 1 +// LLVM: %[[RESULT_VAL:.*]] = getelementptr [2 x { i32, i32 }], ptr %[[ARR]], i32 0, i64 1 // LLVM: %[[TMP:.*]] = load { i32, i32 }, ptr %[[RESULT_VAL]], align 8 // LLVM: store { i32, i32 } %[[TMP]], ptr %[[RESULT]], align 4 diff --git a/clang/test/CIR/CodeGen/union.c b/clang/test/CIR/CodeGen/union.c index 7cf2c14e78e9d..aa66091985caa 100644 --- a/clang/test/CIR/CodeGen/union.c +++ b/clang/test/CIR/CodeGen/union.c @@ -177,16 +177,14 @@ void f3(union U3 u) { // CIR-NEXT: %[[ZERO_CHAR:.*]] = cir.cast integral %[[ZERO]] : !s32i -> !s8i // CIR-NEXT: %[[IDX:.*]] = cir.const #cir.int<2> : !s32i // CIR-NEXT: %[[C_PTR:.*]] = cir.get_member %[[U]][0] {name = "c"} : !cir.ptr<!rec_U3> -> !cir.ptr<!cir.array<!s8i x 5>> -// CIR-NEXT: %[[C_DECAY:.*]] = cir.cast array_to_ptrdecay %[[C_PTR]] : !cir.ptr<!cir.array<!s8i x 5>> -> !cir.ptr<!s8i> -// CIR-NEXT: %[[ELEM_PTR:.*]] = cir.ptr_stride %[[C_DECAY]], %[[IDX]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i> +// CIR-NEXT: %[[ELEM_PTR:.*]] = cir.get_element %[[C_PTR]][%[[IDX]]] : (!cir.ptr<!cir.array<!s8i x 5>>, !s32i) -> !cir.ptr<!s8i> // CIR-NEXT: cir.store{{.*}} %[[ZERO_CHAR]], %[[ELEM_PTR]] : !s8i, !cir.ptr<!s8i> // CIR-NEXT: cir.return // LLVM: define{{.*}} void @f3(%union.U3 %[[ARG:.*]]) // LLVM-NEXT: %[[U:.*]] = alloca %union.U3, i64 1, align 1 // LLVM-NEXT: store %union.U3 %[[ARG]], ptr %[[U]], align 1 -// LLVM-NEXT: %[[C_PTR:.*]] = getelementptr i8, ptr %[[U]], i32 0 -// LLVM-NEXT: %[[ELEM_PTR:.*]] = getelementptr i8, ptr %[[C_PTR]], i64 2 +// LLVM-NEXT: %[[ELEM_PTR:.*]] = getelementptr [5 x i8], ptr %[[U]], i32 0, i64 2 // LLVM-NEXT: store i8 0, ptr %[[ELEM_PTR]], align 1 // LLVM-NEXT: ret void @@ -209,16 +207,14 @@ void f5(union U4 u) { // CIR-NEXT: %[[CHAR_CAST:.*]] = cir.cast integral %[[CHAR_VAL]] : !s32i -> !s8i // CIR-NEXT: %[[IDX:.*]] = cir.const #cir.int<4> : !s32i // CIR-NEXT: %[[C_PTR:.*]] = cir.get_member %[[U]][0] {name = "c"} : !cir.ptr<!rec_U4> -> !cir.ptr<!cir.array<!s8i x 5>> -// CIR-NEXT: %[[C_DECAY:.*]] = cir.cast array_to_ptrdecay %[[C_PTR]] : !cir.ptr<!cir.array<!s8i x 5>> -> !cir.ptr<!s8i> -// CIR-NEXT: %[[ELEM_PTR:.*]] = cir.ptr_stride %[[C_DECAY]], %[[IDX]] : (!cir.ptr<!s8i>, !s32i) -> !cir.ptr<!s8i> +// CIR-NEXT: %[[ELEM_PTR:.*]] = cir.get_element %[[C_PTR]][%[[IDX]]] : (!cir.ptr<!cir.array<!s8i x 5>>, !s32i) -> !cir.ptr<!s8i> // CIR-NEXT: cir.store{{.*}} %[[CHAR_CAST]], %[[ELEM_PTR]] : !s8i, !cir.ptr<!s8i> // CIR-NEXT: cir.return // LLVM: define{{.*}} void @f5(%union.U4 %[[ARG:.*]]) // LLVM-NEXT: %[[U:.*]] = alloca %union.U4, i64 1, align 4 // LLVM-NEXT: store %union.U4 %[[ARG]], ptr %[[U]], align 4 -// LLVM-NEXT: %[[C_PTR:.*]] = getelementptr i8, ptr %[[U]], i32 0 -// LLVM-NEXT: %[[ELEM_PTR:.*]] = getelementptr i8, ptr %[[C_PTR]], i64 4 +// LLVM-NEXT: %[[ELEM_PTR:.*]] = getelementptr [5 x i8], ptr %[[U]], i32 0, i64 4 // LLVM-NEXT: store i8 65, ptr %[[ELEM_PTR]], align 4 // LLVM-NEXT: ret void diff --git a/clang/test/CIR/CodeGenBuiltins/builtin-constant-p.c b/clang/test/CIR/CodeGenBuiltins/builtin-constant-p.c index d684659216cba..31a27239ff178 100644 --- a/clang/test/CIR/CodeGenBuiltins/builtin-constant-p.c +++ b/clang/test/CIR/CodeGenBuiltins/builtin-constant-p.c @@ -168,8 +168,7 @@ int test6(void) { // CIR: cir.func {{.*}} @test6() -> !s32i // CIR: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i // CIR: %[[ARR:.*]] = cir.get_global @arr : !cir.ptr<!cir.array<!s32i x 3>> -// CIR: %[[ARR_PTR:.*]] = cir.cast array_to_ptrdecay %[[ARR]] : !cir.ptr<!cir.array<!s32i x 3>> -> !cir.ptr<!s32i> -// CIR: %[[ELE_PTR:.*]] = cir.ptr_stride %[[ARR_PTR]], %[[TWO]] : (!cir.ptr<!s32i>, !s32i) -> !cir.ptr<!s32i> +// CIR: %[[ELE_PTR:.*]] = cir.get_element %[[ARR]][%[[TWO]]] : (!cir.ptr<!cir.array<!s32i x 3>>, !s32i) -> !cir.ptr<!s32i> // CIR: %[[ELE:.*]] = cir.load{{.*}} %[[ELE_PTR]] : !cir.ptr<!s32i>, !s32i // CIR: %[[IS_CONSTANT:.*]] = cir.is_constant %[[ELE]] : !s32i -> !cir.bool diff --git a/clang/test/CIR/CodeGenOpenACC/combined-copy.c b/clang/test/CIR/CodeGenOpenACC/combined-copy.c index e1b4e593a86fd..09d5d55182f24 100644 --- a/clang/test/CIR/CodeGenOpenACC/combined-copy.c +++ b/clang/test/CIR/CodeGenOpenACC/combined-copy.c @@ -1088,9 +1088,8 @@ void copy_member_of_array_element_member() { for(int i = 0; i < 5; ++i); // CHECK-NEXT: %[[TWO:.*]] = cir.const #cir.int<2> : !s32i // CHECK-NEXT: %[[GETINNER:.*]] = cir.get_member %[[OUTER]][0] {name = "inner"} : !cir.ptr<!rec_OuterTy> -> !cir.ptr<!cir.array<!rec_InnerTy x 4>> - // CHECK-NEXT: %[[INNERDECAY:.*]] = cir.cast array_to_ptrdecay %[[GETINNER]] : !cir.ptr<!cir.array<!rec_InnerTy x 4>> -> !cir.ptr<!rec_InnerTy> - // CHECK-NEXT: %[[STRIDE:.*]] = cir.ptr_stride %[[INNERDECAY]], %[[TWO]] : (!cir.ptr<!rec_InnerTy>, !s32i) -> !cir.ptr<!rec_InnerTy> - // CHECK-NEXT: %[[GETB:.*]] = cir.get_member %[[STRIDE]][1] {name = "b"} : !cir.ptr<!rec_InnerTy> -> !cir.ptr<!s32i> + // CHECK-NEXT: %[[GET_ELT:.*]] = cir.get_element %[[GETINNER]][%[[TWO]]] : (!cir.ptr<!cir.array<!rec_InnerTy x 4>>, !s32i) -> !cir.ptr<!rec_InnerTy> + // CHECK-NEXT: %[[GETB:.*]] = cir.get_member %[[GET_ELT]][1] {name = "b"} : !cir.ptr<!rec_InnerTy> -> !cir.ptr<!s32i> // CHECK-NEXT: %[[COPYIN1:.*]] = acc.copyin varPtr(%[[GETB]] : !cir.ptr<!s32i>) -> !cir.ptr<!s32i> {dataClause = #acc<data_clause acc_copy>, name = "outer.inner[2].b"} // CHECK-NEXT: acc.parallel combined(loop) dataOperands(%[[COPYIN1]] : !cir.ptr<!s32i>) { // CHECK-NEXT: acc.loop combined(parallel) { diff --git a/clang/test/CIR/Lowering/array.cpp b/clang/test/CIR/Lowering/array.cpp index de4a77072b930..2b61ec1f45fcf 100644 --- a/clang/test/CIR/Lowering/array.cpp +++ b/clang/test/CIR/Lowering/array.cpp @@ -45,12 +45,10 @@ void func() { // CHECK-NEXT: %[[ARR_ALLOCA:.*]] = alloca [10 x i32], i64 1, align 16 // CHECK-NEXT: %[[INIT:.*]] = alloca i32, i64 1, align 4 // CHECK-NEXT: %[[INIT_2:.*]] = alloca i32, i64 1, align 4 -// CHECK-NEXT: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR_ALLOCA]], i32 0 -// CHECK-NEXT: %[[ELE_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 0 +// CHECK-NEXT: %[[ELE_PTR:.*]] = getelementptr [10 x i32], ptr %[[ARR_ALLOCA]], i32 0, i64 0 // CHECK-NEXT: %[[TMP:.*]] = load i32, ptr %[[ELE_PTR]], align 16 // CHECK-NEXT: store i32 %[[TMP]], ptr %[[INIT]], align 4 -// CHECK-NEXT: %[[ARR_PTR:.*]] = getelementptr i32, ptr %[[ARR_ALLOCA]], i32 0 -// CHECK-NEXT: %[[ELE_PTR:.*]] = getelementptr i32, ptr %[[ARR_PTR]], i64 1 +// CHECK-NEXT: %[[ELE_PTR:.*]] = getelementptr [10 x i32], ptr %[[ARR_ALLOCA]], i32 0, i64 1 // CHECK-NEXT: %[[TMP:.*]] = load i32, ptr %[[ELE_PTR]], align 4 // CHECK-NEXT: store i32 %[[TMP]], ptr %[[INIT_2]], align 4 @@ -78,10 +76,8 @@ void func4() { // CHECK: %[[ARR_ALLOCA:.*]] = alloca [2 x [1 x i32]], i64 1, align 4 // CHECK: %[[INIT:.*]] = alloca i32, i64 1, align 4 // CHECK: store [2 x [1 x i32]] {{\[}}[1 x i32] [i32 5], [1 x i32] [i32 6]], ptr %[[ARR_ALLOCA]], align 4 -// CHECK: %[[ARR_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_ALLOCA]], i32 0 -// CHECK: %[[ARR_1:.*]] = getelementptr [1 x i32], ptr %[[ARR_PTR]], i64 1 -// CHECK: %[[ARR_1_0:.*]] = getelementptr i32, ptr %[[ARR_1]], i32 0 -// CHECK: %[[ELE_PTR:.*]] = getelementptr i32, ptr %[[ARR_1_0]], i64 0 +// CHECK: %[[ARR_1:.*]] = getelementptr [2 x [1 x i32]], ptr %[[ARR_ALLOCA]], i32 0, i64 1 +// CHECK: %[[ELE_PTR:.*]] = getelementptr [1 x i32], ptr %[[ARR_1]], i32 0, i64 0 // CHECK: %[[TMP:.*]] = load i32, ptr %[[ELE_PTR]], align 4 // CHECK: store i32 %[[TMP]], ptr %[[INIT]], align 4 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
