@@ -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,45 @@ 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" );
491
+ // TODO(cir): CGFPOptionsRAII
492
+ assert (!UnimplementedFeature::CGFPOptionsRAII ());
484
493
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);
494
+ if (type->isHalfType () && !CGF.getContext ().getLangOpts ().NativeHalfType )
495
+ llvm_unreachable (" __fp16 type NYI" );
496
+
497
+ if (value.getType ().isa <mlir::cir::SingleType, mlir::cir::DoubleType>()) {
498
+ // Create the inc/dec operation.
499
+ // NOTE(CIR): clang calls CreateAdd but folds this to a unary op
500
+ auto kind =
501
+ (isInc ? mlir::cir::UnaryOpKind::Inc : mlir::cir::UnaryOpKind::Dec);
502
+ value = buildUnaryOp (E, kind, input);
503
+ } else {
504
+ // Remaining types are Half, Bfloat16, LongDouble, __ibm128 or
505
+ // __float128. Convert from float.
506
+
507
+ llvm::APFloat F (static_cast <float >(amount));
508
+ bool ignored;
509
+ const llvm::fltSemantics *FS;
510
+ // Don't use getFloatTypeSemantics because Half isn't
511
+ // necessarily represented using the "half" LLVM type.
512
+ if (value.getType ().isa <mlir::cir::LongDoubleType>())
513
+ FS = &CGF.getTarget ().getLongDoubleFormat ();
514
+ else if (value.getType ().isa <mlir::cir::FP16Type>())
515
+ FS = &CGF.getTarget ().getHalfFormat ();
516
+ else if (value.getType ().isa <mlir::cir::BF16Type>())
517
+ FS = &CGF.getTarget ().getBFloat16Format ();
518
+ else
519
+ llvm_unreachable (" fp128 / ppc_fp128 NYI" );
520
+ F.convert (*FS, llvm::APFloat::rmTowardZero, &ignored);
521
+
522
+ auto loc = CGF.getLoc (E->getExprLoc ());
523
+ auto amt = Builder.getConstant (
524
+ loc, mlir::cir::FPAttr::get (value.getType (), F));
525
+ value = Builder.createBinop (value, mlir::cir::BinOpKind::Add, amt);
526
+ }
527
+
528
+ if (type->isHalfType () && !CGF.getContext ().getLangOpts ().NativeHalfType )
529
+ llvm_unreachable (" NYI" );
489
530
490
531
} else if (type->isFixedPointType ()) {
491
532
llvm_unreachable (" no fixed point inc/dec yet" );
@@ -549,21 +590,22 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
549
590
return Visit (E->getSubExpr ()); // the actual value should be unused
550
591
return buildLoadOfLValue (E);
551
592
}
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 ());
593
+ mlir::Value VisitUnaryPlus (const UnaryOperator *E,
594
+ QualType PromotionType = QualType()) {
595
+ QualType promotionTy = PromotionType.isNull ()
596
+ ? getPromotionType (E->getSubExpr ()->getType ())
597
+ : PromotionType;
556
598
auto result = VisitPlus (E, promotionTy);
557
599
if (result && !promotionTy.isNull ())
558
- assert ( 0 && " not implemented yet " );
600
+ result = buildUnPromotedValue (result, E-> getType () );
559
601
return buildUnaryOp (E, mlir::cir::UnaryOpKind::Plus, result);
560
602
}
561
603
562
604
mlir::Value VisitPlus (const UnaryOperator *E, QualType PromotionType) {
563
605
// This differs from gcc, though, most likely due to a bug in gcc.
564
606
TestAndClearIgnoreResultAssign ();
565
607
if (!PromotionType.isNull ())
566
- assert ( 0 && " scalar promotion not implemented yet " );
608
+ return CGF. buildPromotedScalarExpr (E-> getSubExpr (), PromotionType );
567
609
return Visit (E->getSubExpr ());
568
610
}
569
611
@@ -573,14 +615,14 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
573
615
QualType promotionTy = getPromotionType (E->getSubExpr ()->getType ());
574
616
auto result = VisitMinus (E, promotionTy);
575
617
if (result && !promotionTy.isNull ())
576
- assert ( 0 && " not implemented yet " );
618
+ result = buildUnPromotedValue (result, E-> getType () );
577
619
return buildUnaryOp (E, mlir::cir::UnaryOpKind::Minus, result);
578
620
}
579
621
580
622
mlir::Value VisitMinus (const UnaryOperator *E, QualType PromotionType) {
581
623
TestAndClearIgnoreResultAssign ();
582
624
if (!PromotionType.isNull ())
583
- assert ( 0 && " scalar promotion not implemented yet " );
625
+ return CGF. buildPromotedScalarExpr (E-> getSubExpr (), PromotionType );
584
626
585
627
// NOTE: LLVM codegen will lower this directly to either a FNeg
586
628
// or a Sub instruction. In CIR this will be handled later in LowerToLLVM.
@@ -752,18 +794,23 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
752
794
QualType DstType, mlir::Type SrcTy,
753
795
mlir::Type DstTy, ScalarConversionOpts Opts);
754
796
755
- BinOpInfo buildBinOps (const BinaryOperator *E) {
797
+ BinOpInfo buildBinOps (const BinaryOperator *E,
798
+ QualType PromotionType = QualType()) {
756
799
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 ())) {
800
+ Result.LHS = CGF.buildPromotedScalarExpr (E->getLHS (), PromotionType);
801
+ Result.RHS = CGF.buildPromotedScalarExpr (E->getRHS (), PromotionType);
802
+ if (!PromotionType.isNull ())
803
+ Result.FullType = PromotionType;
804
+ else
805
+ Result.FullType = E->getType ();
806
+ Result.CompType = Result.FullType ;
807
+ if (const auto *VecType = dyn_cast_or_null<VectorType>(Result.FullType )) {
762
808
Result.CompType = VecType->getElementType ();
763
809
}
764
810
Result.Opcode = E->getOpcode ();
765
811
Result.Loc = E->getSourceRange ();
766
812
// TODO: Result.FPFeatures
813
+ assert (!UnimplementedFeature::getFPFeaturesInEffect ());
767
814
Result.E = E;
768
815
return Result;
769
816
}
@@ -793,15 +840,22 @@ class ScalarExprEmitter : public StmtVisitor<ScalarExprEmitter, mlir::Value> {
793
840
if (auto *CT = Ty->getAs <ComplexType>()) {
794
841
llvm_unreachable (" NYI" );
795
842
}
796
- if (Ty.UseExcessPrecision (CGF.getContext ()))
797
- llvm_unreachable (" NYI" );
843
+ if (Ty.UseExcessPrecision (CGF.getContext ())) {
844
+ if (auto *VT = Ty->getAs <VectorType>())
845
+ llvm_unreachable (" NYI" );
846
+ return CGF.getContext ().FloatTy ;
847
+ }
798
848
return QualType ();
799
849
}
800
850
801
851
// Binary operators and binary compound assignment operators.
802
852
#define HANDLEBINOP (OP ) \
803
853
mlir::Value VisitBin##OP(const BinaryOperator *E) { \
804
- return build##OP (buildBinOps (E)); \
854
+ QualType promotionTy = getPromotionType (E->getType ()); \
855
+ auto result = build##OP (buildBinOps (E, promotionTy)); \
856
+ if (result && !promotionTy.isNull ()) \
857
+ result = buildUnPromotedValue (result, E->getType ()); \
858
+ return result; \
805
859
} \
806
860
mlir::Value VisitBin##OP##Assign(const CompoundAssignOperator *E) { \
807
861
return buildCompoundAssign (E, &ScalarExprEmitter::build##OP); \
@@ -1053,6 +1107,13 @@ mlir::Value CIRGenFunction::buildScalarExpr(const Expr *E) {
1053
1107
return ScalarExprEmitter (*this , builder).Visit (const_cast <Expr *>(E));
1054
1108
}
1055
1109
1110
+ mlir::Value CIRGenFunction::buildPromotedScalarExpr (const Expr *E,
1111
+ QualType PromotionType) {
1112
+ if (!PromotionType.isNull ())
1113
+ return ScalarExprEmitter (*this , builder).buildPromoted (E, PromotionType);
1114
+ return ScalarExprEmitter (*this , builder).Visit (const_cast <Expr *>(E));
1115
+ }
1116
+
1056
1117
[[maybe_unused]] static bool MustVisitNullValue (const Expr *E) {
1057
1118
// If a null pointer expression's type is the C++0x nullptr_t, then
1058
1119
// it's not necessarily a simple constant and it must be evaluated
@@ -1885,8 +1946,20 @@ LValue ScalarExprEmitter::buildCompoundAssignLValue(
1885
1946
1886
1947
// Emit the RHS first. __block variables need to have the rhs evaluated
1887
1948
// first, plus this should improve codegen a little.
1888
- OpInfo.RHS = Visit (E->getRHS ());
1889
- OpInfo.FullType = E->getComputationResultType ();
1949
+
1950
+ QualType PromotionTypeCR = getPromotionType (E->getComputationResultType ());
1951
+ if (PromotionTypeCR.isNull ())
1952
+ PromotionTypeCR = E->getComputationResultType ();
1953
+
1954
+ QualType PromotionTypeLHS = getPromotionType (E->getComputationLHSType ());
1955
+ QualType PromotionTypeRHS = getPromotionType (E->getRHS ()->getType ());
1956
+
1957
+ if (!PromotionTypeRHS.isNull ())
1958
+ OpInfo.RHS = CGF.buildPromotedScalarExpr (E->getRHS (), PromotionTypeRHS);
1959
+ else
1960
+ OpInfo.RHS = Visit (E->getRHS ());
1961
+
1962
+ OpInfo.FullType = PromotionTypeCR;
1890
1963
OpInfo.CompType = OpInfo.FullType ;
1891
1964
if (auto VecType = dyn_cast_or_null<VectorType>(OpInfo.FullType )) {
1892
1965
OpInfo.CompType = VecType->getElementType ();
@@ -1908,16 +1981,20 @@ LValue ScalarExprEmitter::buildCompoundAssignLValue(
1908
1981
CIRGenFunction::SourceLocRAIIObject sourceloc{
1909
1982
CGF, CGF.getLoc (E->getSourceRange ())};
1910
1983
SourceLocation Loc = E->getExprLoc ();
1911
- OpInfo.LHS =
1912
- buildScalarConversion (OpInfo.LHS , LHSTy, E->getComputationLHSType (), Loc);
1984
+ if (!PromotionTypeLHS.isNull ())
1985
+ OpInfo.LHS = buildScalarConversion (OpInfo.LHS , LHSTy, PromotionTypeLHS,
1986
+ E->getExprLoc ());
1987
+ else
1988
+ OpInfo.LHS = buildScalarConversion (OpInfo.LHS , LHSTy,
1989
+ E->getComputationLHSType (), Loc);
1913
1990
1914
1991
// Expand the binary operator.
1915
1992
Result = (this ->*Func)(OpInfo);
1916
1993
1917
1994
// Convert the result back to the LHS type,
1918
1995
// potentially with Implicit Conversion sanitizer check.
1919
- Result = buildScalarConversion (Result, E-> getComputationResultType () , LHSTy,
1920
- Loc, ScalarConversionOpts (CGF.SanOpts ));
1996
+ Result = buildScalarConversion (Result, PromotionTypeCR , LHSTy, Loc ,
1997
+ ScalarConversionOpts (CGF.SanOpts ));
1921
1998
1922
1999
// Store the result value into the LHS lvalue. Bit-fields are handled
1923
2000
// specially because the result is altered by the store, i.e., [C99 6.5.16p1]
@@ -1938,6 +2015,44 @@ mlir::Value ScalarExprEmitter::buildNullValue(QualType Ty, mlir::Location loc) {
1938
2015
return CGF.buildFromMemory (CGF.CGM .buildNullConstant (Ty, loc), Ty);
1939
2016
}
1940
2017
2018
+ mlir::Value ScalarExprEmitter::buildPromoted (const Expr *E,
2019
+ QualType PromotionType) {
2020
+ E = E->IgnoreParens ();
2021
+ if (const auto *BO = dyn_cast<BinaryOperator>(E)) {
2022
+ switch (BO->getOpcode ()) {
2023
+ #define HANDLE_BINOP (OP ) \
2024
+ case BO_##OP: \
2025
+ return build##OP (buildBinOps (BO, PromotionType));
2026
+ HANDLE_BINOP (Add)
2027
+ HANDLE_BINOP (Sub)
2028
+ HANDLE_BINOP (Mul)
2029
+ HANDLE_BINOP (Div)
2030
+ #undef HANDLE_BINOP
2031
+ default :
2032
+ break ;
2033
+ }
2034
+ } else if (const auto *UO = dyn_cast<UnaryOperator>(E)) {
2035
+ switch (UO->getOpcode ()) {
2036
+ case UO_Imag:
2037
+ case UO_Real:
2038
+ llvm_unreachable (" NYI" );
2039
+ case UO_Minus:
2040
+ return VisitMinus (UO, PromotionType);
2041
+ case UO_Plus:
2042
+ return VisitPlus (UO, PromotionType);
2043
+ default :
2044
+ break ;
2045
+ }
2046
+ }
2047
+ auto result = Visit (const_cast <Expr *>(E));
2048
+ if (result) {
2049
+ if (!PromotionType.isNull ())
2050
+ return buildPromotedValue (result, PromotionType);
2051
+ return buildUnPromotedValue (result, E->getType ());
2052
+ }
2053
+ return result;
2054
+ }
2055
+
1941
2056
mlir::Value ScalarExprEmitter::buildCompoundAssign (
1942
2057
const CompoundAssignOperator *E,
1943
2058
mlir::Value (ScalarExprEmitter::*Func)(const BinOpInfo &)) {
0 commit comments