[llvm] r363810 - [ConstantFolding] Refactor ConstantFoldScalarCall. NFC
Bjorn Pettersson via llvm-commits
llvm-commits at lists.llvm.org
Wed Jun 19 07:27:51 PDT 2019
Author: bjope
Date: Wed Jun 19 07:27:51 2019
New Revision: 363810
URL: http://llvm.org/viewvc/llvm-project?rev=363810&view=rev
Log:
[ConstantFolding] Refactor ConstantFoldScalarCall. NFC
This patch splits ConstantFoldScalarCall into several
functions.
Benefits:
- Reduces indentation levels and avoids long if-statements.
- Makes it easier to add support for > 3 operands.
Modified:
llvm/trunk/lib/Analysis/ConstantFolding.cpp
Modified: llvm/trunk/lib/Analysis/ConstantFolding.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/lib/Analysis/ConstantFolding.cpp?rev=363810&r1=363809&r2=363810&view=diff
==============================================================================
--- llvm/trunk/lib/Analysis/ConstantFolding.cpp (original)
+++ llvm/trunk/lib/Analysis/ConstantFolding.cpp Wed Jun 19 07:27:51 2019
@@ -1647,524 +1647,535 @@ static bool getConstIntOrUndef(Value *Op
return false;
}
-static Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID,
- Type *Ty,
- ArrayRef<Constant *> Operands,
- const TargetLibraryInfo *TLI,
- const CallBase *Call) {
- if (Operands.size() == 1) {
- if (IntrinsicID == Intrinsic::is_constant) {
- // We know we have a "Constant" argument. But we want to only
- // return true for manifest constants, not those that depend on
- // constants with unknowable values, e.g. GlobalValue or BlockAddress.
- if (isManifestConstant(Operands[0]))
- return ConstantInt::getTrue(Ty->getContext());
- return nullptr;
- }
- if (isa<UndefValue>(Operands[0])) {
- // cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN.
- // ctpop() is between 0 and bitwidth, pick 0 for undef.
- if (IntrinsicID == Intrinsic::cos ||
- IntrinsicID == Intrinsic::ctpop)
- return Constant::getNullValue(Ty);
- if (IntrinsicID == Intrinsic::bswap ||
- IntrinsicID == Intrinsic::bitreverse ||
- IntrinsicID == Intrinsic::launder_invariant_group ||
- IntrinsicID == Intrinsic::strip_invariant_group)
- return Operands[0];
- }
+static Constant *ConstantFoldScalarCall1(StringRef Name, unsigned IntrinsicID,
+ Type *Ty,
+ ArrayRef<Constant *> Operands,
+ const TargetLibraryInfo *TLI,
+ const CallBase *Call) {
+ assert(Operands.size() == 1 && "Wrong number of operands.");
+
+ if (IntrinsicID == Intrinsic::is_constant) {
+ // We know we have a "Constant" argument. But we want to only
+ // return true for manifest constants, not those that depend on
+ // constants with unknowable values, e.g. GlobalValue or BlockAddress.
+ if (isManifestConstant(Operands[0]))
+ return ConstantInt::getTrue(Ty->getContext());
+ return nullptr;
+ }
+ if (isa<UndefValue>(Operands[0])) {
+ // cosine(arg) is between -1 and 1. cosine(invalid arg) is NaN.
+ // ctpop() is between 0 and bitwidth, pick 0 for undef.
+ if (IntrinsicID == Intrinsic::cos ||
+ IntrinsicID == Intrinsic::ctpop)
+ return Constant::getNullValue(Ty);
+ if (IntrinsicID == Intrinsic::bswap ||
+ IntrinsicID == Intrinsic::bitreverse ||
+ IntrinsicID == Intrinsic::launder_invariant_group ||
+ IntrinsicID == Intrinsic::strip_invariant_group)
+ return Operands[0];
+ }
- if (isa<ConstantPointerNull>(Operands[0])) {
- // launder(null) == null == strip(null) iff in addrspace 0
- if (IntrinsicID == Intrinsic::launder_invariant_group ||
- IntrinsicID == Intrinsic::strip_invariant_group) {
- // If instruction is not yet put in a basic block (e.g. when cloning
- // a function during inlining), Call's caller may not be available.
- // So check Call's BB first before querying Call->getCaller.
- const Function *Caller =
- Call->getParent() ? Call->getCaller() : nullptr;
- if (Caller &&
- !NullPointerIsDefined(
- Caller, Operands[0]->getType()->getPointerAddressSpace())) {
- return Operands[0];
- }
- return nullptr;
+ if (isa<ConstantPointerNull>(Operands[0])) {
+ // launder(null) == null == strip(null) iff in addrspace 0
+ if (IntrinsicID == Intrinsic::launder_invariant_group ||
+ IntrinsicID == Intrinsic::strip_invariant_group) {
+ // If instruction is not yet put in a basic block (e.g. when cloning
+ // a function during inlining), Call's caller may not be available.
+ // So check Call's BB first before querying Call->getCaller.
+ const Function *Caller =
+ Call->getParent() ? Call->getCaller() : nullptr;
+ if (Caller &&
+ !NullPointerIsDefined(
+ Caller, Operands[0]->getType()->getPointerAddressSpace())) {
+ return Operands[0];
}
+ return nullptr;
}
+ }
- if (auto *Op = dyn_cast<ConstantFP>(Operands[0])) {
- if (IntrinsicID == Intrinsic::convert_to_fp16) {
- APFloat Val(Op->getValueAPF());
-
- bool lost = false;
- Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &lost);
+ if (auto *Op = dyn_cast<ConstantFP>(Operands[0])) {
+ if (IntrinsicID == Intrinsic::convert_to_fp16) {
+ APFloat Val(Op->getValueAPF());
- return ConstantInt::get(Ty->getContext(), Val.bitcastToAPInt());
- }
+ bool lost = false;
+ Val.convert(APFloat::IEEEhalf(), APFloat::rmNearestTiesToEven, &lost);
- if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
- return nullptr;
+ return ConstantInt::get(Ty->getContext(), Val.bitcastToAPInt());
+ }
- if (IntrinsicID == Intrinsic::round) {
- APFloat V = Op->getValueAPF();
- V.roundToIntegral(APFloat::rmNearestTiesToAway);
- return ConstantFP::get(Ty->getContext(), V);
- }
+ if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
+ return nullptr;
- if (IntrinsicID == Intrinsic::floor) {
- APFloat V = Op->getValueAPF();
- V.roundToIntegral(APFloat::rmTowardNegative);
- return ConstantFP::get(Ty->getContext(), V);
- }
+ if (IntrinsicID == Intrinsic::round) {
+ APFloat V = Op->getValueAPF();
+ V.roundToIntegral(APFloat::rmNearestTiesToAway);
+ return ConstantFP::get(Ty->getContext(), V);
+ }
- if (IntrinsicID == Intrinsic::ceil) {
- APFloat V = Op->getValueAPF();
- V.roundToIntegral(APFloat::rmTowardPositive);
- return ConstantFP::get(Ty->getContext(), V);
- }
+ if (IntrinsicID == Intrinsic::floor) {
+ APFloat V = Op->getValueAPF();
+ V.roundToIntegral(APFloat::rmTowardNegative);
+ return ConstantFP::get(Ty->getContext(), V);
+ }
- if (IntrinsicID == Intrinsic::trunc) {
- APFloat V = Op->getValueAPF();
- V.roundToIntegral(APFloat::rmTowardZero);
- return ConstantFP::get(Ty->getContext(), V);
- }
+ if (IntrinsicID == Intrinsic::ceil) {
+ APFloat V = Op->getValueAPF();
+ V.roundToIntegral(APFloat::rmTowardPositive);
+ return ConstantFP::get(Ty->getContext(), V);
+ }
- if (IntrinsicID == Intrinsic::rint) {
- APFloat V = Op->getValueAPF();
- V.roundToIntegral(APFloat::rmNearestTiesToEven);
- return ConstantFP::get(Ty->getContext(), V);
- }
+ if (IntrinsicID == Intrinsic::trunc) {
+ APFloat V = Op->getValueAPF();
+ V.roundToIntegral(APFloat::rmTowardZero);
+ return ConstantFP::get(Ty->getContext(), V);
+ }
- if (IntrinsicID == Intrinsic::nearbyint) {
- APFloat V = Op->getValueAPF();
- V.roundToIntegral(APFloat::rmNearestTiesToEven);
- return ConstantFP::get(Ty->getContext(), V);
- }
+ if (IntrinsicID == Intrinsic::rint) {
+ APFloat V = Op->getValueAPF();
+ V.roundToIntegral(APFloat::rmNearestTiesToEven);
+ return ConstantFP::get(Ty->getContext(), V);
+ }
- /// We only fold functions with finite arguments. Folding NaN and inf is
- /// likely to be aborted with an exception anyway, and some host libms
- /// have known errors raising exceptions.
- if (Op->getValueAPF().isNaN() || Op->getValueAPF().isInfinity())
- return nullptr;
+ if (IntrinsicID == Intrinsic::nearbyint) {
+ APFloat V = Op->getValueAPF();
+ V.roundToIntegral(APFloat::rmNearestTiesToEven);
+ return ConstantFP::get(Ty->getContext(), V);
+ }
- /// Currently APFloat versions of these functions do not exist, so we use
- /// the host native double versions. Float versions are not called
- /// directly but for all these it is true (float)(f((double)arg)) ==
- /// f(arg). Long double not supported yet.
- double V = getValueAsDouble(Op);
+ /// We only fold functions with finite arguments. Folding NaN and inf is
+ /// likely to be aborted with an exception anyway, and some host libms
+ /// have known errors raising exceptions.
+ if (Op->getValueAPF().isNaN() || Op->getValueAPF().isInfinity())
+ return nullptr;
- switch (IntrinsicID) {
- default: break;
- case Intrinsic::fabs:
- return ConstantFoldFP(fabs, V, Ty);
- case Intrinsic::log2:
- return ConstantFoldFP(Log2, V, Ty);
- case Intrinsic::log:
- return ConstantFoldFP(log, V, Ty);
- case Intrinsic::log10:
- return ConstantFoldFP(log10, V, Ty);
- case Intrinsic::exp:
- return ConstantFoldFP(exp, V, Ty);
- case Intrinsic::exp2:
- return ConstantFoldFP(exp2, V, Ty);
- case Intrinsic::sin:
- return ConstantFoldFP(sin, V, Ty);
- case Intrinsic::cos:
- return ConstantFoldFP(cos, V, Ty);
- case Intrinsic::sqrt:
- return ConstantFoldFP(sqrt, V, Ty);
- }
+ /// Currently APFloat versions of these functions do not exist, so we use
+ /// the host native double versions. Float versions are not called
+ /// directly but for all these it is true (float)(f((double)arg)) ==
+ /// f(arg). Long double not supported yet.
+ double V = getValueAsDouble(Op);
- if (!TLI)
- return nullptr;
+ switch (IntrinsicID) {
+ default: break;
+ case Intrinsic::fabs:
+ return ConstantFoldFP(fabs, V, Ty);
+ case Intrinsic::log2:
+ return ConstantFoldFP(Log2, V, Ty);
+ case Intrinsic::log:
+ return ConstantFoldFP(log, V, Ty);
+ case Intrinsic::log10:
+ return ConstantFoldFP(log10, V, Ty);
+ case Intrinsic::exp:
+ return ConstantFoldFP(exp, V, Ty);
+ case Intrinsic::exp2:
+ return ConstantFoldFP(exp2, V, Ty);
+ case Intrinsic::sin:
+ return ConstantFoldFP(sin, V, Ty);
+ case Intrinsic::cos:
+ return ConstantFoldFP(cos, V, Ty);
+ case Intrinsic::sqrt:
+ return ConstantFoldFP(sqrt, V, Ty);
+ }
- char NameKeyChar = Name[0];
- if (Name[0] == '_' && Name.size() > 2 && Name[1] == '_')
- NameKeyChar = Name[2];
-
- switch (NameKeyChar) {
- case 'a':
- if ((Name == "acos" && TLI->has(LibFunc_acos)) ||
- (Name == "acosf" && TLI->has(LibFunc_acosf)) ||
- (Name == "__acos_finite" && TLI->has(LibFunc_acos_finite)) ||
- (Name == "__acosf_finite" && TLI->has(LibFunc_acosf_finite)))
- return ConstantFoldFP(acos, V, Ty);
- else if ((Name == "asin" && TLI->has(LibFunc_asin)) ||
- (Name == "asinf" && TLI->has(LibFunc_asinf)) ||
- (Name == "__asin_finite" && TLI->has(LibFunc_asin_finite)) ||
- (Name == "__asinf_finite" && TLI->has(LibFunc_asinf_finite)))
- return ConstantFoldFP(asin, V, Ty);
- else if ((Name == "atan" && TLI->has(LibFunc_atan)) ||
- (Name == "atanf" && TLI->has(LibFunc_atanf)))
- return ConstantFoldFP(atan, V, Ty);
- break;
- case 'c':
- if ((Name == "ceil" && TLI->has(LibFunc_ceil)) ||
- (Name == "ceilf" && TLI->has(LibFunc_ceilf)))
- return ConstantFoldFP(ceil, V, Ty);
- else if ((Name == "cos" && TLI->has(LibFunc_cos)) ||
- (Name == "cosf" && TLI->has(LibFunc_cosf)))
- return ConstantFoldFP(cos, V, Ty);
- else if ((Name == "cosh" && TLI->has(LibFunc_cosh)) ||
- (Name == "coshf" && TLI->has(LibFunc_coshf)) ||
- (Name == "__cosh_finite" && TLI->has(LibFunc_cosh_finite)) ||
- (Name == "__coshf_finite" && TLI->has(LibFunc_coshf_finite)))
- return ConstantFoldFP(cosh, V, Ty);
- break;
- case 'e':
- if ((Name == "exp" && TLI->has(LibFunc_exp)) ||
- (Name == "expf" && TLI->has(LibFunc_expf)) ||
- (Name == "__exp_finite" && TLI->has(LibFunc_exp_finite)) ||
- (Name == "__expf_finite" && TLI->has(LibFunc_expf_finite)))
- return ConstantFoldFP(exp, V, Ty);
- if ((Name == "exp2" && TLI->has(LibFunc_exp2)) ||
- (Name == "exp2f" && TLI->has(LibFunc_exp2f)) ||
- (Name == "__exp2_finite" && TLI->has(LibFunc_exp2_finite)) ||
- (Name == "__exp2f_finite" && TLI->has(LibFunc_exp2f_finite)))
- // Constant fold exp2(x) as pow(2,x) in case the host doesn't have a
- // C99 library.
- return ConstantFoldBinaryFP(pow, 2.0, V, Ty);
- break;
- case 'f':
- if ((Name == "fabs" && TLI->has(LibFunc_fabs)) ||
- (Name == "fabsf" && TLI->has(LibFunc_fabsf)))
- return ConstantFoldFP(fabs, V, Ty);
- else if ((Name == "floor" && TLI->has(LibFunc_floor)) ||
- (Name == "floorf" && TLI->has(LibFunc_floorf)))
- return ConstantFoldFP(floor, V, Ty);
- break;
- case 'l':
- if ((Name == "log" && V > 0 && TLI->has(LibFunc_log)) ||
- (Name == "logf" && V > 0 && TLI->has(LibFunc_logf)) ||
- (Name == "__log_finite" && V > 0 &&
- TLI->has(LibFunc_log_finite)) ||
- (Name == "__logf_finite" && V > 0 &&
- TLI->has(LibFunc_logf_finite)))
- return ConstantFoldFP(log, V, Ty);
- else if ((Name == "log10" && V > 0 && TLI->has(LibFunc_log10)) ||
- (Name == "log10f" && V > 0 && TLI->has(LibFunc_log10f)) ||
- (Name == "__log10_finite" && V > 0 &&
- TLI->has(LibFunc_log10_finite)) ||
- (Name == "__log10f_finite" && V > 0 &&
- TLI->has(LibFunc_log10f_finite)))
- return ConstantFoldFP(log10, V, Ty);
- break;
- case 'r':
- if ((Name == "round" && TLI->has(LibFunc_round)) ||
- (Name == "roundf" && TLI->has(LibFunc_roundf)))
- return ConstantFoldFP(round, V, Ty);
- break;
- case 's':
- if ((Name == "sin" && TLI->has(LibFunc_sin)) ||
- (Name == "sinf" && TLI->has(LibFunc_sinf)))
- return ConstantFoldFP(sin, V, Ty);
- else if ((Name == "sinh" && TLI->has(LibFunc_sinh)) ||
- (Name == "sinhf" && TLI->has(LibFunc_sinhf)) ||
- (Name == "__sinh_finite" && TLI->has(LibFunc_sinh_finite)) ||
- (Name == "__sinhf_finite" && TLI->has(LibFunc_sinhf_finite)))
- return ConstantFoldFP(sinh, V, Ty);
- else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc_sqrt)) ||
- (Name == "sqrtf" && V >= 0 && TLI->has(LibFunc_sqrtf)))
- return ConstantFoldFP(sqrt, V, Ty);
- break;
- case 't':
- if ((Name == "tan" && TLI->has(LibFunc_tan)) ||
- (Name == "tanf" && TLI->has(LibFunc_tanf)))
- return ConstantFoldFP(tan, V, Ty);
- else if ((Name == "tanh" && TLI->has(LibFunc_tanh)) ||
- (Name == "tanhf" && TLI->has(LibFunc_tanhf)))
- return ConstantFoldFP(tanh, V, Ty);
- break;
- default:
- break;
- }
+ if (!TLI)
return nullptr;
+
+ char NameKeyChar = Name[0];
+ if (Name[0] == '_' && Name.size() > 2 && Name[1] == '_')
+ NameKeyChar = Name[2];
+
+ switch (NameKeyChar) {
+ case 'a':
+ if ((Name == "acos" && TLI->has(LibFunc_acos)) ||
+ (Name == "acosf" && TLI->has(LibFunc_acosf)) ||
+ (Name == "__acos_finite" && TLI->has(LibFunc_acos_finite)) ||
+ (Name == "__acosf_finite" && TLI->has(LibFunc_acosf_finite)))
+ return ConstantFoldFP(acos, V, Ty);
+ else if ((Name == "asin" && TLI->has(LibFunc_asin)) ||
+ (Name == "asinf" && TLI->has(LibFunc_asinf)) ||
+ (Name == "__asin_finite" && TLI->has(LibFunc_asin_finite)) ||
+ (Name == "__asinf_finite" && TLI->has(LibFunc_asinf_finite)))
+ return ConstantFoldFP(asin, V, Ty);
+ else if ((Name == "atan" && TLI->has(LibFunc_atan)) ||
+ (Name == "atanf" && TLI->has(LibFunc_atanf)))
+ return ConstantFoldFP(atan, V, Ty);
+ break;
+ case 'c':
+ if ((Name == "ceil" && TLI->has(LibFunc_ceil)) ||
+ (Name == "ceilf" && TLI->has(LibFunc_ceilf)))
+ return ConstantFoldFP(ceil, V, Ty);
+ else if ((Name == "cos" && TLI->has(LibFunc_cos)) ||
+ (Name == "cosf" && TLI->has(LibFunc_cosf)))
+ return ConstantFoldFP(cos, V, Ty);
+ else if ((Name == "cosh" && TLI->has(LibFunc_cosh)) ||
+ (Name == "coshf" && TLI->has(LibFunc_coshf)) ||
+ (Name == "__cosh_finite" && TLI->has(LibFunc_cosh_finite)) ||
+ (Name == "__coshf_finite" && TLI->has(LibFunc_coshf_finite)))
+ return ConstantFoldFP(cosh, V, Ty);
+ break;
+ case 'e':
+ if ((Name == "exp" && TLI->has(LibFunc_exp)) ||
+ (Name == "expf" && TLI->has(LibFunc_expf)) ||
+ (Name == "__exp_finite" && TLI->has(LibFunc_exp_finite)) ||
+ (Name == "__expf_finite" && TLI->has(LibFunc_expf_finite)))
+ return ConstantFoldFP(exp, V, Ty);
+ if ((Name == "exp2" && TLI->has(LibFunc_exp2)) ||
+ (Name == "exp2f" && TLI->has(LibFunc_exp2f)) ||
+ (Name == "__exp2_finite" && TLI->has(LibFunc_exp2_finite)) ||
+ (Name == "__exp2f_finite" && TLI->has(LibFunc_exp2f_finite)))
+ // Constant fold exp2(x) as pow(2,x) in case the host doesn't have a
+ // C99 library.
+ return ConstantFoldBinaryFP(pow, 2.0, V, Ty);
+ break;
+ case 'f':
+ if ((Name == "fabs" && TLI->has(LibFunc_fabs)) ||
+ (Name == "fabsf" && TLI->has(LibFunc_fabsf)))
+ return ConstantFoldFP(fabs, V, Ty);
+ else if ((Name == "floor" && TLI->has(LibFunc_floor)) ||
+ (Name == "floorf" && TLI->has(LibFunc_floorf)))
+ return ConstantFoldFP(floor, V, Ty);
+ break;
+ case 'l':
+ if ((Name == "log" && V > 0 && TLI->has(LibFunc_log)) ||
+ (Name == "logf" && V > 0 && TLI->has(LibFunc_logf)) ||
+ (Name == "__log_finite" && V > 0 &&
+ TLI->has(LibFunc_log_finite)) ||
+ (Name == "__logf_finite" && V > 0 &&
+ TLI->has(LibFunc_logf_finite)))
+ return ConstantFoldFP(log, V, Ty);
+ else if ((Name == "log10" && V > 0 && TLI->has(LibFunc_log10)) ||
+ (Name == "log10f" && V > 0 && TLI->has(LibFunc_log10f)) ||
+ (Name == "__log10_finite" && V > 0 &&
+ TLI->has(LibFunc_log10_finite)) ||
+ (Name == "__log10f_finite" && V > 0 &&
+ TLI->has(LibFunc_log10f_finite)))
+ return ConstantFoldFP(log10, V, Ty);
+ break;
+ case 'r':
+ if ((Name == "round" && TLI->has(LibFunc_round)) ||
+ (Name == "roundf" && TLI->has(LibFunc_roundf)))
+ return ConstantFoldFP(round, V, Ty);
+ break;
+ case 's':
+ if ((Name == "sin" && TLI->has(LibFunc_sin)) ||
+ (Name == "sinf" && TLI->has(LibFunc_sinf)))
+ return ConstantFoldFP(sin, V, Ty);
+ else if ((Name == "sinh" && TLI->has(LibFunc_sinh)) ||
+ (Name == "sinhf" && TLI->has(LibFunc_sinhf)) ||
+ (Name == "__sinh_finite" && TLI->has(LibFunc_sinh_finite)) ||
+ (Name == "__sinhf_finite" && TLI->has(LibFunc_sinhf_finite)))
+ return ConstantFoldFP(sinh, V, Ty);
+ else if ((Name == "sqrt" && V >= 0 && TLI->has(LibFunc_sqrt)) ||
+ (Name == "sqrtf" && V >= 0 && TLI->has(LibFunc_sqrtf)))
+ return ConstantFoldFP(sqrt, V, Ty);
+ break;
+ case 't':
+ if ((Name == "tan" && TLI->has(LibFunc_tan)) ||
+ (Name == "tanf" && TLI->has(LibFunc_tanf)))
+ return ConstantFoldFP(tan, V, Ty);
+ else if ((Name == "tanh" && TLI->has(LibFunc_tanh)) ||
+ (Name == "tanhf" && TLI->has(LibFunc_tanhf)))
+ return ConstantFoldFP(tanh, V, Ty);
+ break;
+ default:
+ break;
}
+ return nullptr;
+ }
- if (auto *Op = dyn_cast<ConstantInt>(Operands[0])) {
- switch (IntrinsicID) {
- case Intrinsic::bswap:
- return ConstantInt::get(Ty->getContext(), Op->getValue().byteSwap());
- case Intrinsic::ctpop:
- return ConstantInt::get(Ty, Op->getValue().countPopulation());
- case Intrinsic::bitreverse:
- return ConstantInt::get(Ty->getContext(), Op->getValue().reverseBits());
- case Intrinsic::convert_from_fp16: {
- APFloat Val(APFloat::IEEEhalf(), Op->getValue());
-
- bool lost = false;
- APFloat::opStatus status = Val.convert(
- Ty->getFltSemantics(), APFloat::rmNearestTiesToEven, &lost);
-
- // Conversion is always precise.
- (void)status;
- assert(status == APFloat::opOK && !lost &&
- "Precision lost during fp16 constfolding");
+ if (auto *Op = dyn_cast<ConstantInt>(Operands[0])) {
+ switch (IntrinsicID) {
+ case Intrinsic::bswap:
+ return ConstantInt::get(Ty->getContext(), Op->getValue().byteSwap());
+ case Intrinsic::ctpop:
+ return ConstantInt::get(Ty, Op->getValue().countPopulation());
+ case Intrinsic::bitreverse:
+ return ConstantInt::get(Ty->getContext(), Op->getValue().reverseBits());
+ case Intrinsic::convert_from_fp16: {
+ APFloat Val(APFloat::IEEEhalf(), Op->getValue());
+
+ bool lost = false;
+ APFloat::opStatus status = Val.convert(
+ Ty->getFltSemantics(), APFloat::rmNearestTiesToEven, &lost);
+
+ // Conversion is always precise.
+ (void)status;
+ assert(status == APFloat::opOK && !lost &&
+ "Precision lost during fp16 constfolding");
- return ConstantFP::get(Ty->getContext(), Val);
- }
- default:
- return nullptr;
- }
+ return ConstantFP::get(Ty->getContext(), Val);
}
-
- // Support ConstantVector in case we have an Undef in the top.
- if (isa<ConstantVector>(Operands[0]) ||
- isa<ConstantDataVector>(Operands[0])) {
- auto *Op = cast<Constant>(Operands[0]);
- switch (IntrinsicID) {
- default: break;
- case Intrinsic::x86_sse_cvtss2si:
- case Intrinsic::x86_sse_cvtss2si64:
- case Intrinsic::x86_sse2_cvtsd2si:
- case Intrinsic::x86_sse2_cvtsd2si64:
- if (ConstantFP *FPOp =
- dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
- return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
- /*roundTowardZero=*/false, Ty,
- /*IsSigned*/true);
- break;
- case Intrinsic::x86_sse_cvttss2si:
- case Intrinsic::x86_sse_cvttss2si64:
- case Intrinsic::x86_sse2_cvttsd2si:
- case Intrinsic::x86_sse2_cvttsd2si64:
- if (ConstantFP *FPOp =
- dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
- return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
- /*roundTowardZero=*/true, Ty,
- /*IsSigned*/true);
- break;
- }
+ default:
+ return nullptr;
}
+ }
- return nullptr;
+ // Support ConstantVector in case we have an Undef in the top.
+ if (isa<ConstantVector>(Operands[0]) ||
+ isa<ConstantDataVector>(Operands[0])) {
+ auto *Op = cast<Constant>(Operands[0]);
+ switch (IntrinsicID) {
+ default: break;
+ case Intrinsic::x86_sse_cvtss2si:
+ case Intrinsic::x86_sse_cvtss2si64:
+ case Intrinsic::x86_sse2_cvtsd2si:
+ case Intrinsic::x86_sse2_cvtsd2si64:
+ if (ConstantFP *FPOp =
+ dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
+ return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
+ /*roundTowardZero=*/false, Ty,
+ /*IsSigned*/true);
+ break;
+ case Intrinsic::x86_sse_cvttss2si:
+ case Intrinsic::x86_sse_cvttss2si64:
+ case Intrinsic::x86_sse2_cvttsd2si:
+ case Intrinsic::x86_sse2_cvttsd2si64:
+ if (ConstantFP *FPOp =
+ dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
+ return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
+ /*roundTowardZero=*/true, Ty,
+ /*IsSigned*/true);
+ break;
+ }
}
- if (Operands.size() == 2) {
- if (auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
- if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
- return nullptr;
- double Op1V = getValueAsDouble(Op1);
+ return nullptr;
+}
- if (auto *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
- if (Op2->getType() != Op1->getType())
- return nullptr;
+static Constant *ConstantFoldScalarCall2(StringRef Name, unsigned IntrinsicID,
+ Type *Ty,
+ ArrayRef<Constant *> Operands,
+ const TargetLibraryInfo *TLI,
+ const CallBase *Call) {
+ assert(Operands.size() == 2 && "Wrong number of operands.");
- double Op2V = getValueAsDouble(Op2);
- if (IntrinsicID == Intrinsic::pow) {
- return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty);
- }
- if (IntrinsicID == Intrinsic::copysign) {
- APFloat V1 = Op1->getValueAPF();
- const APFloat &V2 = Op2->getValueAPF();
- V1.copySign(V2);
- return ConstantFP::get(Ty->getContext(), V1);
- }
+ if (auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
+ if (!Ty->isHalfTy() && !Ty->isFloatTy() && !Ty->isDoubleTy())
+ return nullptr;
+ double Op1V = getValueAsDouble(Op1);
- if (IntrinsicID == Intrinsic::minnum) {
- const APFloat &C1 = Op1->getValueAPF();
- const APFloat &C2 = Op2->getValueAPF();
- return ConstantFP::get(Ty->getContext(), minnum(C1, C2));
- }
+ if (auto *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
+ if (Op2->getType() != Op1->getType())
+ return nullptr;
- if (IntrinsicID == Intrinsic::maxnum) {
- const APFloat &C1 = Op1->getValueAPF();
- const APFloat &C2 = Op2->getValueAPF();
- return ConstantFP::get(Ty->getContext(), maxnum(C1, C2));
- }
+ double Op2V = getValueAsDouble(Op2);
+ if (IntrinsicID == Intrinsic::pow) {
+ return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty);
+ }
+ if (IntrinsicID == Intrinsic::copysign) {
+ APFloat V1 = Op1->getValueAPF();
+ const APFloat &V2 = Op2->getValueAPF();
+ V1.copySign(V2);
+ return ConstantFP::get(Ty->getContext(), V1);
+ }
- if (IntrinsicID == Intrinsic::minimum) {
- const APFloat &C1 = Op1->getValueAPF();
- const APFloat &C2 = Op2->getValueAPF();
- return ConstantFP::get(Ty->getContext(), minimum(C1, C2));
- }
+ if (IntrinsicID == Intrinsic::minnum) {
+ const APFloat &C1 = Op1->getValueAPF();
+ const APFloat &C2 = Op2->getValueAPF();
+ return ConstantFP::get(Ty->getContext(), minnum(C1, C2));
+ }
- if (IntrinsicID == Intrinsic::maximum) {
- const APFloat &C1 = Op1->getValueAPF();
- const APFloat &C2 = Op2->getValueAPF();
- return ConstantFP::get(Ty->getContext(), maximum(C1, C2));
- }
+ if (IntrinsicID == Intrinsic::maxnum) {
+ const APFloat &C1 = Op1->getValueAPF();
+ const APFloat &C2 = Op2->getValueAPF();
+ return ConstantFP::get(Ty->getContext(), maxnum(C1, C2));
+ }
- if (!TLI)
- return nullptr;
- if ((Name == "pow" && TLI->has(LibFunc_pow)) ||
- (Name == "powf" && TLI->has(LibFunc_powf)) ||
- (Name == "__pow_finite" && TLI->has(LibFunc_pow_finite)) ||
- (Name == "__powf_finite" && TLI->has(LibFunc_powf_finite)))
- return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty);
- if ((Name == "fmod" && TLI->has(LibFunc_fmod)) ||
- (Name == "fmodf" && TLI->has(LibFunc_fmodf)))
- return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty);
- if ((Name == "atan2" && TLI->has(LibFunc_atan2)) ||
- (Name == "atan2f" && TLI->has(LibFunc_atan2f)) ||
- (Name == "__atan2_finite" && TLI->has(LibFunc_atan2_finite)) ||
- (Name == "__atan2f_finite" && TLI->has(LibFunc_atan2f_finite)))
- return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty);
- } else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) {
- if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy())
- return ConstantFP::get(Ty->getContext(),
- APFloat((float)std::pow((float)Op1V,
- (int)Op2C->getZExtValue())));
- if (IntrinsicID == Intrinsic::powi && Ty->isFloatTy())
- return ConstantFP::get(Ty->getContext(),
- APFloat((float)std::pow((float)Op1V,
- (int)Op2C->getZExtValue())));
- if (IntrinsicID == Intrinsic::powi && Ty->isDoubleTy())
- return ConstantFP::get(Ty->getContext(),
- APFloat((double)std::pow((double)Op1V,
- (int)Op2C->getZExtValue())));
+ if (IntrinsicID == Intrinsic::minimum) {
+ const APFloat &C1 = Op1->getValueAPF();
+ const APFloat &C2 = Op2->getValueAPF();
+ return ConstantFP::get(Ty->getContext(), minimum(C1, C2));
}
- return nullptr;
- }
- if (Operands[0]->getType()->isIntegerTy() &&
- Operands[1]->getType()->isIntegerTy()) {
- const APInt *C0, *C1;
- if (!getConstIntOrUndef(Operands[0], C0) ||
- !getConstIntOrUndef(Operands[1], C1))
+ if (IntrinsicID == Intrinsic::maximum) {
+ const APFloat &C1 = Op1->getValueAPF();
+ const APFloat &C2 = Op2->getValueAPF();
+ return ConstantFP::get(Ty->getContext(), maximum(C1, C2));
+ }
+
+ if (!TLI)
return nullptr;
+ if ((Name == "pow" && TLI->has(LibFunc_pow)) ||
+ (Name == "powf" && TLI->has(LibFunc_powf)) ||
+ (Name == "__pow_finite" && TLI->has(LibFunc_pow_finite)) ||
+ (Name == "__powf_finite" && TLI->has(LibFunc_powf_finite)))
+ return ConstantFoldBinaryFP(pow, Op1V, Op2V, Ty);
+ if ((Name == "fmod" && TLI->has(LibFunc_fmod)) ||
+ (Name == "fmodf" && TLI->has(LibFunc_fmodf)))
+ return ConstantFoldBinaryFP(fmod, Op1V, Op2V, Ty);
+ if ((Name == "atan2" && TLI->has(LibFunc_atan2)) ||
+ (Name == "atan2f" && TLI->has(LibFunc_atan2f)) ||
+ (Name == "__atan2_finite" && TLI->has(LibFunc_atan2_finite)) ||
+ (Name == "__atan2f_finite" && TLI->has(LibFunc_atan2f_finite)))
+ return ConstantFoldBinaryFP(atan2, Op1V, Op2V, Ty);
+ } else if (auto *Op2C = dyn_cast<ConstantInt>(Operands[1])) {
+ if (IntrinsicID == Intrinsic::powi && Ty->isHalfTy())
+ return ConstantFP::get(Ty->getContext(),
+ APFloat((float)std::pow((float)Op1V,
+ (int)Op2C->getZExtValue())));
+ if (IntrinsicID == Intrinsic::powi && Ty->isFloatTy())
+ return ConstantFP::get(Ty->getContext(),
+ APFloat((float)std::pow((float)Op1V,
+ (int)Op2C->getZExtValue())));
+ if (IntrinsicID == Intrinsic::powi && Ty->isDoubleTy())
+ return ConstantFP::get(Ty->getContext(),
+ APFloat((double)std::pow((double)Op1V,
+ (int)Op2C->getZExtValue())));
+ }
+ return nullptr;
+ }
+ if (Operands[0]->getType()->isIntegerTy() &&
+ Operands[1]->getType()->isIntegerTy()) {
+ const APInt *C0, *C1;
+ if (!getConstIntOrUndef(Operands[0], C0) ||
+ !getConstIntOrUndef(Operands[1], C1))
+ return nullptr;
+
+ switch (IntrinsicID) {
+ default: break;
+ case Intrinsic::smul_with_overflow:
+ case Intrinsic::umul_with_overflow:
+ // Even if both operands are undef, we cannot fold muls to undef
+ // in the general case. For example, on i2 there are no inputs
+ // that would produce { i2 -1, i1 true } as the result.
+ if (!C0 || !C1)
+ return Constant::getNullValue(Ty);
+ LLVM_FALLTHROUGH;
+ case Intrinsic::sadd_with_overflow:
+ case Intrinsic::uadd_with_overflow:
+ case Intrinsic::ssub_with_overflow:
+ case Intrinsic::usub_with_overflow: {
+ if (!C0 || !C1)
+ return UndefValue::get(Ty);
+
+ APInt Res;
+ bool Overflow;
switch (IntrinsicID) {
- default: break;
- case Intrinsic::smul_with_overflow:
- case Intrinsic::umul_with_overflow:
- // Even if both operands are undef, we cannot fold muls to undef
- // in the general case. For example, on i2 there are no inputs
- // that would produce { i2 -1, i1 true } as the result.
- if (!C0 || !C1)
- return Constant::getNullValue(Ty);
- LLVM_FALLTHROUGH;
+ default: llvm_unreachable("Invalid case");
case Intrinsic::sadd_with_overflow:
+ Res = C0->sadd_ov(*C1, Overflow);
+ break;
case Intrinsic::uadd_with_overflow:
+ Res = C0->uadd_ov(*C1, Overflow);
+ break;
case Intrinsic::ssub_with_overflow:
- case Intrinsic::usub_with_overflow: {
- if (!C0 || !C1)
- return UndefValue::get(Ty);
-
- APInt Res;
- bool Overflow;
- switch (IntrinsicID) {
- default: llvm_unreachable("Invalid case");
- case Intrinsic::sadd_with_overflow:
- Res = C0->sadd_ov(*C1, Overflow);
- break;
- case Intrinsic::uadd_with_overflow:
- Res = C0->uadd_ov(*C1, Overflow);
- break;
- case Intrinsic::ssub_with_overflow:
- Res = C0->ssub_ov(*C1, Overflow);
- break;
- case Intrinsic::usub_with_overflow:
- Res = C0->usub_ov(*C1, Overflow);
- break;
- case Intrinsic::smul_with_overflow:
- Res = C0->smul_ov(*C1, Overflow);
- break;
- case Intrinsic::umul_with_overflow:
- Res = C0->umul_ov(*C1, Overflow);
- break;
- }
- Constant *Ops[] = {
- ConstantInt::get(Ty->getContext(), Res),
- ConstantInt::get(Type::getInt1Ty(Ty->getContext()), Overflow)
- };
- return ConstantStruct::get(cast<StructType>(Ty), Ops);
- }
- case Intrinsic::uadd_sat:
- case Intrinsic::sadd_sat:
- if (!C0 && !C1)
- return UndefValue::get(Ty);
- if (!C0 || !C1)
- return Constant::getAllOnesValue(Ty);
- if (IntrinsicID == Intrinsic::uadd_sat)
- return ConstantInt::get(Ty, C0->uadd_sat(*C1));
- else
- return ConstantInt::get(Ty, C0->sadd_sat(*C1));
- case Intrinsic::usub_sat:
- case Intrinsic::ssub_sat:
- if (!C0 && !C1)
- return UndefValue::get(Ty);
- if (!C0 || !C1)
- return Constant::getNullValue(Ty);
- if (IntrinsicID == Intrinsic::usub_sat)
- return ConstantInt::get(Ty, C0->usub_sat(*C1));
- else
- return ConstantInt::get(Ty, C0->ssub_sat(*C1));
- case Intrinsic::cttz:
- case Intrinsic::ctlz:
- assert(C1 && "Must be constant int");
-
- // cttz(0, 1) and ctlz(0, 1) are undef.
- if (C1->isOneValue() && (!C0 || C0->isNullValue()))
- return UndefValue::get(Ty);
- if (!C0)
- return Constant::getNullValue(Ty);
- if (IntrinsicID == Intrinsic::cttz)
- return ConstantInt::get(Ty, C0->countTrailingZeros());
- else
- return ConstantInt::get(Ty, C0->countLeadingZeros());
- }
-
- return nullptr;
- }
-
- // Support ConstantVector in case we have an Undef in the top.
- if ((isa<ConstantVector>(Operands[0]) ||
- isa<ConstantDataVector>(Operands[0])) &&
- // Check for default rounding mode.
- // FIXME: Support other rounding modes?
- isa<ConstantInt>(Operands[1]) &&
- cast<ConstantInt>(Operands[1])->getValue() == 4) {
- auto *Op = cast<Constant>(Operands[0]);
- switch (IntrinsicID) {
- default: break;
- case Intrinsic::x86_avx512_vcvtss2si32:
- case Intrinsic::x86_avx512_vcvtss2si64:
- case Intrinsic::x86_avx512_vcvtsd2si32:
- case Intrinsic::x86_avx512_vcvtsd2si64:
- if (ConstantFP *FPOp =
- dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
- return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
- /*roundTowardZero=*/false, Ty,
- /*IsSigned*/true);
+ Res = C0->ssub_ov(*C1, Overflow);
break;
- case Intrinsic::x86_avx512_vcvtss2usi32:
- case Intrinsic::x86_avx512_vcvtss2usi64:
- case Intrinsic::x86_avx512_vcvtsd2usi32:
- case Intrinsic::x86_avx512_vcvtsd2usi64:
- if (ConstantFP *FPOp =
- dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
- return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
- /*roundTowardZero=*/false, Ty,
- /*IsSigned*/false);
+ case Intrinsic::usub_with_overflow:
+ Res = C0->usub_ov(*C1, Overflow);
break;
- case Intrinsic::x86_avx512_cvttss2si:
- case Intrinsic::x86_avx512_cvttss2si64:
- case Intrinsic::x86_avx512_cvttsd2si:
- case Intrinsic::x86_avx512_cvttsd2si64:
- if (ConstantFP *FPOp =
- dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
- return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
- /*roundTowardZero=*/true, Ty,
- /*IsSigned*/true);
+ case Intrinsic::smul_with_overflow:
+ Res = C0->smul_ov(*C1, Overflow);
break;
- case Intrinsic::x86_avx512_cvttss2usi:
- case Intrinsic::x86_avx512_cvttss2usi64:
- case Intrinsic::x86_avx512_cvttsd2usi:
- case Intrinsic::x86_avx512_cvttsd2usi64:
- if (ConstantFP *FPOp =
- dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
- return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
- /*roundTowardZero=*/true, Ty,
- /*IsSigned*/false);
+ case Intrinsic::umul_with_overflow:
+ Res = C0->umul_ov(*C1, Overflow);
break;
}
+ Constant *Ops[] = {
+ ConstantInt::get(Ty->getContext(), Res),
+ ConstantInt::get(Type::getInt1Ty(Ty->getContext()), Overflow)
+ };
+ return ConstantStruct::get(cast<StructType>(Ty), Ops);
}
+ case Intrinsic::uadd_sat:
+ case Intrinsic::sadd_sat:
+ if (!C0 && !C1)
+ return UndefValue::get(Ty);
+ if (!C0 || !C1)
+ return Constant::getAllOnesValue(Ty);
+ if (IntrinsicID == Intrinsic::uadd_sat)
+ return ConstantInt::get(Ty, C0->uadd_sat(*C1));
+ else
+ return ConstantInt::get(Ty, C0->sadd_sat(*C1));
+ case Intrinsic::usub_sat:
+ case Intrinsic::ssub_sat:
+ if (!C0 && !C1)
+ return UndefValue::get(Ty);
+ if (!C0 || !C1)
+ return Constant::getNullValue(Ty);
+ if (IntrinsicID == Intrinsic::usub_sat)
+ return ConstantInt::get(Ty, C0->usub_sat(*C1));
+ else
+ return ConstantInt::get(Ty, C0->ssub_sat(*C1));
+ case Intrinsic::cttz:
+ case Intrinsic::ctlz:
+ assert(C1 && "Must be constant int");
+
+ // cttz(0, 1) and ctlz(0, 1) are undef.
+ if (C1->isOneValue() && (!C0 || C0->isNullValue()))
+ return UndefValue::get(Ty);
+ if (!C0)
+ return Constant::getNullValue(Ty);
+ if (IntrinsicID == Intrinsic::cttz)
+ return ConstantInt::get(Ty, C0->countTrailingZeros());
+ else
+ return ConstantInt::get(Ty, C0->countLeadingZeros());
+ }
+
return nullptr;
}
- if (Operands.size() != 3)
- return nullptr;
+ // Support ConstantVector in case we have an Undef in the top.
+ if ((isa<ConstantVector>(Operands[0]) ||
+ isa<ConstantDataVector>(Operands[0])) &&
+ // Check for default rounding mode.
+ // FIXME: Support other rounding modes?
+ isa<ConstantInt>(Operands[1]) &&
+ cast<ConstantInt>(Operands[1])->getValue() == 4) {
+ auto *Op = cast<Constant>(Operands[0]);
+ switch (IntrinsicID) {
+ default: break;
+ case Intrinsic::x86_avx512_vcvtss2si32:
+ case Intrinsic::x86_avx512_vcvtss2si64:
+ case Intrinsic::x86_avx512_vcvtsd2si32:
+ case Intrinsic::x86_avx512_vcvtsd2si64:
+ if (ConstantFP *FPOp =
+ dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
+ return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
+ /*roundTowardZero=*/false, Ty,
+ /*IsSigned*/true);
+ break;
+ case Intrinsic::x86_avx512_vcvtss2usi32:
+ case Intrinsic::x86_avx512_vcvtss2usi64:
+ case Intrinsic::x86_avx512_vcvtsd2usi32:
+ case Intrinsic::x86_avx512_vcvtsd2usi64:
+ if (ConstantFP *FPOp =
+ dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
+ return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
+ /*roundTowardZero=*/false, Ty,
+ /*IsSigned*/false);
+ break;
+ case Intrinsic::x86_avx512_cvttss2si:
+ case Intrinsic::x86_avx512_cvttss2si64:
+ case Intrinsic::x86_avx512_cvttsd2si:
+ case Intrinsic::x86_avx512_cvttsd2si64:
+ if (ConstantFP *FPOp =
+ dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
+ return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
+ /*roundTowardZero=*/true, Ty,
+ /*IsSigned*/true);
+ break;
+ case Intrinsic::x86_avx512_cvttss2usi:
+ case Intrinsic::x86_avx512_cvttss2usi64:
+ case Intrinsic::x86_avx512_cvttsd2usi:
+ case Intrinsic::x86_avx512_cvttsd2usi64:
+ if (ConstantFP *FPOp =
+ dyn_cast_or_null<ConstantFP>(Op->getAggregateElement(0U)))
+ return ConstantFoldSSEConvertToInt(FPOp->getValueAPF(),
+ /*roundTowardZero=*/true, Ty,
+ /*IsSigned*/false);
+ break;
+ }
+ }
+ return nullptr;
+}
+
+static Constant *ConstantFoldScalarCall3(StringRef Name, unsigned IntrinsicID,
+ Type *Ty,
+ ArrayRef<Constant *> Operands,
+ const TargetLibraryInfo *TLI,
+ const CallBase *Call) {
+ assert(Operands.size() == 3 && "Wrong number of operands.");
if (const auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
if (const auto *Op2 = dyn_cast<ConstantFP>(Operands[1])) {
@@ -2219,6 +2230,23 @@ static Constant *ConstantFoldScalarCall(
return nullptr;
}
+
+static Constant *ConstantFoldScalarCall(StringRef Name, unsigned IntrinsicID,
+ Type *Ty,
+ ArrayRef<Constant *> Operands,
+ const TargetLibraryInfo *TLI,
+ const CallBase *Call) {
+ if (Operands.size() == 1)
+ return ConstantFoldScalarCall1(Name, IntrinsicID, Ty, Operands, TLI, Call);
+
+ if (Operands.size() == 2)
+ return ConstantFoldScalarCall2(Name, IntrinsicID, Ty, Operands, TLI, Call);
+
+ if (Operands.size() == 3)
+ return ConstantFoldScalarCall3(Name, IntrinsicID, Ty, Operands, TLI, Call);
+
+ return nullptr;
+}
static Constant *ConstantFoldVectorCall(StringRef Name, unsigned IntrinsicID,
VectorType *VTy,
More information about the llvm-commits
mailing list