diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-01-19 10:01:25 +0000 |
commit | d8e91e46262bc44006913e6796843909f1ac7bcd (patch) | |
tree | 7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/Analysis/DemandedBits.cpp | |
parent | b7eb8e35e481a74962664b63dfb09483b200209a (diff) |
Notes
Diffstat (limited to 'lib/Analysis/DemandedBits.cpp')
-rw-r--r-- | lib/Analysis/DemandedBits.cpp | 195 |
1 files changed, 139 insertions, 56 deletions
diff --git a/lib/Analysis/DemandedBits.cpp b/lib/Analysis/DemandedBits.cpp index e7637cd88327..34f785fb02be 100644 --- a/lib/Analysis/DemandedBits.cpp +++ b/lib/Analysis/DemandedBits.cpp @@ -21,8 +21,7 @@ #include "llvm/Analysis/DemandedBits.h" #include "llvm/ADT/APInt.h" -#include "llvm/ADT/SmallPtrSet.h" -#include "llvm/ADT/SmallVector.h" +#include "llvm/ADT/SetVector.h" #include "llvm/ADT/StringExtras.h" #include "llvm/Analysis/AssumptionCache.h" #include "llvm/Analysis/ValueTracking.h" @@ -39,6 +38,7 @@ #include "llvm/IR/Module.h" #include "llvm/IR/Operator.h" #include "llvm/IR/PassManager.h" +#include "llvm/IR/PatternMatch.h" #include "llvm/IR/Type.h" #include "llvm/IR/Use.h" #include "llvm/Pass.h" @@ -50,6 +50,7 @@ #include <cstdint> using namespace llvm; +using namespace llvm::PatternMatch; #define DEBUG_TYPE "demanded-bits" @@ -78,13 +79,14 @@ void DemandedBitsWrapperPass::print(raw_ostream &OS, const Module *M) const { } static bool isAlwaysLive(Instruction *I) { - return isa<TerminatorInst>(I) || isa<DbgInfoIntrinsic>(I) || - I->isEHPad() || I->mayHaveSideEffects(); + return I->isTerminator() || isa<DbgInfoIntrinsic>(I) || I->isEHPad() || + I->mayHaveSideEffects(); } void DemandedBits::determineLiveOperandBits( - const Instruction *UserI, const Instruction *I, unsigned OperandNo, - const APInt &AOut, APInt &AB, KnownBits &Known, KnownBits &Known2) { + const Instruction *UserI, const Value *Val, unsigned OperandNo, + const APInt &AOut, APInt &AB, KnownBits &Known, KnownBits &Known2, + bool &KnownBitsComputed) { unsigned BitWidth = AB.getBitWidth(); // We're called once per operand, but for some instructions, we need to @@ -95,7 +97,11 @@ void DemandedBits::determineLiveOperandBits( // provided here. auto ComputeKnownBits = [&](unsigned BitWidth, const Value *V1, const Value *V2) { - const DataLayout &DL = I->getModule()->getDataLayout(); + if (KnownBitsComputed) + return; + KnownBitsComputed = true; + + const DataLayout &DL = UserI->getModule()->getDataLayout(); Known = KnownBits(BitWidth); computeKnownBits(V1, Known, DL, 0, &AC, UserI, &DT); @@ -127,7 +133,7 @@ void DemandedBits::determineLiveOperandBits( // We need some output bits, so we need all bits of the // input to the left of, and including, the leftmost bit // known to be one. - ComputeKnownBits(BitWidth, I, nullptr); + ComputeKnownBits(BitWidth, Val, nullptr); AB = APInt::getHighBitsSet(BitWidth, std::min(BitWidth, Known.countMaxLeadingZeros()+1)); } @@ -137,11 +143,33 @@ void DemandedBits::determineLiveOperandBits( // We need some output bits, so we need all bits of the // input to the right of, and including, the rightmost bit // known to be one. - ComputeKnownBits(BitWidth, I, nullptr); + ComputeKnownBits(BitWidth, Val, nullptr); AB = APInt::getLowBitsSet(BitWidth, std::min(BitWidth, Known.countMaxTrailingZeros()+1)); } break; + case Intrinsic::fshl: + case Intrinsic::fshr: { + const APInt *SA; + if (OperandNo == 2) { + // Shift amount is modulo the bitwidth. For powers of two we have + // SA % BW == SA & (BW - 1). + if (isPowerOf2_32(BitWidth)) + AB = BitWidth - 1; + } else if (match(II->getOperand(2), m_APInt(SA))) { + // Normalize to funnel shift left. APInt shifts of BitWidth are well- + // defined, so no need to special-case zero shifts here. + uint64_t ShiftAmt = SA->urem(BitWidth); + if (II->getIntrinsicID() == Intrinsic::fshr) + ShiftAmt = BitWidth - ShiftAmt; + + if (OperandNo == 0) + AB = AOut.lshr(ShiftAmt); + else if (OperandNo == 1) + AB = AOut.shl(BitWidth - ShiftAmt); + } + break; + } } break; case Instruction::Add: @@ -153,8 +181,9 @@ void DemandedBits::determineLiveOperandBits( AB = APInt::getLowBitsSet(BitWidth, AOut.getActiveBits()); break; case Instruction::Shl: - if (OperandNo == 0) - if (auto *ShiftAmtC = dyn_cast<ConstantInt>(UserI->getOperand(1))) { + if (OperandNo == 0) { + const APInt *ShiftAmtC; + if (match(UserI->getOperand(1), m_APInt(ShiftAmtC))) { uint64_t ShiftAmt = ShiftAmtC->getLimitedValue(BitWidth - 1); AB = AOut.lshr(ShiftAmt); @@ -166,10 +195,12 @@ void DemandedBits::determineLiveOperandBits( else if (S->hasNoUnsignedWrap()) AB |= APInt::getHighBitsSet(BitWidth, ShiftAmt); } + } break; case Instruction::LShr: - if (OperandNo == 0) - if (auto *ShiftAmtC = dyn_cast<ConstantInt>(UserI->getOperand(1))) { + if (OperandNo == 0) { + const APInt *ShiftAmtC; + if (match(UserI->getOperand(1), m_APInt(ShiftAmtC))) { uint64_t ShiftAmt = ShiftAmtC->getLimitedValue(BitWidth - 1); AB = AOut.shl(ShiftAmt); @@ -178,10 +209,12 @@ void DemandedBits::determineLiveOperandBits( if (cast<LShrOperator>(UserI)->isExact()) AB |= APInt::getLowBitsSet(BitWidth, ShiftAmt); } + } break; case Instruction::AShr: - if (OperandNo == 0) - if (auto *ShiftAmtC = dyn_cast<ConstantInt>(UserI->getOperand(1))) { + if (OperandNo == 0) { + const APInt *ShiftAmtC; + if (match(UserI->getOperand(1), m_APInt(ShiftAmtC))) { uint64_t ShiftAmt = ShiftAmtC->getLimitedValue(BitWidth - 1); AB = AOut.shl(ShiftAmt); // Because the high input bit is replicated into the @@ -196,6 +229,7 @@ void DemandedBits::determineLiveOperandBits( if (cast<AShrOperator>(UserI)->isExact()) AB |= APInt::getLowBitsSet(BitWidth, ShiftAmt); } + } break; case Instruction::And: AB = AOut; @@ -204,14 +238,11 @@ void DemandedBits::determineLiveOperandBits( // other operand are dead (unless they're both zero, in which // case they can't both be dead, so just mark the LHS bits as // dead). - if (OperandNo == 0) { - ComputeKnownBits(BitWidth, I, UserI->getOperand(1)); + ComputeKnownBits(BitWidth, UserI->getOperand(0), UserI->getOperand(1)); + if (OperandNo == 0) AB &= ~Known2.Zero; - } else { - if (!isa<Instruction>(UserI->getOperand(0))) - ComputeKnownBits(BitWidth, UserI->getOperand(0), I); + else AB &= ~(Known.Zero & ~Known2.Zero); - } break; case Instruction::Or: AB = AOut; @@ -220,14 +251,11 @@ void DemandedBits::determineLiveOperandBits( // other operand are dead (unless they're both one, in which // case they can't both be dead, so just mark the LHS bits as // dead). - if (OperandNo == 0) { - ComputeKnownBits(BitWidth, I, UserI->getOperand(1)); + ComputeKnownBits(BitWidth, UserI->getOperand(0), UserI->getOperand(1)); + if (OperandNo == 0) AB &= ~Known2.One; - } else { - if (!isa<Instruction>(UserI->getOperand(0))) - ComputeKnownBits(BitWidth, UserI->getOperand(0), I); + else AB &= ~(Known.One & ~Known2.One); - } break; case Instruction::Xor: case Instruction::PHI: @@ -253,6 +281,15 @@ void DemandedBits::determineLiveOperandBits( if (OperandNo != 0) AB = AOut; break; + case Instruction::ExtractElement: + if (OperandNo == 0) + AB = AOut; + break; + case Instruction::InsertElement: + case Instruction::ShuffleVector: + if (OperandNo == 0 || OperandNo == 1) + AB = AOut; + break; } } @@ -275,8 +312,9 @@ void DemandedBits::performAnalysis() { Visited.clear(); AliveBits.clear(); + DeadUses.clear(); - SmallVector<Instruction*, 128> Worklist; + SmallSetVector<Instruction*, 16> Worklist; // Collect the set of "root" instructions that are known live. for (Instruction &I : instructions(F)) { @@ -288,9 +326,10 @@ void DemandedBits::performAnalysis() { // bits and add the instruction to the work list. For other instructions // add their operands to the work list (for integer values operands, mark // all bits as live). - if (IntegerType *IT = dyn_cast<IntegerType>(I.getType())) { - if (AliveBits.try_emplace(&I, IT->getBitWidth(), 0).second) - Worklist.push_back(&I); + Type *T = I.getType(); + if (T->isIntOrIntVectorTy()) { + if (AliveBits.try_emplace(&I, T->getScalarSizeInBits(), 0).second) + Worklist.insert(&I); continue; } @@ -298,9 +337,10 @@ void DemandedBits::performAnalysis() { // Non-integer-typed instructions... for (Use &OI : I.operands()) { if (Instruction *J = dyn_cast<Instruction>(OI)) { - if (IntegerType *IT = dyn_cast<IntegerType>(J->getType())) - AliveBits[J] = APInt::getAllOnesValue(IT->getBitWidth()); - Worklist.push_back(J); + Type *T = J->getType(); + if (T->isIntOrIntVectorTy()) + AliveBits[J] = APInt::getAllOnesValue(T->getScalarSizeInBits()); + Worklist.insert(J); } } // To save memory, we don't add I to the Visited set here. Instead, we @@ -315,35 +355,51 @@ void DemandedBits::performAnalysis() { LLVM_DEBUG(dbgs() << "DemandedBits: Visiting: " << *UserI); APInt AOut; - if (UserI->getType()->isIntegerTy()) { + if (UserI->getType()->isIntOrIntVectorTy()) { AOut = AliveBits[UserI]; - LLVM_DEBUG(dbgs() << " Alive Out: " << AOut); + LLVM_DEBUG(dbgs() << " Alive Out: 0x" + << Twine::utohexstr(AOut.getLimitedValue())); } LLVM_DEBUG(dbgs() << "\n"); - if (!UserI->getType()->isIntegerTy()) + if (!UserI->getType()->isIntOrIntVectorTy()) Visited.insert(UserI); KnownBits Known, Known2; + bool KnownBitsComputed = false; // Compute the set of alive bits for each operand. These are anded into the // existing set, if any, and if that changes the set of alive bits, the // operand is added to the work-list. for (Use &OI : UserI->operands()) { - if (Instruction *I = dyn_cast<Instruction>(OI)) { - if (IntegerType *IT = dyn_cast<IntegerType>(I->getType())) { - unsigned BitWidth = IT->getBitWidth(); - APInt AB = APInt::getAllOnesValue(BitWidth); - if (UserI->getType()->isIntegerTy() && !AOut && - !isAlwaysLive(UserI)) { - AB = APInt(BitWidth, 0); - } else { - // If all bits of the output are dead, then all bits of the input - // Bits of each operand that are used to compute alive bits of the - // output are alive, all others are dead. - determineLiveOperandBits(UserI, I, OI.getOperandNo(), AOut, AB, - Known, Known2); - } + // We also want to detect dead uses of arguments, but will only store + // demanded bits for instructions. + Instruction *I = dyn_cast<Instruction>(OI); + if (!I && !isa<Argument>(OI)) + continue; + + Type *T = OI->getType(); + if (T->isIntOrIntVectorTy()) { + unsigned BitWidth = T->getScalarSizeInBits(); + APInt AB = APInt::getAllOnesValue(BitWidth); + if (UserI->getType()->isIntOrIntVectorTy() && !AOut && + !isAlwaysLive(UserI)) { + // If all bits of the output are dead, then all bits of the input + // are also dead. + AB = APInt(BitWidth, 0); + } else { + // Bits of each operand that are used to compute alive bits of the + // output are alive, all others are dead. + determineLiveOperandBits(UserI, OI, OI.getOperandNo(), AOut, AB, + Known, Known2, KnownBitsComputed); + + // Keep track of uses which have no demanded bits. + if (AB.isNullValue()) + DeadUses.insert(&OI); + else + DeadUses.erase(&OI); + } + if (I) { // If we've added to the set of alive bits (or the operand has not // been previously visited), then re-queue the operand to be visited // again. @@ -355,11 +411,11 @@ void DemandedBits::performAnalysis() { APInt ABNew = AB | ABPrev; if (ABNew != ABPrev || ABI == AliveBits.end()) { AliveBits[I] = std::move(ABNew); - Worklist.push_back(I); + Worklist.insert(I); } - } else if (!Visited.count(I)) { - Worklist.push_back(I); } + } else if (I && !Visited.count(I)) { + Worklist.insert(I); } } } @@ -368,11 +424,13 @@ void DemandedBits::performAnalysis() { APInt DemandedBits::getDemandedBits(Instruction *I) { performAnalysis(); - const DataLayout &DL = I->getModule()->getDataLayout(); auto Found = AliveBits.find(I); if (Found != AliveBits.end()) return Found->second; - return APInt::getAllOnesValue(DL.getTypeSizeInBits(I->getType())); + + const DataLayout &DL = I->getModule()->getDataLayout(); + return APInt::getAllOnesValue( + DL.getTypeSizeInBits(I->getType()->getScalarType())); } bool DemandedBits::isInstructionDead(Instruction *I) { @@ -382,6 +440,31 @@ bool DemandedBits::isInstructionDead(Instruction *I) { !isAlwaysLive(I); } +bool DemandedBits::isUseDead(Use *U) { + // We only track integer uses, everything else is assumed live. + if (!(*U)->getType()->isIntOrIntVectorTy()) + return false; + + // Uses by always-live instructions are never dead. + Instruction *UserI = cast<Instruction>(U->getUser()); + if (isAlwaysLive(UserI)) + return false; + + performAnalysis(); + if (DeadUses.count(U)) + return true; + + // If no output bits are demanded, no input bits are demanded and the use + // is dead. These uses might not be explicitly present in the DeadUses map. + if (UserI->getType()->isIntOrIntVectorTy()) { + auto Found = AliveBits.find(UserI); + if (Found != AliveBits.end() && Found->second.isNullValue()) + return true; + } + + return false; +} + void DemandedBits::print(raw_ostream &OS) { performAnalysis(); for (auto &KV : AliveBits) { |