diff options
Diffstat (limited to 'llvm/lib/Analysis')
-rw-r--r-- | llvm/lib/Analysis/ConstantFolding.cpp | 25 | ||||
-rw-r--r-- | llvm/lib/Analysis/Loads.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Analysis/MemoryLocation.cpp | 16 | ||||
-rw-r--r-- | llvm/lib/Analysis/StackLifetime.cpp | 42 | ||||
-rw-r--r-- | llvm/lib/Analysis/ValueTracking.cpp | 27 |
5 files changed, 79 insertions, 47 deletions
diff --git a/llvm/lib/Analysis/ConstantFolding.cpp b/llvm/lib/Analysis/ConstantFolding.cpp index dd98b62..4969528 100644 --- a/llvm/lib/Analysis/ConstantFolding.cpp +++ b/llvm/lib/Analysis/ConstantFolding.cpp @@ -1659,6 +1659,7 @@ bool llvm::canConstantFoldCallTo(const CallBase *Call, const Function *F) { case Intrinsic::aarch64_sve_convert_from_svbool: case Intrinsic::wasm_alltrue: case Intrinsic::wasm_anytrue: + case Intrinsic::wasm_dot: // WebAssembly float semantics are always known case Intrinsic::wasm_trunc_signed: case Intrinsic::wasm_trunc_unsigned: @@ -3989,6 +3990,30 @@ static Constant *ConstantFoldFixedVectorCall( } return ConstantVector::get(Result); } + case Intrinsic::wasm_dot: { + unsigned NumElements = + cast<FixedVectorType>(Operands[0]->getType())->getNumElements(); + + assert(NumElements == 8 && Result.size() == 4 && + "wasm dot takes i16x8 and produces i32x4"); + assert(Ty->isIntegerTy()); + int32_t MulVector[8]; + + for (unsigned I = 0; I < NumElements; ++I) { + ConstantInt *Elt0 = + cast<ConstantInt>(Operands[0]->getAggregateElement(I)); + ConstantInt *Elt1 = + cast<ConstantInt>(Operands[1]->getAggregateElement(I)); + + MulVector[I] = Elt0->getSExtValue() * Elt1->getSExtValue(); + } + for (unsigned I = 0; I < Result.size(); I++) { + int32_t IAdd = MulVector[I * 2] + MulVector[I * 2 + 1]; + Result[I] = ConstantInt::get(Ty, IAdd); + } + + return ConstantVector::get(Result); + } default: break; } diff --git a/llvm/lib/Analysis/Loads.cpp b/llvm/lib/Analysis/Loads.cpp index 6fc81d787..78d0887 100644 --- a/llvm/lib/Analysis/Loads.cpp +++ b/llvm/lib/Analysis/Loads.cpp @@ -631,9 +631,13 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr, if (!Val || !Len) return nullptr; - // TODO: Handle offsets. - Value *Dst = MSI->getDest(); - if (!AreEquivalentAddressValues(Dst, Ptr)) + // Handle offsets. + int64_t StoreOffset = 0, LoadOffset = 0; + const Value *StoreBase = + GetPointerBaseWithConstantOffset(MSI->getDest(), StoreOffset, DL); + const Value *LoadBase = + GetPointerBaseWithConstantOffset(Ptr, LoadOffset, DL); + if (StoreBase != LoadBase || LoadOffset < StoreOffset) return nullptr; if (IsLoadCSE) @@ -645,7 +649,7 @@ static Value *getAvailableLoadStore(Instruction *Inst, const Value *Ptr, // Make sure the read bytes are contained in the memset. uint64_t LoadSize = LoadTypeSize.getFixedValue(); - if ((Len->getValue() * 8).ult(LoadSize)) + if ((Len->getValue() * 8).ult(LoadSize + (LoadOffset - StoreOffset) * 8)) return nullptr; APInt Splat = LoadSize >= 8 ? APInt::getSplat(LoadSize, Val->getValue()) @@ -833,6 +837,10 @@ bool llvm::canReplacePointersInUseIfEqual(const Use &U, const Value *To, if (!To->getType()->isPointerTy()) return true; + // Do not perform replacements in lifetime intrinsic arguments. + if (isa<LifetimeIntrinsic>(U.getUser())) + return false; + if (isPointerAlwaysReplaceable(&*U, To, DL)) return true; return isPointerUseReplacable(U); diff --git a/llvm/lib/Analysis/MemoryLocation.cpp b/llvm/lib/Analysis/MemoryLocation.cpp index c8daab7a..28a2640 100644 --- a/llvm/lib/Analysis/MemoryLocation.cpp +++ b/llvm/lib/Analysis/MemoryLocation.cpp @@ -190,7 +190,21 @@ MemoryLocation MemoryLocation::getForArgument(const CallBase *Call, return MemoryLocation::getAfter(Arg, AATags); case Intrinsic::lifetime_start: - case Intrinsic::lifetime_end: + case Intrinsic::lifetime_end: { + assert(ArgIdx == 1 && "Invalid argument index"); + auto *AI = dyn_cast<AllocaInst>(Arg); + if (!AI) + // lifetime of poison value. + return MemoryLocation::getBeforeOrAfter(Arg); + + std::optional<TypeSize> AllocSize = + AI->getAllocationSize(II->getDataLayout()); + return MemoryLocation(Arg, + AllocSize ? LocationSize::precise(*AllocSize) + : LocationSize::afterPointer(), + AATags); + } + case Intrinsic::invariant_start: assert(ArgIdx == 1 && "Invalid argument index"); return MemoryLocation( diff --git a/llvm/lib/Analysis/StackLifetime.cpp b/llvm/lib/Analysis/StackLifetime.cpp index 34a7a04..abe4985 100644 --- a/llvm/lib/Analysis/StackLifetime.cpp +++ b/llvm/lib/Analysis/StackLifetime.cpp @@ -59,44 +59,20 @@ bool StackLifetime::isAliveAfter(const AllocaInst *AI, return getLiveRange(AI).test(InstNum); } -// Returns unique alloca annotated by lifetime marker only if -// markers has the same size and points to the alloca start. -static const AllocaInst *findMatchingAlloca(const IntrinsicInst &II, - const DataLayout &DL) { - const AllocaInst *AI = cast<AllocaInst>(II.getArgOperand(1)); - auto AllocaSize = AI->getAllocationSize(DL); - if (!AllocaSize) - return nullptr; - - auto *Size = dyn_cast<ConstantInt>(II.getArgOperand(0)); - if (!Size) - return nullptr; - int64_t LifetimeSize = Size->getSExtValue(); - - if (LifetimeSize != -1 && uint64_t(LifetimeSize) != *AllocaSize) - return nullptr; - - return AI; -} - void StackLifetime::collectMarkers() { InterestingAllocas.resize(NumAllocas); DenseMap<const BasicBlock *, SmallDenseMap<const IntrinsicInst *, Marker>> BBMarkerSet; - const DataLayout &DL = F.getDataLayout(); - // Compute the set of start/end markers per basic block. for (const BasicBlock *BB : depth_first(&F)) { for (const Instruction &I : *BB) { const IntrinsicInst *II = dyn_cast<IntrinsicInst>(&I); if (!II || !II->isLifetimeStartOrEnd()) continue; - const AllocaInst *AI = findMatchingAlloca(*II, DL); - if (!AI) { - HasUnknownLifetimeStartOrEnd = true; + const AllocaInst *AI = dyn_cast<AllocaInst>(II->getArgOperand(1)); + if (!AI) continue; - } auto It = AllocaNumbering.find(AI); if (It == AllocaNumbering.end()) continue; @@ -325,20 +301,6 @@ StackLifetime::StackLifetime(const Function &F, } void StackLifetime::run() { - if (HasUnknownLifetimeStartOrEnd) { - // There is marker which we can't assign to a specific alloca, so we - // fallback to the most conservative results for the type. - switch (Type) { - case LivenessType::May: - LiveRanges.resize(NumAllocas, getFullLiveRange()); - break; - case LivenessType::Must: - LiveRanges.resize(NumAllocas, LiveRange(Instructions.size())); - break; - } - return; - } - LiveRanges.resize(NumAllocas, LiveRange(Instructions.size())); for (unsigned I = 0; I < NumAllocas; ++I) if (!InterestingAllocas.test(I)) diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp index af85ce4..1e70228 100644 --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -1351,6 +1351,8 @@ static void computeKnownBitsFromOperator(const Operator *I, isa<ScalableVectorType>(I->getType())) break; + unsigned NumElts = DemandedElts.getBitWidth(); + bool IsLE = Q.DL.isLittleEndian(); // Look through a cast from narrow vector elements to wider type. // Examples: v4i32 -> v2i64, v3i8 -> v24 unsigned SubBitWidth = SrcVecTy->getScalarSizeInBits(); @@ -1369,7 +1371,6 @@ static void computeKnownBitsFromOperator(const Operator *I, // // The known bits of each sub-element are then inserted into place // (dependent on endian) to form the full result of known bits. - unsigned NumElts = DemandedElts.getBitWidth(); unsigned SubScale = BitWidth / SubBitWidth; APInt SubDemandedElts = APInt::getZero(NumElts * SubScale); for (unsigned i = 0; i != NumElts; ++i) { @@ -1381,10 +1382,32 @@ static void computeKnownBitsFromOperator(const Operator *I, for (unsigned i = 0; i != SubScale; ++i) { computeKnownBits(I->getOperand(0), SubDemandedElts.shl(i), KnownSrc, Q, Depth + 1); - unsigned ShiftElt = Q.DL.isLittleEndian() ? i : SubScale - 1 - i; + unsigned ShiftElt = IsLE ? i : SubScale - 1 - i; Known.insertBits(KnownSrc, ShiftElt * SubBitWidth); } } + // Look through a cast from wider vector elements to narrow type. + // Examples: v2i64 -> v4i32 + if (SubBitWidth % BitWidth == 0) { + unsigned SubScale = SubBitWidth / BitWidth; + KnownBits KnownSrc(SubBitWidth); + APInt SubDemandedElts = + APIntOps::ScaleBitMask(DemandedElts, NumElts / SubScale); + computeKnownBits(I->getOperand(0), SubDemandedElts, KnownSrc, Q, + Depth + 1); + + Known.Zero.setAllBits(); + Known.One.setAllBits(); + for (unsigned i = 0; i != NumElts; ++i) { + if (DemandedElts[i]) { + unsigned Shifts = IsLE ? i : NumElts - 1 - i; + unsigned Offset = (Shifts % SubScale) * BitWidth; + Known = Known.intersectWith(KnownSrc.extractBits(BitWidth, Offset)); + if (Known.isUnknown()) + break; + } + } + } break; } case Instruction::SExt: { |