diff --git a/llvm/include/llvm/IR/ConstantFolder.h b/llvm/include/llvm/IR/ConstantFolder.h index c2b30a65e32e2..6671d5f3314eb 100644 --- a/llvm/include/llvm/IR/ConstantFolder.h +++ b/llvm/include/llvm/IR/ConstantFolder.h @@ -58,8 +58,7 @@ class ConstantFolder final : public IRBuilderFolder { auto *RC = dyn_cast(RHS); if (LC && RC) { if (ConstantExpr::isDesirableBinOp(Opc)) - return ConstantExpr::get(Opc, LC, RC, - IsExact ? PossiblyExactOperator::IsExact : 0); + return ConstantExpr::get(Opc, LC, RC); return ConstantFoldBinaryInstruction(Opc, LC, RC); } return nullptr; diff --git a/llvm/include/llvm/IR/InstrTypes.h b/llvm/include/llvm/IR/InstrTypes.h index fc5e228168a05..b4b58bccd94dc 100644 --- a/llvm/include/llvm/IR/InstrTypes.h +++ b/llvm/include/llvm/IR/InstrTypes.h @@ -706,6 +706,26 @@ class PossiblyNonNegInst : public CastInst { } }; +/// A div or shr instruction, which can be marked as "exact", +/// indicating that no bits are destroyed. +class PossiblyExactInst : public BinaryOperator { +public: + enum { IsExact = (1 << 0) }; + + static bool classof(const Instruction *I) { + unsigned OpC = I->getOpcode(); + return OpC == Instruction::SDiv || OpC == Instruction::UDiv || + OpC == Instruction::AShr || OpC == Instruction::LShr; + } + + static bool classof(const Value *V) { + return isa(V) && classof(cast(V)); + } +}; + +// TODO: Drop compatibility alias. +using PossiblyExactOperator = PossiblyExactInst; + //===----------------------------------------------------------------------===// // CmpInst Class //===----------------------------------------------------------------------===// diff --git a/llvm/include/llvm/IR/Operator.h b/llvm/include/llvm/IR/Operator.h index 12733529a74dc..306d3b53e7589 100644 --- a/llvm/include/llvm/IR/Operator.h +++ b/llvm/include/llvm/IR/Operator.h @@ -124,47 +124,6 @@ class OverflowingBinaryOperator : public Operator { } }; -/// A udiv or sdiv instruction, which can be marked as "exact", -/// indicating that no bits are destroyed. -class PossiblyExactOperator : public Operator { -public: - enum { - IsExact = (1 << 0) - }; - -private: - friend class Instruction; - friend class ConstantExpr; - - void setIsExact(bool B) { - SubclassOptionalData = (SubclassOptionalData & ~IsExact) | (B * IsExact); - } - -public: - /// Test whether this division is known to be exact, with zero remainder. - bool isExact() const { - return SubclassOptionalData & IsExact; - } - - static bool isPossiblyExactOpcode(unsigned OpC) { - return OpC == Instruction::SDiv || - OpC == Instruction::UDiv || - OpC == Instruction::AShr || - OpC == Instruction::LShr; - } - - static bool classof(const ConstantExpr *CE) { - return isPossiblyExactOpcode(CE->getOpcode()); - } - static bool classof(const Instruction *I) { - return isPossiblyExactOpcode(I->getOpcode()); - } - static bool classof(const Value *V) { - return (isa(V) && classof(cast(V))) || - (isa(V) && classof(cast(V))); - } -}; - /// Utility class for floating point operations which can have /// information about relaxed accuracy requirements attached to them. class FPMathOperator : public Operator { @@ -360,13 +319,6 @@ class ShlOperator : public ConcreteOperator { }; -class AShrOperator - : public ConcreteOperator { -}; -class LShrOperator - : public ConcreteOperator { -}; - class GEPOperator : public ConcreteOperator { friend class GetElementPtrInst; diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index f709a5ac52a41..ffb1b44910156 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -1342,8 +1342,8 @@ template struct Exact_match { Exact_match(const SubPattern_t &SP) : SubPattern(SP) {} template bool match(OpTy *V) { - if (auto *PEO = dyn_cast(V)) - return PEO->isExact() && SubPattern.match(V); + if (auto *PEI = dyn_cast(V)) + return PEI->isExact() && SubPattern.match(V); return false; } }; diff --git a/llvm/lib/Analysis/DemandedBits.cpp b/llvm/lib/Analysis/DemandedBits.cpp index c5017bf52498e..0429df87480a6 100644 --- a/llvm/lib/Analysis/DemandedBits.cpp +++ b/llvm/lib/Analysis/DemandedBits.cpp @@ -197,7 +197,7 @@ void DemandedBits::determineLiveOperandBits( // If the shift is exact, then the low bits are not dead // (they must be zero). - if (cast(UserI)->isExact()) + if (UserI->isExact()) AB |= APInt::getLowBitsSet(BitWidth, ShiftAmt); } } @@ -217,7 +217,7 @@ void DemandedBits::determineLiveOperandBits( // If the shift is exact, then the low bits are not dead // (they must be zero). - if (cast(UserI)->isExact()) + if (UserI->isExact()) AB |= APInt::getLowBitsSet(BitWidth, ShiftAmt); } } diff --git a/llvm/lib/Analysis/VectorUtils.cpp b/llvm/lib/Analysis/VectorUtils.cpp index 4f5db8b7aaf74..27e1f8a1c51ad 100644 --- a/llvm/lib/Analysis/VectorUtils.cpp +++ b/llvm/lib/Analysis/VectorUtils.cpp @@ -674,13 +674,11 @@ llvm::computeMinimumValueSizes(ArrayRef Blocks, DemandedBits &DB, // If any of M's operands demand more bits than MinBW then M cannot be // performed safely in MinBW. - if (any_of(MI->operands(), [&DB, MinBW](Use &U) { + if (any_of(MI->operands(), [&DB, MinBW, MI](Use &U) { auto *CI = dyn_cast(U); // For constants shift amounts, check if the shift would result in // poison. - if (CI && - isa(U.getUser()) && - U.getOperandNo() == 1) + if (CI && MI->isShift() && U.getOperandNo() == 1) return CI->uge(MinBW); uint64_t BW = bit_width(DB.getDemandedBits(&U).getZExtValue()); return bit_ceil(BW) > MinBW; diff --git a/llvm/lib/IR/Constants.cpp b/llvm/lib/IR/Constants.cpp index bc55d5b485271..5c7af2ff3b961 100644 --- a/llvm/lib/IR/Constants.cpp +++ b/llvm/lib/IR/Constants.cpp @@ -3244,8 +3244,6 @@ Instruction *ConstantExpr::getAsInstruction(Instruction *InsertBefore) const { BO->setHasNoSignedWrap(SubclassOptionalData & OverflowingBinaryOperator::NoSignedWrap); } - if (isa(BO)) - BO->setIsExact(SubclassOptionalData & PossiblyExactOperator::IsExact); return BO; } } diff --git a/llvm/lib/IR/Instruction.cpp b/llvm/lib/IR/Instruction.cpp index 7449692f05d7b..188338bdc5c59 100644 --- a/llvm/lib/IR/Instruction.cpp +++ b/llvm/lib/IR/Instruction.cpp @@ -314,7 +314,9 @@ void Instruction::setHasNoSignedWrap(bool b) { } void Instruction::setIsExact(bool b) { - cast(this)->setIsExact(b); + assert(isa(this) && "Instruction must support exact flag"); + SubclassOptionalData = (SubclassOptionalData & ~PossiblyExactInst::IsExact) | + (b * PossiblyExactInst::IsExact); } void Instruction::setNonNeg(bool b) { @@ -354,7 +356,7 @@ void Instruction::dropPoisonGeneratingFlags() { case Instruction::SDiv: case Instruction::AShr: case Instruction::LShr: - cast(this)->setIsExact(false); + setIsExact(false); break; case Instruction::GetElementPtr: @@ -416,7 +418,8 @@ void Instruction::dropUBImplyingAttrsAndMetadata() { } bool Instruction::isExact() const { - return cast(this)->isExact(); + assert(isa(this) && "Instruction must support exact flag"); + return (SubclassOptionalData & PossiblyExactInst::IsExact) != 0; } void Instruction::setFast(bool B) { diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp index 9bc84c7dd6e15..f61d70406c3ac 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1009,7 +1009,8 @@ Instruction *InstCombinerImpl::foldICmpShrConstConst(ICmpInst &I, Value *A, if (AP2.isZero()) return nullptr; - bool IsAShr = isa(I.getOperand(0)); + bool IsAShr = + cast(I.getOperand(0))->getOpcode() == Instruction::AShr; if (IsAShr) { if (AP2.isAllOnes()) return nullptr;