Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions llvm/include/llvm/Analysis/ConstantFolding.h
Original file line number Diff line number Diff line change
Expand Up @@ -169,11 +169,8 @@ LLVM_ABI Constant *ConstantFoldCall(const CallBase *Call, Function *F,
const TargetLibraryInfo *TLI = nullptr,
bool AllowNonDeterministic = true);

LLVM_ABI Constant *ConstantFoldUnaryIntrinsic(Intrinsic::ID ID, Constant *Op,
Type *Ty);

LLVM_ABI Constant *ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS,
Constant *RHS, Type *Ty);
LLVM_ABI Constant *ConstantFoldIntrinsic(Intrinsic::ID ID,
ArrayRef<Constant *> Ops, Type *Ty);

/// ConstantFoldLoadThroughBitcast - try to cast constant to destination type
/// returning null if unsuccessful. Can cast pointer to pointer or pointer to
Expand Down
14 changes: 4 additions & 10 deletions llvm/include/llvm/Analysis/InstSimplifyFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -120,16 +120,10 @@ class LLVM_ABI InstSimplifyFolder final : public IRBuilderFolder {
return simplifyCastInst(Op, V, DestTy, SQ);
}

Value *
FoldUnaryIntrinsic(Intrinsic::ID ID, Value *Op, Type *Ty,
FastMathFlags FMF = FastMathFlags()) const override {
return simplifyUnaryIntrinsic(ID, Op, FMF, SQ);
}

Value *
FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
FastMathFlags FMF = FastMathFlags()) const override {
return simplifyBinaryIntrinsic(ID, Ty, LHS, RHS, FMF, SQ);
Value *FoldIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Ops, Type *Ty,
FastMathFlags FMF = {},
Function *CtxF = nullptr) const override {
return simplifyIntrinsic(ID, Ty, Ops, FMF, SQ, CtxF);
}

//===--------------------------------------------------------------------===//
Expand Down
11 changes: 0 additions & 11 deletions llvm/include/llvm/Analysis/InstructionSimplify.h
Original file line number Diff line number Diff line change
Expand Up @@ -194,17 +194,6 @@ LLVM_ABI Value *simplifyExtractElementInst(Value *Vec, Value *Idx,
LLVM_ABI Value *simplifyCastInst(unsigned CastOpc, Value *Op, Type *Ty,
const SimplifyQuery &Q);

/// Given operands for a unary intrinsic, fold the result or return null.
LLVM_ABI Value *simplifyUnaryIntrinsic(Intrinsic::ID IID, Value *Op0,
FastMathFlags FMF,
const SimplifyQuery &Q);

/// Given operands for a binary intrinsic, fold the result or return null.
LLVM_ABI Value *simplifyBinaryIntrinsic(Intrinsic::ID IID, Type *ReturnType,
Value *Op0, Value *Op1,
FastMathFlags FMF,
const SimplifyQuery &Q);

/// Given operands for an intrinsic, fold the result or return null. Context
/// Function is passed as \p CxtF. \p ExBehavior and \p Rounding only apply to
/// constrained FP intrinsics.
Expand Down
19 changes: 6 additions & 13 deletions llvm/include/llvm/Analysis/TargetFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -191,19 +191,12 @@ class LLVM_ABI TargetFolder final : public IRBuilderFolder {
return nullptr;
}

Value *FoldUnaryIntrinsic(Intrinsic::ID ID, Value *Op, Type *Ty,
FastMathFlags FMF) const override {
if (auto *OpC = dyn_cast<Constant>(Op))
return ConstantFoldUnaryIntrinsic(ID, OpC, Ty);
return nullptr;
}

Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
FastMathFlags FMF) const override {
auto *C1 = dyn_cast<Constant>(LHS);
auto *C2 = dyn_cast<Constant>(RHS);
if (C1 && C2)
return ConstantFoldBinaryIntrinsic(ID, C1, C2, Ty);
Value *FoldIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Ops, Type *Ty,
FastMathFlags FMF = {},
Function *CtxF = nullptr) const override {
if (all_of(Ops, IsaPred<Constant>))
return ConstantFoldIntrinsic(
ID, ArrayRef((Constant *const *)Ops.data(), Ops.size()), Ty);
return nullptr;
}

