llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clang Author: Erich Keane (erichkeane) <details> <summary>Changes</summary> As a GNU extension, clang supports math on void* and function pointers in C mode only. From a CIR perspective, it makes sense to leave these types in the IR, since it might be useful to do analysis. During lowering, we already properly lower these to a size-1 element, so there is no changes that need to happen besides letting this get through CIR generation. This patch does that, plus adds some tests. --- Full diff: https://github.com/llvm/llvm-project/pull/184254.diff 2 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (-10) - (added) clang/test/CIR/CodeGen/gnu-ptr-math.c (+156) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp index 03c8369753f35..411f973118252 100644 --- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp @@ -676,11 +676,6 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> { // VLA types don't have constant size. cgf.cgm.errorNYI(e->getSourceRange(), "Pointer arithmetic on VLA"); return {}; - } else if (type->isFunctionType()) { - // Arithmetic on function pointers (!) is just +-1. - cgf.cgm.errorNYI(e->getSourceRange(), - "Pointer arithmetic on function pointer"); - return {}; } else { // For everything else, we can just do a simple increment. mlir::Location loc = cgf.getLoc(e->getSourceRange()); @@ -1812,11 +1807,6 @@ static mlir::Value emitPointerArithmetic(CIRGenFunction &cgf, return nullptr; } - if (elementType->isVoidType() || elementType->isFunctionType()) { - cgf.cgm.errorNYI("void* or function pointer arithmetic"); - return nullptr; - } - assert(!cir::MissingFeatures::sanitizers()); return cir::PtrStrideOp::create(cgf.getBuilder(), cgf.getLoc(op.e->getExprLoc()), diff --git a/clang/test/CIR/CodeGen/gnu-ptr-math.c b/clang/test/CIR/CodeGen/gnu-ptr-math.c new file mode 100644 index 0000000000000..e5b811a1d42fd --- /dev/null +++ b/clang/test/CIR/CodeGen/gnu-ptr-math.c @@ -0,0 +1,156 @@ +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-cir -mmlir --mlir-print-ir-before=cir-lowering-prepare %s -o %t.cir 2> %t-before.cir +// RUN: FileCheck %s --input-file=%t-before.cir --check-prefixes=CIR +// RUN: FileCheck %s --input-file=%t.cir --check-prefixes=CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -fclangir -emit-llvm %s -o - | FileCheck %s --check-prefixes=LLVM,LLVM_CIR +// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu -emit-llvm %s -o - | FileCheck %s --check-prefixes=LLVM,LLVM_OG + +typedef void *vptr; +typedef int(*fptr)(int, double); + +vptr vptr_add(vptr p) { + // CIR-LABEL: vptr_add + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<3> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]] + + // LLVM-LABEL: vptr_add + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]] + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 3 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: ret ptr %[[STRIDE]] + return p + 3; +} + +vptr vptr_sub(vptr p) { + // CIR-LABEL: vptr_sub + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-2> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]] + + // LLVM-LABEL: vptr_sub + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]] + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 -2 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: ret ptr %[[STRIDE]] + return p - 2; +} + +vptr vptr_inc(vptr p) { + // CIR-LABEL: vptr_inc + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[ARG]] + + // LLVM-LABEL: vptr_inc + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]] + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} 1 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: store ptr %[[STRIDE]], ptr %[[ARG]] + return p ++; +} +vptr vptr_dec(vptr p) { + // CIR-LABEL: vptr_dec + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!void>, !cir.ptr<!cir.ptr<!void>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!void>>, !cir.ptr<!void> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-1> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]] + + // LLVM-LABEL: vptr_dec + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]] + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} -1 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: ret ptr %[[STRIDE]] + return --p; +} + +fptr fptr_add(fptr p) { + // CIR-LABEL: fptr_add + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<3> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]] + + // LLVM-LABEL: fptr_add + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM-CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]] + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 3 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: ret ptr %[[STRIDE]] + return p + 3; +} + +fptr fptr_sub(fptr p) { + // CIR-LABEL: fptr_sub + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-2> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]] + + // LLVM-LABEL: fptr_sub + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[ARG_LOAD:.*]] = load ptr, ptr %[[ARG]] + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], i64 -2 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: ret ptr %[[STRIDE]] + return p - 2; +} + +fptr fptr_inc(fptr p) { + // CIR-LABEL: fptr_inc + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<1> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[ARG]] + + // LLVM-LABEL: fptr_inc + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} 1 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: store ptr %[[STRIDE]], ptr %[[ARG]] + return p ++; +} +fptr fptr_dec(fptr p) { + // CIR-LABEL: fptr_dec + // CIR: %[[ARG:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["p", init] + // CIR: %[[RET:.*]] = cir.alloca !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>, !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, ["__retval"] + // CIR: %[[ARG_LOAD:.*]] = cir.load {{.*}}%[[ARG]] : !cir.ptr<!cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>>>, !cir.ptr<!cir.func<(!s32i, !cir.double) -> !s32i>> + // CIR: %[[OFFSET:.*]] = cir.const #cir.int<-1> : !s32i + // CIR: %[[STRIDE:.*]] = cir.ptr_stride %[[ARG_LOAD]], %[[OFFSET]] + // CIR: cir.store {{.*}}%[[STRIDE]], %[[RET]] + + // LLVM-LABEL: fptr_dec + // LLVM: %[[ARG:.*]] = alloca ptr + // LLVM_CIR: %[[RET:.*]] = alloca ptr + // LLVM: %[[STRIDE:.*]] = getelementptr {{.*}}i8, ptr %[[ARG_LOAD]], {{.*}} -1 + // LLVM_CIR: store ptr %[[STRIDE:.*]], ptr %[[RET]] + // LLVM_OG: ret ptr %[[STRIDE]] + return --p; +} `````````` </details> https://github.com/llvm/llvm-project/pull/184254 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
