[clang] [CIR] Upstream support for promoted types with unary plus/minus (PR #133829)
via cfe-commits
cfe-commits at lists.llvm.org
Mon Mar 31 17:07:21 PDT 2025
llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT-->
@llvm/pr-subscribers-clang
Author: Andy Kaylor (andykaylor)
<details>
<summary>Changes</summary>
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.
---
Full diff: https://github.com/llvm/llvm-project/pull/133829.diff
3 Files Affected:
- (modified) clang/lib/CIR/CodeGen/CIRGenBuilder.h (+9)
- (modified) clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp (+17-21)
- (modified) clang/test/CIR/CodeGen/unary.cpp (+42)
``````````diff
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 2cf92dfbf3a5b..44377aca7b82e 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);
@@ -448,36 +446,34 @@ 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());
assert(!cir::MissingFeatures::opUnarySignedOverflow());
// 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);
+ mlir::Value result = emitUnaryOp(e, kind, operand);
+ 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 3e041e14ce177..5cb0e9b1ea5bd 100644
--- a/clang/test/CIR/CodeGen/unary.cpp
+++ b/clang/test/CIR/CodeGen/unary.cpp
@@ -405,3 +405,45 @@ float fpPostInc2() {
// OGCG: store float %[[A_INC]], ptr %[[A]], align 4
// OGCG: store float %[[A_LOAD]], ptr %[[B]], align 4
// OGCG: %[[B_TO_OUTPUT:.*]] = load float, ptr %[[B]], align 4
+
+_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
``````````
</details>
https://github.com/llvm/llvm-project/pull/133829
More information about the cfe-commits
mailing list