Expand Down
10 changes: 2 additions & 8 deletions llvm/include/llvm/IR/ConstantFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -182,14 +182,8 @@ class LLVM_ABI ConstantFolder final : public IRBuilderFolder {
return nullptr;
}

Value *FoldUnaryIntrinsic(Intrinsic::ID ID, Value *Op, Type *Ty,
FastMathFlags FMF) const override {
// Use TargetFolder or InstSimplifyFolder instead.
return nullptr;
}

Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
FastMathFlags FMF) const override {
Value *FoldIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Ops, Type *Ty,
FastMathFlags FMF, Function *CtxF) const override {
// Use TargetFolder or InstSimplifyFolder instead.
return nullptr;
}
Expand Down
10 changes: 3 additions & 7 deletions llvm/include/llvm/IR/IRBuilderFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,13 +76,9 @@ class LLVM_ABI IRBuilderFolder {
virtual Value *FoldCast(Instruction::CastOps Op, Value *V,
Type *DestTy) const = 0;

virtual Value *
FoldUnaryIntrinsic(Intrinsic::ID ID, Value *Op, Type *Ty,
FastMathFlags FMF = FastMathFlags()) const = 0;

virtual Value *
FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
FastMathFlags FMF = FastMathFlags()) const = 0;
virtual Value *FoldIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Ops,
Type *Ty, FastMathFlags FMF = {},
Function *CtxF = nullptr) const = 0;

//===--------------------------------------------------------------------===//
// Cast/Conversion Operators
Expand Down
9 changes: 2 additions & 7 deletions llvm/include/llvm/IR/NoFolder.h
Original file line number Diff line number Diff line change
Expand Up @@ -114,13 +114,8 @@ class LLVM_ABI NoFolder final : public IRBuilderFolder {
return nullptr;
}

Value *FoldUnaryIntrinsic(Intrinsic::ID ID, Value *Op, Type *Ty,
FastMathFlags FMF) const override {
return nullptr;
}

