27 #define DEBUG_TYPE "bypass-slow-division"
35 DivOpInfo(
bool InSignedOp,
Value *InDividend,
Value *InDivisor)
36 : SignedOp(InSignedOp), Dividend(InDividend), Divisor(InDivisor) {}
44 : Quotient(InQuotient), Remainder(InRemainder) {}
51 static bool isEqual(
const DivOpInfo &Val1,
const DivOpInfo &Val2) {
52 return Val1.SignedOp == Val2.SignedOp &&
53 Val1.Dividend == Val2.Dividend &&
54 Val1.Divisor == Val2.Divisor;
58 return DivOpInfo(
false,
nullptr,
nullptr);
62 return DivOpInfo(
true,
nullptr,
nullptr);
66 return (
unsigned)(
reinterpret_cast<uintptr_t
>(Val.Dividend) ^
67 reinterpret_cast<uintptr_t>(Val.Divisor)) ^
68 (
unsigned)Val.SignedOp;
79 bool UseDivOp,
bool UseSignedOp,
86 if (isa<ConstantInt>(Divisor)) {
93 if (
ConstantInt *ConstDividend = dyn_cast<ConstantInt>(Dividend))
94 if (ConstDividend->getValue().getActiveBits() > BypassType->
getBitWidth())
106 Value *SlowQuotientV;
107 Value *SlowRemainderV;
109 SlowQuotientV = SlowBuilder.
CreateSDiv(Dividend, Divisor);
110 SlowRemainderV = SlowBuilder.CreateSRem(Dividend, Divisor);
112 SlowQuotientV = SlowBuilder.
CreateUDiv(Dividend, Divisor);
113 SlowRemainderV = SlowBuilder.CreateURem(Dividend, Divisor);
115 SlowBuilder.CreateBr(SuccessorBB);
122 Value *ShortDivisorV = FastBuilder.CreateCast(Instruction::Trunc, Divisor,
124 Value *ShortDividendV = FastBuilder.CreateCast(Instruction::Trunc, Dividend,
128 Value *ShortQuotientV = FastBuilder.CreateUDiv(ShortDividendV, ShortDivisorV);
129 Value *ShortRemainderV = FastBuilder.CreateURem(ShortDividendV,
131 Value *FastQuotientV = FastBuilder.CreateCast(Instruction::ZExt,
134 Value *FastRemainderV = FastBuilder.CreateCast(Instruction::ZExt,
137 FastBuilder.CreateBr(SuccessorBB);
142 QuoPhi->addIncoming(SlowQuotientV, SlowBB);
143 QuoPhi->addIncoming(FastQuotientV, FastBB);
162 assert(!isa<ConstantInt>(Divisor));
165 if (!isa<ConstantInt>(Dividend))
166 OrV = MainBuilder.CreateOr(Dividend, Divisor);
173 Value *AndV = MainBuilder.CreateAnd(OrV, BitMask);
177 Value *CmpV = MainBuilder.CreateICmpEQ(AndV, ZeroV);
178 MainBuilder.CreateCondBr(CmpV, FastBB, SlowBB);
182 DivOpInfo Key(UseSignedOp, Dividend, Divisor);
183 DivPhiNodes
Value(QuoPhi, RemPhi);
184 PerBBDivCache.
insert(std::pair<DivOpInfo, DivPhiNodes>(Key, Value));
193 bool UseDivOp,
bool UseSignedOp,
199 if (CacheI == PerBBDivCache.
end()) {
201 return insertFastDiv(I, BypassType, UseDivOp, UseSignedOp, PerBBDivCache);
205 DivPhiNodes &
Value = CacheI->second;
226 bool MadeChange =
false;
228 while (Next !=
nullptr) {
236 bool UseDivOp = Opcode == Instruction::SDiv || Opcode == Instruction::UDiv;
237 bool UseRemOp = Opcode == Instruction::SRem || Opcode == Instruction::URem;
238 bool UseSignedOp = Opcode == Instruction::SDiv ||
239 Opcode == Instruction::SRem;
242 if (!UseDivOp && !UseRemOp)
255 if (BI == BypassWidths.
end())
267 for (
auto &KV : DivCache)
268 for (
Instruction *Phi : {KV.second.Quotient, KV.second.Remainder})
SymbolTableList< Instruction >::iterator eraseFromParent()
This method unlinks 'this' from the containing basic block and deletes it.
void addIncoming(Value *V, BasicBlock *BB)
Add an incoming value to the end of the PHI list.
LLVMContext & getContext() const
getContext - Return a reference to the LLVMContext associated with this function. ...
NodeTy * getNextNode()
Get the next node, or nullptr for the list tail.
const Function * getParent() const
Return the enclosing method, or null if none.
unsigned getBitWidth() const
Get the number of bits in this IntegerType.
iterator begin()
Instruction iterator methods.
std::pair< iterator, bool > insert(const std::pair< KeyT, ValueT > &KV)
static DivOpInfo getEmptyKey()
bool bypassSlowDivision(BasicBlock *BB, const DenseMap< unsigned int, unsigned int > &BypassWidth)
This optimization identifies DIV instructions in a BB that can be profitably bypassed and carried out...
This provides a uniform API for creating instructions and inserting them into a basic block: either a...
void replaceAllUsesWith(Value *V)
Change all uses of this to point to a new Value.
static DivOpInfo getTombstoneKey()
LLVM Basic Block Representation.
const InstListType & getInstList() const
Return the underlying instruction list container.
Value * getOperand(unsigned i) const
static BasicBlock * Create(LLVMContext &Context, const Twine &Name="", Function *Parent=nullptr, BasicBlock *InsertBefore=nullptr)
Creates a new BasicBlock.
Class to represent integer types.
bool RecursivelyDeleteTriviallyDeadInstructions(Value *V, const TargetLibraryInfo *TLI=nullptr)
If the specified value is a trivially dead instruction, delete it.
LLVMContext & getContext() const
All values hold a context through their type.
static IntegerType * get(LLVMContext &C, unsigned NumBits)
This static method is the primary way of constructing an IntegerType.
This is the shared class of boolean and integer constants.
Type * getType() const
All values are typed, get the type of this value.
static ConstantInt * getSigned(IntegerType *Ty, int64_t V)
Return a ConstantInt with the specified value for the specified type.
Value * CreateSDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
Value * CreateUDiv(Value *LHS, Value *RHS, const Twine &Name="", bool isExact=false)
bool isIntegerTy() const
True if this is an instance of IntegerType.
uint64_t getBitMask() const
Return a bitmask with ones set for all of the bits that can be set by an unsigned version of this typ...
static bool insertFastDiv(Instruction *I, IntegerType *BypassType, bool UseDivOp, bool UseSignedOp, DivCacheTy &PerBBDivCache)
DenseMap< DivOpInfo, DivPhiNodes > DivCacheTy
iterator find(const KeyT &Val)
BasicBlock * splitBasicBlock(iterator I, const Twine &BBName="")
Split the basic block into two basic blocks at the specified instruction.
static bool isEqual(const DivOpInfo &Val1, const DivOpInfo &Val2)
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
static unsigned getHashValue(const DivOpInfo &Val)
LLVM Value Representation.
unsigned getOpcode() const
Returns a member of one of the enums like Instruction::Add.
void moveBefore(BasicBlock *MovePos)
Unlink this basic block from its current function and insert it into the function that MovePos lives ...
const BasicBlock * getParent() const
static bool reuseOrInsertFastDiv(Instruction *I, IntegerType *BypassType, bool UseDivOp, bool UseSignedOp, DivCacheTy &PerBBDivCache)