20 using namespace PatternMatch;
22 #define DEBUG_TYPE "instcombine"
29 if (SimplifyDemandedInstructionBits(I))
33 if (isa<Constant>(Op0))
38 if (
Constant *CUI = dyn_cast<Constant>(Op1))
39 if (
Instruction *Res = FoldShiftByConstant(Op0, CUI, I))
70 bool IsFirstShiftLeft,
77 if (!SecondShiftConst)
80 unsigned SecondShiftAmt = SecondShiftConst->
getZExtValue();
81 bool IsSecondShiftLeft = SecondShift->
getOpcode() == Instruction::Shl;
85 if (IsFirstShiftLeft == IsSecondShiftLeft)
90 if (FirstShiftAmt == SecondShiftAmt)
101 if (SecondShiftAmt > FirstShiftAmt && SecondShiftAmt < TypeWidth) {
102 unsigned MaskShift = IsSecondShiftLeft ? TypeWidth - SecondShiftAmt
103 : SecondShiftAmt - FirstShiftAmt;
127 if (isa<Constant>(V))
131 if (!I)
return false;
146 uint32_t OrigBitWidth = OrigTy->getScalarSizeInBits();
147 uint32_t BitWidth = Ty->getScalarSizeInBits();
151 return CanEvaluateTruncated(I->
getOperand(0), Ty);
163 default:
return false;
171 case Instruction::Shl:
172 case Instruction::LShr:
182 case Instruction::PHI: {
200 if (
Constant *
C = dyn_cast<Constant>(V)) {
206 if (
auto *
C = dyn_cast<Constant>(V))
228 case Instruction::Shl: {
239 if (NewShAmt >= TypeWidth)
272 case Instruction::LShr: {
282 if (NewShAmt >= TypeWidth)
318 case Instruction::PHI: {
325 isLeftShift, IC, DL));
341 if (ShiftOp && !ShiftOp->
isShift())
344 if (ShiftOp && isa<ConstantInt>(ShiftOp->
getOperand(1))) {
361 assert(ShiftAmt2 != 0 &&
"Should have been simplified earlier");
370 uint32_t AmtSum = ShiftAmt1 + ShiftAmt2;
373 if (AmtSum >= TypeBits) {
376 AmtSum = TypeBits - 1;
383 if (ShiftAmt1 == ShiftAmt2) {
385 if (I.
getOpcode() == Instruction::LShr &&
386 ShiftOp->
getOpcode() == Instruction::Shl) {
388 return BinaryOperator::CreateAnd(
391 }
else if (ShiftAmt1 < ShiftAmt2) {
392 uint32_t ShiftDiff = ShiftAmt2 - ShiftAmt1;
400 ShiftOp->
getOpcode() == Instruction::AShr);
410 if (I.
getOpcode() == Instruction::LShr &&
411 ShiftOp->
getOpcode() == Instruction::Shl) {
423 return BinaryOperator::CreateAnd(
429 if (I.
getOpcode() == Instruction::AShr &&
430 ShiftOp->
getOpcode() == Instruction::Shl) {
441 assert(ShiftAmt2 < ShiftAmt1);
442 uint32_t ShiftDiff = ShiftAmt1 - ShiftAmt2;
457 if (I.
getOpcode() == Instruction::LShr &&
458 ShiftOp->
getOpcode() == Instruction::Shl) {
470 return BinaryOperator::CreateAnd(
476 if (I.
getOpcode() == Instruction::AShr &&
477 ShiftOp->
getOpcode() == Instruction::Shl) {
495 bool isLeftShift = I.
getOpcode() == Instruction::Shl;
499 COp1 = dyn_cast_or_null<ConstantInt>(CV->getSplatValue());
501 COp1 = dyn_cast_or_null<ConstantInt>(CV->getSplatValue());
510 if (I.
getOpcode() != Instruction::AShr &&
512 DEBUG(
dbgs() <<
"ICE: GetShiftedValue propagating shift through expression"
513 " to eliminate shift:\n IN: " << *Op0 <<
"\n SH: " << I <<
"\n");
515 return replaceInstUsesWith(
524 "Shift over the type width should have been removed already");
528 if (BO->getOpcode() == Instruction::Mul && isLeftShift)
529 if (
Constant *BOOp = dyn_cast<Constant>(BO->getOperand(1)))
533 if (
Instruction *FoldedShift = foldOpWithConstantIntoOperand(I))
537 if (
TruncInst *TI = dyn_cast<TruncInst>(Op0)) {
556 unsigned DstSize = TI->getType()->getScalarSizeInBits();
571 Value *
And = Builder->CreateAnd(NSh,
585 switch (Op0BO->getOpcode()) {
593 if (isLeftShift && Op0BO->getOperand(1)->hasOneUse() &&
597 Builder->CreateShl(Op0BO->getOperand(0), Op1, Op0BO->
getName());
599 Value *
X = Builder->CreateBinOp(Op0BO->getOpcode(), YS, V1,
600 Op0BO->getOperand(1)->
getName());
607 return BinaryOperator::CreateAnd(X, Mask);
611 Value *Op0BOOp1 = Op0BO->getOperand(1);
612 if (isLeftShift && Op0BOOp1->
hasOneUse() &&
617 Builder->CreateShl(Op0BO->getOperand(0), Op1,
627 case Instruction::Sub: {
629 if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
633 Builder->CreateShl(Op0BO->getOperand(1), Op1, Op0BO->
getName());
635 Value *
X = Builder->CreateBinOp(Op0BO->getOpcode(), V1, YS,
636 Op0BO->getOperand(0)->
getName());
643 return BinaryOperator::CreateAnd(X, Mask);
647 if (isLeftShift && Op0BO->getOperand(0)->hasOneUse() &&
648 match(Op0BO->getOperand(0),
652 Builder->CreateShl(Op0BO->getOperand(1), Op1, Op0BO->
getName());
667 if (
ConstantInt *Op0C = dyn_cast<ConstantInt>(Op0BO->getOperand(1))) {
669 bool highBitSet =
false;
671 switch (Op0BO->getOpcode()) {
672 default: isValid =
false;
break;
674 isValid = isLeftShift;
691 if (isValid && I.
getOpcode() == Instruction::AShr)
692 isValid = Op0C->getValue()[TypeBits-1] == highBitSet;
698 Builder->CreateBinOp(I.
getOpcode(), Op0BO->getOperand(0), Op1);
715 if (
Value *V = SimplifyVectorOp(I))
716 return replaceInstUsesWith(I, V);
721 return replaceInstUsesWith(I, V);
727 unsigned ShAmt = Op1C->getZExtValue();
738 if (
auto *ZI = dyn_cast<ZExtInst>(I.
getOperand(0))) {
739 unsigned SrcBitWidth = ZI->getSrcTy()->getScalarSizeInBits();
740 if (ShAmt < SrcBitWidth &&
743 auto *Shl = Builder->CreateShl(ZI->getOperand(0), ShAmt);
776 if (
Value *V = SimplifyVectorOp(I))
777 return replaceInstUsesWith(I, V);
781 return replaceInstUsesWith(I, V);
788 if (
ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
789 unsigned ShAmt = Op1C->getZExtValue();
796 if ((II->getIntrinsicID() == Intrinsic::ctlz ||
797 II->getIntrinsicID() == Intrinsic::cttz ||
798 II->getIntrinsicID() == Intrinsic::ctpop) &&
800 bool isCtPop = II->getIntrinsicID() == Intrinsic::ctpop;
802 Value *Cmp = Builder->CreateICmpEQ(II->getArgOperand(0), RHS);
803 return new ZExtInst(Cmp, II->getType());
820 if (
Value *V = SimplifyVectorOp(I))
821 return replaceInstUsesWith(I, V);
825 return replaceInstUsesWith(I, V);
832 if (
ConstantInt *Op1C = dyn_cast<ConstantInt>(Op1)) {
833 unsigned ShAmt = Op1C->getZExtValue();
844 if (
ZExtInst *ZI = dyn_cast<ZExtInst>(X)) {
845 uint32_t SrcBits = ZI->getOperand(0)->getType()->getScalarSizeInBits();
846 uint32_t DestBits = ZI->getType()->getScalarSizeInBits();
847 if (Op1C->getZExtValue() == DestBits-SrcBits)
848 return new SExtInst(ZI->getOperand(0), ZI->getType());
865 return BinaryOperator::CreateLShr(Op0, Op1);
static bool canEvaluateShiftedShift(unsigned FirstShiftAmt, bool IsFirstShiftLeft, Instruction *SecondShift, InstCombiner &IC, Instruction *CxtI)
Return true if we can simplify two logical (either left or right) shifts that have constant shift amo...
A vector constant whose element type is a simple 1/2/4/8-byte integer or float/double, and whose elements are just simple data values (i.e.
BinaryOp_match< LHS, RHS, Instruction::And > m_And(const LHS &L, const RHS &R)
A parsed version of the target data layout string in and methods for querying it. ...
class_match< Value > m_Value()
Match an arbitrary value and ignore it.
static APInt getSignBit(unsigned BitWidth)
Get the SignBit for a specific bit width.
BinaryOp_match< LHS, RHS, Instruction::SRem > m_SRem(const LHS &L, const RHS &R)
This class represents zero extension of integer types.
static APInt getLowBitsSet(unsigned numBits, unsigned loBitsSet)
Get a value with low bits set.
class_match< Constant > m_Constant()
Match an arbitrary Constant and ignore it.
static Instruction * foldShiftByConstOfShiftByConst(BinaryOperator &I, ConstantInt *COp1, InstCombiner::BuilderTy *Builder)
Try to fold (X << C1) << C2, where the shifts are some combination of shl/ashr/lshr.
void Add(Instruction *I)
Add - Add the specified instruction to the worklist if it isn't already in it.
This class represents a sign extension of integer types.
static Constant * getNullValue(Type *Ty)
Constructor to create a '0' constant of arbitrary type.
StringRef getName() const
Return a constant reference to the value's name.
bool uge(uint64_t Num) const
This function will return true iff this constant represents a value with active bits bigger than 64 b...
bool match(Val *V, const Pattern &P)
This class represents the LLVM 'select' instruction.
Instruction * commonShiftTransforms(BinaryOperator &I)
const APInt & getValue() const
Return the constant as an APInt value reference.
BinOp2_match< LHS, RHS, Instruction::LShr, Instruction::AShr > m_Shr(const LHS &L, const RHS &R)
Matches LShr or AShr.
APInt lshr(unsigned shiftAmt) const
Logical right-shift function.
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
The core instruction combiner logic.
BinaryOp_match< LHS, RHS, Instruction::Add > m_Add(const LHS &L, const RHS &R)
uint64_t getZExtValue() const
Return the constant as a 64-bit unsigned integer value after it has been zero extended as appropriate...
Constant * ConstantFoldConstant(const Constant *C, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr)
ConstantFoldConstant - Attempt to fold the constant using the specified DataLayout.
static Constant * get(unsigned Opcode, Constant *C1, Constant *C2, unsigned Flags=0, Type *OnlyIfReducedTy=nullptr)
get - Return a binary or shift operator constant expression, folding if possible. ...
static Constant * getZExt(Constant *C, Type *Ty, bool OnlyIfReduced=false)
void setIsExact(bool b=true)
Set or clear the exact flag on this instruction, which must be an operator which supports this flag...
uint64_t getLimitedValue(uint64_t Limit=~0ULL) const
getLimitedValue - If the value is smaller than the specified limit, return it, otherwise return the l...
TargetLibraryInfo & getTargetLibraryInfo() const
bool isLogicalShift() const
Return true if this is a logical shift left or a logical shift right.
class_match< ConstantInt > m_ConstantInt()
Match an arbitrary ConstantInt and ignore it.
static GCRegistry::Add< OcamlGC > B("ocaml","ocaml 3.10-compatible GC")
cst_pred_ty< is_power2 > m_Power2()
Match an integer or vector power of 2.
void takeName(Value *V)
Transfer the name from V to this value.
This class represents a truncation of integer types.
unsigned getNumIncomingValues() const
Return the number of incoming edges.
static APInt getHighBitsSet(unsigned numBits, unsigned hiBitsSet)
Get a value with high bits set.
OneUse_match< T > m_OneUse(const T &SubPattern)
BinaryOp_match< LHS, RHS, Instruction::LShr > m_LShr(const LHS &L, const RHS &R)
constexpr bool isPowerOf2_32(uint32_t Value)
isPowerOf2_32 - This function returns true if the argument is a power of two > 0. ...
bool isExact() const
Determine whether the exact flag is set.
bool isKnownNonNegative(const Value *V, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
Returns true if the give value is known to be non-negative.
This is an important base class in LLVM.
bool MaskedValueIsZero(const Value *V, const APInt &Mask, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
Return true if 'V & Mask' is known to be zero.
APInt Or(const APInt &LHS, const APInt &RHS)
Bitwise OR function for APInt.
bool hasNoSignedWrap() const
Determine whether the no signed wrap flag is set.
APInt Xor(const APInt &LHS, const APInt &RHS)
Bitwise XOR function for APInt.
Value * SimplifyShlInst(Value *Op0, Value *Op1, bool isNSW, bool isNUW, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr)
Given operands for a Shl, fold the result or return null.
specificval_ty m_Specific(const Value *V)
Match if we have a specific specified value.
BinaryOp_match< LHS, RHS, Instruction::Shl > m_Shl(const LHS &L, const RHS &R)
static GCMetadataPrinterRegistry::Add< ErlangGCPrinter > X("erlang","erlang-compatible garbage collector")
Value * getOperand(unsigned i) const
Class to represent integer types.
Constant Vector Declarations.
Instruction * visitLShr(BinaryOperator &I)
LLVMContext & getContext() const
All values hold a context through their type.
const Value * getTrueValue() const
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
InstCombineWorklist & Worklist
A worklist of the instructions that need to be simplified.
BinaryOps getOpcode() const
static Constant * getSplat(unsigned NumElts, Constant *Elt)
Return a ConstantVector with the specified constant in each element.
void setHasNoSignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag...
This is the shared class of boolean and integer constants.
unsigned ComputeNumSignBits(const Value *Op, const DataLayout &DL, unsigned Depth=0, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr, const DominatorTree *DT=nullptr)
Return the number of times the sign bit of the register is replicated into the other bits...
bool hasNoUnsignedWrap() const
Determine whether the no unsigned wrap flag is set.
Value * getIncomingValue(unsigned i) const
Return incoming value number x.
unsigned getScalarSizeInBits() const LLVM_READONLY
If this is a vector type, return the getPrimitiveSizeInBits value for the element type...
Type * getType() const
All values are typed, get the type of this value.
INITIALIZE_PASS(HexagonGenMux,"hexagon-mux","Hexagon generate mux instructions", false, false) void HexagonGenMux I isValid()
static Constant * get(Type *Ty, uint64_t V, bool isSigned=false)
If Ty is a vector type, return a Constant with a splat of the given value.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
static GCRegistry::Add< ShadowStackGC > C("shadow-stack","Very portable GC for uncooperative code generators")
void setOperand(unsigned i, Value *Val)
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
unsigned Log2_32(uint32_t Value)
Log2_32 - This function returns the floor log base 2 of the specified value, -1 if the value is zero...
Class to represent vector types.
Class for arbitrary precision integers.
static BinaryOperator * Create(BinaryOps Op, Value *S1, Value *S2, const Twine &Name=Twine(), Instruction *InsertBefore=nullptr)
Construct a binary instruction, given the opcode and the two operands.
Value * CreateShl(Value *LHS, Value *RHS, const Twine &Name="", bool HasNUW=false, bool HasNSW=false)
static bool CanEvaluateShifted(Value *V, unsigned NumBits, bool IsLeftShift, InstCombiner &IC, Instruction *CxtI)
See if we can compute the specified value, but shifted logically to the left or right by some number ...
APInt And(const APInt &LHS, const APInt &RHS)
Bitwise AND function for APInt.
static Value * GetShiftedValue(Value *V, unsigned NumBits, bool isLeftShift, InstCombiner &IC, const DataLayout &DL)
When CanEvaluateShifted returned true for an expression, this value inserts the new computation that ...
bool hasOneUse() const
Return true if there is exactly one user of this value.
LLVM_NODISCARD std::enable_if<!is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type >::type dyn_cast(const Y &Val)
static Constant * getShl(Constant *C1, Constant *C2, bool HasNUW=false, bool HasNSW=false)
bool MaskedValueIsZero(Value *V, const APInt &Mask, unsigned Depth=0, Instruction *CxtI=nullptr) const
Value * SimplifyLShrInst(Value *Op0, Value *Op1, bool isExact, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr)
Given operands for a LShr, fold the result or return null.
void setHasNoUnsignedWrap(bool b=true)
Set or clear the nsw flag on this instruction, which must be an operator which supports this flag...
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Value * SimplifyAShrInst(Value *Op0, Value *Op1, bool isExact, const DataLayout &DL, const TargetLibraryInfo *TLI=nullptr, const DominatorTree *DT=nullptr, AssumptionCache *AC=nullptr, const Instruction *CxtI=nullptr)
Given operands for a AShr, fold the result or return nulll.
This file provides internal interfaces used to implement the InstCombine.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
#define LLVM_FALLTHROUGH
LLVM_FALLTHROUGH - Mark fallthrough cases in switch statements.
std::underlying_type< E >::type Mask()
Get a bitmask with 1s in all places up to the high-order bit of E's largest value.
Value * CreateLShr(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
const Value * getFalseValue() const
Instruction * visitAShr(BinaryOperator &I)
void setIncomingValue(unsigned i, Value *V)
Instruction * visitShl(BinaryOperator &I)
static BinaryOperator * CreateMul(Value *S1, Value *S2, const Twine &Name, Instruction *InsertBefore, Value *FlagsOp)
op_range incoming_values()
static GCRegistry::Add< ErlangGC > A("erlang","erlang-compatible garbage collector")
Instruction * FoldShiftByConstant(Value *Op0, Constant *Op1, BinaryOperator &I)
A wrapper class for inspecting calls to intrinsic functions.