aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp')
-rw-r--r--contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp161
1 files changed, 119 insertions, 42 deletions
diff --git a/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp b/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
index 839fe16cd772..4d45f6d64c1c 100644
--- a/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
+++ b/contrib/llvm-project/clang/lib/CodeGen/CGExprComplex.cpp
@@ -28,6 +28,10 @@ using namespace CodeGen;
// Complex Expression Emitter
//===----------------------------------------------------------------------===//
+namespace llvm {
+extern cl::opt<bool> EnableSingleByteCoverage;
+} // namespace llvm
+
typedef CodeGenFunction::ComplexPairTy ComplexPairTy;
/// Return the complex type that we are meant to emit.
@@ -47,11 +51,12 @@ class ComplexExprEmitter
CGBuilderTy &Builder;
bool IgnoreReal;
bool IgnoreImag;
-public:
- ComplexExprEmitter(CodeGenFunction &cgf, bool ir=false, bool ii=false)
- : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii) {
- }
+ bool FPHasBeenPromoted;
+public:
+ ComplexExprEmitter(CodeGenFunction &cgf, bool ir = false, bool ii = false)
+ : CGF(cgf), Builder(CGF.Builder), IgnoreReal(ir), IgnoreImag(ii),
+ FPHasBeenPromoted(false) {}
//===--------------------------------------------------------------------===//
// Utilities
@@ -283,9 +288,62 @@ public:
ComplexPairTy EmitComplexBinOpLibCall(StringRef LibCallName,
const BinOpInfo &Op);
- QualType getPromotionType(QualType Ty) {
+ QualType GetHigherPrecisionFPType(QualType ElementType) {
+ const auto *CurrentBT = cast<BuiltinType>(ElementType);
+ switch (CurrentBT->getKind()) {
+ case BuiltinType::Kind::Float16:
+ return CGF.getContext().FloatTy;
+ case BuiltinType::Kind::Float:
+ case BuiltinType::Kind::BFloat16:
+ return CGF.getContext().DoubleTy;
+ case BuiltinType::Kind::Double:
+ return CGF.getContext().LongDoubleTy;
+ default:
+ return ElementType;
+ }
+ }
+
+ QualType HigherPrecisionTypeForComplexArithmetic(QualType ElementType,
+ bool IsDivOpCode) {
+ QualType HigherElementType = GetHigherPrecisionFPType(ElementType);
+ const llvm::fltSemantics &ElementTypeSemantics =
+ CGF.getContext().getFloatTypeSemantics(ElementType);
+ const llvm::fltSemantics &HigherElementTypeSemantics =
+ CGF.getContext().getFloatTypeSemantics(HigherElementType);
+ // Check that the promoted type can handle the intermediate values without
+ // overflowing. This can be interpreted as:
+ // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal) * 2 <=
+ // LargerType.LargestFiniteVal.
+ // In terms of exponent it gives this formula:
+ // (SmallerType.LargestFiniteVal * SmallerType.LargestFiniteVal
+ // doubles the exponent of SmallerType.LargestFiniteVal)
+ if (llvm::APFloat::semanticsMaxExponent(ElementTypeSemantics) * 2 + 1 <=
+ llvm::APFloat::semanticsMaxExponent(HigherElementTypeSemantics)) {
+ FPHasBeenPromoted = true;
+ return CGF.getContext().getComplexType(HigherElementType);
+ } else {
+ DiagnosticsEngine &Diags = CGF.CGM.getDiags();
+ Diags.Report(diag::warn_next_larger_fp_type_same_size_than_fp);
+ return QualType();
+ }
+ }
+
+ QualType getPromotionType(FPOptionsOverride Features, QualType Ty,
+ bool IsDivOpCode = false) {
if (auto *CT = Ty->getAs<ComplexType>()) {
QualType ElementType = CT->getElementType();
+ bool IsFloatingType = ElementType->isFloatingType();
+ bool IsComplexRangePromoted = CGF.getLangOpts().getComplexRange() ==
+ LangOptions::ComplexRangeKind::CX_Promoted;
+ bool HasNoComplexRangeOverride = !Features.hasComplexRangeOverride();
+ bool HasMatchingComplexRange = Features.hasComplexRangeOverride() &&
+ Features.getComplexRangeOverride() ==
+ CGF.getLangOpts().getComplexRange();
+
+ if (IsDivOpCode && IsFloatingType && IsComplexRangePromoted &&
+ (HasNoComplexRangeOverride || HasMatchingComplexRange))
+ return HigherPrecisionTypeForComplexArithmetic(ElementType,
+ IsDivOpCode);
if (ElementType.UseExcessPrecision(CGF.getContext()))
return CGF.getContext().getComplexType(CGF.getContext().FloatTy);
}
@@ -296,11 +354,12 @@ public:
#define HANDLEBINOP(OP) \
ComplexPairTy VisitBin##OP(const BinaryOperator *E) { \
- QualType promotionTy = getPromotionType(E->getType()); \
+ QualType promotionTy = getPromotionType( \
+ E->getStoredFPFeaturesOrDefault(), E->getType(), \
+ (E->getOpcode() == BinaryOperatorKind::BO_Div) ? true : false); \
ComplexPairTy result = EmitBin##OP(EmitBinOps(E, promotionTy)); \
if (!promotionTy.isNull()) \
- result = \
- CGF.EmitUnPromotedValue(result, E->getType()); \
+ result = CGF.EmitUnPromotedValue(result, E->getType()); \
return result; \
}
@@ -354,6 +413,10 @@ public:
ComplexPairTy VisitAtomicExpr(AtomicExpr *E) {
return CGF.EmitAtomicExpr(E).getComplexVal();
}
+
+ ComplexPairTy VisitPackIndexingExpr(PackIndexingExpr *E) {
+ return Visit(E->getSelectedExpr());
+ }
};
} // end anonymous namespace.
@@ -379,7 +442,7 @@ ComplexPairTy ComplexExprEmitter::EmitLoadOfLValue(LValue lvalue,
if (lvalue.getType()->isAtomicType())
return CGF.EmitAtomicLoad(lvalue, loc).getComplexVal();
- Address SrcPtr = lvalue.getAddress(CGF);
+ Address SrcPtr = lvalue.getAddress();
bool isVolatile = lvalue.isVolatileQualified();
llvm::Value *Real = nullptr, *Imag = nullptr;
@@ -405,7 +468,7 @@ void ComplexExprEmitter::EmitStoreOfComplex(ComplexPairTy Val, LValue lvalue,
(!isInit && CGF.LValueIsSuitableForInlineAtomic(lvalue)))
return CGF.EmitAtomicStore(RValue::getComplex(Val), lvalue, isInit);
- Address Ptr = lvalue.getAddress(CGF);
+ Address Ptr = lvalue.getAddress();
Address RealPtr = CGF.emitAddrOfRealComponent(Ptr, lvalue.getType());
Address ImagPtr = CGF.emitAddrOfImagComponent(Ptr, lvalue.getType());
@@ -496,14 +559,14 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_LValueBitCast: {
LValue origLV = CGF.EmitLValue(Op);
- Address V = origLV.getAddress(CGF).withElementType(CGF.ConvertType(DestTy));
+ Address V = origLV.getAddress().withElementType(CGF.ConvertType(DestTy));
return EmitLoadOfLValue(CGF.MakeAddrLValue(V, DestTy), Op->getExprLoc());
}
case CK_LValueToRValueBitCast: {
LValue SourceLVal = CGF.EmitLValue(Op);
- Address Addr = SourceLVal.getAddress(CGF).withElementType(
- CGF.ConvertTypeForMem(DestTy));
+ Address Addr =
+ SourceLVal.getAddress().withElementType(CGF.ConvertTypeForMem(DestTy));
LValue DestLV = CGF.MakeAddrLValue(Addr, DestTy);
DestLV.setTBAAInfo(TBAAAccessInfo::getMayAliasInfo());
return EmitLoadOfLValue(DestLV, Op->getExprLoc());
@@ -560,6 +623,8 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
case CK_FixedPointToIntegral:
case CK_IntegralToFixedPoint:
case CK_MatrixCast:
+ case CK_HLSLVectorTruncation:
+ case CK_HLSLArrayRValue:
llvm_unreachable("invalid cast kind for complex value");
case CK_FloatingRealToComplex:
@@ -584,9 +649,12 @@ ComplexPairTy ComplexExprEmitter::EmitCast(CastKind CK, Expr *Op,
ComplexPairTy ComplexExprEmitter::VisitUnaryPlus(const UnaryOperator *E,
QualType PromotionType) {
- QualType promotionTy = PromotionType.isNull()
- ? getPromotionType(E->getSubExpr()->getType())
- : PromotionType;
+ E->hasStoredFPFeatures();
+ QualType promotionTy =
+ PromotionType.isNull()
+ ? getPromotionType(E->getStoredFPFeaturesOrDefault(),
+ E->getSubExpr()->getType())
+ : PromotionType;
ComplexPairTy result = VisitPlus(E, promotionTy);
if (!promotionTy.isNull())
return CGF.EmitUnPromotedValue(result, E->getSubExpr()->getType());
@@ -604,9 +672,11 @@ ComplexPairTy ComplexExprEmitter::VisitPlus(const UnaryOperator *E,
ComplexPairTy ComplexExprEmitter::VisitUnaryMinus(const UnaryOperator *E,
QualType PromotionType) {
- QualType promotionTy = PromotionType.isNull()
- ? getPromotionType(E->getSubExpr()->getType())
- : PromotionType;
+ QualType promotionTy =
+ PromotionType.isNull()
+ ? getPromotionType(E->getStoredFPFeaturesOrDefault(),
+ E->getSubExpr()->getType())
+ : PromotionType;
ComplexPairTy result = VisitMinus(E, promotionTy);
if (!promotionTy.isNull())
return CGF.EmitUnPromotedValue(result, E->getSubExpr()->getType());
@@ -760,8 +830,6 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
//
// But we can fold away components which would be zero due to a real
// operand according to C11 Annex G.5.1p2.
- // FIXME: C11 also provides for imaginary types which would allow folding
- // still more of this within the type system.
CodeGenFunction::CGFPOptionsRAII FPOptsRAII(CGF, Op.FPFeatures);
if (Op.LHS.second && Op.RHS.second) {
@@ -785,8 +853,9 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
ResR = Builder.CreateFSub(AC, BD, "mul_r");
ResI = Builder.CreateFAdd(AD, BC, "mul_i");
- if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited ||
- Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran)
+ if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
+ Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
+ Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
return ComplexPairTy(ResR, ResI);
// Emit the test for the real part becoming NaN and create a branch to
@@ -798,8 +867,7 @@ ComplexPairTy ComplexExprEmitter::EmitBinMul(const BinOpInfo &Op) {
llvm::BasicBlock *OrigBB = Branch->getParent();
// Give hint that we very much don't expect to see NaNs.
- // Value chosen to match UR_NONTAKEN_WEIGHT, see BranchProbabilityInfo.cpp
- llvm::MDNode *BrWeight = MDHelper.createBranchWeights(1, (1U << 20) - 1);
+ llvm::MDNode *BrWeight = MDHelper.createUnlikelyBranchWeights();
Branch->setMetadata(llvm::LLVMContext::MD_prof, BrWeight);
// Now test the imaginary part and create its branch.
@@ -977,22 +1045,21 @@ ComplexPairTy ComplexExprEmitter::EmitBinDiv(const BinOpInfo &Op) {
llvm::Value *OrigLHSi = LHSi;
if (!LHSi)
LHSi = llvm::Constant::getNullValue(RHSi->getType());
- if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Fortran)
+ if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Improved ||
+ (Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted &&
+ !FPHasBeenPromoted))
return EmitRangeReductionDiv(LHSr, LHSi, RHSr, RHSi);
- else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Limited)
+ else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Basic ||
+ Op.FPFeatures.getComplexRange() == LangOptions::CX_Promoted)
return EmitAlgebraicDiv(LHSr, LHSi, RHSr, RHSi);
- else if (!CGF.getLangOpts().FastMath ||
- // '-ffast-math' is used in the command line but followed by an
- // '-fno-cx-limited-range'.
- Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) {
+ // '-ffast-math' is used in the command line but followed by an
+ // '-fno-cx-limited-range' or '-fcomplex-arithmetic=full'.
+ else if (Op.FPFeatures.getComplexRange() == LangOptions::CX_Full) {
LHSi = OrigLHSi;
// If we have a complex operand on the RHS and FastMath is not allowed, we
// delegate to a libcall to handle all of the complexities and minimize
// underflow/overflow cases. When FastMath is allowed we construct the
// divide inline using the same algorithm as for integer operands.
- //
- // FIXME: We would be able to avoid the libcall in many places if we
- // supported imaginary types in addition to complex types.
BinOpInfo LibCallOp = Op;
// If LHS was a real, supply a null imaginary part.
if (!LHSi)
@@ -1164,13 +1231,15 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
// __block variables need to have the rhs evaluated first, plus this should
// improve codegen a little.
QualType PromotionTypeCR;
- PromotionTypeCR = getPromotionType(E->getComputationResultType());
+ PromotionTypeCR = getPromotionType(E->getStoredFPFeaturesOrDefault(),
+ E->getComputationResultType());
if (PromotionTypeCR.isNull())
PromotionTypeCR = E->getComputationResultType();
OpInfo.Ty = PromotionTypeCR;
QualType ComplexElementTy =
OpInfo.Ty->castAs<ComplexType>()->getElementType();
- QualType PromotionTypeRHS = getPromotionType(E->getRHS()->getType());
+ QualType PromotionTypeRHS = getPromotionType(
+ E->getStoredFPFeaturesOrDefault(), E->getRHS()->getType());
// The RHS should have been converted to the computation type.
if (E->getRHS()->getType()->isRealFloatingType()) {
@@ -1198,7 +1267,8 @@ EmitCompoundAssignLValue(const CompoundAssignOperator *E,
// Load from the l-value and convert it.
SourceLocation Loc = E->getExprLoc();
- QualType PromotionTypeLHS = getPromotionType(E->getComputationLHSType());
+ QualType PromotionTypeLHS = getPromotionType(
+ E->getStoredFPFeaturesOrDefault(), E->getComputationLHSType());
if (LHSTy->isAnyComplexType()) {
ComplexPairTy LHSVal = EmitLoadOfLValue(LHS, Loc);
if (!PromotionTypeLHS.isNull())
@@ -1325,7 +1395,11 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(LHSBlock);
- CGF.incrementProfileCounter(E);
+ if (llvm::EnableSingleByteCoverage)
+ CGF.incrementProfileCounter(E->getTrueExpr());
+ else
+ CGF.incrementProfileCounter(E);
+
ComplexPairTy LHS = Visit(E->getTrueExpr());
LHSBlock = Builder.GetInsertBlock();
CGF.EmitBranch(ContBlock);
@@ -1333,9 +1407,13 @@ VisitAbstractConditionalOperator(const AbstractConditionalOperator *E) {
eval.begin(CGF);
CGF.EmitBlock(RHSBlock);
+ if (llvm::EnableSingleByteCoverage)
+ CGF.incrementProfileCounter(E->getFalseExpr());
ComplexPairTy RHS = Visit(E->getFalseExpr());
RHSBlock = Builder.GetInsertBlock();
CGF.EmitBlock(ContBlock);
+ if (llvm::EnableSingleByteCoverage)
+ CGF.incrementProfileCounter(E);
eval.end(CGF);
// Create a PHI node for the real part.
@@ -1381,9 +1459,9 @@ ComplexPairTy ComplexExprEmitter::VisitInitListExpr(InitListExpr *E) {
ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
Address ArgValue = Address::invalid();
- Address ArgPtr = CGF.EmitVAArg(E, ArgValue);
+ RValue RV = CGF.EmitVAArg(E, ArgValue);
- if (!ArgPtr.isValid()) {
+ if (!ArgValue.isValid()) {
CGF.ErrorUnsupported(E, "complex va_arg expression");
llvm::Type *EltTy =
CGF.ConvertType(E->getType()->castAs<ComplexType>()->getElementType());
@@ -1391,8 +1469,7 @@ ComplexPairTy ComplexExprEmitter::VisitVAArgExpr(VAArgExpr *E) {
return ComplexPairTy(U, U);
}
- return EmitLoadOfLValue(CGF.MakeAddrLValue(ArgPtr, E->getType()),
- E->getExprLoc());
+ return RV.getComplexVal();
}
//===----------------------------------------------------------------------===//