diff options
Diffstat (limited to 'llvm/lib/Transforms')
| -rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroFrame.cpp | 190 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroInternal.h | 16 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Coroutines/CoroSplit.cpp | 35 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp | 9 | ||||
| -rw-r--r-- | llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp | 45 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/ConstantHoisting.cpp | 3 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/ConstraintElimination.cpp | 63 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/LICM.cpp | 19 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Utils/LoopRotationUtils.cpp | 5 | ||||
| -rw-r--r-- | llvm/lib/Transforms/Utils/MemoryOpRemark.cpp | 10 |
11 files changed, 276 insertions, 124 deletions
diff --git a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp index 6b85de15947c..f37b4dc938d3 100644 --- a/llvm/lib/Transforms/Coroutines/CoroFrame.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroFrame.cpp @@ -964,12 +964,17 @@ static void cacheDIVar(FrameDataInfo &FrameData, continue; SmallVector<DbgDeclareInst *, 1> DDIs; - findDbgDeclares(DDIs, V); - auto *I = llvm::find_if(DDIs, [](DbgDeclareInst *DDI) { - return DDI->getExpression()->getNumElements() == 0; - }); - if (I != DDIs.end()) - DIVarCache.insert({V, (*I)->getVariable()}); + SmallVector<DPValue *, 1> DPVs; + findDbgDeclares(DDIs, V, &DPVs); + auto CacheIt = [&DIVarCache, V](auto &Container) { + auto *I = llvm::find_if(Container, [](auto *DDI) { + return DDI->getExpression()->getNumElements() == 0; + }); + if (I != Container.end()) + DIVarCache.insert({V, (*I)->getVariable()}); + }; + CacheIt(DDIs); + CacheIt(DPVs); } } @@ -1121,15 +1126,25 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, "Coroutine with switch ABI should own Promise alloca"); SmallVector<DbgDeclareInst *, 1> DIs; - findDbgDeclares(DIs, PromiseAlloca); - if (DIs.empty()) + SmallVector<DPValue *, 1> DPVs; + findDbgDeclares(DIs, PromiseAlloca, &DPVs); + + DILocalVariable *PromiseDIVariable = nullptr; + DILocation *DILoc = nullptr; + if (!DIs.empty()) { + DbgDeclareInst *PromiseDDI = DIs.front(); + PromiseDIVariable = PromiseDDI->getVariable(); + DILoc = PromiseDDI->getDebugLoc().get(); + } else if (!DPVs.empty()) { + DPValue *PromiseDPV = DPVs.front(); + PromiseDIVariable = PromiseDPV->getVariable(); + DILoc = PromiseDPV->getDebugLoc().get(); + } else { return; + } - DbgDeclareInst *PromiseDDI = DIs.front(); - DILocalVariable *PromiseDIVariable = PromiseDDI->getVariable(); DILocalScope *PromiseDIScope = PromiseDIVariable->getScope(); DIFile *DFile = PromiseDIScope->getFile(); - DILocation *DILoc = PromiseDDI->getDebugLoc().get(); unsigned LineNum = PromiseDIVariable->getLine(); DICompositeType *FrameDITy = DBuilder.createStructType( @@ -1243,7 +1258,7 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, auto *FrameDIVar = DBuilder.createAutoVariable(PromiseDIScope, "__coro_frame", DFile, LineNum, FrameDITy, true, DINode::FlagArtificial); - assert(FrameDIVar->isValidLocationForIntrinsic(PromiseDDI->getDebugLoc())); + assert(FrameDIVar->isValidLocationForIntrinsic(DILoc)); // Subprogram would have ContainedNodes field which records the debug // variables it contained. So we need to add __coro_frame to the @@ -1261,9 +1276,17 @@ static void buildFrameDebugInfo(Function &F, coro::Shape &Shape, 7, (MDTuple::get(F.getContext(), RetainedNodesVec))); } - DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar, - DBuilder.createExpression(), DILoc, - Shape.getInsertPtAfterFramePtr()); + if (UseNewDbgInfoFormat) { + DPValue *NewDPV = new DPValue(ValueAsMetadata::get(Shape.FramePtr), + FrameDIVar, DBuilder.createExpression(), + DILoc, DPValue::LocationType::Declare); + BasicBlock::iterator It = Shape.getInsertPtAfterFramePtr(); + It->getParent()->insertDPValueBefore(NewDPV, It); + } else { + DBuilder.insertDeclare(Shape.FramePtr, FrameDIVar, + DBuilder.createExpression(), DILoc, + &*Shape.getInsertPtAfterFramePtr()); + } } // Build a struct that will keep state for an active coroutine. @@ -1771,7 +1794,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { if (auto *Arg = dyn_cast<Argument>(Def)) { // For arguments, we will place the store instruction right after // the coroutine frame pointer instruction, i.e. coro.begin. - InsertPt = Shape.getInsertPtAfterFramePtr()->getIterator(); + InsertPt = Shape.getInsertPtAfterFramePtr(); // If we're spilling an Argument, make sure we clear 'nocapture' // from the coroutine function. @@ -1788,7 +1811,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { if (!DT.dominates(CB, I)) { // If it is not dominated by CoroBegin, then spill should be // inserted immediately after CoroFrame is computed. - InsertPt = Shape.getInsertPtAfterFramePtr()->getIterator(); + InsertPt = Shape.getInsertPtAfterFramePtr(); } else if (auto *II = dyn_cast<InvokeInst>(I)) { // If we are spilling the result of the invoke instruction, split // the normal edge and insert the spill in the new block. @@ -1843,7 +1866,8 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { SpillAlignment, E.first->getName() + Twine(".reload")); SmallVector<DbgDeclareInst *, 1> DIs; - findDbgDeclares(DIs, Def); + SmallVector<DPValue *, 1> DPVs; + findDbgDeclares(DIs, Def, &DPVs); // Try best to find dbg.declare. If the spill is a temp, there may not // be a direct dbg.declare. Walk up the load chain to find one from an // alias. @@ -1858,24 +1882,36 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { if (!isa<AllocaInst, LoadInst>(CurDef)) break; DIs.clear(); - findDbgDeclares(DIs, CurDef); + DPVs.clear(); + findDbgDeclares(DIs, CurDef, &DPVs); } } - for (DbgDeclareInst *DDI : DIs) { + auto SalvageOne = [&](auto *DDI) { bool AllowUnresolved = false; // This dbg.declare is preserved for all coro-split function // fragments. It will be unreachable in the main function, and // processed by coro::salvageDebugInfo() by CoroCloner. - DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved) - .insertDeclare(CurrentReload, DDI->getVariable(), - DDI->getExpression(), DDI->getDebugLoc(), - &*Builder.GetInsertPoint()); + if (UseNewDbgInfoFormat) { + DPValue *NewDPV = + new DPValue(ValueAsMetadata::get(CurrentReload), + DDI->getVariable(), DDI->getExpression(), + DDI->getDebugLoc(), DPValue::LocationType::Declare); + Builder.GetInsertPoint()->getParent()->insertDPValueBefore( + NewDPV, Builder.GetInsertPoint()); + } else { + DIBuilder(*CurrentBlock->getParent()->getParent(), AllowUnresolved) + .insertDeclare(CurrentReload, DDI->getVariable(), + DDI->getExpression(), DDI->getDebugLoc(), + &*Builder.GetInsertPoint()); + } // This dbg.declare is for the main function entry point. It // will be deleted in all coro-split functions. - coro::salvageDebugInfo(ArgToAllocaMap, DDI, Shape.OptimizeFrame, + coro::salvageDebugInfo(ArgToAllocaMap, *DDI, Shape.OptimizeFrame, false /*UseEntryValue*/); - } + }; + for_each(DIs, SalvageOne); + for_each(DPVs, SalvageOne); } // If we have a single edge PHINode, remove it and replace it with a @@ -1893,6 +1929,10 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { // Replace all uses of CurrentValue in the current instruction with // reload. U->replaceUsesOfWith(Def, CurrentReload); + // Instructions are added to Def's user list if the attached + // debug records use Def. Update those now. + for (auto &DPV : U->getDbgValueRange()) + DPV.replaceVariableLocationOp(Def, CurrentReload, true); } } @@ -1943,9 +1983,12 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { G->setName(Alloca->getName() + Twine(".reload.addr")); SmallVector<DbgVariableIntrinsic *, 4> DIs; - findDbgUsers(DIs, Alloca); + SmallVector<DPValue *> DPValues; + findDbgUsers(DIs, Alloca, &DPValues); for (auto *DVI : DIs) DVI->replaceUsesOfWith(Alloca, G); + for (auto *DPV : DPValues) + DPV->replaceVariableLocationOp(Alloca, G); for (Instruction *I : UsersToUpdate) { // It is meaningless to retain the lifetime intrinsics refer for the @@ -1959,7 +2002,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { I->replaceUsesOfWith(Alloca, G); } } - Builder.SetInsertPoint(Shape.getInsertPtAfterFramePtr()); + Builder.SetInsertPoint(&*Shape.getInsertPtAfterFramePtr()); for (const auto &A : FrameData.Allocas) { AllocaInst *Alloca = A.Alloca; if (A.MayWriteBeforeCoroBegin) { @@ -2020,7 +2063,7 @@ static void insertSpills(const FrameDataInfo &FrameData, coro::Shape &Shape) { isa<BitCastInst>(Inst); }); if (HasAccessingPromiseBeforeCB) { - Builder.SetInsertPoint(Shape.getInsertPtAfterFramePtr()); + Builder.SetInsertPoint(&*Shape.getInsertPtAfterFramePtr()); auto *G = GetFramePointer(PA); auto *Value = Builder.CreateLoad(PA->getAllocatedType(), PA); Builder.CreateStore(Value, G); @@ -2802,21 +2845,16 @@ static void collectFrameAlloca(AllocaInst *AI, coro::Shape &Shape, Visitor.getMayWriteBeforeCoroBegin()); } -void coro::salvageDebugInfo( - SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, - DbgVariableIntrinsic *DVI, bool OptimizeFrame, bool UseEntryValue) { - Function *F = DVI->getFunction(); +static std::optional<std::pair<Value &, DIExpression &>> +salvageDebugInfoImpl(SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, + bool OptimizeFrame, bool UseEntryValue, Function *F, + Value *Storage, DIExpression *Expr, + bool SkipOutermostLoad) { IRBuilder<> Builder(F->getContext()); auto InsertPt = F->getEntryBlock().getFirstInsertionPt(); while (isa<IntrinsicInst>(InsertPt)) ++InsertPt; Builder.SetInsertPoint(&F->getEntryBlock(), InsertPt); - DIExpression *Expr = DVI->getExpression(); - // Follow the pointer arithmetic all the way to the incoming - // function argument and convert into a DIExpression. - bool SkipOutermostLoad = !isa<DbgValueInst>(DVI); - Value *Storage = DVI->getVariableLocationOp(0); - Value *OriginalStorage = Storage; while (auto *Inst = dyn_cast_or_null<Instruction>(Storage)) { if (auto *LdInst = dyn_cast<LoadInst>(Inst)) { @@ -2848,7 +2886,7 @@ void coro::salvageDebugInfo( SkipOutermostLoad = false; } if (!Storage) - return; + return std::nullopt; auto *StorageAsArg = dyn_cast<Argument>(Storage); const bool IsSwiftAsyncArg = @@ -2884,8 +2922,30 @@ void coro::salvageDebugInfo( Expr = DIExpression::prepend(Expr, DIExpression::DerefBefore); } - DVI->replaceVariableLocationOp(OriginalStorage, Storage); - DVI->setExpression(Expr); + return {{*Storage, *Expr}}; +} + +void coro::salvageDebugInfo( + SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, + DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool UseEntryValue) { + + Function *F = DVI.getFunction(); + // Follow the pointer arithmetic all the way to the incoming + // function argument and convert into a DIExpression. + bool SkipOutermostLoad = !isa<DbgValueInst>(DVI); + Value *OriginalStorage = DVI.getVariableLocationOp(0); + + auto SalvagedInfo = ::salvageDebugInfoImpl( + ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage, + DVI.getExpression(), SkipOutermostLoad); + if (!SalvagedInfo) + return; + + Value *Storage = &SalvagedInfo->first; + DIExpression *Expr = &SalvagedInfo->second; + + DVI.replaceVariableLocationOp(OriginalStorage, Storage); + DVI.setExpression(Expr); // We only hoist dbg.declare today since it doesn't make sense to hoist // dbg.value since it does not have the same function wide guarantees that // dbg.declare does. @@ -2896,7 +2956,44 @@ void coro::salvageDebugInfo( else if (isa<Argument>(Storage)) InsertPt = F->getEntryBlock().begin(); if (InsertPt) - DVI->moveBefore(*(*InsertPt)->getParent(), *InsertPt); + DVI.moveBefore(*(*InsertPt)->getParent(), *InsertPt); + } +} + +void coro::salvageDebugInfo( + SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DPValue &DPV, + bool OptimizeFrame, bool UseEntryValue) { + + Function *F = DPV.getFunction(); + // Follow the pointer arithmetic all the way to the incoming + // function argument and convert into a DIExpression. + bool SkipOutermostLoad = DPV.getType() == DPValue::LocationType::Declare; + Value *OriginalStorage = DPV.getVariableLocationOp(0); + + auto SalvagedInfo = ::salvageDebugInfoImpl( + ArgToAllocaMap, OptimizeFrame, UseEntryValue, F, OriginalStorage, + DPV.getExpression(), SkipOutermostLoad); + if (!SalvagedInfo) + return; + + Value *Storage = &SalvagedInfo->first; + DIExpression *Expr = &SalvagedInfo->second; + + DPV.replaceVariableLocationOp(OriginalStorage, Storage); + DPV.setExpression(Expr); + // We only hoist dbg.declare today since it doesn't make sense to hoist + // dbg.value since it does not have the same function wide guarantees that + // dbg.declare does. + if (DPV.getType() == DPValue::LocationType::Declare) { + std::optional<BasicBlock::iterator> InsertPt; + if (auto *I = dyn_cast<Instruction>(Storage)) + InsertPt = I->getInsertionPointAfterDef(); + else if (isa<Argument>(Storage)) + InsertPt = F->getEntryBlock().begin(); + if (InsertPt) { + DPV.removeFromParent(); + (*InsertPt)->getParent()->insertDPValueBefore(&DPV, *InsertPt); + } } } @@ -3087,10 +3184,15 @@ void coro::buildCoroutineFrame( for (auto &Iter : FrameData.Spills) { auto *V = Iter.first; SmallVector<DbgValueInst *, 16> DVIs; - findDbgValues(DVIs, V); + SmallVector<DPValue *, 16> DPVs; + findDbgValues(DVIs, V, &DPVs); for (DbgValueInst *DVI : DVIs) if (Checker.isDefinitionAcrossSuspend(*V, DVI)) FrameData.Spills[V].push_back(DVI); + // Add the instructions which carry debug info that is in the frame. + for (DPValue *DPV : DPVs) + if (Checker.isDefinitionAcrossSuspend(*V, DPV->Marker->MarkedInstr)) + FrameData.Spills[V].push_back(DPV->Marker->MarkedInstr); } LLVM_DEBUG(dumpSpills("Spills", FrameData.Spills)); diff --git a/llvm/lib/Transforms/Coroutines/CoroInternal.h b/llvm/lib/Transforms/Coroutines/CoroInternal.h index 0856c4925cc5..fb16a4090689 100644 --- a/llvm/lib/Transforms/Coroutines/CoroInternal.h +++ b/llvm/lib/Transforms/Coroutines/CoroInternal.h @@ -32,7 +32,10 @@ void replaceCoroFree(CoroIdInst *CoroId, bool Elide); /// OptimizeFrame is false. void salvageDebugInfo( SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, - DbgVariableIntrinsic *DVI, bool OptimizeFrame, bool IsEntryPoint); + DbgVariableIntrinsic &DVI, bool OptimizeFrame, bool IsEntryPoint); +void salvageDebugInfo( + SmallDenseMap<Argument *, AllocaInst *, 4> &ArgToAllocaMap, DPValue &DPV, + bool OptimizeFrame, bool UseEntryValue); // Keeps data and helper functions for lowering coroutine intrinsics. struct LowererBase { @@ -240,10 +243,13 @@ struct LLVM_LIBRARY_VISIBILITY Shape { return nullptr; } - Instruction *getInsertPtAfterFramePtr() const { - if (auto *I = dyn_cast<Instruction>(FramePtr)) - return I->getNextNode(); - return &cast<Argument>(FramePtr)->getParent()->getEntryBlock().front(); + BasicBlock::iterator getInsertPtAfterFramePtr() const { + if (auto *I = dyn_cast<Instruction>(FramePtr)) { + BasicBlock::iterator It = std::next(I->getIterator()); + It.setHeadBit(true); // Copy pre-RemoveDIs behaviour. + return It; + } + return cast<Argument>(FramePtr)->getParent()->getEntryBlock().begin(); } /// Allocate memory according to the rules of the active lowering. diff --git a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp index 244580f503d5..7758b52abc20 100644 --- a/llvm/lib/Transforms/Coroutines/CoroSplit.cpp +++ b/llvm/lib/Transforms/Coroutines/CoroSplit.cpp @@ -725,13 +725,17 @@ static void replaceSwiftErrorOps(Function &F, coro::Shape &Shape, } /// Returns all DbgVariableIntrinsic in F. -static SmallVector<DbgVariableIntrinsic *, 8> +static std::pair<SmallVector<DbgVariableIntrinsic *, 8>, SmallVector<DPValue *>> collectDbgVariableIntrinsics(Function &F) { SmallVector<DbgVariableIntrinsic *, 8> Intrinsics; - for (auto &I : instructions(F)) + SmallVector<DPValue *> DPValues; + for (auto &I : instructions(F)) { + for (DPValue &DPV : I.getDbgValueRange()) + DPValues.push_back(&DPV); if (auto *DVI = dyn_cast<DbgVariableIntrinsic>(&I)) Intrinsics.push_back(DVI); - return Intrinsics; + } + return {Intrinsics, DPValues}; } void CoroCloner::replaceSwiftErrorOps() { @@ -739,15 +743,17 @@ void CoroCloner::replaceSwiftErrorOps() { } void CoroCloner::salvageDebugInfo() { - SmallVector<DbgVariableIntrinsic *, 8> Worklist = - collectDbgVariableIntrinsics(*NewF); + auto [Worklist, DPValues] = collectDbgVariableIntrinsics(*NewF); SmallDenseMap<Argument *, AllocaInst *, 4> ArgToAllocaMap; // Only 64-bit ABIs have a register we can refer to with the entry value. bool UseEntryValue = llvm::Triple(OrigF.getParent()->getTargetTriple()).isArch64Bit(); for (DbgVariableIntrinsic *DVI : Worklist) - coro::salvageDebugInfo(ArgToAllocaMap, DVI, Shape.OptimizeFrame, + coro::salvageDebugInfo(ArgToAllocaMap, *DVI, Shape.OptimizeFrame, + UseEntryValue); + for (DPValue *DPV : DPValues) + coro::salvageDebugInfo(ArgToAllocaMap, *DPV, Shape.OptimizeFrame, UseEntryValue); // Remove all salvaged dbg.declare intrinsics that became @@ -757,7 +763,7 @@ void CoroCloner::salvageDebugInfo() { return !isPotentiallyReachable(&NewF->getEntryBlock(), BB, nullptr, &DomTree); }; - for (DbgVariableIntrinsic *DVI : Worklist) { + auto RemoveOne = [&](auto *DVI) { if (IsUnreachableBlock(DVI->getParent())) DVI->eraseFromParent(); else if (isa_and_nonnull<AllocaInst>(DVI->getVariableLocationOp(0))) { @@ -770,7 +776,9 @@ void CoroCloner::salvageDebugInfo() { if (!Uses) DVI->eraseFromParent(); } - } + }; + for_each(Worklist, RemoveOne); + for_each(DPValues, RemoveOne); } void CoroCloner::replaceEntryBlock() { @@ -1243,7 +1251,7 @@ static void updateCoroFrame(coro::Shape &Shape, Function *ResumeFn, Function *DestroyFn, Function *CleanupFn) { assert(Shape.ABI == coro::ABI::Switch); - IRBuilder<> Builder(Shape.getInsertPtAfterFramePtr()); + IRBuilder<> Builder(&*Shape.getInsertPtAfterFramePtr()); auto *ResumeAddr = Builder.CreateStructGEP( Shape.FrameTy, Shape.FramePtr, coro::Shape::SwitchFieldIndex::Resume, @@ -2039,10 +2047,13 @@ splitCoroutine(Function &F, SmallVectorImpl<Function *> &Clones, // original function. The Cloner has already salvaged debug info in the new // coroutine funclets. SmallDenseMap<Argument *, AllocaInst *, 4> ArgToAllocaMap; - for (auto *DDI : collectDbgVariableIntrinsics(F)) - coro::salvageDebugInfo(ArgToAllocaMap, DDI, Shape.OptimizeFrame, + auto [DbgInsts, DPValues] = collectDbgVariableIntrinsics(F); + for (auto *DDI : DbgInsts) + coro::salvageDebugInfo(ArgToAllocaMap, *DDI, Shape.OptimizeFrame, + false /*UseEntryValue*/); + for (DPValue *DPV : DPValues) + coro::salvageDebugInfo(ArgToAllocaMap, *DPV, Shape.OptimizeFrame, false /*UseEntryValue*/); - return Shape; } diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp index 104c73602223..1539fa9a3269 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -4227,12 +4227,9 @@ InstCombinerImpl::foldCommutativeIntrinsicOverSelects(IntrinsicInst &II) { assert(II.isCommutative()); Value *A, *B, *C; - bool LHSIsSelect = - match(II.getOperand(0), m_Select(m_Value(A), m_Value(B), m_Value(C))); - bool RHSIsSymmetricalSelect = match( - II.getOperand(1), m_Select(m_Specific(A), m_Specific(C), m_Specific(B))); - - if (LHSIsSelect && RHSIsSymmetricalSelect) { + if (match(II.getOperand(0), m_Select(m_Value(A), m_Value(B), m_Value(C))) && + match(II.getOperand(1), + m_Select(m_Specific(A), m_Specific(C), m_Specific(B)))) { replaceOperand(II, 0, B); replaceOperand(II, 1, C); return &II; diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp index 8d5866e98a8e..e5566578869d 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp @@ -1205,6 +1205,38 @@ Instruction *InstCombinerImpl::commonIDivTransforms(BinaryOperator &I) { } } + // (X * Y) / (X * Z) --> Y / Z (and commuted variants) + if (match(Op0, m_Mul(m_Value(X), m_Value(Y)))) { + auto OB0HasNSW = cast<OverflowingBinaryOperator>(Op0)->hasNoSignedWrap(); + auto OB0HasNUW = cast<OverflowingBinaryOperator>(Op0)->hasNoUnsignedWrap(); + + auto CreateDivOrNull = [&](Value *A, Value *B) -> Instruction * { + auto OB1HasNSW = cast<OverflowingBinaryOperator>(Op1)->hasNoSignedWrap(); + auto OB1HasNUW = + cast<OverflowingBinaryOperator>(Op1)->hasNoUnsignedWrap(); + const APInt *C1, *C2; + if (IsSigned && OB0HasNSW) { + if (OB1HasNSW && match(B, m_APInt(C1)) && !C1->isAllOnes()) + return BinaryOperator::CreateSDiv(A, B); + } + if (!IsSigned && OB0HasNUW) { + if (OB1HasNUW) + return BinaryOperator::CreateUDiv(A, B); + if (match(A, m_APInt(C1)) && match(B, m_APInt(C2)) && C2->ule(*C1)) + return BinaryOperator::CreateUDiv(A, B); + } + return nullptr; + }; + + if (match(Op1, m_c_Mul(m_Specific(X), m_Value(Z)))) { + if (auto *Val = CreateDivOrNull(Y, Z)) + return Val; + } + if (match(Op1, m_c_Mul(m_Specific(Y), m_Value(Z)))) { + if (auto *Val = CreateDivOrNull(X, Z)) + return Val; + } + } return nullptr; } @@ -1375,20 +1407,7 @@ Instruction *InstCombinerImpl::visitUDiv(BinaryOperator &I) { if (Instruction *NarrowDiv = narrowUDivURem(I, *this)) return NarrowDiv; - // If the udiv operands are non-overflowing multiplies with a common operand, - // then eliminate the common factor: - // (A * B) / (A * X) --> B / X (and commuted variants) - // TODO: The code would be reduced if we had m_c_NUWMul pattern matching. - // TODO: If -reassociation handled this generally, we could remove this. Value *A, *B; - if (match(Op0, m_NUWMul(m_Value(A), m_Value(B)))) { - if (match(Op1, m_NUWMul(m_Specific(A), m_Value(X))) || - match(Op1, m_NUWMul(m_Value(X), m_Specific(A)))) - return BinaryOperator::CreateUDiv(B, X); - if (match(Op1, m_NUWMul(m_Specific(B), m_Value(X))) || - match(Op1, m_NUWMul(m_Value(X), m_Specific(B)))) - return BinaryOperator::CreateUDiv(A, X); - } // Look through a right-shift to find the common factor: // ((Op1 *nuw A) >> B) / Op1 --> A >> B diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp index 3e5d979f11cc..1fb9d7fff32f 100644 --- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp +++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp @@ -523,7 +523,8 @@ void ConstantHoistingPass::collectConstantCandidates(Function &Fn) { if (!DT->isReachableFromEntry(&BB)) continue; for (Instruction &Inst : BB) - collectConstantCandidates(ConstCandMap, &Inst); + if (!TTI->preferToKeepConstantsAttached(Inst, Fn)) + collectConstantCandidates(ConstCandMap, &Inst); } } diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp index fafbe17583f5..18266ba07898 100644 --- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp +++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp @@ -1109,6 +1109,16 @@ void State::addInfoFor(BasicBlock &BB) { CmpI->getOperand(1))); } +#ifndef NDEBUG +static void dumpUnpackedICmp(raw_ostream &OS, ICmpInst::Predicate Pred, + Value *LHS, Value *RHS) { + OS << "icmp " << Pred << ' '; + LHS->printAsOperand(OS, /*PrintType=*/true); + OS << ", "; + RHS->printAsOperand(OS, /*PrintType=*/false); +} +#endif + namespace { /// Helper to keep track of a condition and if it should be treated as negated /// for reproducer construction. @@ -1241,10 +1251,9 @@ static void generateReproducer(CmpInst *Cond, Module *M, if (Entry.Pred == ICmpInst::BAD_ICMP_PREDICATE) continue; - LLVM_DEBUG( - dbgs() << " Materializing assumption icmp " << Entry.Pred << ' '; - Entry.LHS->printAsOperand(dbgs(), /*PrintType=*/true); dbgs() << ", "; - Entry.RHS->printAsOperand(dbgs(), /*PrintType=*/false); dbgs() << "\n"); + LLVM_DEBUG(dbgs() << " Materializing assumption "; + dumpUnpackedICmp(dbgs(), Entry.Pred, Entry.LHS, Entry.RHS); + dbgs() << "\n"); CloneInstructions({Entry.LHS, Entry.RHS}, CmpInst::isSigned(Entry.Pred)); auto *Cmp = Builder.CreateICmp(Entry.Pred, Entry.LHS, Entry.RHS); @@ -1260,14 +1269,12 @@ static void generateReproducer(CmpInst *Cond, Module *M, assert(!verifyFunction(*F, &dbgs())); } -static std::optional<bool> checkCondition(CmpInst *Cmp, ConstraintInfo &Info, - unsigned NumIn, unsigned NumOut, +static std::optional<bool> checkCondition(CmpInst::Predicate Pred, Value *A, + Value *B, Instruction *CheckInst, + ConstraintInfo &Info, unsigned NumIn, + unsigned NumOut, Instruction *ContextInst) { - LLVM_DEBUG(dbgs() << "Checking " << *Cmp << "\n"); - - CmpInst::Predicate Pred = Cmp->getPredicate(); - Value *A = Cmp->getOperand(0); - Value *B = Cmp->getOperand(1); + LLVM_DEBUG(dbgs() << "Checking " << *CheckInst << "\n"); auto R = Info.getConstraintForSolving(Pred, A, B); if (R.empty() || !R.isValid(Info)){ @@ -1292,13 +1299,10 @@ static std::optional<bool> checkCondition(CmpInst *Cmp, ConstraintInfo &Info, return std::nullopt; LLVM_DEBUG({ - if (*ImpliedCondition) { - dbgs() << "Condition " << *Cmp; - } else { - auto InversePred = Cmp->getInversePredicate(); - dbgs() << "Condition " << CmpInst::getPredicateName(InversePred) << " " - << *A << ", " << *B; - } + dbgs() << "Condition "; + dumpUnpackedICmp( + dbgs(), *ImpliedCondition ? Pred : CmpInst::getInversePredicate(Pred), + A, B); dbgs() << " implied by dominating constraints\n"; CSToUse.dump(); }); @@ -1338,8 +1342,9 @@ static bool checkAndReplaceCondition( return true; }; - if (auto ImpliedCondition = - checkCondition(Cmp, Info, NumIn, NumOut, ContextInst)) + if (auto ImpliedCondition = checkCondition( + Cmp->getPredicate(), Cmp->getOperand(0), Cmp->getOperand(1), Cmp, + Info, NumIn, NumOut, ContextInst)) return ReplaceCmpWithConstant(Cmp, *ImpliedCondition); return false; } @@ -1380,9 +1385,10 @@ static bool checkAndSecondOpImpliedByFirst( bool Changed = false; // Check if the second condition can be simplified now. - if (auto ImpliedCondition = - checkCondition(cast<ICmpInst>(And->getOperand(1)), Info, CB.NumIn, - CB.NumOut, CB.getContextInst())) { + ICmpInst *Cmp = cast<ICmpInst>(And->getOperand(1)); + if (auto ImpliedCondition = checkCondition( + Cmp->getPredicate(), Cmp->getOperand(0), Cmp->getOperand(1), Cmp, + Info, CB.NumIn, CB.NumOut, CB.getContextInst())) { And->setOperand(1, ConstantInt::getBool(And->getType(), *ImpliedCondition)); Changed = true; } @@ -1408,9 +1414,8 @@ void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B, if (!R.isValid(*this) || R.isNe()) return; - LLVM_DEBUG(dbgs() << "Adding '" << Pred << " "; - A->printAsOperand(dbgs(), false); dbgs() << ", "; - B->printAsOperand(dbgs(), false); dbgs() << "'\n"); + LLVM_DEBUG(dbgs() << "Adding '"; dumpUnpackedICmp(dbgs(), Pred, A, B); + dbgs() << "'\n"); bool Added = false; auto &CSToUse = getCS(R.IsSigned); if (R.Coefficients.empty()) @@ -1616,10 +1621,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI, } auto AddFact = [&](CmpInst::Predicate Pred, Value *A, Value *B) { - LLVM_DEBUG(dbgs() << "fact to add to the system: " - << CmpInst::getPredicateName(Pred) << " "; - A->printAsOperand(dbgs()); dbgs() << ", "; - B->printAsOperand(dbgs(), false); dbgs() << "\n"); + LLVM_DEBUG(dbgs() << "fact to add to the system: "; + dumpUnpackedICmp(dbgs(), Pred, A, B); dbgs() << "\n"); if (Info.getCS(CmpInst::isSigned(Pred)).size() > MaxRows) { LLVM_DEBUG( dbgs() diff --git a/llvm/lib/Transforms/Scalar/LICM.cpp b/llvm/lib/Transforms/Scalar/LICM.cpp index d0afe09ce41d..9117378568b7 100644 --- a/llvm/lib/Transforms/Scalar/LICM.cpp +++ b/llvm/lib/Transforms/Scalar/LICM.cpp @@ -193,7 +193,7 @@ static Instruction *cloneInstructionInExitBlock( static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU); -static void moveInstructionBefore(Instruction &I, Instruction &Dest, +static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, ScalarEvolution *SE); @@ -1011,7 +1011,8 @@ bool llvm::hoistRegion(DomTreeNode *N, AAResults *AA, LoopInfo *LI, LLVM_DEBUG(dbgs() << "LICM rehoisting to " << HoistPoint->getParent()->getNameOrAsOperand() << ": " << *I << "\n"); - moveInstructionBefore(*I, *HoistPoint, *SafetyInfo, MSSAU, SE); + moveInstructionBefore(*I, HoistPoint->getIterator(), *SafetyInfo, MSSAU, + SE); HoistPoint = I; Changed = true; } @@ -1491,16 +1492,17 @@ static void eraseInstruction(Instruction &I, ICFLoopSafetyInfo &SafetyInfo, I.eraseFromParent(); } -static void moveInstructionBefore(Instruction &I, Instruction &Dest, +static void moveInstructionBefore(Instruction &I, BasicBlock::iterator Dest, ICFLoopSafetyInfo &SafetyInfo, MemorySSAUpdater &MSSAU, ScalarEvolution *SE) { SafetyInfo.removeInstruction(&I); - SafetyInfo.insertInstructionTo(&I, Dest.getParent()); - I.moveBefore(&Dest); + SafetyInfo.insertInstructionTo(&I, Dest->getParent()); + I.moveBefore(*Dest->getParent(), Dest); if (MemoryUseOrDef *OldMemAcc = cast_or_null<MemoryUseOrDef>( MSSAU.getMemorySSA()->getMemoryAccess(&I))) - MSSAU.moveToPlace(OldMemAcc, Dest.getParent(), MemorySSA::BeforeTerminator); + MSSAU.moveToPlace(OldMemAcc, Dest->getParent(), + MemorySSA::BeforeTerminator); if (SE) SE->forgetBlockAndLoopDispositions(&I); } @@ -1747,10 +1749,11 @@ static void hoist(Instruction &I, const DominatorTree *DT, const Loop *CurLoop, if (isa<PHINode>(I)) // Move the new node to the end of the phi list in the destination block. - moveInstructionBefore(I, *Dest->getFirstNonPHI(), *SafetyInfo, MSSAU, SE); + moveInstructionBefore(I, Dest->getFirstNonPHIIt(), *SafetyInfo, MSSAU, SE); else // Move the new node to the destination block, before its terminator. - moveInstructionBefore(I, *Dest->getTerminator(), *SafetyInfo, MSSAU, SE); + moveInstructionBefore(I, Dest->getTerminator()->getIterator(), *SafetyInfo, + MSSAU, SE); I.updateLocationAfterHoist(); diff --git a/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp b/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp index 13e06c79d0d7..9d5e6693c0e5 100644 --- a/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp +++ b/llvm/lib/Transforms/Scalar/LoopVersioningLICM.cpp @@ -266,6 +266,11 @@ bool LoopVersioningLICM::legalLoopMemoryAccesses() { for (const auto &A : AS) { Value *Ptr = A.getValue(); // Alias tracker should have pointers of same data type. + // + // FIXME: check no longer effective since opaque pointers? + // If the intent is to check that the memory accesses use the + // same data type (such that LICM can promote them), then we + // can no longer see this from the pointer value types. TypeCheck = (TypeCheck && (SomePtr->getType() == Ptr->getType())); } // At least one alias tracker should have pointers of same data type. diff --git a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp index 76280ed492b3..504f4430dc2c 100644 --- a/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp +++ b/llvm/lib/Transforms/Utils/LoopRotationUtils.cpp @@ -708,12 +708,13 @@ bool LoopRotate::rotateLoop(Loop *L, bool SimplifiedLatch) { // as U1'' and U1' scopes will not be compatible wrt to the local restrict // Clone the llvm.experimental.noalias.decl again for the NewHeader. - Instruction *NewHeaderInsertionPoint = &(*NewHeader->getFirstNonPHI()); + BasicBlock::iterator NewHeaderInsertionPoint = + NewHeader->getFirstNonPHIIt(); for (NoAliasScopeDeclInst *NAD : NoAliasDeclInstructions) { LLVM_DEBUG(dbgs() << " Cloning llvm.experimental.noalias.scope.decl:" << *NAD << "\n"); Instruction *NewNAD = NAD->clone(); - NewNAD->insertBefore(NewHeaderInsertionPoint); + NewNAD->insertBefore(*NewHeader, NewHeaderInsertionPoint); } // Scopes must now be duplicated, once for OrigHeader and once for diff --git a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp index 5c3776683d5d..47c6bcbaf26e 100644 --- a/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp +++ b/llvm/lib/Transforms/Utils/MemoryOpRemark.cpp @@ -322,8 +322,9 @@ void MemoryOpRemark::visitVariable(const Value *V, // Try to get an llvm.dbg.declare, which has a DILocalVariable giving us the // real debug info name and size of the variable. SmallVector<DbgDeclareInst *, 1> DbgDeclares; - findDbgDeclares(DbgDeclares, const_cast<Value *>(V)); - for (const DbgVariableIntrinsic *DVI : DbgDeclares) { + SmallVector<DPValue *, 1> DPValues; + findDbgDeclares(DbgDeclares, const_cast<Value *>(V), &DPValues); + auto FindDI = [&](const auto *DVI) { if (DILocalVariable *DILV = DVI->getVariable()) { std::optional<uint64_t> DISize = getSizeInBytes(DILV->getSizeInBits()); VariableInfo Var{DILV->getName(), DISize}; @@ -332,7 +333,10 @@ void MemoryOpRemark::visitVariable(const Value *V, FoundDI = true; } } - } + }; + for_each(DbgDeclares, FindDI); + for_each(DPValues, FindDI); + if (FoundDI) { assert(!Result.empty()); return; |