Value *FoldBinaryIntrinsic(Intrinsic::ID ID, Value *LHS, Value *RHS, Type *Ty,
FastMathFlags FMF) const override {
Value *FoldIntrinsic(Intrinsic::ID ID, ArrayRef<Value *> Ops, Type *Ty,
FastMathFlags FMF, Function *CtxF) const override {
return nullptr;
}

Expand Down
142 changes: 69 additions & 73 deletions llvm/lib/Analysis/ConstantFolding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2489,13 +2489,13 @@ getEvaluationRoundingMode(const ConstrainedFPIntrinsic *CI) {
}

/// Try to constant fold llvm.canonicalize for the given caller and value.
static Constant *constantFoldCanonicalize(const Type *Ty, const CallBase *CI,
const APFloat &Src) {
static Constant *constantFoldCanonicalize(const Type *Ty, const APFloat &Src,
const Function *CtxF = nullptr) {
// Zero, positive and negative, is always OK to fold.
if (Src.isZero()) {
// Get a fresh 0, since ppc_fp128 does have non-canonical zeros.
return ConstantFP::get(
CI->getContext(),
Ty->getContext(),
APFloat::getZero(Src.getSemantics(), Src.isNegative()));
}

Expand All @@ -2507,14 +2507,13 @@ static Constant *constantFoldCanonicalize(const Type *Ty, const CallBase *CI,
// Denorms and nans may have special encodings, but it should be OK to fold a
// totally average number.
if (Src.isNormal() || Src.isInfinity())
return ConstantFP::get(CI->getContext(), Src);
return ConstantFP::get(Ty->getContext(), Src);

if (Src.isDenormal() && CI->getParent() && CI->getFunction()) {
DenormalMode DenormMode =
CI->getFunction()->getDenormalMode(Src.getSemantics());
if (Src.isDenormal() && CtxF) {
DenormalMode DenormMode = CtxF->getDenormalMode(Src.getSemantics());

if (DenormMode == DenormalMode::getIEEE())
return ConstantFP::get(CI->getContext(), Src);
return ConstantFP::get(Ty->getContext(), Src);

if (DenormMode.Input == DenormalMode::Dynamic)
return nullptr;
Expand All @@ -2531,19 +2530,18 @@ static Constant *constantFoldCanonicalize(const Type *Ty, const CallBase *CI,
(DenormMode.Output == DenormalMode::PositiveZero &&
DenormMode.Input == DenormalMode::IEEE));

return ConstantFP::get(CI->getContext(),
return ConstantFP::get(Ty->getContext(),
APFloat::getZero(Src.getSemantics(), !IsPositive));
}

return nullptr;
}

static Constant *ConstantFoldScalarCall1(StringRef Name,
Intrinsic::ID IntrinsicID,
Type *Ty,
Intrinsic::ID IntrinsicID, Type *Ty,
ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI,
const CallBase *Call) {
const TargetLibraryInfo *TLI = nullptr,
const CallBase *Call = nullptr) {
assert(Operands.size() == 1 && "Wrong number of operands.");

if (IntrinsicID == Intrinsic::is_constant) {
Expand Down Expand Up @@ -2580,7 +2578,7 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
// 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;
Call && Call->getParent() ? Call->getCaller() : nullptr;
if (Caller &&
!NullPointerIsDefined(
Caller, Operands[0]->getType()->getPointerAddressSpace())) {
Expand Down Expand Up @@ -2622,8 +2620,11 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
return ConstantInt::get(Ty, Int);
}

if (IntrinsicID == Intrinsic::canonicalize)
return constantFoldCanonicalize(Ty, Call, U);
if (IntrinsicID == Intrinsic::canonicalize) {
const Function *CtxF =
Call && Call->getParent() ? Call->getFunction() : nullptr;
return constantFoldCanonicalize(Ty, U, CtxF);
}

#if defined(HAS_IEE754_FLOAT128) && defined(HAS_LOGF128)
if (Ty->isFP128Ty()) {
Expand Down Expand Up @@ -2697,48 +2698,49 @@ static Constant *ConstantFoldScalarCall1(StringRef Name,
// Rounding operations (floor, trunc, ceil, round and nearbyint) do not
// raise FP exceptions, unless the argument is signaling NaN.

std::optional<APFloat::roundingMode> RM;
switch (IntrinsicID) {
default:
break;
case Intrinsic::experimental_constrained_nearbyint:
case Intrinsic::experimental_constrained_rint: {
auto CI = cast<ConstrainedFPIntrinsic>(Call);
RM = CI->getRoundingMode();
if (!RM || *RM == RoundingMode::Dynamic)
return nullptr;
break;
}
case Intrinsic::experimental_constrained_round:
RM = APFloat::rmNearestTiesToAway;
break;
case Intrinsic::experimental_constrained_ceil:
RM = APFloat::rmTowardPositive;
break;
case Intrinsic::experimental_constrained_floor:
RM = APFloat::rmTowardNegative;
break;
case Intrinsic::experimental_constrained_trunc:
RM = APFloat::rmTowardZero;
break;
}
if (RM) {
auto CI = cast<ConstrainedFPIntrinsic>(Call);
if (U.isFinite()) {
APFloat::opStatus St = U.roundToIntegral(*RM);
if (IntrinsicID == Intrinsic::experimental_constrained_rint &&
St == APFloat::opInexact) {
if (auto *CI = dyn_cast_or_null<ConstrainedFPIntrinsic>(Call)) {
std::optional<APFloat::roundingMode> RM;
switch (IntrinsicID) {
default:
break;
case Intrinsic::experimental_constrained_nearbyint:
case Intrinsic::experimental_constrained_rint: {
RM = CI->getRoundingMode();
if (!RM || *RM == RoundingMode::Dynamic)
return nullptr;
break;
}
case Intrinsic::experimental_constrained_round:
RM = APFloat::rmNearestTiesToAway;
break;
case Intrinsic::experimental_constrained_ceil:
RM = APFloat::rmTowardPositive;
break;
case Intrinsic::experimental_constrained_floor:
RM = APFloat::rmTowardNegative;
break;
case Intrinsic::experimental_constrained_trunc:
RM = APFloat::rmTowardZero;
break;
}
if (RM) {
if (U.isFinite()) {
APFloat::opStatus St = U.roundToIntegral(*RM);
if (IntrinsicID == Intrinsic::experimental_constrained_rint &&
St == APFloat::opInexact) {
std::optional<fp::ExceptionBehavior> EB =
CI->getExceptionBehavior();
if (EB == fp::ebStrict)
return nullptr;
}
} else if (U.isSignaling()) {
std::optional<fp::ExceptionBehavior> EB = CI->getExceptionBehavior();
if (EB == fp::ebStrict)
if (EB && *EB != fp::ebIgnore)
return nullptr;
U = APFloat::getQNaN(U.getSemantics());
}
} else if (U.isSignaling()) {
std::optional<fp::ExceptionBehavior> EB = CI->getExceptionBehavior();
if (EB && *EB != fp::ebIgnore)
return nullptr;
U = APFloat::getQNaN(U.getSemantics());
return ConstantFP::get(Ty, U);
}
return ConstantFP::get(Ty, U);
}

// NVVM float/double to signed/unsigned int32/int64 conversions:
Expand Down Expand Up @@ -3350,7 +3352,7 @@ static Constant *ConstantFoldNextToward(const APFloat &Op0, const APFloat &Op1,

static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty,
ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI) {
const TargetLibraryInfo *TLI = nullptr) {
if (!TLI)
return nullptr;

Expand Down Expand Up @@ -3421,7 +3423,7 @@ static Constant *ConstantFoldLibCall2(StringRef Name, Type *Ty,

static Constant *ConstantFoldIntrinsicCall2(Intrinsic::ID IntrinsicID, Type *Ty,
ArrayRef<Constant *> Operands,
const CallBase *Call) {
const CallBase *Call = nullptr) {
assert(Operands.size() == 2 && "Wrong number of operands.");

if (Ty->isFloatingPointTy()) {
Expand Down Expand Up @@ -4098,11 +4100,10 @@ static Constant *ConstantFoldAMDGCNPermIntrinsic(ArrayRef<Constant *> Operands,
}

static Constant *ConstantFoldScalarCall3(StringRef Name,
Intrinsic::ID IntrinsicID,
Type *Ty,
Intrinsic::ID IntrinsicID, Type *Ty,
ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI,
const CallBase *Call) {
const TargetLibraryInfo *TLI = nullptr,
const CallBase *Call = nullptr) {
assert(Operands.size() == 3 && "Wrong number of operands.");

if (const auto *Op1 = dyn_cast<ConstantFP>(Operands[0])) {
Expand All @@ -4112,7 +4113,8 @@ static Constant *ConstantFoldScalarCall3(StringRef Name,
const APFloat &C2 = Op2->getValueAPF();
const APFloat &C3 = Op3->getValueAPF();

if (const auto *ConstrIntr = dyn_cast<ConstrainedFPIntrinsic>(Call)) {
if (const auto *ConstrIntr =
dyn_cast_or_null<ConstrainedFPIntrinsic>(Call)) {
RoundingMode RM = getEvaluationRoundingMode(ConstrIntr);
APFloat Res = C1;
APFloat::opStatus St;
Expand Down Expand Up @@ -4262,11 +4264,10 @@ static Constant *ConstantFoldScalarCall3(StringRef Name,
}

static Constant *ConstantFoldScalarCall(StringRef Name,
Intrinsic::ID IntrinsicID,
Type *Ty,
Intrinsic::ID IntrinsicID, Type *Ty,
ArrayRef<Constant *> Operands,
const TargetLibraryInfo *TLI,
const CallBase *Call) {
const TargetLibraryInfo *TLI = nullptr,
const CallBase *Call = nullptr) {
if (IntrinsicID != Intrinsic::not_intrinsic &&
any_of(Operands, IsaPred<PoisonValue>) &&
intrinsicPropagatesPoison(IntrinsicID))
Expand Down Expand Up @@ -4706,14 +4707,9 @@ ConstantFoldStructCall(StringRef Name, Intrinsic::ID IntrinsicID,

} // end anonymous namespace

Constant *llvm::ConstantFoldUnaryIntrinsic(Intrinsic::ID ID, Constant *Op,
Type *Ty) {
return ConstantFoldScalarCall1("", ID, Ty, Op, nullptr, nullptr);
}

Constant *llvm::ConstantFoldBinaryIntrinsic(Intrinsic::ID ID, Constant *LHS,
Constant *RHS, Type *Ty) {
return ConstantFoldIntrinsicCall2(ID, Ty, {LHS, RHS}, nullptr);
Constant *llvm::ConstantFoldIntrinsic(Intrinsic::ID ID,
ArrayRef<Constant *> Ops, Type *Ty) {
return ConstantFoldScalarCall("", ID, Ty, Ops);
}

Constant *llvm::ConstantFoldCall(const CallBase *Call, Function *F,
Expand Down
Loading
Loading