void StraightLineStrengthReduce::factorArrayIndex(Value *ArrayIdx, const SCEV *Base, uint64_t ElementSize, GetElementPtrInst *GEP) { // At least, ArrayIdx = ArrayIdx *nsw 1. allocateCandidatesAndFindBasisForGEP( Base, ConstantInt::get(cast<IntegerType>(ArrayIdx->getType()), 1), ArrayIdx, ElementSize, GEP); Value *LHS = nullptr; ConstantInt *RHS = nullptr; // One alternative is matching the SCEV of ArrayIdx instead of ArrayIdx // itself. This would allow us to handle the shl case for free. However, // matching SCEVs has two issues: // // 1. this would complicate rewriting because the rewriting procedure // would have to translate SCEVs back to IR instructions. This translation // is difficult when LHS is further evaluated to a composite SCEV. // // 2. ScalarEvolution is designed to be control-flow oblivious. It tends // to strip nsw/nuw flags which are critical for SLSR to trace into // sext'ed multiplication. if (match(ArrayIdx, m_NSWMul(m_Value(LHS), m_ConstantInt(RHS)))) { // SLSR is currently unsafe if i * S may overflow. // GEP = Base + sext(LHS *nsw RHS) * ElementSize allocateCandidatesAndFindBasisForGEP(Base, RHS, LHS, ElementSize, GEP); } else if (match(ArrayIdx, m_NSWShl(m_Value(LHS), m_ConstantInt(RHS)))) { // GEP = Base + sext(LHS <<nsw RHS) * ElementSize // = Base + sext(LHS *nsw (1 << RHS)) * ElementSize APInt One(RHS->getBitWidth(), 1); ConstantInt *PowerOf2 = ConstantInt::get(RHS->getContext(), One << RHS->getValue()); allocateCandidatesAndFindBasisForGEP(Base, PowerOf2, LHS, ElementSize, GEP); } }
void StraightLineStrengthReduce::allocateCandidatesAndFindBasisForAdd( Value *LHS, Value *RHS, Instruction *I) { Value *S = nullptr; ConstantInt *Idx = nullptr; if (match(RHS, m_Mul(m_Value(S), m_ConstantInt(Idx)))) { // I = LHS + RHS = LHS + Idx * S allocateCandidatesAndFindBasis(Candidate::Add, SE->getSCEV(LHS), Idx, S, I); } else if (match(RHS, m_Shl(m_Value(S), m_ConstantInt(Idx)))) { // I = LHS + RHS = LHS + (S << Idx) = LHS + S * (1 << Idx) APInt One(Idx->getBitWidth(), 1); Idx = ConstantInt::get(Idx->getContext(), One << Idx->getValue()); allocateCandidatesAndFindBasis(Candidate::Add, SE->getSCEV(LHS), Idx, S, I); } else { // At least, I = LHS + 1 * RHS ConstantInt *One = ConstantInt::get(cast<IntegerType>(I->getType()), 1); allocateCandidatesAndFindBasis(Candidate::Add, SE->getSCEV(LHS), One, RHS, I); } }
// switchConvert - Convert the switch statement into a binary lookup of // the case values. The function recursively builds this tree. // LowerBound and UpperBound are used to keep track of the bounds for Val // that have already been checked by a block emitted by one of the previous // calls to switchConvert in the call stack. BasicBlock * LowerSwitch::switchConvert(CaseItr Begin, CaseItr End, ConstantInt *LowerBound, ConstantInt *UpperBound, Value *Val, BasicBlock *Predecessor, BasicBlock *OrigBlock, BasicBlock *Default, const std::vector<IntRange> &UnreachableRanges) { unsigned Size = End - Begin; if (Size == 1) { // Check if the Case Range is perfectly squeezed in between // already checked Upper and Lower bounds. If it is then we can avoid // emitting the code that checks if the value actually falls in the range // because the bounds already tell us so. if (Begin->Low == LowerBound && Begin->High == UpperBound) { unsigned NumMergedCases = 0; if (LowerBound && UpperBound) NumMergedCases = UpperBound->getSExtValue() - LowerBound->getSExtValue(); fixPhis(Begin->BB, OrigBlock, Predecessor, NumMergedCases); return Begin->BB; } return newLeafBlock(*Begin, Val, OrigBlock, Default); } unsigned Mid = Size / 2; std::vector<CaseRange> LHS(Begin, Begin + Mid); DEBUG(dbgs() << "LHS: " << LHS << "\n"); std::vector<CaseRange> RHS(Begin + Mid, End); DEBUG(dbgs() << "RHS: " << RHS << "\n"); CaseRange &Pivot = *(Begin + Mid); DEBUG(dbgs() << "Pivot ==> " << Pivot.Low->getValue() << " -" << Pivot.High->getValue() << "\n"); // NewLowerBound here should never be the integer minimal value. // This is because it is computed from a case range that is never // the smallest, so there is always a case range that has at least // a smaller value. ConstantInt *NewLowerBound = Pivot.Low; // Because NewLowerBound is never the smallest representable integer // it is safe here to subtract one. ConstantInt *NewUpperBound = ConstantInt::get(NewLowerBound->getContext(), NewLowerBound->getValue() - 1); if (!UnreachableRanges.empty()) { // Check if the gap between LHS's highest and NewLowerBound is unreachable. int64_t GapLow = LHS.back().High->getSExtValue() + 1; int64_t GapHigh = NewLowerBound->getSExtValue() - 1; IntRange Gap = { GapLow, GapHigh }; if (GapHigh >= GapLow && IsInRanges(Gap, UnreachableRanges)) NewUpperBound = LHS.back().High; } DEBUG(dbgs() << "LHS Bounds ==> "; if (LowerBound) { dbgs() << LowerBound->getSExtValue(); } else { dbgs() << "NONE"; } dbgs() << " - " << NewUpperBound->getSExtValue() << "\n"; dbgs() << "RHS Bounds ==> "; dbgs() << NewLowerBound->getSExtValue() << " - "; if (UpperBound) { dbgs() << UpperBound->getSExtValue() << "\n"; } else { dbgs() << "NONE\n"; });