@@ -115,6 +115,16 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
115
115
// / Emit a value that corresponds to null for the given type.
116
116
mlir::Value buildNullValue (QualType Ty, mlir::Location loc);
117
117
118
+ mlir::Value buildPromotedValue (mlir::Value result, QualType PromotionType) {
119
+ return Builder.createFloatingCast (result, ConvertType (PromotionType));
120
+ }
121
+
122
+ mlir::Value buildUnPromotedValue (mlir::Value result, QualType ExprType) {
123
+ return Builder.createFloatingCast (result, ConvertType (ExprType));
124
+ }
125
+
126
+ mlir::Value buildPromoted (const Expr *E, QualType PromotionType);
127
+
118
128
// ===--------------------------------------------------------------------===//
119
129
// Visitor Methods
120
130
// ===--------------------------------------------------------------------===//
@@ -478,14 +488,38 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
478
488
} else if (type->isVectorType ()) {
479
489
llvm_unreachable (" no vector inc/dec yet" );
480
490
} else if (type->isRealFloatingType ()) {
481
- auto isFloatOrDouble = type->isSpecificBuiltinType (BuiltinType::Float) ||
482
- type->isSpecificBuiltinType (BuiltinType::Double);
483
- assert (isFloatOrDouble && " Non-float/double NYI" );
484
-
485
- // Create the inc/dec operation.
486
- auto kind =
487
- (isInc ? mlir::cir::UnaryOpKind::Inc : mlir::cir::UnaryOpKind::Dec);
488
- value = buildUnaryOp (E, kind, input);
491
+ if (type->isHalfType ())
492
+ llvm_unreachable (" __fp16 type NYI" );
493
+
494
+ if (value.getType ().isa <mlir::cir::SingleType, mlir::cir::DoubleType>()) {
495
+ // Create the inc/dec operation.
496
+ auto kind =
497
+ (isInc ? mlir::cir::UnaryOpKind::Inc : mlir::cir::UnaryOpKind::Dec);
498
+ value = buildUnaryOp (E, kind, input);
499
+ } else {
500
+ // Remaining types are Half, Bfloat16, LongDouble, __ibm128 or
501
+ // __float128. Convert from float.
502
+
503
+ llvm::APFloat F (static_cast <float >(amount));
504
+ bool ignored;
505
+ const llvm::fltSemantics *FS;
506
+ // Don't use getFloatTypeSemantics because Half isn't
507
+ // necessarily represented using the "half" LLVM type.
508
+ if (value.getType ().isa <mlir::cir::LongDoubleType>())
509
+ FS = &CGF.getTarget ().getLongDoubleFormat ();
510
+ else if (value.getType ().isa <mlir::cir::FP16Type>())
511
+ FS = &CGF.getTarget ().getHalfFormat ();
512
+ else if (value.getType ().isa <mlir::cir::BF16Type>())
513
+ FS = &CGF.getTarget ().getBFloat16Format ();
514
+ else
515
+ llvm_unreachable (" fp128 / ppc_fp128 NYI" );
516
+ F.convert (*FS, llvm::APFloat::rmTowardZero, &ignored);
517
+
518
+ auto loc = CGF.getLoc (E->getExprLoc ());
519
+ auto amt = Builder.getConstant (
520
+ loc, mlir::cir::FPAttr::get (value.getType (), F));
521
+ value = Builder.createBinop (value, mlir::cir::BinOpKind::Add, amt);
522
+ }
489
523
490
524
} else if (type->isFixedPointType ()) {
491
525
llvm_unreachable (" no fixed point inc/dec yet" );
@@ -549,21 +583,22 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
549
583
return Visit (E->getSubExpr ()); // the actual value should be unused
550
584
return buildLoadOfLValue (E);
551
585
}
552
- mlir::Value VisitUnaryPlus (const UnaryOperator *E) {
553
- // NOTE(cir): QualType function parameter still not used, so don´t replicate
554
- // it here yet.
555
- QualType promotionTy = getPromotionType (E->getSubExpr ()->getType ());
586
+ mlir::Value VisitUnaryPlus (const UnaryOperator *E,
587
+ QualType PromotionType = QualType()) {
588
+ QualType promotionTy = PromotionType.isNull ()
589
+ ? getPromotionType (E->getSubExpr ()->getType ())
590
+ : PromotionType;
556
591
auto result = VisitPlus (E, promotionTy);
557
592
if (result && !promotionTy.isNull ())
558
- assert ( 0 && " not implemented yet " );
593
+ result = buildUnPromotedValue (result, E-> getType () );
559
594
return buildUnaryOp (E, mlir::cir::UnaryOpKind::Plus, result);
560
595
}
561
596
562
597
mlir::Value VisitPlus (const UnaryOperator *E, QualType PromotionType) {
563
598
// This differs from gcc, though, most likely due to a bug in gcc.
564
599
TestAndClearIgnoreResultAssign ();
565
600
if (!PromotionType.isNull ())
566
- assert ( 0 && " scalar promotion not implemented yet " );
601
+ return CGF. buildPromotedScalarExpr (E-> getSubExpr (), PromotionType );
567
602
return Visit (E->getSubExpr ());
568
603
}
569
604
@@ -573,14 +608,14 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
573
608
QualType promotionTy = getPromotionType (E->getSubExpr ()->getType ());
574
609
auto result = VisitMinus (E, promotionTy);
575
610
if (result && !promotionTy.isNull ())
576
- assert ( 0 && " not implemented yet " );
611
+ result = buildUnPromotedValue (result, E-> getType () );
577
612
return buildUnaryOp (E, mlir::cir::UnaryOpKind::Minus, result);
578
613
}
579
614
580
615
mlir::Value VisitMinus (const UnaryOperator *E, QualType PromotionType) {
581
616
TestAndClearIgnoreResultAssign ();
582
617
if (!PromotionType.isNull ())
583
- assert ( 0 && " scalar promotion not implemented yet " );
618
+ return CGF. buildPromotedScalarExpr (E-> getSubExpr (), PromotionType );
584
619
585
620
// NOTE: LLVM codegen will lower this directly to either a FNeg
586
621
// or a Sub instruction. In CIR this will be handled later in LowerToLLVM.
@@ -752,13 +787,17 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
752
787
QualType DstType, mlir::Type SrcTy,
753
788
mlir::Type DstTy, ScalarConversionOpts Opts);
754
789
755
- BinOpInfo buildBinOps (const BinaryOperator *E) {
790
+ BinOpInfo buildBinOps (const BinaryOperator *E,
791
+ QualType PromotionType = QualType()) {
756
792
BinOpInfo Result;
757
- Result.LHS = Visit (E->getLHS ());
758
- Result.RHS = Visit (E->getRHS ());
759
- Result.FullType = E->getType ();
760
- Result.CompType = E->getType ();
761
- if (auto VecType = dyn_cast_or_null<VectorType>(E->getType ())) {
793
+ Result.LHS = CGF.buildPromotedScalarExpr (E->getLHS (), PromotionType);
794
+ Result.RHS = CGF.buildPromotedScalarExpr (E->getRHS (), PromotionType);
795
+ if (!PromotionType.isNull ())
796
+ Result.FullType = PromotionType;
797
+ else
798
+ Result.FullType = E->getType ();
799
+ Result.CompType = Result.FullType ;
800
+ if (const auto *VecType = dyn_cast_or_null<VectorType>(Result.FullType )) {
762
801
Result.CompType = VecType->getElementType ();
763
802
}
764
803
Result.Opcode = E->getOpcode ();
@@ -793,15 +832,22 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
793
832
if (auto *CT = Ty->getAs <ComplexType>()) {
794
833
llvm_unreachable (" NYI" );
795
834
}
796
- if (Ty.UseExcessPrecision (CGF.getContext ()))
797
- llvm_unreachable (" NYI" );
835
+ if (Ty.UseExcessPrecision (CGF.getContext ())) {
836
+ if (auto *VT = Ty->getAs <VectorType>())
837
+ llvm_unreachable (" NYI" );
838
+ return CGF.getContext ().FloatTy ;
839
+ }
798
840
return QualType ();
799
841
}
800
842
801
843
// Binary operators and binary compound assignment operators.
802
844
#define HANDLEBINOP (OP ) \
803
845
mlir::Value VisitBin##OP(const BinaryOperator *E) { \
804
- return build##OP (buildBinOps (E)); \
846
+ QualType promotionTy = getPromotionType (E->getType ()); \
847
+ auto result = build##OP (buildBinOps (E, promotionTy)); \
848
+ if (result && !promotionTy.isNull ()) \
849
+ result = buildUnPromotedValue (result, E->getType ()); \
850
+ return result; \
805
851
} \
806
852
mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *E) { \
807
853
return buildCompoundAssign (E, &ScalarExprEmitter::build##OP); \
@@ -1053,6 +1099,13 @@ mlir::Value CIRGenFunction::buildScalarExpr(const Expr *E) {
1053
1099
return ScalarExprEmitter (*this , builder).Visit (const_cast <Expr *>(E));
1054
1100
}
1055
1101
1102
+ mlir::Value CIRGenFunction::buildPromotedScalarExpr (const Expr *E,
1103
+ QualType PromotionType) {
1104
+ if (!PromotionType.isNull ())
1105
+ return ScalarExprEmitter (*this , builder).buildPromoted (E, PromotionType);
1106
+ return ScalarExprEmitter (*this , builder).Visit (const_cast <Expr *>(E));
1107
+ }
1108
+
1056
1109
[[maybe_unused]] static bool MustVisitNullValue (const Expr *E) {
1057
1110
// If a null pointer expression's type is the C++0x nullptr_t, then
1058
1111
// it's not necessarily a simple constant and it must be evaluated
@@ -1885,8 +1938,20 @@ LValue ScalarExprEmitter::buildCompoundAssignLValue(
1885
1938
1886
1939
// Emit the RHS first. __block variables need to have the rhs evaluated
1887
1940
// first, plus this should improve codegen a little.
1888
- OpInfo.RHS = Visit (E->getRHS ());
1889
- OpInfo.FullType = E->getComputationResultType ();
1941
+
1942
+ QualType PromotionTypeCR = getPromotionType (E->getComputationResultType ());
1943
+ if (PromotionTypeCR.isNull ())
1944
+ PromotionTypeCR = E->getComputationResultType ();
1945
+
1946
+ QualType PromotionTypeLHS = getPromotionType (E->getComputationLHSType ());
1947
+ QualType PromotionTypeRHS = getPromotionType (E->getRHS ()->getType ());
1948
+
1949
+ if (!PromotionTypeRHS.isNull ())
1950
+ OpInfo.RHS = CGF.buildPromotedScalarExpr (E->getRHS (), PromotionTypeRHS);
1951
+ else
1952
+ OpInfo.RHS = Visit (E->getRHS ());
1953
+
1954
+ OpInfo.FullType = PromotionTypeCR;
1890
1955
OpInfo.CompType = OpInfo.FullType ;
1891
1956
if (auto VecType = dyn_cast_or_null<VectorType>(OpInfo.FullType )) {
1892
1957
OpInfo.CompType = VecType->getElementType ();
@@ -1908,16 +1973,20 @@ LValue ScalarExprEmitter::buildCompoundAssignLValue(
1908
1973
CIRGenFunction::SourceLocRAIIObject sourceloc{
1909
1974
CGF, CGF.getLoc (E->getSourceRange ())};
1910
1975
SourceLocation Loc = E->getExprLoc ();
1911
- OpInfo.LHS =
1912
- buildScalarConversion (OpInfo.LHS , LHSTy, E->getComputationLHSType (), Loc);
1976
+ if (!PromotionTypeLHS.isNull ())
1977
+ OpInfo.LHS = buildScalarConversion (OpInfo.LHS , LHSTy, PromotionTypeLHS,
1978
+ E->getExprLoc ());
1979
+ else
1980
+ OpInfo.LHS = buildScalarConversion (OpInfo.LHS , LHSTy,
1981
+ E->getComputationLHSType (), Loc);
1913
1982
1914
1983
// Expand the binary operator.
1915
1984
Result = (this ->*Func)(OpInfo);
1916
1985
1917
1986
// Convert the result back to the LHS type,
1918
1987
// potentially with Implicit Conversion sanitizer check.
1919
- Result = buildScalarConversion (Result, E-> getComputationResultType () , LHSTy,
1920
- Loc, ScalarConversionOpts (CGF.SanOpts ));
1988
+ Result = buildScalarConversion (Result, PromotionTypeCR , LHSTy, Loc ,
1989
+ ScalarConversionOpts (CGF.SanOpts ));
1921
1990
1922
1991
// Store the result value into the LHS lvalue. Bit-fields are handled
1923
1992
// specially because the result is altered by the store, i.e., [C99 6.5.16p1]
@@ -1938,6 +2007,44 @@ mlir::Value ScalarExprEmitter::buildNullValue(QualType Ty, mlir::Location loc) {
1938
2007
return CGF.buildFromMemory (CGF.CGM .buildNullConstant (Ty, loc), Ty);
1939
2008
}
1940
2009
2010
+ mlir::Value ScalarExprEmitter::buildPromoted (const Expr *E,
2011
+ QualType PromotionType) {
2012
+ E = E->IgnoreParens ();
2013
+ if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
2014
+ switch (BO->getOpcode ()) {
2015
+ #define HANDLE_BINOP (OP ) \
2016
+ case BO_##OP: \
2017
+ return build##OP (buildBinOps (BO, PromotionType));
2018
+ HANDLE_BINOP (Add)
2019
+ HANDLE_BINOP (Sub)
2020
+ HANDLE_BINOP (Mul)
2021
+ HANDLE_BINOP (Div)
2022
+ #undef HANDLE_BINOP
2023
+ default :
2024
+ break ;
2025
+ }
2026
+ } else if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
2027
+ switch (UO->getOpcode ()) {
2028
+ case UO_Imag:
2029
+ case UO_Real:
2030
+ llvm_unreachable (" NYI" );
2031
+ case UO_Minus:
2032
+ return VisitMinus (UO, PromotionType);
2033
+ case UO_Plus:
2034
+ return VisitPlus (UO, PromotionType);
2035
+ default :
2036
+ break ;
2037
+ }
2038
+ }
2039
+ auto result = Visit (const_cast <Expr *>(E));
2040
+ if (result) {
2041
+ if (!PromotionType.isNull ())
2042
+ return buildPromotedValue (result, PromotionType);
2043
+ return buildUnPromotedValue (result, E->getType ());
2044
+ }
2045
+ return result;
2046
+ }
2047
+
1941
2048
mlir::Value ScalarExprEmitter::buildCompoundAssign (
1942
2049
const CompoundAssignOperator *E,
1943
2050
mlir::Value (ScalarExprEmitter::*Func)(const BinOpInfo &)) {
0 commit comments