[clang] [CIR] Upstream support for promoted types with unary plus/minus (PR #133829)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Thu Apr 3 11:23:24 PDT 2025
https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/133829
>From 92d711c92b89e08d47d7f617a222d982040a4f19 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Mon, 31 Mar 2025 17:02:08 -0700
Subject: [PATCH] [CIR] Upstream support for promoted types with unary
plus/minus
The initial upstreaming of unary operations left promoted types unhandled
for the unary plus and minus operators. This change implements support
for promoted types and performs a bit of related code cleanup.
---
clang/lib/CIR/CodeGen/CIRGenBuilder.h | 9 +++++
clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp | 38 +++++++++-----------
clang/test/CIR/CodeGen/unary.cpp | 42 ++++++++++++++++++++++
3 files changed, 68 insertions(+), 21 deletions(-)
diff --git a/clang/lib/CIR/CodeGen/CIRGenBuilder.h b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
index 03fb227a464a1..61a747254b3d0 100644
--- a/clang/lib/CIR/CodeGen/CIRGenBuilder.h
+++ b/clang/lib/CIR/CodeGen/CIRGenBuilder.h
@@ -160,6 +160,15 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
llvm_unreachable("negation for the given type is NYI");
}
+ // TODO: split this to createFPExt/createFPTrunc when we have dedicated cast
+ // operations.
+ mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType) {
+ assert(!cir::MissingFeatures::fpConstraints());
+
+ return create<cir::CastOp>(v.getLoc(), destType, cir::CastKind::floating,
+ v);
+ }
+
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
assert(!cir::MissingFeatures::metaDataNode());
assert(!cir::MissingFeatures::fpConstraints());
diff --git a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
index 5ac1dc1052c2e..6289a8f1d2ed7 100644
--- a/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
+++ b/clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp
@@ -88,13 +88,11 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
//===--------------------------------------------------------------------===//
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
- cgf.cgm.errorNYI(result.getLoc(), "floating cast for promoted value");
- return {};
+ return builder.createFloatingCast(result, cgf.convertType(promotionType));
}
mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
- cgf.cgm.errorNYI(result.getLoc(), "floating cast for unpromoted value");
- return {};
+ return builder.createFloatingCast(result, cgf.convertType(exprType));
}
mlir::Value emitPromoted(const Expr *e, QualType promotionType);
@@ -446,37 +444,35 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
llvm_unreachable("Unexpected signed overflow behavior kind");
}
- mlir::Value VisitUnaryPlus(const UnaryOperator *e,
- QualType promotionType = QualType()) {
- if (!promotionType.isNull())
- cgf.cgm.errorNYI(e->getSourceRange(), "VisitUnaryPlus: promotionType");
- assert(!cir::MissingFeatures::opUnaryPromotionType());
- mlir::Value result = emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
- return result;
+ mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
+ return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
}
- mlir::Value VisitUnaryMinus(const UnaryOperator *e,
- QualType promotionType = QualType()) {
- if (!promotionType.isNull())
- cgf.cgm.errorNYI(e->getSourceRange(), "VisitUnaryMinus: promotionType");
- assert(!cir::MissingFeatures::opUnaryPromotionType());
- mlir::Value result = emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
- return result;
+ mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
+ return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
}
mlir::Value emitUnaryPlusOrMinus(const UnaryOperator *e,
cir::UnaryOpKind kind) {
ignoreResultAssign = false;
- assert(!cir::MissingFeatures::opUnaryPromotionType());
- mlir::Value operand = Visit(e->getSubExpr());
+ QualType promotionType = getPromotionType(e->getSubExpr()->getType());
+
+ mlir::Value operand;
+ if (!promotionType.isNull())
+ operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
+ else
+ operand = Visit(e->getSubExpr());
bool nsw =
kind == cir::UnaryOpKind::Minus && e->getType()->isSignedIntegerType();
// NOTE: LLVM codegen will lower this directly to either a FNeg
// or a Sub instruction. In CIR this will be handled later in LowerToLLVM.
- return emitUnaryOp(e, kind, operand, nsw);
+ mlir::Value result = emitUnaryOp(e, kind, operand, nsw);
+ if (result && !promotionType.isNull())
+ return emitUnPromotedValue(result, e->getType());
+ return result;
}
mlir::Value emitUnaryOp(const UnaryOperator *e, cir::UnaryOpKind kind,
diff --git a/clang/test/CIR/CodeGen/unary.cpp b/clang/test/CIR/CodeGen/unary.cpp
index ca47c1068e08d..a6405e653a07c 100644
--- a/clang/test/CIR/CodeGen/unary.cpp
+++ b/clang/test/CIR/CodeGen/unary.cpp
@@ -424,3 +424,45 @@ void chars(char c) {
c++; // CHECK: cir.unary(inc, %{{.+}}) : !s8i, !s8i
c--; // CHECK: cir.unary(dec, %{{.+}}) : !s8i, !s8i
}
+
+_Float16 fp16UPlus(_Float16 f) {
+ return +f;
+}
+
+// CHECK: cir.func @fp16UPlus({{.*}}) -> !cir.f16
+// CHECK: %[[INPUT:.*]] = cir.load %[[F:.*]]
+// CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float
+// CHECK: %[[RESULT:.*]] = cir.unary(plus, %[[PROMOTED]])
+// CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16
+
+// LLVM: define half @fp16UPlus({{.*}})
+// LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
+// LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
+
+// OGCG: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}})
+// OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
+// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
+
+_Float16 fp16UMinus(_Float16 f) {
+ return -f;
+}
+
+// CHECK: cir.func @fp16UMinus({{.*}}) -> !cir.f16
+// CHECK: %[[INPUT:.*]] = cir.load %[[F:.*]]
+// CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float
+// CHECK: %[[RESULT:.*]] = cir.unary(minus, %[[PROMOTED]])
+// CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16
+
+// LLVM: define half @fp16UMinus({{.*}})
+// LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
+// LLVM: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
+// LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
+
+// OGCG: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}})
+// OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
+// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
+// OGCG: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
+// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
More information about the cfe-commits
mailing list