Skip to content

Commit 3abe579

Browse files
committed
[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.
1 parent 32f2402 commit 3abe579

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);
@@ -448,36 +446,34 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
448446
llvm_unreachable("Unexpected signed overflow behavior kind");
449447
}
450448

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

460-
mlir::Value VisitUnaryMinus(const UnaryOperator *e,
461-
QualType promotionType = QualType()) {
462-
if (!promotionType.isNull())
463-
cgf.cgm.errorNYI(e->getSourceRange(), "VisitUnaryMinus: promotionType");
464-
assert(!cir::MissingFeatures::opUnaryPromotionType());
465-
mlir::Value result = emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
466-
return result;
453+
mlir::Value VisitUnaryMinus(const UnaryOperator *e) {
454+
return emitUnaryPlusOrMinus(e, cir::UnaryOpKind::Minus);
467455
}
468456

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

473-
assert(!cir::MissingFeatures::opUnaryPromotionType());
474-
mlir::Value operand = Visit(e->getSubExpr());
461+
QualType promotionType = getPromotionType(e->getSubExpr()->getType());
462+
463+
mlir::Value operand;
464+
if (!promotionType.isNull())
465+
operand = cgf.emitPromotedScalarExpr(e->getSubExpr(), promotionType);
466+
else
467+
operand = Visit(e->getSubExpr());
475468

476469
assert(!cir::MissingFeatures::opUnarySignedOverflow());
477470

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

483479
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
@@ -405,3 +405,45 @@ float fpPostInc2() {
405405
// OGCG: store float %[[A_INC]], ptr %[[A]], align 4
406406
// OGCG: store float %[[A_LOAD]], ptr %[[B]], align 4
407407
// OGCG: %[[B_TO_OUTPUT:.*]] = load float, ptr %[[B]], align 4
408+
409+
_Float16 fp16UPlus(_Float16 f) {
410+
return +f;
411+
}
412+
413+
// CHECK: cir.func @fp16UPlus({{.*}}) -> !cir.f16
414+
// CHECK: %[[INPUT:.*]] = cir.load %[[F:.*]]
415+
// CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float
416+
// CHECK: %[[RESULT:.*]] = cir.unary(plus, %[[PROMOTED]])
417+
// CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16
418+
419+
// LLVM: define half @fp16UPlus({{.*}})
420+
// LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
421+
// LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
422+
// LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
423+
424+
// OGCG: define{{.*}} half @_Z9fp16UPlusDF16_({{.*}})
425+
// OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
426+
// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
427+
// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[PROMOTED]] to half
428+
429+
_Float16 fp16UMinus(_Float16 f) {
430+
return -f;
431+
}
432+
433+
// CHECK: cir.func @fp16UMinus({{.*}}) -> !cir.f16
434+
// CHECK: %[[INPUT:.*]] = cir.load %[[F:.*]]
435+
// CHECK: %[[PROMOTED:.*]] = cir.cast(floating, %[[INPUT]] : !cir.f16), !cir.float
436+
// CHECK: %[[RESULT:.*]] = cir.unary(minus, %[[PROMOTED]])
437+
// CHECK: %[[UNPROMOTED:.*]] = cir.cast(floating, %[[RESULT]] : !cir.float), !cir.f16
438+
439+
// LLVM: define half @fp16UMinus({{.*}})
440+
// LLVM: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
441+
// LLVM: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
442+
// LLVM: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
443+
// LLVM: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half
444+
445+
// OGCG: define{{.*}} half @_Z10fp16UMinusDF16_({{.*}})
446+
// OGCG: %[[F_LOAD:.*]] = load half, ptr %{{.*}}, align 2
447+
// OGCG: %[[PROMOTED:.*]] = fpext half %[[F_LOAD]] to float
448+
// OGCG: %[[RESULT:.*]] = fneg float %[[PROMOTED]]
449+
// OGCG: %[[UNPROMOTED:.*]] = fptrunc float %[[RESULT]] to half

0 commit comments

Comments
 (0)