aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms/Utils/Local.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Transforms/Utils/Local.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/Transforms/Utils/Local.cpp')
-rw-r--r--llvm/lib/Transforms/Utils/Local.cpp709
1 files changed, 410 insertions, 299 deletions
diff --git a/llvm/lib/Transforms/Utils/Local.cpp b/llvm/lib/Transforms/Utils/Local.cpp
index 477ea458c763..d03d76f57ca1 100644
--- a/llvm/lib/Transforms/Utils/Local.cpp
+++ b/llvm/lib/Transforms/Utils/Local.cpp
@@ -24,7 +24,6 @@
#include "llvm/ADT/SmallPtrSet.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/ADT/Statistic.h"
-#include "llvm/ADT/TinyPtrVector.h"
#include "llvm/Analysis/AssumeBundleQueries.h"
#include "llvm/Analysis/ConstantFolding.h"
#include "llvm/Analysis/DomTreeUpdater.h"
@@ -65,6 +64,7 @@
#include "llvm/IR/Module.h"
#include "llvm/IR/Operator.h"
#include "llvm/IR/PatternMatch.h"
+#include "llvm/IR/PseudoProbe.h"
#include "llvm/IR/Type.h"
#include "llvm/IR/Use.h"
#include "llvm/IR/User.h"
@@ -111,8 +111,8 @@ static cl::opt<unsigned> PHICSENumPHISmallSize(
"perform a (faster!) exhaustive search instead of set-driven one."));
// Max recursion depth for collectBitParts used when detecting bswap and
-// bitreverse idioms
-static const unsigned BitPartRecursionMaxDepth = 64;
+// bitreverse idioms.
+static const unsigned BitPartRecursionMaxDepth = 48;
//===----------------------------------------------------------------------===//
// Local constant propagation.
@@ -148,7 +148,12 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
Dest1->removePredecessor(BI->getParent());
// Replace the conditional branch with an unconditional one.
- Builder.CreateBr(Dest1);
+ BranchInst *NewBI = Builder.CreateBr(Dest1);
+
+ // Transfer the metadata to the new branch instruction.
+ NewBI->copyMetadata(*BI, {LLVMContext::MD_loop, LLVMContext::MD_dbg,
+ LLVMContext::MD_annotation});
+
Value *Cond = BI->getCondition();
BI->eraseFromParent();
if (DeleteDeadConditions)
@@ -167,7 +172,12 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
OldDest->removePredecessor(BB);
// Replace the conditional branch with an unconditional one.
- Builder.CreateBr(Destination);
+ BranchInst *NewBI = Builder.CreateBr(Destination);
+
+ // Transfer the metadata to the new branch instruction.
+ NewBI->copyMetadata(*BI, {LLVMContext::MD_loop, LLVMContext::MD_dbg,
+ LLVMContext::MD_annotation});
+
BI->eraseFromParent();
if (DTU)
DTU->applyUpdates({{DominatorTree::Delete, BB, OldDest}});
@@ -257,7 +267,7 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
Builder.CreateBr(TheOnlyDest);
BasicBlock *BB = SI->getParent();
- SmallSetVector<BasicBlock *, 8> RemovedSuccessors;
+ SmallSet<BasicBlock *, 8> RemovedSuccessors;
// Remove entries from PHI nodes which we no longer branch to...
BasicBlock *SuccToKeep = TheOnlyDest;
@@ -329,7 +339,7 @@ bool llvm::ConstantFoldTerminator(BasicBlock *BB, bool DeleteDeadConditions,
if (auto *BA =
dyn_cast<BlockAddress>(IBI->getAddress()->stripPointerCasts())) {
BasicBlock *TheOnlyDest = BA->getBasicBlock();
- SmallSetVector<BasicBlock *, 8> RemovedSuccessors;
+ SmallSet<BasicBlock *, 8> RemovedSuccessors;
// Insert the new branch.
Builder.CreateBr(TheOnlyDest);
@@ -410,7 +420,7 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
return true;
}
if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(I)) {
- if (DVI->getValue())
+ if (DVI->hasArgList() || DVI->getValue(0))
return false;
return true;
}
@@ -420,13 +430,8 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
return true;
}
- if (auto *CB = dyn_cast<CallBase>(I)) {
- // Treat calls that may not return as alive.
- // TODO: Remove the intrinsic escape hatch once all intrinsics set
- // willreturn properly.
- if (!CB->willReturn() && !isa<IntrinsicInst>(I))
- return false;
- }
+ if (!I->willReturn())
+ return false;
if (!I->mayHaveSideEffects())
return true;
@@ -461,13 +466,18 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
// sophisticated tradeoffs for guards considering potential for check
// widening, but for now we keep things simple.
if ((II->getIntrinsicID() == Intrinsic::assume &&
- isAssumeWithEmptyBundle(*II)) ||
+ isAssumeWithEmptyBundle(cast<AssumeInst>(*II))) ||
II->getIntrinsicID() == Intrinsic::experimental_guard) {
if (ConstantInt *Cond = dyn_cast<ConstantInt>(II->getArgOperand(0)))
return !Cond->isZero();
return false;
}
+
+ if (auto *FPI = dyn_cast<ConstrainedFPIntrinsic>(I)) {
+ Optional<fp::ExceptionBehavior> ExBehavior = FPI->getExceptionBehavior();
+ return ExBehavior.getValue() != fp::ebStrict;
+ }
}
if (isAllocLikeFn(I, TLI))
@@ -481,6 +491,16 @@ bool llvm::wouldInstructionBeTriviallyDead(Instruction *I,
if (isMathLibCallNoop(Call, TLI))
return true;
+ // To express possible interaction with floating point environment constrained
+ // intrinsics are described as if they access memory. So they look like having
+ // side effect but actually do not have it unless they raise floating point
+ // exception. If FP exceptions are ignored, the intrinsic may be deleted.
+ if (auto *CI = dyn_cast<ConstrainedFPIntrinsic>(I)) {
+ Optional<fp::ExceptionBehavior> EB = CI->getExceptionBehavior();
+ if (!EB || *EB == fp::ExceptionBehavior::ebIgnore)
+ return true;
+ }
+
return false;
}
@@ -570,8 +590,7 @@ bool llvm::replaceDbgUsesWithUndef(Instruction *I) {
findDbgUsers(DbgUsers, I);
for (auto *DII : DbgUsers) {
Value *Undef = UndefValue::get(I->getType());
- DII->setOperand(0, MetadataAsValue::get(DII->getContext(),
- ValueAsMetadata::get(Undef)));
+ DII->replaceVariableLocationOp(I, Undef);
}
return !DbgUsers.empty();
}
@@ -734,21 +753,22 @@ void llvm::MergeBasicBlockIntoOnlyPred(BasicBlock *DestBB,
BasicBlock *PredBB = DestBB->getSinglePredecessor();
assert(PredBB && "Block doesn't have a single predecessor!");
- bool ReplaceEntryBB = false;
- if (PredBB == &DestBB->getParent()->getEntryBlock())
- ReplaceEntryBB = true;
+ bool ReplaceEntryBB = PredBB->isEntryBlock();
// DTU updates: Collect all the edges that enter
// PredBB. These dominator edges will be redirected to DestBB.
SmallVector<DominatorTree::UpdateType, 32> Updates;
if (DTU) {
- for (auto I = pred_begin(PredBB), E = pred_end(PredBB); I != E; ++I) {
+ SmallPtrSet<BasicBlock *, 2> PredsOfPredBB(pred_begin(PredBB),
+ pred_end(PredBB));
+ Updates.reserve(Updates.size() + 2 * PredsOfPredBB.size() + 1);
+ for (BasicBlock *PredOfPredBB : PredsOfPredBB)
// This predecessor of PredBB may already have DestBB as a successor.
- if (!llvm::is_contained(successors(*I), DestBB))
- Updates.push_back({DominatorTree::Insert, *I, DestBB});
- Updates.push_back({DominatorTree::Delete, *I, PredBB});
- }
+ if (PredOfPredBB != PredBB)
+ Updates.push_back({DominatorTree::Insert, PredOfPredBB, DestBB});
+ for (BasicBlock *PredOfPredBB : PredsOfPredBB)
+ Updates.push_back({DominatorTree::Delete, PredOfPredBB, PredBB});
Updates.push_back({DominatorTree::Delete, PredBB, DestBB});
}
@@ -923,6 +943,7 @@ static void gatherIncomingValuesToPhi(PHINode *PN,
/// \param IncomingValues A map from block to value.
static void replaceUndefValuesInPhi(PHINode *PN,
const IncomingValueMap &IncomingValues) {
+ SmallVector<unsigned> TrueUndefOps;
for (unsigned i = 0, e = PN->getNumIncomingValues(); i != e; ++i) {
Value *V = PN->getIncomingValue(i);
@@ -930,10 +951,31 @@ static void replaceUndefValuesInPhi(PHINode *PN,
BasicBlock *BB = PN->getIncomingBlock(i);
IncomingValueMap::const_iterator It = IncomingValues.find(BB);
- if (It == IncomingValues.end()) continue;
+ // Keep track of undef/poison incoming values. Those must match, so we fix
+ // them up below if needed.
+ // Note: this is conservatively correct, but we could try harder and group
+ // the undef values per incoming basic block.
+ if (It == IncomingValues.end()) {
+ TrueUndefOps.push_back(i);
+ continue;
+ }
+
+ // There is a defined value for this incoming block, so map this undef
+ // incoming value to the defined value.
PN->setIncomingValue(i, It->second);
}
+
+ // If there are both undef and poison values incoming, then convert those
+ // values to undef. It is invalid to have different values for the same
+ // incoming block.
+ unsigned PoisonCount = count_if(TrueUndefOps, [&](unsigned i) {
+ return isa<PoisonValue>(PN->getIncomingValue(i));
+ });
+ if (PoisonCount != 0 && PoisonCount != TrueUndefOps.size()) {
+ for (unsigned i : TrueUndefOps)
+ PN->setIncomingValue(i, UndefValue::get(PN->getType()));
+ }
}
/// Replace a value flowing from a block to a phi with
@@ -1040,8 +1082,8 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
// We cannot fold the block if it's a branch to an already present callbr
// successor because that creates duplicate successors.
- for (auto I = pred_begin(BB), E = pred_end(BB); I != E; ++I) {
- if (auto *CBI = dyn_cast<CallBrInst>((*I)->getTerminator())) {
+ for (BasicBlock *PredBB : predecessors(BB)) {
+ if (auto *CBI = dyn_cast<CallBrInst>(PredBB->getTerminator())) {
if (Succ == CBI->getDefaultDest())
return false;
for (unsigned i = 0, e = CBI->getNumIndirectDests(); i != e; ++i)
@@ -1055,14 +1097,15 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
SmallVector<DominatorTree::UpdateType, 32> Updates;
if (DTU) {
// All predecessors of BB will be moved to Succ.
- SmallSetVector<BasicBlock *, 8> Predecessors(pred_begin(BB), pred_end(BB));
- Updates.reserve(Updates.size() + 2 * Predecessors.size());
- for (auto *Predecessor : Predecessors) {
+ SmallPtrSet<BasicBlock *, 8> PredsOfBB(pred_begin(BB), pred_end(BB));
+ SmallPtrSet<BasicBlock *, 8> PredsOfSucc(pred_begin(Succ), pred_end(Succ));
+ Updates.reserve(Updates.size() + 2 * PredsOfBB.size() + 1);
+ for (auto *PredOfBB : PredsOfBB)
// This predecessor of BB may already have Succ as a successor.
- if (!llvm::is_contained(successors(Predecessor), Succ))
- Updates.push_back({DominatorTree::Insert, Predecessor, Succ});
- Updates.push_back({DominatorTree::Delete, Predecessor, BB});
- }
+ if (!PredsOfSucc.contains(PredOfBB))
+ Updates.push_back({DominatorTree::Insert, PredOfBB, Succ});
+ for (auto *PredOfBB : PredsOfBB)
+ Updates.push_back({DominatorTree::Delete, PredOfBB, BB});
Updates.push_back({DominatorTree::Delete, BB, Succ});
}
@@ -1102,10 +1145,8 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
Instruction *TI = BB->getTerminator();
if (TI)
if (MDNode *LoopMD = TI->getMetadata(LoopMDKind))
- for (pred_iterator PI = pred_begin(BB), E = pred_end(BB); PI != E; ++PI) {
- BasicBlock *Pred = *PI;
+ for (BasicBlock *Pred : predecessors(BB))
Pred->getTerminator()->setMetadata(LoopMDKind, LoopMD);
- }
// Everything that jumped to BB now goes to Succ.
BB->replaceAllUsesWith(Succ);
@@ -1118,12 +1159,11 @@ bool llvm::TryToSimplifyUncondBranchFromEmptyBlock(BasicBlock *BB,
assert(succ_empty(BB) && "The successor list of BB isn't empty before "
"applying corresponding DTU updates.");
- if (DTU) {
+ if (DTU)
DTU->applyUpdates(Updates);
- DTU->deleteBB(BB);
- } else {
- BB->eraseFromParent(); // Delete the old basic block.
- }
+
+ DeleteDeadBlock(BB, DTU);
+
return true;
}
@@ -1339,7 +1379,7 @@ static bool PhiHasDebugValue(DILocalVariable *DIVar,
SmallVector<DbgValueInst *, 1> DbgValues;
findDbgValues(DbgValues, APN);
for (auto *DVI : DbgValues) {
- assert(DVI->getValue() == APN);
+ assert(is_contained(DVI->getValues(), APN));
if ((DVI->getVariable() == DIVar) && (DVI->getExpression() == DIExpr))
return true;
}
@@ -1366,13 +1406,19 @@ static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) {
// We can't always calculate the size of the DI variable (e.g. if it is a
// VLA). Try to use the size of the alloca that the dbg intrinsic describes
// intead.
- if (DII->isAddressOfVariable())
- if (auto *AI = dyn_cast_or_null<AllocaInst>(DII->getVariableLocation()))
+ if (DII->isAddressOfVariable()) {
+ // DII should have exactly 1 location when it is an address.
+ assert(DII->getNumVariableLocationOps() == 1 &&
+ "address of variable must have exactly 1 location operand.");
+ if (auto *AI =
+ dyn_cast_or_null<AllocaInst>(DII->getVariableLocationOp(0))) {
if (Optional<TypeSize> FragmentSize = AI->getAllocationSizeInBits(DL)) {
assert(ValueSize.isScalable() == FragmentSize->isScalable() &&
"Both sizes should agree on the scalable flag.");
return TypeSize::isKnownGE(ValueSize, *FragmentSize);
}
+ }
+ }
// Could not determine size of variable. Conservatively return false.
return false;
}
@@ -1383,7 +1429,7 @@ static bool valueCoversEntireFragment(Type *ValTy, DbgVariableIntrinsic *DII) {
/// case this DebugLoc leaks into any adjacent instructions.
static DebugLoc getDebugValueLoc(DbgVariableIntrinsic *DII, Instruction *Src) {
// Original dbg.declare must have a location.
- DebugLoc DeclareLoc = DII->getDebugLoc();
+ const DebugLoc &DeclareLoc = DII->getDebugLoc();
MDNode *Scope = DeclareLoc.getScope();
DILocation *InlinedAt = DeclareLoc.getInlinedAt();
// Produce an unknown location with the correct scope / inlinedAt fields.
@@ -1575,93 +1621,56 @@ void llvm::insertDebugValuesForPHIs(BasicBlock *BB,
ValueToValueMapTy DbgValueMap;
for (auto &I : *BB) {
if (auto DbgII = dyn_cast<DbgVariableIntrinsic>(&I)) {
- if (auto *Loc = dyn_cast_or_null<PHINode>(DbgII->getVariableLocation()))
- DbgValueMap.insert({Loc, DbgII});
+ for (Value *V : DbgII->location_ops())
+ if (auto *Loc = dyn_cast_or_null<PHINode>(V))
+ DbgValueMap.insert({Loc, DbgII});
}
}
if (DbgValueMap.size() == 0)
return;
+ // Map a pair of the destination BB and old dbg.value to the new dbg.value,
+ // so that if a dbg.value is being rewritten to use more than one of the
+ // inserted PHIs in the same destination BB, we can update the same dbg.value
+ // with all the new PHIs instead of creating one copy for each.
+ MapVector<std::pair<BasicBlock *, DbgVariableIntrinsic *>,
+ DbgVariableIntrinsic *>
+ NewDbgValueMap;
// Then iterate through the new PHIs and look to see if they use one of the
- // previously mapped PHIs. If so, insert a new dbg.value intrinsic that will
- // propagate the info through the new PHI.
- LLVMContext &C = BB->getContext();
+ // previously mapped PHIs. If so, create a new dbg.value intrinsic that will
+ // propagate the info through the new PHI. If we use more than one new PHI in
+ // a single destination BB with the same old dbg.value, merge the updates so
+ // that we get a single new dbg.value with all the new PHIs.
for (auto PHI : InsertedPHIs) {
BasicBlock *Parent = PHI->getParent();
// Avoid inserting an intrinsic into an EH block.
if (Parent->getFirstNonPHI()->isEHPad())
continue;
- auto PhiMAV = MetadataAsValue::get(C, ValueAsMetadata::get(PHI));
for (auto VI : PHI->operand_values()) {
auto V = DbgValueMap.find(VI);
if (V != DbgValueMap.end()) {
auto *DbgII = cast<DbgVariableIntrinsic>(V->second);
- Instruction *NewDbgII = DbgII->clone();
- NewDbgII->setOperand(0, PhiMAV);
- auto InsertionPt = Parent->getFirstInsertionPt();
- assert(InsertionPt != Parent->end() && "Ill-formed basic block");
- NewDbgII->insertBefore(&*InsertionPt);
+ auto NewDI = NewDbgValueMap.find({Parent, DbgII});
+ if (NewDI == NewDbgValueMap.end()) {
+ auto *NewDbgII = cast<DbgVariableIntrinsic>(DbgII->clone());
+ NewDI = NewDbgValueMap.insert({{Parent, DbgII}, NewDbgII}).first;
+ }
+ DbgVariableIntrinsic *NewDbgII = NewDI->second;
+ // If PHI contains VI as an operand more than once, we may
+ // replaced it in NewDbgII; confirm that it is present.
+ if (is_contained(NewDbgII->location_ops(), VI))
+ NewDbgII->replaceVariableLocationOp(VI, PHI);
}
}
}
-}
-
-/// Finds all intrinsics declaring local variables as living in the memory that
-/// 'V' points to. This may include a mix of dbg.declare and
-/// dbg.addr intrinsics.
-TinyPtrVector<DbgVariableIntrinsic *> llvm::FindDbgAddrUses(Value *V) {
- // This function is hot. Check whether the value has any metadata to avoid a
- // DenseMap lookup.
- if (!V->isUsedByMetadata())
- return {};
- auto *L = LocalAsMetadata::getIfExists(V);
- if (!L)
- return {};
- auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L);
- if (!MDV)
- return {};
-
- TinyPtrVector<DbgVariableIntrinsic *> Declares;
- for (User *U : MDV->users()) {
- if (auto *DII = dyn_cast<DbgVariableIntrinsic>(U))
- if (DII->isAddressOfVariable())
- Declares.push_back(DII);
+ // Insert thew new dbg.values into their destination blocks.
+ for (auto DI : NewDbgValueMap) {
+ BasicBlock *Parent = DI.first.first;
+ auto *NewDbgII = DI.second;
+ auto InsertionPt = Parent->getFirstInsertionPt();
+ assert(InsertionPt != Parent->end() && "Ill-formed basic block");
+ NewDbgII->insertBefore(&*InsertionPt);
}
-
- return Declares;
-}
-
-TinyPtrVector<DbgDeclareInst *> llvm::FindDbgDeclareUses(Value *V) {
- TinyPtrVector<DbgDeclareInst *> DDIs;
- for (DbgVariableIntrinsic *DVI : FindDbgAddrUses(V))
- if (auto *DDI = dyn_cast<DbgDeclareInst>(DVI))
- DDIs.push_back(DDI);
- return DDIs;
-}
-
-void llvm::findDbgValues(SmallVectorImpl<DbgValueInst *> &DbgValues, Value *V) {
- // This function is hot. Check whether the value has any metadata to avoid a
- // DenseMap lookup.
- if (!V->isUsedByMetadata())
- return;
- if (auto *L = LocalAsMetadata::getIfExists(V))
- if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
- for (User *U : MDV->users())
- if (DbgValueInst *DVI = dyn_cast<DbgValueInst>(U))
- DbgValues.push_back(DVI);
-}
-
-void llvm::findDbgUsers(SmallVectorImpl<DbgVariableIntrinsic *> &DbgUsers,
- Value *V) {
- // This function is hot. Check whether the value has any metadata to avoid a
- // DenseMap lookup.
- if (!V->isUsedByMetadata())
- return;
- if (auto *L = LocalAsMetadata::getIfExists(V))
- if (auto *MDV = MetadataAsValue::getIfExists(V->getContext(), L))
- for (User *U : MDV->users())
- if (DbgVariableIntrinsic *DII = dyn_cast<DbgVariableIntrinsic>(U))
- DbgUsers.push_back(DII);
}
bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
@@ -1669,7 +1678,7 @@ bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
int Offset) {
auto DbgAddrs = FindDbgAddrUses(Address);
for (DbgVariableIntrinsic *DII : DbgAddrs) {
- DebugLoc Loc = DII->getDebugLoc();
+ const DebugLoc &Loc = DII->getDebugLoc();
auto *DIVar = DII->getVariable();
auto *DIExpr = DII->getExpression();
assert(DIVar && "Missing variable");
@@ -1684,7 +1693,7 @@ bool llvm::replaceDbgDeclare(Value *Address, Value *NewAddress,
static void replaceOneDbgValueForAlloca(DbgValueInst *DVI, Value *NewAddress,
DIBuilder &Builder, int Offset) {
- DebugLoc Loc = DVI->getDebugLoc();
+ const DebugLoc &Loc = DVI->getDebugLoc();
auto *DIVar = DVI->getVariable();
auto *DIExpr = DVI->getExpression();
assert(DIVar && "Missing variable");
@@ -1709,16 +1718,9 @@ void llvm::replaceDbgValueForAlloca(AllocaInst *AI, Value *NewAllocaAddress,
DIBuilder &Builder, int Offset) {
if (auto *L = LocalAsMetadata::getIfExists(AI))
if (auto *MDV = MetadataAsValue::getIfExists(AI->getContext(), L))
- for (auto UI = MDV->use_begin(), UE = MDV->use_end(); UI != UE;) {
- Use &U = *UI++;
+ for (Use &U : llvm::make_early_inc_range(MDV->uses()))
if (auto *DVI = dyn_cast<DbgValueInst>(U.getUser()))
replaceOneDbgValueForAlloca(DVI, NewAllocaAddress, Builder, Offset);
- }
-}
-
-/// Wrap \p V in a ValueAsMetadata instance.
-static MetadataAsValue *wrapValueInMetadata(LLVMContext &C, Value *V) {
- return MetadataAsValue::get(C, ValueAsMetadata::get(V));
}
/// Where possible to salvage debug information for \p I do so
@@ -1731,26 +1733,53 @@ void llvm::salvageDebugInfo(Instruction &I) {
void llvm::salvageDebugInfoForDbgValues(
Instruction &I, ArrayRef<DbgVariableIntrinsic *> DbgUsers) {
- auto &Ctx = I.getContext();
+ // This is an arbitrary chosen limit on the maximum number of values we can
+ // salvage up to in a DIArgList, used for performance reasons.
+ const unsigned MaxDebugArgs = 16;
bool Salvaged = false;
- auto wrapMD = [&](Value *V) { return wrapValueInMetadata(Ctx, V); };
for (auto *DII : DbgUsers) {
// Do not add DW_OP_stack_value for DbgDeclare and DbgAddr, because they
// are implicitly pointing out the value as a DWARF memory location
// description.
bool StackValue = isa<DbgValueInst>(DII);
-
- DIExpression *DIExpr =
- salvageDebugInfoImpl(I, DII->getExpression(), StackValue);
-
+ auto DIILocation = DII->location_ops();
+ assert(
+ is_contained(DIILocation, &I) &&
+ "DbgVariableIntrinsic must use salvaged instruction as its location");
+ SmallVector<Value *, 4> AdditionalValues;
+ // `I` may appear more than once in DII's location ops, and each use of `I`
+ // must be updated in the DIExpression and potentially have additional
+ // values added; thus we call salvageDebugInfoImpl for each `I` instance in
+ // DIILocation.
+ DIExpression *SalvagedExpr = DII->getExpression();
+ auto LocItr = find(DIILocation, &I);
+ while (SalvagedExpr && LocItr != DIILocation.end()) {
+ unsigned LocNo = std::distance(DIILocation.begin(), LocItr);
+ SalvagedExpr = salvageDebugInfoImpl(I, SalvagedExpr, StackValue, LocNo,
+ AdditionalValues);
+ LocItr = std::find(++LocItr, DIILocation.end(), &I);
+ }
// salvageDebugInfoImpl should fail on examining the first element of
// DbgUsers, or none of them.
- if (!DIExpr)
+ if (!SalvagedExpr)
break;
- DII->setOperand(0, wrapMD(I.getOperand(0)));
- DII->setOperand(2, MetadataAsValue::get(Ctx, DIExpr));
+ DII->replaceVariableLocationOp(&I, I.getOperand(0));
+ if (AdditionalValues.empty()) {
+ DII->setExpression(SalvagedExpr);
+ } else if (isa<DbgValueInst>(DII) &&
+ DII->getNumVariableLocationOps() + AdditionalValues.size() <=
+ MaxDebugArgs) {
+ DII->addVariableLocationOps(AdditionalValues, SalvagedExpr);
+ } else {
+ // Do not salvage using DIArgList for dbg.addr/dbg.declare, as it is
+ // currently only valid for stack value expressions.
+ // Also do not salvage if the resulting DIArgList would contain an
+ // unreasonably large number of values.
+ Value *Undef = UndefValue::get(I.getOperand(0)->getType());
+ DII->replaceVariableLocationOp(I.getOperand(0), Undef);
+ }
LLVM_DEBUG(dbgs() << "SALVAGE: " << *DII << '\n');
Salvaged = true;
}
@@ -1760,14 +1789,111 @@ void llvm::salvageDebugInfoForDbgValues(
for (auto *DII : DbgUsers) {
Value *Undef = UndefValue::get(I.getType());
- DII->setOperand(0, MetadataAsValue::get(DII->getContext(),
- ValueAsMetadata::get(Undef)));
+ DII->replaceVariableLocationOp(&I, Undef);
+ }
+}
+
+bool getSalvageOpsForGEP(GetElementPtrInst *GEP, const DataLayout &DL,
+ uint64_t CurrentLocOps,
+ SmallVectorImpl<uint64_t> &Opcodes,
+ SmallVectorImpl<Value *> &AdditionalValues) {
+ unsigned BitWidth = DL.getIndexSizeInBits(GEP->getPointerAddressSpace());
+ // Rewrite a GEP into a DIExpression.
+ MapVector<Value *, APInt> VariableOffsets;
+ APInt ConstantOffset(BitWidth, 0);
+ if (!GEP->collectOffset(DL, BitWidth, VariableOffsets, ConstantOffset))
+ return false;
+ if (!VariableOffsets.empty() && !CurrentLocOps) {
+ Opcodes.insert(Opcodes.begin(), {dwarf::DW_OP_LLVM_arg, 0});
+ CurrentLocOps = 1;
+ }
+ for (auto Offset : VariableOffsets) {
+ AdditionalValues.push_back(Offset.first);
+ assert(Offset.second.isStrictlyPositive() &&
+ "Expected strictly positive multiplier for offset.");
+ Opcodes.append({dwarf::DW_OP_LLVM_arg, CurrentLocOps++, dwarf::DW_OP_constu,
+ Offset.second.getZExtValue(), dwarf::DW_OP_mul,
+ dwarf::DW_OP_plus});
+ }
+ DIExpression::appendOffset(Opcodes, ConstantOffset.getSExtValue());
+ return true;
+}
+
+uint64_t getDwarfOpForBinOp(Instruction::BinaryOps Opcode) {
+ switch (Opcode) {
+ case Instruction::Add:
+ return dwarf::DW_OP_plus;
+ case Instruction::Sub:
+ return dwarf::DW_OP_minus;
+ case Instruction::Mul:
+ return dwarf::DW_OP_mul;
+ case Instruction::SDiv:
+ return dwarf::DW_OP_div;
+ case Instruction::SRem:
+ return dwarf::DW_OP_mod;
+ case Instruction::Or:
+ return dwarf::DW_OP_or;
+ case Instruction::And:
+ return dwarf::DW_OP_and;
+ case Instruction::Xor:
+ return dwarf::DW_OP_xor;
+ case Instruction::Shl:
+ return dwarf::DW_OP_shl;
+ case Instruction::LShr:
+ return dwarf::DW_OP_shr;
+ case Instruction::AShr:
+ return dwarf::DW_OP_shra;
+ default:
+ // TODO: Salvage from each kind of binop we know about.
+ return 0;
}
}
-DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,
- DIExpression *SrcDIExpr,
- bool WithStackValue) {
+bool getSalvageOpsForBinOp(BinaryOperator *BI, uint64_t CurrentLocOps,
+ SmallVectorImpl<uint64_t> &Opcodes,
+ SmallVectorImpl<Value *> &AdditionalValues) {
+ // Handle binary operations with constant integer operands as a special case.
+ auto *ConstInt = dyn_cast<ConstantInt>(BI->getOperand(1));
+ // Values wider than 64 bits cannot be represented within a DIExpression.
+ if (ConstInt && ConstInt->getBitWidth() > 64)
+ return false;
+
+ Instruction::BinaryOps BinOpcode = BI->getOpcode();
+ // Push any Constant Int operand onto the expression stack.
+ if (ConstInt) {
+ uint64_t Val = ConstInt->getSExtValue();
+ // Add or Sub Instructions with a constant operand can potentially be
+ // simplified.
+ if (BinOpcode == Instruction::Add || BinOpcode == Instruction::Sub) {
+ uint64_t Offset = BinOpcode == Instruction::Add ? Val : -int64_t(Val);
+ DIExpression::appendOffset(Opcodes, Offset);
+ return true;
+ }
+ Opcodes.append({dwarf::DW_OP_constu, Val});
+ } else {
+ if (!CurrentLocOps) {
+ Opcodes.append({dwarf::DW_OP_LLVM_arg, 0});
+ CurrentLocOps = 1;
+ }
+ Opcodes.append({dwarf::DW_OP_LLVM_arg, CurrentLocOps});
+ AdditionalValues.push_back(BI->getOperand(1));
+ }
+
+ // Add salvaged binary operator to expression stack, if it has a valid
+ // representation in a DIExpression.
+ uint64_t DwarfBinOp = getDwarfOpForBinOp(BinOpcode);
+ if (!DwarfBinOp)
+ return false;
+ Opcodes.push_back(DwarfBinOp);
+
+ return true;
+}
+
+DIExpression *
+llvm::salvageDebugInfoImpl(Instruction &I, DIExpression *SrcDIExpr,
+ bool WithStackValue, unsigned LocNo,
+ SmallVectorImpl<Value *> &AdditionalValues) {
+ uint64_t CurrentLocOps = SrcDIExpr->getNumLocationOperands();
auto &M = *I.getModule();
auto &DL = M.getDataLayout();
@@ -1775,20 +1901,13 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,
auto doSalvage = [&](SmallVectorImpl<uint64_t> &Ops) -> DIExpression * {
DIExpression *DIExpr = SrcDIExpr;
if (!Ops.empty()) {
- DIExpr = DIExpression::prependOpcodes(DIExpr, Ops, WithStackValue);
+ DIExpr = DIExpression::appendOpsToArg(DIExpr, Ops, LocNo, WithStackValue);
}
return DIExpr;
};
- // Apply the given offset to the source DIExpression.
- auto applyOffset = [&](uint64_t Offset) -> DIExpression * {
- SmallVector<uint64_t, 8> Ops;
- DIExpression::appendOffset(Ops, Offset);
- return doSalvage(Ops);
- };
-
// initializer-list helper for applying operators to the source DIExpression.
- auto applyOps = [&](ArrayRef<uint64_t> Opcodes) -> DIExpression * {
+ auto applyOps = [&](ArrayRef<uint64_t> Opcodes) {
SmallVector<uint64_t, 8> Ops(Opcodes.begin(), Opcodes.end());
return doSalvage(Ops);
};
@@ -1812,54 +1931,17 @@ DIExpression *llvm::salvageDebugInfoImpl(Instruction &I,
isa<SExtInst>(&I)));
}
+ SmallVector<uint64_t, 8> Ops;
if (auto *GEP = dyn_cast<GetElementPtrInst>(&I)) {
- unsigned BitWidth =
- M.getDataLayout().getIndexSizeInBits(GEP->getPointerAddressSpace());
- // Rewrite a constant GEP into a DIExpression.
- APInt Offset(BitWidth, 0);
- if (GEP->accumulateConstantOffset(M.getDataLayout(), Offset)) {
- return applyOffset(Offset.getSExtValue());
- } else {
- return nullptr;
- }
+ if (getSalvageOpsForGEP(GEP, DL, CurrentLocOps, Ops, AdditionalValues))
+ return doSalvage(Ops);
} else if (auto *BI = dyn_cast<BinaryOperator>(&I)) {
- // Rewrite binary operations with constant integer operands.
- auto *ConstInt = dyn_cast<ConstantInt>(I.getOperand(1));
- if (!ConstInt || ConstInt->getBitWidth() > 64)
- return nullptr;
-
- uint64_t Val = ConstInt->getSExtValue();
- switch (BI->getOpcode()) {
- case Instruction::Add:
- return applyOffset(Val);
- case Instruction::Sub:
- return applyOffset(-int64_t(Val));
- case Instruction::Mul:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_mul});
- case Instruction::SDiv:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_div});
- case Instruction::SRem:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_mod});
- case Instruction::Or:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_or});
- case Instruction::And:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_and});
- case Instruction::Xor:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_xor});
- case Instruction::Shl:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shl});
- case Instruction::LShr:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shr});
- case Instruction::AShr:
- return applyOps({dwarf::DW_OP_constu, Val, dwarf::DW_OP_shra});
- default:
- // TODO: Salvage constants from each kind of binop we know about.
- return nullptr;
- }
- // *Not* to do: we should not attempt to salvage load instructions,
- // because the validity and lifetime of a dbg.value containing
- // DW_OP_deref becomes difficult to analyze. See PR40628 for examples.
+ if (getSalvageOpsForBinOp(BI, CurrentLocOps, Ops, AdditionalValues))
+ return doSalvage(Ops);
}
+ // *Not* to do: we should not attempt to salvage load instructions,
+ // because the validity and lifetime of a dbg.value containing
+ // DW_OP_deref becomes difficult to analyze. See PR40628 for examples.
return nullptr;
}
@@ -1905,13 +1987,12 @@ static bool rewriteDebugUsers(
if (UndefOrSalvage.count(DII))
continue;
- LLVMContext &Ctx = DII->getContext();
DbgValReplacement DVR = RewriteExpr(*DII);
if (!DVR)
continue;
- DII->setOperand(0, wrapValueInMetadata(Ctx, &To));
- DII->setOperand(2, MetadataAsValue::get(Ctx, *DVR));
+ DII->replaceVariableLocationOp(&From, &To);
+ DII->setExpression(*DVR);
LLVM_DEBUG(dbgs() << "REWRITE: " << *DII << '\n');
Changed = true;
}
@@ -2029,15 +2110,15 @@ llvm::removeAllNonTerminatorAndEHPadInstructions(BasicBlock *BB) {
return {NumDeadInst, NumDeadDbgInst};
}
-unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap,
- bool PreserveLCSSA, DomTreeUpdater *DTU,
+unsigned llvm::changeToUnreachable(Instruction *I, bool PreserveLCSSA,
+ DomTreeUpdater *DTU,
MemorySSAUpdater *MSSAU) {
BasicBlock *BB = I->getParent();
if (MSSAU)
MSSAU->changeToUnreachable(I);
- SmallSetVector<BasicBlock *, 8> UniqueSuccessors;
+ SmallSet<BasicBlock *, 8> UniqueSuccessors;
// Loop over all of the successors, removing BB's entry from any PHI
// nodes.
@@ -2046,14 +2127,6 @@ unsigned llvm::changeToUnreachable(Instruction *I, bool UseLLVMTrap,
if (DTU)
UniqueSuccessors.insert(Successor);
}
- // Insert a call to llvm.trap right before this. This turns the undefined
- // behavior into a hard fail instead of falling through into random code.
- if (UseLLVMTrap) {
- Function *TrapFn =
- Intrinsic::getDeclaration(BB->getParent()->getParent(), Intrinsic::trap);
- CallInst *CallTrap = CallInst::Create(TrapFn, "", I);
- CallTrap->setDebugLoc(I->getDebugLoc());
- }
auto *UI = new UnreachableInst(I->getContext(), I);
UI->setDebugLoc(I->getDebugLoc());
@@ -2122,15 +2195,16 @@ void llvm::changeToCall(InvokeInst *II, DomTreeUpdater *DTU) {
}
BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
- BasicBlock *UnwindEdge) {
+ BasicBlock *UnwindEdge,
+ DomTreeUpdater *DTU) {
BasicBlock *BB = CI->getParent();
// Convert this function call into an invoke instruction. First, split the
// basic block.
- BasicBlock *Split =
- BB->splitBasicBlock(CI->getIterator(), CI->getName() + ".noexc");
+ BasicBlock *Split = SplitBlock(BB, CI, DTU, /*LI=*/nullptr, /*MSSAU*/ nullptr,
+ CI->getName() + ".noexc");
- // Delete the unconditional branch inserted by splitBasicBlock
+ // Delete the unconditional branch inserted by SplitBlock
BB->getInstList().pop_back();
// Create the new invoke instruction.
@@ -2150,6 +2224,9 @@ BasicBlock *llvm::changeToInvokeAndSplitBasicBlock(CallInst *CI,
II->setCallingConv(CI->getCallingConv());
II->setAttributes(CI->getAttributes());
+ if (DTU)
+ DTU->applyUpdates({{DominatorTree::Insert, BB, UnwindEdge}});
+
// Make sure that anything using the call now uses the invoke! This also
// updates the CallGraph if present, because it uses a WeakTrackingVH.
CI->replaceAllUsesWith(II);
@@ -2186,7 +2263,7 @@ static bool markAliveBlocks(Function &F,
if (IntrinsicID == Intrinsic::assume) {
if (match(CI->getArgOperand(0), m_CombineOr(m_Zero(), m_Undef()))) {
// Don't insert a call to llvm.trap right before the unreachable.
- changeToUnreachable(CI, false, false, DTU);
+ changeToUnreachable(CI, false, DTU);
Changed = true;
break;
}
@@ -2202,8 +2279,7 @@ static bool markAliveBlocks(Function &F,
// still be useful for widening.
if (match(CI->getArgOperand(0), m_Zero()))
if (!isa<UnreachableInst>(CI->getNextNode())) {
- changeToUnreachable(CI->getNextNode(), /*UseLLVMTrap=*/false,
- false, DTU);
+ changeToUnreachable(CI->getNextNode(), false, DTU);
Changed = true;
break;
}
@@ -2211,7 +2287,7 @@ static bool markAliveBlocks(Function &F,
} else if ((isa<ConstantPointerNull>(Callee) &&
!NullPointerIsDefined(CI->getFunction())) ||
isa<UndefValue>(Callee)) {
- changeToUnreachable(CI, /*UseLLVMTrap=*/false, false, DTU);
+ changeToUnreachable(CI, false, DTU);
Changed = true;
break;
}
@@ -2221,7 +2297,7 @@ static bool markAliveBlocks(Function &F,
// though.
if (!isa<UnreachableInst>(CI->getNextNode())) {
// Don't insert a call to llvm.trap right before the unreachable.
- changeToUnreachable(CI->getNextNode(), false, false, DTU);
+ changeToUnreachable(CI->getNextNode(), false, DTU);
Changed = true;
}
break;
@@ -2240,7 +2316,7 @@ static bool markAliveBlocks(Function &F,
(isa<ConstantPointerNull>(Ptr) &&
!NullPointerIsDefined(SI->getFunction(),
SI->getPointerAddressSpace()))) {
- changeToUnreachable(SI, true, false, DTU);
+ changeToUnreachable(SI, false, DTU);
Changed = true;
break;
}
@@ -2254,7 +2330,7 @@ static bool markAliveBlocks(Function &F,
if ((isa<ConstantPointerNull>(Callee) &&
!NullPointerIsDefined(BB->getParent())) ||
isa<UndefValue>(Callee)) {
- changeToUnreachable(II, true, false, DTU);
+ changeToUnreachable(II, false, DTU);
Changed = true;
} else if (II->doesNotThrow() && canSimplifyInvokeNoUnwind(&F)) {
if (II->use_empty() && II->onlyReadsMemory()) {
@@ -2294,7 +2370,7 @@ static bool markAliveBlocks(Function &F,
}
};
- SmallMapVector<BasicBlock *, int, 8> NumPerSuccessorCases;
+ SmallDenseMap<BasicBlock *, int, 8> NumPerSuccessorCases;
// Set of unique CatchPads.
SmallDenseMap<CatchPadInst *, detail::DenseSetEmpty, 4,
CatchPadDenseMapInfo, detail::DenseSetPair<CatchPadInst *>>
@@ -2304,22 +2380,25 @@ static bool markAliveBlocks(Function &F,
E = CatchSwitch->handler_end();
I != E; ++I) {
BasicBlock *HandlerBB = *I;
- ++NumPerSuccessorCases[HandlerBB];
+ if (DTU)
+ ++NumPerSuccessorCases[HandlerBB];
auto *CatchPad = cast<CatchPadInst>(HandlerBB->getFirstNonPHI());
if (!HandlerSet.insert({CatchPad, Empty}).second) {
- --NumPerSuccessorCases[HandlerBB];
+ if (DTU)
+ --NumPerSuccessorCases[HandlerBB];
CatchSwitch->removeHandler(I);
--I;
--E;
Changed = true;
}
}
- std::vector<DominatorTree::UpdateType> Updates;
- for (const std::pair<BasicBlock *, int> &I : NumPerSuccessorCases)
- if (I.second == 0)
- Updates.push_back({DominatorTree::Delete, BB, I.first});
- if (DTU)
+ if (DTU) {
+ std::vector<DominatorTree::UpdateType> Updates;
+ for (const std::pair<BasicBlock *, int> &I : NumPerSuccessorCases)
+ if (I.second == 0)
+ Updates.push_back({DominatorTree::Delete, BB, I.first});
DTU->applyUpdates(Updates);
+ }
}
Changed |= ConstantFoldTerminator(BB, true, nullptr, DTU);
@@ -2401,44 +2480,7 @@ bool llvm::removeUnreachableBlocks(Function &F, DomTreeUpdater *DTU,
if (MSSAU)
MSSAU->removeBlocks(BlocksToRemove);
- // Loop over all of the basic blocks that are up for removal, dropping all of
- // their internal references. Update DTU if available.
- std::vector<DominatorTree::UpdateType> Updates;
- for (auto *BB : BlocksToRemove) {
- SmallSetVector<BasicBlock *, 8> UniqueSuccessors;
- for (BasicBlock *Successor : successors(BB)) {
- // Only remove references to BB in reachable successors of BB.
- if (Reachable.count(Successor))
- Successor->removePredecessor(BB);
- if (DTU)
- UniqueSuccessors.insert(Successor);
- }
- BB->dropAllReferences();
- if (DTU) {
- Instruction *TI = BB->getTerminator();
- assert(TI && "Basic block should have a terminator");
- // Terminators like invoke can have users. We have to replace their users,
- // before removing them.
- if (!TI->use_empty())
- TI->replaceAllUsesWith(UndefValue::get(TI->getType()));
- TI->eraseFromParent();
- new UnreachableInst(BB->getContext(), BB);
- assert(succ_empty(BB) && "The successor list of BB isn't empty before "
- "applying corresponding DTU updates.");
- Updates.reserve(Updates.size() + UniqueSuccessors.size());
- for (auto *UniqueSuccessor : UniqueSuccessors)
- Updates.push_back({DominatorTree::Delete, BB, UniqueSuccessor});
- }
- }
-
- if (DTU) {
- DTU->applyUpdates(Updates);
- for (auto *BB : BlocksToRemove)
- DTU->deleteBB(BB);
- } else {
- for (auto *BB : BlocksToRemove)
- BB->eraseFromParent();
- }
+ DeleteDeadBlocks(BlocksToRemove.takeVector(), DTU);
return Changed;
}
@@ -2669,11 +2711,10 @@ unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
unsigned llvm::replaceDominatedUsesWith(Value *From, Value *To,
DominatorTree &DT,
const BasicBlock *BB) {
- auto ProperlyDominates = [&DT](const BasicBlock *BB, const Use &U) {
- auto *I = cast<Instruction>(U.getUser())->getParent();
- return DT.properlyDominates(BB, I);
+ auto Dominates = [&DT](const BasicBlock *BB, const Use &U) {
+ return DT.dominates(BB, U);
};
- return ::replaceDominatedUsesWith(From, To, BB, ProperlyDominates);
+ return ::replaceDominatedUsesWith(From, To, BB, Dominates);
}
bool llvm::callsGCLeafFunction(const CallBase *Call,
@@ -2778,13 +2819,14 @@ void llvm::hoistAllInstructionsInto(BasicBlock *DomBlock, Instruction *InsertPt,
// TODO: Extend llvm.dbg.value to take more than one SSA Value (PR39141) to
// encode predicated DIExpressions that yield different results on different
// code paths.
+
for (BasicBlock::iterator II = BB->begin(), IE = BB->end(); II != IE;) {
Instruction *I = &*II;
- I->dropUnknownNonDebugMetadata();
+ I->dropUndefImplyingAttrsAndUnknownMetadata();
if (I->isUsedByMetadata())
dropDebugUsers(*I);
- if (isa<DbgInfoIntrinsic>(I)) {
- // Remove DbgInfo Intrinsics.
+ if (I->isDebugOrPseudoInst()) {
+ // Remove DbgInfo and pseudo probe Intrinsics.
II = I->eraseFromParent();
continue;
}
@@ -2846,7 +2888,8 @@ struct BitPart {
/// does not invalidate internal references (std::map instead of DenseMap).
static const Optional<BitPart> &
collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
- std::map<Value *, Optional<BitPart>> &BPS, int Depth) {
+ std::map<Value *, Optional<BitPart>> &BPS, int Depth,
+ bool &FoundRoot) {
auto I = BPS.find(V);
if (I != BPS.end())
return I->second;
@@ -2854,6 +2897,10 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
auto &Result = BPS[V] = None;
auto BitWidth = V->getType()->getScalarSizeInBits();
+ // Can't do integer/elements > 128 bits.
+ if (BitWidth > 128)
+ return Result;
+
// Prevent stack overflow by limiting the recursion depth
if (Depth == BitPartRecursionMaxDepth) {
LLVM_DEBUG(dbgs() << "collectBitParts max recursion depth reached.\n");
@@ -2866,17 +2913,18 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
// If this is an or instruction, it may be an inner node of the bswap.
if (match(V, m_Or(m_Value(X), m_Value(Y)))) {
- const auto &A =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
- const auto &B =
- collectBitParts(Y, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
- if (!A || !B)
+ // Check we have both sources and they are from the same provider.
+ const auto &A = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
+ if (!A || !A->Provider)
return Result;
- // Try and merge the two together.
- if (!A->Provider || A->Provider != B->Provider)
+ const auto &B = collectBitParts(Y, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
+ if (!B || A->Provider != B->Provider)
return Result;
+ // Try and merge the two together.
Result = BitPart(A->Provider, BitWidth);
for (unsigned BitIdx = 0; BitIdx < BitWidth; ++BitIdx) {
if (A->Provenance[BitIdx] != BitPart::Unset &&
@@ -2901,8 +2949,12 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
if (BitShift.uge(BitWidth))
return Result;
- const auto &Res =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
+ // For bswap-only, limit shift amounts to whole bytes, for an early exit.
+ if (!MatchBitReversals && (BitShift.getZExtValue() % 8) != 0)
+ return Result;
+
+ const auto &Res = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
if (!Res)
return Result;
Result = Res;
@@ -2931,8 +2983,8 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
if (!MatchBitReversals && (NumMaskedBits % 8) != 0)
return Result;
- const auto &Res =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
+ const auto &Res = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
if (!Res)
return Result;
Result = Res;
@@ -2946,8 +2998,8 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
// If this is a zext instruction zero extend the result.
if (match(V, m_ZExt(m_Value(X)))) {
- const auto &Res =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
+ const auto &Res = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
if (!Res)
return Result;
@@ -2960,11 +3012,24 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
return Result;
}
+ // If this is a truncate instruction, extract the lower bits.
+ if (match(V, m_Trunc(m_Value(X)))) {
+ const auto &Res = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
+ if (!Res)
+ return Result;
+
+ Result = BitPart(Res->Provider, BitWidth);
+ for (unsigned BitIdx = 0; BitIdx < BitWidth; ++BitIdx)
+ Result->Provenance[BitIdx] = Res->Provenance[BitIdx];
+ return Result;
+ }
+
// BITREVERSE - most likely due to us previous matching a partial
// bitreverse.
if (match(V, m_BitReverse(m_Value(X)))) {
- const auto &Res =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
+ const auto &Res = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
if (!Res)
return Result;
@@ -2976,8 +3041,8 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
// BSWAP - most likely due to us previous matching a partial bswap.
if (match(V, m_BSwap(m_Value(X)))) {
- const auto &Res =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
+ const auto &Res = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
if (!Res)
return Result;
@@ -3003,13 +3068,19 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
if (cast<IntrinsicInst>(I)->getIntrinsicID() == Intrinsic::fshr)
ModAmt = BitWidth - ModAmt;
- const auto &LHS =
- collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
- const auto &RHS =
- collectBitParts(Y, MatchBSwaps, MatchBitReversals, BPS, Depth + 1);
+ // For bswap-only, limit shift amounts to whole bytes, for an early exit.
+ if (!MatchBitReversals && (ModAmt % 8) != 0)
+ return Result;
// Check we have both sources and they are from the same provider.
- if (!LHS || !RHS || !LHS->Provider || LHS->Provider != RHS->Provider)
+ const auto &LHS = collectBitParts(X, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
+ if (!LHS || !LHS->Provider)
+ return Result;
+
+ const auto &RHS = collectBitParts(Y, MatchBSwaps, MatchBitReversals, BPS,
+ Depth + 1, FoundRoot);
+ if (!RHS || LHS->Provider != RHS->Provider)
return Result;
unsigned StartBitRHS = BitWidth - ModAmt;
@@ -3022,8 +3093,14 @@ collectBitParts(Value *V, bool MatchBSwaps, bool MatchBitReversals,
}
}
- // Okay, we got to something that isn't a shift, 'or' or 'and'. This must be
- // the input value to the bswap/bitreverse.
+ // If we've already found a root input value then we're never going to merge
+ // these back together.
+ if (FoundRoot)
+ return Result;
+
+ // Okay, we got to something that isn't a shift, 'or', 'and', etc. This must
+ // be the root input value to the bswap/bitreverse.
+ FoundRoot = true;
Result = BitPart(V, BitWidth);
for (unsigned BitIdx = 0; BitIdx < BitWidth; ++BitIdx)
Result->Provenance[BitIdx] = BitIdx;
@@ -3049,7 +3126,9 @@ static bool bitTransformIsCorrectForBitReverse(unsigned From, unsigned To,
bool llvm::recognizeBSwapOrBitReverseIdiom(
Instruction *I, bool MatchBSwaps, bool MatchBitReversals,
SmallVectorImpl<Instruction *> &InsertedInsts) {
- if (Operator::getOpcode(I) != Instruction::Or)
+ if (!match(I, m_Or(m_Value(), m_Value())) &&
+ !match(I, m_FShl(m_Value(), m_Value(), m_Value())) &&
+ !match(I, m_FShr(m_Value(), m_Value(), m_Value())))
return false;
if (!MatchBSwaps && !MatchBitReversals)
return false;
@@ -3063,8 +3142,10 @@ bool llvm::recognizeBSwapOrBitReverseIdiom(
DemandedTy = Trunc->getType();
// Try to find all the pieces corresponding to the bswap.
+ bool FoundRoot = false;
std::map<Value *, Optional<BitPart>> BPS;
- auto Res = collectBitParts(I, MatchBSwaps, MatchBitReversals, BPS, 0);
+ const auto &Res =
+ collectBitParts(I, MatchBSwaps, MatchBitReversals, BPS, 0, FoundRoot);
if (!Res)
return false;
ArrayRef<int8_t> BitProvenance = Res->Provenance;
@@ -3263,3 +3344,33 @@ Value *llvm::invertCondition(Value *Condition) {
Inverted->insertBefore(&*Parent->getFirstInsertionPt());
return Inverted;
}
+
+bool llvm::inferAttributesFromOthers(Function &F) {
+ // Note: We explicitly check for attributes rather than using cover functions
+ // because some of the cover functions include the logic being implemented.
+
+ bool Changed = false;
+ // readnone + not convergent implies nosync
+ if (!F.hasFnAttribute(Attribute::NoSync) &&
+ F.doesNotAccessMemory() && !F.isConvergent()) {
+ F.setNoSync();
+ Changed = true;
+ }
+
+ // readonly implies nofree
+ if (!F.hasFnAttribute(Attribute::NoFree) && F.onlyReadsMemory()) {
+ F.setDoesNotFreeMemory();
+ Changed = true;
+ }
+
+ // willreturn implies mustprogress
+ if (!F.hasFnAttribute(Attribute::MustProgress) && F.willReturn()) {
+ F.setMustProgress();
+ Changed = true;
+ }
+
+ // TODO: There are a bunch of cases of restrictive memory effects we
+ // can infer by inspecting arguments of argmemonly-ish functions.
+
+ return Changed;
+}