Skip to content

Commit a06ae97

Browse files
authored
[CIR] Upstream support for promoted types with unary plus/minus (#133829)
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.
1 parent 13aac46 commit a06ae97

File tree

3 files changed

+68
-21
lines changed

3 files changed

+68
-21
lines changed

clang/lib/CIR/CodeGen/CIRGenBuilder.h

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -160,6 +160,15 @@ class CIRGenBuilderTy : public cir::CIRBaseBuilderTy {
160160
llvm_unreachable("negation for the given type is NYI");
161161
}
162162

163+
// TODO: split this to createFPExt/createFPTrunc when we have dedicated cast
164+
// operations.
165+
mlir::Value createFloatingCast(mlir::Value v, mlir::Type destType) {
166+
assert(!cir::MissingFeatures::fpConstraints());
167+
168+
return create<cir::CastOp>(v.getLoc(), destType, cir::CastKind::floating,
169+
v);
170+
}
171+
163172
mlir::Value createFSub(mlir::Location loc, mlir::Value lhs, mlir::Value rhs) {
164173
assert(!cir::MissingFeatures::metaDataNode());
165174
assert(!cir::MissingFeatures::fpConstraints());

clang/lib/CIR/CodeGen/CIRGenExprScalar.cpp

Lines changed: 17 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,11 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
8888
//===--------------------------------------------------------------------===//
8989

9090
mlir::Value emitPromotedValue(mlir::Value result, QualType promotionType) {
91-
cgf.cgm.errorNYI(result.getLoc(), "floating cast for promoted value");
92-
return {};
91+
return builder.createFloatingCast(result, cgf.convertType(promotionType));
9392
}
9493

9594
mlir::Value emitUnPromotedValue(mlir::Value result, QualType exprType) {
96-
cgf.cgm.errorNYI(result.getLoc(), "floating cast for unpromoted value");
97-
return {};
95+
return builder.createFloatingCast(result, cgf.convertType(exprType));
9896
}
9997

10098
mlir::Value emitPromoted(const Expr *e, QualType promotionType);
@@ -446,37 +444,35 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
446444
llvm_unreachable("Unexpected signed overflow behavior kind");
447445
}
448446

449-
mlir::Value VisitUnaryPlus(const UnaryOperator *e,
450-
QualType promotionType = QualType()) {
451-
if (!promotionType.isNull())
452-
cgf.cgm.errorNYI(e->getSourceRange(), "VisitUnaryPlus: promotionType");
453-
assert(!cir::MissingFeatures::opUnaryPromotionType());
454-
mlir::Value result = emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
455-
return result;
447+
mlir::Value VisitUnaryPlus(const UnaryOperator *e) {
448+
return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Plus);
456449
}
457450

458-
mlir::Value VisitUnaryMinus(const UnaryOperator *e,
459-
QualType promotionType = QualType()) {
460-
if (!promotionType.isNull())
461-
cgf.cgm.errorNYI(e->getSourceRange(), "VisitUnaryMinus: promotionType");
462-
assert(!cir::MissingFeatures::opUnaryPromotionType());
463-
mlir::Value result = emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
464-
return result;
451+
mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
452+
return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
465453
}
466454

467455
mlir::Value emitUnaryPlusOrMinus(const UnaryOperator *e,
468456
cir::UnaryOpKind kind) {
469457
ignoreResultAssign = false;
470458

471-
assert(!cir::MissingFeatures::opUnaryPromotionType());
472-
mlir::Value operand = Visit(e->getSubExpr());
459+
QualType promotionType = getPromotionType(e->getSubExpr()->getType());
460+
461+
mlir::Value operand;
462+
if (!promotionType.isNull())
463+
operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
464+
else
465+
operand = Visit(e->getSubExpr());
473466

474467
bool nsw =
475468
kind == cir::UnaryOpKind::Minus && e->getType()->isSignedIntegerType();
476469

477470
// NOTE: LLVM codegen will lower this directly to either a FNeg
478471
// or a Sub instruction. In CIR this will be handled later in LowerToLLVM.
479-
return emitUnaryOp(e, kind, operand, nsw);
472+
mlir::Value result = emitUnaryOp(e, kind, operand, nsw);
473+
if (result && !promotionType.isNull())
474+
return emitUnPromotedValue(result, e->getType());
475+
return result;
480476
}
481477

482478
mlir::Value emitUnaryOp(const UnaryOperator *e, cir::UnaryOpKind kind,

clang/test/CIR/CodeGen/unary.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -424,3 +424,45 @@ void chars(char c) {
424424
c++; // CHECK: cir.unary(inc, %{{.+}}) : !s8i, !s8i
425425
c--; // CHECK: cir.unary(dec, %{{.+}}) : !s8i, !s8i
426426
}
427+
428+
_Float16 fp16UPlus(_Float16 f) {
429+
return +f;
430+
}
431+
432+
// CHECK: cir.func @fp16UPlus({{.*}}) -> !cir.f16
433+
// CHECK: %[[INPUT:.*]] = cir.load %[[F:.*]]
434+
// CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float
435+
// CHECK: %[[RESULT:.*]] = cir.unary(plus, %[[PROMOTED]])
436+
// CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16
437+
438+
// LLVM: define half @fp16UPlus({{.*}})
439+
// LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
440+
// LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
441+
// LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
442+
443+
// OGCG: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}})
444+
// OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
445+
// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
446+
// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
447+
448+
_Float16 fp16UMinus(_Float16 f) {
449+
return -f;
450+
}
451+
452+
// CHECK: cir.func @fp16UMinus({{.*}}) -> !cir.f16
453+
// CHECK: %[[INPUT:.*]] = cir.load %[[F:.*]]
454+
// CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float
455+
// CHECK: %[[RESULT:.*]] = cir.unary(minus, %[[PROMOTED]])
456+
// CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16
457+
458+
// LLVM: define half @fp16UMinus({{.*}})
459+
// LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
460+
// LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
461+
// LLVM: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
462+
// LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
463+
464+
// OGCG: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}})
465+
// OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
466+
// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
467+
// OGCG: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
468+
// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half

0 commit comments

Comments
 (0)