aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/Transforms
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/Transforms')
-rw-r--r--llvm/lib/Transforms/IPO/AttributorAttributes.cpp53
-rw-r--r--llvm/lib/Transforms/IPO/OpenMPOpt.cpp18
-rw-r--r--llvm/lib/Transforms/IPO/SampleProfile.cpp13
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp49
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp59
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineInternal.h17
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp7
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp4
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp134
-rw-r--r--llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp44
-rw-r--r--llvm/lib/Transforms/InstCombine/InstructionCombining.cpp106
-rw-r--r--llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp2
-rw-r--r--llvm/lib/Transforms/Instrumentation/MemProfiler.cpp2
-rw-r--r--llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp2
-rw-r--r--llvm/lib/Transforms/Scalar/ConstantHoisting.cpp5
-rw-r--r--llvm/lib/Transforms/Scalar/ConstraintElimination.cpp75
-rw-r--r--llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp6
-rw-r--r--llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp2
-rw-r--r--llvm/lib/Transforms/Scalar/GVN.cpp2
-rw-r--r--llvm/lib/Transforms/Scalar/LoopFlatten.cpp5
-rw-r--r--llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp2
-rw-r--r--llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp9
-rw-r--r--llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp2
-rw-r--r--llvm/lib/Transforms/Scalar/SROA.cpp1
-rw-r--r--llvm/lib/Transforms/Utils/DXILUpgrade.cpp12
-rw-r--r--llvm/lib/Transforms/Utils/FunctionComparator.cpp25
-rw-r--r--llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp2
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyCFG.cpp8
-rw-r--r--llvm/lib/Transforms/Utils/SimplifyIndVar.cpp7
-rw-r--r--llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp123
30 files changed, 488 insertions, 308 deletions
diff --git a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
index 8e1f782f7cd8..b2618e35b085 100644
--- a/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
+++ b/llvm/lib/Transforms/IPO/AttributorAttributes.cpp
@@ -291,42 +291,15 @@ static const Value *getPointerOperand(const Instruction *I,
}
/// Helper function to create a pointer based on \p Ptr, and advanced by \p
-/// Offset bytes. To aid later analysis the method tries to build
-/// getelement pointer instructions that traverse the natural type of \p Ptr if
-/// possible. If that fails, the remaining offset is adjusted byte-wise, hence
-/// through a cast to i8*.
-///
-/// TODO: This could probably live somewhere more prominantly if it doesn't
-/// already exist.
-static Value *constructPointer(Type *PtrElemTy, Value *Ptr, int64_t Offset,
- IRBuilder<NoFolder> &IRB, const DataLayout &DL) {
- assert(Offset >= 0 && "Negative offset not supported yet!");
+/// Offset bytes.
+static Value *constructPointer(Value *Ptr, int64_t Offset,
+ IRBuilder<NoFolder> &IRB) {
LLVM_DEBUG(dbgs() << "Construct pointer: " << *Ptr << " + " << Offset
<< "-bytes\n");
- if (Offset) {
- Type *Ty = PtrElemTy;
- APInt IntOffset(DL.getIndexTypeSizeInBits(Ptr->getType()), Offset);
- SmallVector<APInt> IntIndices = DL.getGEPIndicesForOffset(Ty, IntOffset);
-
- SmallVector<Value *, 4> ValIndices;
- std::string GEPName = Ptr->getName().str();
- for (const APInt &Index : IntIndices) {
- ValIndices.push_back(IRB.getInt(Index));
- GEPName += "." + std::to_string(Index.getZExtValue());
- }
-
- // Create a GEP for the indices collected above.
- Ptr = IRB.CreateGEP(PtrElemTy, Ptr, ValIndices, GEPName);
-
- // If an offset is left we use byte-wise adjustment.
- if (IntOffset != 0) {
- Ptr = IRB.CreateGEP(IRB.getInt8Ty(), Ptr, IRB.getInt(IntOffset),
- GEPName + ".b" + Twine(IntOffset.getZExtValue()));
- }
- }
-
- LLVM_DEBUG(dbgs() << "Constructed pointer: " << *Ptr << "\n");
+ if (Offset)
+ Ptr = IRB.CreateGEP(IRB.getInt8Ty(), Ptr, IRB.getInt64(Offset),
+ Ptr->getName() + ".b" + Twine(Offset));
return Ptr;
}
@@ -7487,16 +7460,15 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
if (auto *PrivStructType = dyn_cast<StructType>(PrivType)) {
const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
- Value *Ptr = constructPointer(
- PrivType, &Base, PrivStructLayout->getElementOffset(u), IRB, DL);
+ Value *Ptr =
+ constructPointer(&Base, PrivStructLayout->getElementOffset(u), IRB);
new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
}
} else if (auto *PrivArrayType = dyn_cast<ArrayType>(PrivType)) {
Type *PointeeTy = PrivArrayType->getElementType();
uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
- Value *Ptr =
- constructPointer(PrivType, &Base, u * PointeeTySize, IRB, DL);
+ Value *Ptr = constructPointer(&Base, u * PointeeTySize, IRB);
new StoreInst(F.getArg(ArgNo + u), Ptr, &IP);
}
} else {
@@ -7521,8 +7493,8 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
const StructLayout *PrivStructLayout = DL.getStructLayout(PrivStructType);
for (unsigned u = 0, e = PrivStructType->getNumElements(); u < e; u++) {
Type *PointeeTy = PrivStructType->getElementType(u);
- Value *Ptr = constructPointer(
- PrivType, Base, PrivStructLayout->getElementOffset(u), IRB, DL);
+ Value *Ptr =
+ constructPointer(Base, PrivStructLayout->getElementOffset(u), IRB);
LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
L->setAlignment(Alignment);
ReplacementValues.push_back(L);
@@ -7531,8 +7503,7 @@ struct AAPrivatizablePtrArgument final : public AAPrivatizablePtrImpl {
Type *PointeeTy = PrivArrayType->getElementType();
uint64_t PointeeTySize = DL.getTypeStoreSize(PointeeTy);
for (unsigned u = 0, e = PrivArrayType->getNumElements(); u < e; u++) {
- Value *Ptr =
- constructPointer(PrivType, Base, u * PointeeTySize, IRB, DL);
+ Value *Ptr = constructPointer(Base, u * PointeeTySize, IRB);
LoadInst *L = new LoadInst(PointeeTy, Ptr, "", IP);
L->setAlignment(Alignment);
ReplacementValues.push_back(L);
diff --git a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
index b2665161c090..4176d561363f 100644
--- a/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
+++ b/llvm/lib/Transforms/IPO/OpenMPOpt.cpp
@@ -2053,6 +2053,9 @@ private:
LLVM_DEBUG(dbgs() << "[Attributor] Done with " << SCC.size()
<< " functions, result: " << Changed << ".\n");
+ if (Changed == ChangeStatus::CHANGED)
+ OMPInfoCache.invalidateAnalyses();
+
return Changed == ChangeStatus::CHANGED;
}
@@ -3763,7 +3766,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
ConstantInt *ExecModeC =
KernelInfo::getExecModeFromKernelEnvironment(KernelEnvC);
ConstantInt *AssumedExecModeC = ConstantInt::get(
- ExecModeC->getType(),
+ ExecModeC->getIntegerType(),
ExecModeC->getSExtValue() | OMP_TGT_EXEC_MODE_GENERIC_SPMD);
if (ExecModeC->getSExtValue() & OMP_TGT_EXEC_MODE_SPMD)
SPMDCompatibilityTracker.indicateOptimisticFixpoint();
@@ -3792,7 +3795,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
ConstantInt *MayUseNestedParallelismC =
KernelInfo::getMayUseNestedParallelismFromKernelEnvironment(KernelEnvC);
ConstantInt *AssumedMayUseNestedParallelismC = ConstantInt::get(
- MayUseNestedParallelismC->getType(), NestedParallelism);
+ MayUseNestedParallelismC->getIntegerType(), NestedParallelism);
setMayUseNestedParallelismOfKernelEnvironment(
AssumedMayUseNestedParallelismC);
@@ -3801,7 +3804,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
KernelInfo::getUseGenericStateMachineFromKernelEnvironment(
KernelEnvC);
ConstantInt *AssumedUseGenericStateMachineC =
- ConstantInt::get(UseGenericStateMachineC->getType(), false);
+ ConstantInt::get(UseGenericStateMachineC->getIntegerType(), false);
setUseGenericStateMachineOfKernelEnvironment(
AssumedUseGenericStateMachineC);
}
@@ -4280,8 +4283,9 @@ struct AAKernelInfoFunction : AAKernelInfo {
// kernel is executed in.
assert(ExecModeVal == OMP_TGT_EXEC_MODE_GENERIC &&
"Initially non-SPMD kernel has SPMD exec mode!");
- setExecModeOfKernelEnvironment(ConstantInt::get(
- ExecModeC->getType(), ExecModeVal | OMP_TGT_EXEC_MODE_GENERIC_SPMD));
+ setExecModeOfKernelEnvironment(
+ ConstantInt::get(ExecModeC->getIntegerType(),
+ ExecModeVal | OMP_TGT_EXEC_MODE_GENERIC_SPMD));
++NumOpenMPTargetRegionKernelsSPMD;
@@ -4332,7 +4336,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
// If not SPMD mode, indicate we use a custom state machine now.
setUseGenericStateMachineOfKernelEnvironment(
- ConstantInt::get(UseStateMachineC->getType(), false));
+ ConstantInt::get(UseStateMachineC->getIntegerType(), false));
// If we don't actually need a state machine we are done here. This can
// happen if there simply are no parallel regions. In the resulting kernel
@@ -4658,7 +4662,7 @@ struct AAKernelInfoFunction : AAKernelInfo {
KernelInfo::getMayUseNestedParallelismFromKernelEnvironment(
AA.KernelEnvC);
ConstantInt *NewMayUseNestedParallelismC = ConstantInt::get(
- MayUseNestedParallelismC->getType(), AA.NestedParallelism);
+ MayUseNestedParallelismC->getIntegerType(), AA.NestedParallelism);
AA.setMayUseNestedParallelismOfKernelEnvironment(
NewMayUseNestedParallelismC);
}
diff --git a/llvm/lib/Transforms/IPO/SampleProfile.cpp b/llvm/lib/Transforms/IPO/SampleProfile.cpp
index 6c6f0a0eca72..2fd8668d15e2 100644
--- a/llvm/lib/Transforms/IPO/SampleProfile.cpp
+++ b/llvm/lib/Transforms/IPO/SampleProfile.cpp
@@ -794,10 +794,9 @@ SampleProfileLoader::findIndirectCallFunctionSamples(
return R;
auto CallSite = FunctionSamples::getCallSiteIdentifier(DIL);
- auto T = FS->findCallTargetMapAt(CallSite);
Sum = 0;
- if (T)
- for (const auto &T_C : T.get())
+ if (auto T = FS->findCallTargetMapAt(CallSite))
+ for (const auto &T_C : *T)
Sum += T_C.second;
if (const FunctionSamplesMap *M = FS->findFunctionSamplesMapAt(CallSite)) {
if (M->empty())
@@ -1679,7 +1678,8 @@ void SampleProfileLoader::generateMDProfMetadata(Function &F) {
if (!FS)
continue;
auto CallSite = FunctionSamples::getCallSiteIdentifier(DIL);
- auto T = FS->findCallTargetMapAt(CallSite);
+ ErrorOr<SampleRecord::CallTargetMap> T =
+ FS->findCallTargetMapAt(CallSite);
if (!T || T.get().empty())
continue;
if (FunctionSamples::ProfileIsProbeBased) {
@@ -2261,9 +2261,8 @@ void SampleProfileMatcher::countProfileCallsiteMismatches(
// Compute number of samples in the original profile.
uint64_t CallsiteSamples = 0;
- auto CTM = FS.findCallTargetMapAt(Loc);
- if (CTM) {
- for (const auto &I : CTM.get())
+ if (auto CTM = FS.findCallTargetMapAt(Loc)) {
+ for (const auto &I : *CTM)
CallsiteSamples += I.second;
}
const auto *FSMap = FS.findFunctionSamplesMapAt(Loc);
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
index 5e362f4117d0..63b1e0f64a88 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp
@@ -3956,35 +3956,50 @@ Value *InstCombinerImpl::foldXorOfICmps(ICmpInst *LHS, ICmpInst *RHS,
const APInt *LC, *RC;
if (match(LHS1, m_APInt(LC)) && match(RHS1, m_APInt(RC)) &&
LHS0->getType() == RHS0->getType() &&
- LHS0->getType()->isIntOrIntVectorTy() &&
- (LHS->hasOneUse() || RHS->hasOneUse())) {
+ LHS0->getType()->isIntOrIntVectorTy()) {
// Convert xor of signbit tests to signbit test of xor'd values:
// (X > -1) ^ (Y > -1) --> (X ^ Y) < 0
// (X < 0) ^ (Y < 0) --> (X ^ Y) < 0
// (X > -1) ^ (Y < 0) --> (X ^ Y) > -1
// (X < 0) ^ (Y > -1) --> (X ^ Y) > -1
bool TrueIfSignedL, TrueIfSignedR;
- if (isSignBitCheck(PredL, *LC, TrueIfSignedL) &&
+ if ((LHS->hasOneUse() || RHS->hasOneUse()) &&
+ isSignBitCheck(PredL, *LC, TrueIfSignedL) &&
isSignBitCheck(PredR, *RC, TrueIfSignedR)) {
Value *XorLR = Builder.CreateXor(LHS0, RHS0);
return TrueIfSignedL == TrueIfSignedR ? Builder.CreateIsNeg(XorLR) :
Builder.CreateIsNotNeg(XorLR);
}
- // (X > C) ^ (X < C + 2) --> X != C + 1
- // (X < C + 2) ^ (X > C) --> X != C + 1
- // Considering the correctness of this pattern, we should avoid that C is
- // non-negative and C + 2 is negative, although it will be matched by other
- // patterns.
- const APInt *C1, *C2;
- if ((PredL == CmpInst::ICMP_SGT && match(LHS1, m_APInt(C1)) &&
- PredR == CmpInst::ICMP_SLT && match(RHS1, m_APInt(C2))) ||
- (PredL == CmpInst::ICMP_SLT && match(LHS1, m_APInt(C2)) &&
- PredR == CmpInst::ICMP_SGT && match(RHS1, m_APInt(C1))))
- if (LHS0 == RHS0 && *C1 + 2 == *C2 &&
- (C1->isNegative() || C2->isNonNegative()))
- return Builder.CreateICmpNE(LHS0,
- ConstantInt::get(LHS0->getType(), *C1 + 1));
+ // Fold (icmp pred1 X, C1) ^ (icmp pred2 X, C2)
+ // into a single comparison using range-based reasoning.
+ if (LHS0 == RHS0) {
+ ConstantRange CR1 = ConstantRange::makeExactICmpRegion(PredL, *LC);
+ ConstantRange CR2 = ConstantRange::makeExactICmpRegion(PredR, *RC);
+ auto CRUnion = CR1.exactUnionWith(CR2);
+ auto CRIntersect = CR1.exactIntersectWith(CR2);
+ if (CRUnion && CRIntersect)
+ if (auto CR = CRUnion->exactIntersectWith(CRIntersect->inverse())) {
+ if (CR->isFullSet())
+ return ConstantInt::getTrue(I.getType());
+ if (CR->isEmptySet())
+ return ConstantInt::getFalse(I.getType());
+
+ CmpInst::Predicate NewPred;
+ APInt NewC, Offset;
+ CR->getEquivalentICmp(NewPred, NewC, Offset);
+
+ if ((Offset.isZero() && (LHS->hasOneUse() || RHS->hasOneUse())) ||
+ (LHS->hasOneUse() && RHS->hasOneUse())) {
+ Value *NewV = LHS0;
+ Type *Ty = LHS0->getType();
+ if (!Offset.isZero())
+ NewV = Builder.CreateAdd(NewV, ConstantInt::get(Ty, Offset));
+ return Builder.CreateICmp(NewPred, NewV,
+ ConstantInt::get(Ty, NewC));
+ }
+ }
+ }
}
// Instead of trying to imitate the folds for and/or, decompose this 'xor'
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
index 1539fa9a3269..3b7fe7fa2266 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp
@@ -357,9 +357,9 @@ Instruction *InstCombinerImpl::simplifyMaskedStore(IntrinsicInst &II) {
// Use masked off lanes to simplify operands via SimplifyDemandedVectorElts
APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask);
- APInt UndefElts(DemandedElts.getBitWidth(), 0);
- if (Value *V =
- SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts, UndefElts))
+ APInt PoisonElts(DemandedElts.getBitWidth(), 0);
+ if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts,
+ PoisonElts))
return replaceOperand(II, 0, V);
return nullptr;
@@ -439,12 +439,12 @@ Instruction *InstCombinerImpl::simplifyMaskedScatter(IntrinsicInst &II) {
// Use masked off lanes to simplify operands via SimplifyDemandedVectorElts
APInt DemandedElts = possiblyDemandedEltsInMask(ConstMask);
- APInt UndefElts(DemandedElts.getBitWidth(), 0);
- if (Value *V =
- SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts, UndefElts))
+ APInt PoisonElts(DemandedElts.getBitWidth(), 0);
+ if (Value *V = SimplifyDemandedVectorElts(II.getOperand(0), DemandedElts,
+ PoisonElts))
return replaceOperand(II, 0, V);
- if (Value *V =
- SimplifyDemandedVectorElts(II.getOperand(1), DemandedElts, UndefElts))
+ if (Value *V = SimplifyDemandedVectorElts(II.getOperand(1), DemandedElts,
+ PoisonElts))
return replaceOperand(II, 1, V);
return nullptr;
@@ -1526,9 +1526,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
// support.
if (auto *IIFVTy = dyn_cast<FixedVectorType>(II->getType())) {
auto VWidth = IIFVTy->getNumElements();
- APInt UndefElts(VWidth, 0);
+ APInt PoisonElts(VWidth, 0);
APInt AllOnesEltMask(APInt::getAllOnes(VWidth));
- if (Value *V = SimplifyDemandedVectorElts(II, AllOnesEltMask, UndefElts)) {
+ if (Value *V = SimplifyDemandedVectorElts(II, AllOnesEltMask, PoisonElts)) {
if (V != II)
return replaceInstUsesWith(*II, V);
return II;
@@ -1539,6 +1539,9 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Instruction *I = foldCommutativeIntrinsicOverSelects(*II))
return I;
+ if (Instruction *I = foldCommutativeIntrinsicOverPhis(*II))
+ return I;
+
if (CallInst *NewCall = canonicalizeConstantArg0ToArg1(CI))
return NewCall;
}
@@ -1793,6 +1796,23 @@ Instruction *InstCombinerImpl::visitCallInst(CallInst &CI) {
if (Instruction *NewMinMax = factorizeMinMaxTree(II))
return NewMinMax;
+ // Try to fold minmax with constant RHS based on range information
+ const APInt *RHSC;
+ if (match(I1, m_APIntAllowUndef(RHSC))) {
+ ICmpInst::Predicate Pred =
+ ICmpInst::getNonStrictPredicate(MinMaxIntrinsic::getPredicate(IID));
+ bool IsSigned = MinMaxIntrinsic::isSigned(IID);
+ ConstantRange LHS_CR = computeConstantRangeIncludingKnownBits(
+ I0, IsSigned, SQ.getWithInstruction(II));
+ if (!LHS_CR.isFullSet()) {
+ if (LHS_CR.icmp(Pred, *RHSC))
+ return replaceInstUsesWith(*II, I0);
+ if (LHS_CR.icmp(ICmpInst::getSwappedPredicate(Pred), *RHSC))
+ return replaceInstUsesWith(*II,
+ ConstantInt::get(II->getType(), *RHSC));
+ }
+ }
+
break;
}
case Intrinsic::bitreverse: {
@@ -4237,3 +4257,22 @@ InstCombinerImpl::foldCommutativeIntrinsicOverSelects(IntrinsicInst &II) {
return nullptr;
}
+
+Instruction *
+InstCombinerImpl::foldCommutativeIntrinsicOverPhis(IntrinsicInst &II) {
+ assert(II.isCommutative() && "Instruction should be commutative");
+
+ PHINode *LHS = dyn_cast<PHINode>(II.getOperand(0));
+ PHINode *RHS = dyn_cast<PHINode>(II.getOperand(1));
+
+ if (!LHS || !RHS)
+ return nullptr;
+
+ if (auto P = matchSymmetricPhiNodesPair(LHS, RHS)) {
+ replaceOperand(II, 0, P->first);
+ replaceOperand(II, 1, P->second);
+ return &II;
+ }
+
+ return nullptr;
+}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
index 1d50fa9b6bf7..9e76a0cf17b1 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
+++ b/llvm/lib/Transforms/InstCombine/InstCombineInternal.h
@@ -278,6 +278,16 @@ private:
IntrinsicInst &Tramp);
Instruction *foldCommutativeIntrinsicOverSelects(IntrinsicInst &II);
+ // Match a pair of Phi Nodes like
+ // phi [a, BB0], [b, BB1] & phi [b, BB0], [a, BB1]
+ // Return the matched two operands.
+ std::optional<std::pair<Value *, Value *>>
+ matchSymmetricPhiNodesPair(PHINode *LHS, PHINode *RHS);
+
+ // Tries to fold (op phi(a, b) phi(b, a)) -> (op a, b)
+ // while op is a commutative intrinsic call.
+ Instruction *foldCommutativeIntrinsicOverPhis(IntrinsicInst &II);
+
Value *simplifyMaskedLoad(IntrinsicInst &II);
Instruction *simplifyMaskedStore(IntrinsicInst &II);
Instruction *simplifyMaskedGather(IntrinsicInst &II);
@@ -492,6 +502,11 @@ public:
/// X % (C0 * C1)
Value *SimplifyAddWithRemainder(BinaryOperator &I);
+ // Tries to fold (Binop phi(a, b) phi(b, a)) -> (Binop a, b)
+ // while Binop is commutative.
+ Value *SimplifyPhiCommutativeBinaryOp(BinaryOperator &I, Value *LHS,
+ Value *RHS);
+
// Binary Op helper for select operations where the expression can be
// efficiently reorganized.
Value *SimplifySelectsFeedingBinaryOp(BinaryOperator &I, Value *LHS,
@@ -550,7 +565,7 @@ public:
bool SimplifyDemandedInstructionBits(Instruction &Inst, KnownBits &Known);
Value *SimplifyDemandedVectorElts(Value *V, APInt DemandedElts,
- APInt &UndefElts, unsigned Depth = 0,
+ APInt &PoisonElts, unsigned Depth = 0,
bool AllowMultipleUsers = false) override;
/// Canonicalize the position of binops relative to shufflevector.
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
index e5566578869d..f0ea3d9fcad5 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineMulDivRem.cpp
@@ -350,6 +350,13 @@ Instruction *InstCombinerImpl::visitMul(BinaryOperator &I) {
if (match(&I, m_c_Mul(m_OneUse(m_Neg(m_Value(X))), m_Value(Y))))
return BinaryOperator::CreateNeg(Builder.CreateMul(X, Y));
+ // (-X * Y) * -X --> (X * Y) * X
+ // (-X << Y) * -X --> (X << Y) * X
+ if (match(Op1, m_Neg(m_Value(X)))) {
+ if (Value *NegOp0 = Negator::Negate(false, /*IsNSW*/ false, Op0, *this))
+ return BinaryOperator::CreateMul(NegOp0, X);
+ }
+
// (X / Y) * Y = X - (X % Y)
// (X / Y) * -Y = (X % Y) - X
{
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
index 2dda46986f0f..20bf00344b14 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSelect.cpp
@@ -2440,9 +2440,9 @@ Instruction *InstCombinerImpl::foldVectorSelect(SelectInst &Sel) {
return nullptr;
unsigned NumElts = VecTy->getNumElements();
- APInt UndefElts(NumElts, 0);
+ APInt PoisonElts(NumElts, 0);
APInt AllOnesEltMask(APInt::getAllOnes(NumElts));
- if (Value *V = SimplifyDemandedVectorElts(&Sel, AllOnesEltMask, UndefElts)) {
+ if (Value *V = SimplifyDemandedVectorElts(&Sel, AllOnesEltMask, PoisonElts)) {
if (V != &Sel)
return replaceInstUsesWith(Sel, V);
return &Sel;
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
index 846116a929b1..a8a5f9831e15 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp
@@ -1319,8 +1319,8 @@ Value *InstCombinerImpl::simplifyShrShlDemandedBits(
}
/// The specified value produces a vector with any number of elements.
-/// This method analyzes which elements of the operand are undef or poison and
-/// returns that information in UndefElts.
+/// This method analyzes which elements of the operand are poison and
+/// returns that information in PoisonElts.
///
/// DemandedElts contains the set of elements that are actually used by the
/// caller, and by default (AllowMultipleUsers equals false) the value is
@@ -1333,7 +1333,7 @@ Value *InstCombinerImpl::simplifyShrShlDemandedBits(
/// returned. This returns null if no change was made.
Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
APInt DemandedElts,
- APInt &UndefElts,
+ APInt &PoisonElts,
unsigned Depth,
bool AllowMultipleUsers) {
// Cannot analyze scalable type. The number of vector elements is not a
@@ -1345,18 +1345,18 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
APInt EltMask(APInt::getAllOnes(VWidth));
assert((DemandedElts & ~EltMask) == 0 && "Invalid DemandedElts!");
- if (match(V, m_Undef())) {
- // If the entire vector is undef or poison, just return this info.
- UndefElts = EltMask;
+ if (match(V, m_Poison())) {
+ // If the entire vector is poison, just return this info.
+ PoisonElts = EltMask;
return nullptr;
}
if (DemandedElts.isZero()) { // If nothing is demanded, provide poison.
- UndefElts = EltMask;
+ PoisonElts = EltMask;
return PoisonValue::get(V->getType());
}
- UndefElts = 0;
+ PoisonElts = 0;
if (auto *C = dyn_cast<Constant>(V)) {
// Check if this is identity. If so, return 0 since we are not simplifying
@@ -1370,7 +1370,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
for (unsigned i = 0; i != VWidth; ++i) {
if (!DemandedElts[i]) { // If not demanded, set to poison.
Elts.push_back(Poison);
- UndefElts.setBit(i);
+ PoisonElts.setBit(i);
continue;
}
@@ -1378,8 +1378,8 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
if (!Elt) return nullptr;
Elts.push_back(Elt);
- if (isa<UndefValue>(Elt)) // Already undef or poison.
- UndefElts.setBit(i);
+ if (isa<PoisonValue>(Elt)) // Already poison.
+ PoisonElts.setBit(i);
}
// If we changed the constant, return it.
@@ -1400,7 +1400,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
// They'll be handled when it's their turn to be visited by
// the main instcombine process.
if (Depth != 0)
- // TODO: Just compute the UndefElts information recursively.
+ // TODO: Just compute the PoisonElts information recursively.
return nullptr;
// Conservatively assume that all elements are needed.
@@ -1422,8 +1422,8 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
}
};
- APInt UndefElts2(VWidth, 0);
- APInt UndefElts3(VWidth, 0);
+ APInt PoisonElts2(VWidth, 0);
+ APInt PoisonElts3(VWidth, 0);
switch (I->getOpcode()) {
default: break;
@@ -1449,17 +1449,17 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
if (i == 0 ? match(I->getOperand(i), m_Undef())
: match(I->getOperand(i), m_Poison())) {
// If the entire vector is undefined, just return this info.
- UndefElts = EltMask;
+ PoisonElts = EltMask;
return nullptr;
}
if (I->getOperand(i)->getType()->isVectorTy()) {
- APInt UndefEltsOp(VWidth, 0);
- simplifyAndSetOp(I, i, DemandedElts, UndefEltsOp);
+ APInt PoisonEltsOp(VWidth, 0);
+ simplifyAndSetOp(I, i, DemandedElts, PoisonEltsOp);
// gep(x, undef) is not undef, so skip considering idx ops here
// Note that we could propagate poison, but we can't distinguish between
// undef & poison bits ATM
if (i == 0)
- UndefElts |= UndefEltsOp;
+ PoisonElts |= PoisonEltsOp;
}
}
@@ -1472,7 +1472,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
if (!Idx) {
// Note that we can't propagate undef elt info, because we don't know
// which elt is getting updated.
- simplifyAndSetOp(I, 0, DemandedElts, UndefElts2);
+ simplifyAndSetOp(I, 0, DemandedElts, PoisonElts2);
break;
}
@@ -1487,7 +1487,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
// was extracted from the same index in another vector with the same type,
// replace this insert with that other vector.
// Note: This is attempted before the call to simplifyAndSetOp because that
- // may change UndefElts to a value that does not match with Vec.
+ // may change PoisonElts to a value that does not match with Vec.
Value *Vec;
if (PreInsertDemandedElts == 0 &&
match(I->getOperand(1),
@@ -1496,7 +1496,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
return Vec;
}
- simplifyAndSetOp(I, 0, PreInsertDemandedElts, UndefElts);
+ simplifyAndSetOp(I, 0, PreInsertDemandedElts, PoisonElts);
// If this is inserting an element that isn't demanded, remove this
// insertelement.
@@ -1506,7 +1506,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
}
// The inserted element is defined.
- UndefElts.clearBit(IdxNo);
+ PoisonElts.clearBit(IdxNo);
break;
}
case Instruction::ShuffleVector: {
@@ -1520,17 +1520,17 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
// operand.
if (all_of(Shuffle->getShuffleMask(), [](int Elt) { return Elt == 0; }) &&
DemandedElts.isAllOnes()) {
- if (!match(I->getOperand(1), m_Undef())) {
+ if (!isa<PoisonValue>(I->getOperand(1))) {
I->setOperand(1, PoisonValue::get(I->getOperand(1)->getType()));
MadeChange = true;
}
APInt LeftDemanded(OpWidth, 1);
- APInt LHSUndefElts(OpWidth, 0);
- simplifyAndSetOp(I, 0, LeftDemanded, LHSUndefElts);
- if (LHSUndefElts[0])
- UndefElts = EltMask;
+ APInt LHSPoisonElts(OpWidth, 0);
+ simplifyAndSetOp(I, 0, LeftDemanded, LHSPoisonElts);
+ if (LHSPoisonElts[0])
+ PoisonElts = EltMask;
else
- UndefElts.clearAllBits();
+ PoisonElts.clearAllBits();
break;
}
@@ -1549,11 +1549,11 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
}
}
- APInt LHSUndefElts(OpWidth, 0);
- simplifyAndSetOp(I, 0, LeftDemanded, LHSUndefElts);
+ APInt LHSPoisonElts(OpWidth, 0);
+ simplifyAndSetOp(I, 0, LeftDemanded, LHSPoisonElts);
- APInt RHSUndefElts(OpWidth, 0);
- simplifyAndSetOp(I, 1, RightDemanded, RHSUndefElts);
+ APInt RHSPoisonElts(OpWidth, 0);
+ simplifyAndSetOp(I, 1, RightDemanded, RHSPoisonElts);
// If this shuffle does not change the vector length and the elements
// demanded by this shuffle are an identity mask, then this shuffle is
@@ -1579,7 +1579,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
return Shuffle->getOperand(0);
}
- bool NewUndefElts = false;
+ bool NewPoisonElts = false;
unsigned LHSIdx = -1u, LHSValIdx = -1u;
unsigned RHSIdx = -1u, RHSValIdx = -1u;
bool LHSUniform = true;
@@ -1587,23 +1587,23 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
for (unsigned i = 0; i < VWidth; i++) {
unsigned MaskVal = Shuffle->getMaskValue(i);
if (MaskVal == -1u) {
- UndefElts.setBit(i);
+ PoisonElts.setBit(i);
} else if (!DemandedElts[i]) {
- NewUndefElts = true;
- UndefElts.setBit(i);
+ NewPoisonElts = true;
+ PoisonElts.setBit(i);
} else if (MaskVal < OpWidth) {
- if (LHSUndefElts[MaskVal]) {
- NewUndefElts = true;
- UndefElts.setBit(i);
+ if (LHSPoisonElts[MaskVal]) {
+ NewPoisonElts = true;
+ PoisonElts.setBit(i);
} else {
LHSIdx = LHSIdx == -1u ? i : OpWidth;
LHSValIdx = LHSValIdx == -1u ? MaskVal : OpWidth;
LHSUniform = LHSUniform && (MaskVal == i);
}
} else {
- if (RHSUndefElts[MaskVal - OpWidth]) {
- NewUndefElts = true;
- UndefElts.setBit(i);
+ if (RHSPoisonElts[MaskVal - OpWidth]) {
+ NewPoisonElts = true;
+ PoisonElts.setBit(i);
} else {
RHSIdx = RHSIdx == -1u ? i : OpWidth;
RHSValIdx = RHSValIdx == -1u ? MaskVal - OpWidth : OpWidth;
@@ -1646,11 +1646,11 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
return New;
}
}
- if (NewUndefElts) {
+ if (NewPoisonElts) {
// Add additional discovered undefs.
SmallVector<int, 16> Elts;
for (unsigned i = 0; i < VWidth; ++i) {
- if (UndefElts[i])
+ if (PoisonElts[i])
Elts.push_back(PoisonMaskElem);
else
Elts.push_back(Shuffle->getMaskValue(i));
@@ -1665,12 +1665,12 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
// on the current demanded elements.
SelectInst *Sel = cast<SelectInst>(I);
if (Sel->getCondition()->getType()->isVectorTy()) {
- // TODO: We are not doing anything with UndefElts based on this call.
+ // TODO: We are not doing anything with PoisonElts based on this call.
// It is overwritten below based on the other select operands. If an
// element of the select condition is known undef, then we are free to
// choose the output value from either arm of the select. If we know that
// one of those values is undef, then the output can be undef.
- simplifyAndSetOp(I, 0, DemandedElts, UndefElts);
+ simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
}
// Next, see if we can transform the arms of the select.
@@ -1692,12 +1692,12 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
}
}
- simplifyAndSetOp(I, 1, DemandedLHS, UndefElts2);
- simplifyAndSetOp(I, 2, DemandedRHS, UndefElts3);
+ simplifyAndSetOp(I, 1, DemandedLHS, PoisonElts2);
+ simplifyAndSetOp(I, 2, DemandedRHS, PoisonElts3);
// Output elements are undefined if the element from each arm is undefined.
// TODO: This can be improved. See comment in select condition handling.
- UndefElts = UndefElts2 & UndefElts3;
+ PoisonElts = PoisonElts2 & PoisonElts3;
break;
}
case Instruction::BitCast: {
@@ -1706,7 +1706,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
if (!VTy) break;
unsigned InVWidth = cast<FixedVectorType>(VTy)->getNumElements();
APInt InputDemandedElts(InVWidth, 0);
- UndefElts2 = APInt(InVWidth, 0);
+ PoisonElts2 = APInt(InVWidth, 0);
unsigned Ratio;
if (VWidth == InVWidth) {
@@ -1735,25 +1735,25 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
break;
}
- simplifyAndSetOp(I, 0, InputDemandedElts, UndefElts2);
+ simplifyAndSetOp(I, 0, InputDemandedElts, PoisonElts2);
if (VWidth == InVWidth) {
- UndefElts = UndefElts2;
+ PoisonElts = PoisonElts2;
} else if ((VWidth % InVWidth) == 0) {
// If the number of elements in the output is a multiple of the number of
// elements in the input then an output element is undef if the
// corresponding input element is undef.
for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx)
- if (UndefElts2[OutIdx / Ratio])
- UndefElts.setBit(OutIdx);
+ if (PoisonElts2[OutIdx / Ratio])
+ PoisonElts.setBit(OutIdx);
} else if ((InVWidth % VWidth) == 0) {
// If the number of elements in the input is a multiple of the number of
// elements in the output then an output element is undef if all of the
// corresponding input elements are undef.
for (unsigned OutIdx = 0; OutIdx != VWidth; ++OutIdx) {
- APInt SubUndef = UndefElts2.lshr(OutIdx * Ratio).zextOrTrunc(Ratio);
+ APInt SubUndef = PoisonElts2.lshr(OutIdx * Ratio).zextOrTrunc(Ratio);
if (SubUndef.popcount() == Ratio)
- UndefElts.setBit(OutIdx);
+ PoisonElts.setBit(OutIdx);
}
} else {
llvm_unreachable("Unimp");
@@ -1762,7 +1762,7 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
}
case Instruction::FPTrunc:
case Instruction::FPExt:
- simplifyAndSetOp(I, 0, DemandedElts, UndefElts);
+ simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
break;
case Instruction::Call: {
@@ -1785,18 +1785,18 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
DemandedPassThrough.clearBit(i);
}
if (II->getIntrinsicID() == Intrinsic::masked_gather)
- simplifyAndSetOp(II, 0, DemandedPtrs, UndefElts2);
- simplifyAndSetOp(II, 3, DemandedPassThrough, UndefElts3);
+ simplifyAndSetOp(II, 0, DemandedPtrs, PoisonElts2);
+ simplifyAndSetOp(II, 3, DemandedPassThrough, PoisonElts3);
// Output elements are undefined if the element from both sources are.
// TODO: can strengthen via mask as well.
- UndefElts = UndefElts2 & UndefElts3;
+ PoisonElts = PoisonElts2 & PoisonElts3;
break;
}
default: {
// Handle target specific intrinsics
std::optional<Value *> V = targetSimplifyDemandedVectorEltsIntrinsic(
- *II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
+ *II, DemandedElts, PoisonElts, PoisonElts2, PoisonElts3,
simplifyAndSetOp);
if (V)
return *V;
@@ -1859,18 +1859,18 @@ Value *InstCombinerImpl::SimplifyDemandedVectorElts(Value *V,
return ShufBO;
}
- simplifyAndSetOp(I, 0, DemandedElts, UndefElts);
- simplifyAndSetOp(I, 1, DemandedElts, UndefElts2);
+ simplifyAndSetOp(I, 0, DemandedElts, PoisonElts);
+ simplifyAndSetOp(I, 1, DemandedElts, PoisonElts2);
// Output elements are undefined if both are undefined. Consider things
// like undef & 0. The result is known zero, not undef.
- UndefElts &= UndefElts2;
+ PoisonElts &= PoisonElts2;
}
- // If we've proven all of the lanes undef, return an undef value.
+ // If we've proven all of the lanes poison, return a poison value.
// TODO: Intersect w/demanded lanes
- if (UndefElts.isAllOnes())
- return UndefValue::get(I->getType());
+ if (PoisonElts.isAllOnes())
+ return PoisonValue::get(I->getType());
return MadeChange ? I : nullptr;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
index c8b58c51d4e6..18ab510aae7f 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineVectorOps.cpp
@@ -388,7 +388,7 @@ static APInt findDemandedEltsByAllUsers(Value *V) {
/// arbitrarily pick 64 bit as our canonical type. The actual bitwidth doesn't
/// matter, we just want a consistent type to simplify CSE.
static ConstantInt *getPreferredVectorIndex(ConstantInt *IndexC) {
- const unsigned IndexBW = IndexC->getType()->getBitWidth();
+ const unsigned IndexBW = IndexC->getBitWidth();
if (IndexBW == 64 || IndexC->getValue().getActiveBits() > 64)
return nullptr;
return ConstantInt::get(IndexC->getContext(),
@@ -581,20 +581,20 @@ Instruction *InstCombinerImpl::visitExtractElementInst(ExtractElementInst &EI) {
// If the input vector has a single use, simplify it based on this use
// property.
if (SrcVec->hasOneUse()) {
- APInt UndefElts(NumElts, 0);
+ APInt PoisonElts(NumElts, 0);
APInt DemandedElts(NumElts, 0);
DemandedElts.setBit(IndexC->getZExtValue());
if (Value *V =
- SimplifyDemandedVectorElts(SrcVec, DemandedElts, UndefElts))
+ SimplifyDemandedVectorElts(SrcVec, DemandedElts, PoisonElts))
return replaceOperand(EI, 0, V);
} else {
// If the input vector has multiple uses, simplify it based on a union
// of all elements used.
APInt DemandedElts = findDemandedEltsByAllUsers(SrcVec);
if (!DemandedElts.isAllOnes()) {
- APInt UndefElts(NumElts, 0);
+ APInt PoisonElts(NumElts, 0);
if (Value *V = SimplifyDemandedVectorElts(
- SrcVec, DemandedElts, UndefElts, 0 /* Depth */,
+ SrcVec, DemandedElts, PoisonElts, 0 /* Depth */,
true /* AllowMultipleUsers */)) {
if (V != SrcVec) {
Worklist.addValue(SrcVec);
@@ -777,10 +777,10 @@ static ShuffleOps collectShuffleElements(Value *V, SmallVectorImpl<int> &Mask,
assert(V->getType()->isVectorTy() && "Invalid shuffle!");
unsigned NumElts = cast<FixedVectorType>(V->getType())->getNumElements();
- if (match(V, m_Undef())) {
+ if (match(V, m_Poison())) {
Mask.assign(NumElts, -1);
return std::make_pair(
- PermittedRHS ? UndefValue::get(PermittedRHS->getType()) : V, nullptr);
+ PermittedRHS ? PoisonValue::get(PermittedRHS->getType()) : V, nullptr);
}
if (isa<ConstantAggregateZero>(V)) {
@@ -1633,7 +1633,8 @@ Instruction *InstCombinerImpl::visitInsertElementInst(InsertElementInst &IE) {
// bitcast (inselt undef, ScalarSrc, IdxOp)
Type *ScalarTy = ScalarSrc->getType();
Type *VecTy = VectorType::get(ScalarTy, IE.getType()->getElementCount());
- UndefValue *NewUndef = UndefValue::get(VecTy);
+ Constant *NewUndef = isa<PoisonValue>(VecOp) ? PoisonValue::get(VecTy)
+ : UndefValue::get(VecTy);
Value *NewInsElt = Builder.CreateInsertElement(NewUndef, ScalarSrc, IdxOp);
return new BitCastInst(NewInsElt, IE.getType());
}
@@ -1713,9 +1714,10 @@ Instruction *InstCombinerImpl::visitInsertElementInst(InsertElementInst &IE) {
if (auto VecTy = dyn_cast<FixedVectorType>(VecOp->getType())) {
unsigned VWidth = VecTy->getNumElements();
- APInt UndefElts(VWidth, 0);
+ APInt PoisonElts(VWidth, 0);
APInt AllOnesEltMask(APInt::getAllOnes(VWidth));
- if (Value *V = SimplifyDemandedVectorElts(&IE, AllOnesEltMask, UndefElts)) {
+ if (Value *V = SimplifyDemandedVectorElts(&IE, AllOnesEltMask,
+ PoisonElts)) {
if (V != &IE)
return replaceInstUsesWith(IE, V);
return &IE;
@@ -1918,6 +1920,10 @@ static Value *evaluateInDifferentElementOrder(Value *V, ArrayRef<int> Mask,
assert(V->getType()->isVectorTy() && "can't reorder non-vector elements");
Type *EltTy = V->getType()->getScalarType();
+
+ if (isa<PoisonValue>(V))
+ return PoisonValue::get(FixedVectorType::get(EltTy, Mask.size()));
+
if (match(V, m_Undef()))
return UndefValue::get(FixedVectorType::get(EltTy, Mask.size()));
@@ -2639,7 +2645,7 @@ static Instruction *foldShuffleWithInsert(ShuffleVectorInst &Shuf,
assert(NewInsIndex != -1 && "Did not fold shuffle with unused operand?");
// Index is updated to the potentially translated insertion lane.
- IndexC = ConstantInt::get(IndexC->getType(), NewInsIndex);
+ IndexC = ConstantInt::get(IndexC->getIntegerType(), NewInsIndex);
return true;
};
@@ -2769,6 +2775,11 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
if (Instruction *I = simplifyBinOpSplats(SVI))
return I;
+ // Canonicalize splat shuffle to use poison RHS. Handle this explicitly in
+ // order to support scalable vectors.
+ if (match(SVI.getShuffleMask(), m_ZeroMask()) && !isa<PoisonValue>(RHS))
+ return replaceOperand(SVI, 1, PoisonValue::get(RHS->getType()));
+
if (isa<ScalableVectorType>(LHS->getType()))
return nullptr;
@@ -2855,9 +2866,9 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
if (Instruction *I = foldCastShuffle(SVI, Builder))
return I;
- APInt UndefElts(VWidth, 0);
+ APInt PoisonElts(VWidth, 0);
APInt AllOnesEltMask(APInt::getAllOnes(VWidth));
- if (Value *V = SimplifyDemandedVectorElts(&SVI, AllOnesEltMask, UndefElts)) {
+ if (Value *V = SimplifyDemandedVectorElts(&SVI, AllOnesEltMask, PoisonElts)) {
if (V != &SVI)
return replaceInstUsesWith(SVI, V);
return &SVI;
@@ -3012,10 +3023,11 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
ShuffleVectorInst* LHSShuffle = dyn_cast<ShuffleVectorInst>(LHS);
ShuffleVectorInst* RHSShuffle = dyn_cast<ShuffleVectorInst>(RHS);
if (LHSShuffle)
- if (!match(LHSShuffle->getOperand(1), m_Undef()) && !match(RHS, m_Undef()))
+ if (!match(LHSShuffle->getOperand(1), m_Poison()) &&
+ !match(RHS, m_Poison()))
LHSShuffle = nullptr;
if (RHSShuffle)
- if (!match(RHSShuffle->getOperand(1), m_Undef()))
+ if (!match(RHSShuffle->getOperand(1), m_Poison()))
RHSShuffle = nullptr;
if (!LHSShuffle && !RHSShuffle)
return MadeChange ? &SVI : nullptr;
@@ -3038,7 +3050,7 @@ Instruction *InstCombinerImpl::visitShuffleVectorInst(ShuffleVectorInst &SVI) {
Value* newRHS = RHS;
if (LHSShuffle) {
// case 1
- if (match(RHS, m_Undef())) {
+ if (match(RHS, m_Poison())) {
newLHS = LHSOp0;
newRHS = LHSOp1;
}
diff --git a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
index a7ddadc25de4..7f5a7b666903 100644
--- a/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstructionCombining.cpp
@@ -173,14 +173,14 @@ std::optional<Value *> InstCombiner::targetSimplifyDemandedUseBitsIntrinsic(
}
std::optional<Value *> InstCombiner::targetSimplifyDemandedVectorEltsIntrinsic(
- IntrinsicInst &II, APInt DemandedElts, APInt &UndefElts, APInt &UndefElts2,
- APInt &UndefElts3,
+ IntrinsicInst &II, APInt DemandedElts, APInt &PoisonElts,
+ APInt &PoisonElts2, APInt &PoisonElts3,
std::function<void(Instruction *, unsigned, APInt, APInt &)>
SimplifyAndSetOp) {
// Handle target specific intrinsics
if (II.getCalledFunction()->isTargetIntrinsic()) {
return TTI.simplifyDemandedVectorEltsIntrinsic(
- *this, II, DemandedElts, UndefElts, UndefElts2, UndefElts3,
+ *this, II, DemandedElts, PoisonElts, PoisonElts2, PoisonElts3,
SimplifyAndSetOp);
}
return std::nullopt;
@@ -1096,6 +1096,54 @@ Value *InstCombinerImpl::foldUsingDistributiveLaws(BinaryOperator &I) {
return SimplifySelectsFeedingBinaryOp(I, LHS, RHS);
}
+std::optional<std::pair<Value *, Value *>>
+InstCombinerImpl::matchSymmetricPhiNodesPair(PHINode *LHS, PHINode *RHS) {
+ if (LHS->getParent() != RHS->getParent())
+ return std::nullopt;
+
+ if (LHS->getNumIncomingValues() < 2)
+ return std::nullopt;
+
+ if (!equal(LHS->blocks(), RHS->blocks()))
+ return std::nullopt;
+
+ Value *L0 = LHS->getIncomingValue(0);
+ Value *R0 = RHS->getIncomingValue(0);
+
+ for (unsigned I = 1, E = LHS->getNumIncomingValues(); I != E; ++I) {
+ Value *L1 = LHS->getIncomingValue(I);
+ Value *R1 = RHS->getIncomingValue(I);
+
+ if ((L0 == L1 && R0 == R1) || (L0 == R1 && R0 == L1))
+ continue;
+
+ return std::nullopt;
+ }
+
+ return std::optional(std::pair(L0, R0));
+}
+
+Value *InstCombinerImpl::SimplifyPhiCommutativeBinaryOp(BinaryOperator &I,
+ Value *Op0,
+ Value *Op1) {
+ assert(I.isCommutative() && "Instruction should be commutative");
+
+ PHINode *LHS = dyn_cast<PHINode>(Op0);
+ PHINode *RHS = dyn_cast<PHINode>(Op1);
+
+ if (!LHS || !RHS)
+ return nullptr;
+
+ if (auto P = matchSymmetricPhiNodesPair(LHS, RHS)) {
+ Value *BI = Builder.CreateBinOp(I.getOpcode(), P->first, P->second);
+ if (auto *BO = dyn_cast<BinaryOperator>(BI))
+ BO->copyIRFlags(&I);
+ return BI;
+ }
+
+ return nullptr;
+}
+
Value *InstCombinerImpl::SimplifySelectsFeedingBinaryOp(BinaryOperator &I,
Value *LHS,
Value *RHS) {
@@ -1529,6 +1577,11 @@ Instruction *InstCombinerImpl::foldBinopWithPhiOperands(BinaryOperator &BO) {
BO.getParent() != Phi1->getParent())
return nullptr;
+ if (BO.isCommutative()) {
+ if (Value *V = SimplifyPhiCommutativeBinaryOp(BO, Phi0, Phi1))
+ return replaceInstUsesWith(BO, V);
+ }
+
// Fold if there is at least one specific constant value in phi0 or phi1's
// incoming values that comes from the same block and this specific constant
// value can be used to do optimization for specific binary operator.
@@ -1728,8 +1781,8 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
// If both arguments of the binary operation are shuffles that use the same
// mask and shuffle within a single vector, move the shuffle after the binop.
- if (match(LHS, m_Shuffle(m_Value(V1), m_Undef(), m_Mask(Mask))) &&
- match(RHS, m_Shuffle(m_Value(V2), m_Undef(), m_SpecificMask(Mask))) &&
+ if (match(LHS, m_Shuffle(m_Value(V1), m_Poison(), m_Mask(Mask))) &&
+ match(RHS, m_Shuffle(m_Value(V2), m_Poison(), m_SpecificMask(Mask))) &&
V1->getType() == V2->getType() &&
(LHS->hasOneUse() || RHS->hasOneUse() || LHS == RHS)) {
// Op(shuffle(V1, Mask), shuffle(V2, Mask)) -> shuffle(Op(V1, V2), Mask)
@@ -1770,9 +1823,9 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
Constant *C;
auto *InstVTy = dyn_cast<FixedVectorType>(Inst.getType());
if (InstVTy &&
- match(&Inst,
- m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Undef(), m_Mask(Mask))),
- m_ImmConstant(C))) &&
+ match(&Inst, m_c_BinOp(m_OneUse(m_Shuffle(m_Value(V1), m_Poison(),
+ m_Mask(Mask))),
+ m_ImmConstant(C))) &&
cast<FixedVectorType>(V1->getType())->getNumElements() <=
InstVTy->getNumElements()) {
assert(InstVTy->getScalarType() == V1->getType()->getScalarType() &&
@@ -1787,8 +1840,8 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
ArrayRef<int> ShMask = Mask;
unsigned SrcVecNumElts =
cast<FixedVectorType>(V1->getType())->getNumElements();
- UndefValue *UndefScalar = UndefValue::get(C->getType()->getScalarType());
- SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, UndefScalar);
+ PoisonValue *PoisonScalar = PoisonValue::get(C->getType()->getScalarType());
+ SmallVector<Constant *, 16> NewVecC(SrcVecNumElts, PoisonScalar);
bool MayChange = true;
unsigned NumElts = InstVTy->getNumElements();
for (unsigned I = 0; I < NumElts; ++I) {
@@ -1801,29 +1854,29 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
// 2. The shuffle needs an element of the constant vector that can't
// be mapped to a new constant vector.
// 3. This is a widening shuffle that copies elements of V1 into the
- // extended elements (extending with undef is allowed).
- if (!CElt || (!isa<UndefValue>(NewCElt) && NewCElt != CElt) ||
+ // extended elements (extending with poison is allowed).
+ if (!CElt || (!isa<PoisonValue>(NewCElt) && NewCElt != CElt) ||
I >= SrcVecNumElts) {
MayChange = false;
break;
}
NewVecC[ShMask[I]] = CElt;
}
- // If this is a widening shuffle, we must be able to extend with undef
- // elements. If the original binop does not produce an undef in the high
+ // If this is a widening shuffle, we must be able to extend with poison
+ // elements. If the original binop does not produce a poison in the high
// lanes, then this transform is not safe.
- // Similarly for undef lanes due to the shuffle mask, we can only
- // transform binops that preserve undef.
- // TODO: We could shuffle those non-undef constant values into the
- // result by using a constant vector (rather than an undef vector)
+ // Similarly for poison lanes due to the shuffle mask, we can only
+ // transform binops that preserve poison.
+ // TODO: We could shuffle those non-poison constant values into the
+ // result by using a constant vector (rather than an poison vector)
// as operand 1 of the new binop, but that might be too aggressive
// for target-independent shuffle creation.
if (I >= SrcVecNumElts || ShMask[I] < 0) {
- Constant *MaybeUndef =
+ Constant *MaybePoison =
ConstOp1
- ? ConstantFoldBinaryOpOperands(Opcode, UndefScalar, CElt, DL)
- : ConstantFoldBinaryOpOperands(Opcode, CElt, UndefScalar, DL);
- if (!MaybeUndef || !match(MaybeUndef, m_Undef())) {
+ ? ConstantFoldBinaryOpOperands(Opcode, PoisonScalar, CElt, DL)
+ : ConstantFoldBinaryOpOperands(Opcode, CElt, PoisonScalar, DL);
+ if (!MaybePoison || !isa<PoisonValue>(MaybePoison)) {
MayChange = false;
break;
}
@@ -1831,9 +1884,10 @@ Instruction *InstCombinerImpl::foldVectorBinop(BinaryOperator &Inst) {
}
if (MayChange) {
Constant *NewC = ConstantVector::get(NewVecC);
- // It may not be safe to execute a binop on a vector with undef elements
+ // It may not be safe to execute a binop on a vector with poison elements
// because the entire instruction can be folded to undef or create poison
// that did not exist in the original code.
+ // TODO: The shift case should not be necessary.
if (Inst.isIntDivRem() || (Inst.isShift() && ConstOp1))
NewC = getSafeVectorConstantForBinop(Opcode, NewC, ConstOp1);
@@ -2241,10 +2295,10 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
// compile-time.
if (auto *GEPFVTy = dyn_cast<FixedVectorType>(GEPType)) {
auto VWidth = GEPFVTy->getNumElements();
- APInt UndefElts(VWidth, 0);
+ APInt PoisonElts(VWidth, 0);
APInt AllOnesEltMask(APInt::getAllOnes(VWidth));
if (Value *V = SimplifyDemandedVectorElts(&GEP, AllOnesEltMask,
- UndefElts)) {
+ PoisonElts)) {
if (V != &GEP)
return replaceInstUsesWith(GEP, V);
return &GEP;
@@ -2462,7 +2516,7 @@ Instruction *InstCombinerImpl::visitGetElementPtrInst(GetElementPtrInst &GEP) {
Idx2);
}
ConstantInt *C;
- if (match(GEP.getOperand(1), m_OneUse(m_SExt(m_OneUse(m_NSWAdd(
+ if (match(GEP.getOperand(1), m_OneUse(m_SExtLike(m_OneUse(m_NSWAdd(
m_Value(Idx1), m_ConstantInt(C))))))) {
// %add = add nsw i32 %idx1, idx2
// %sidx = sext i32 %add to i64
diff --git a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
index 6468d07b4f4f..afb0e6cd1548 100644
--- a/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
+++ b/llvm/lib/Transforms/Instrumentation/AddressSanitizer.cpp
@@ -2737,7 +2737,7 @@ bool AddressSanitizer::maybeInsertAsanInitAtFunctionEntry(Function &F) {
// the shadow memory.
// We cannot just ignore these methods, because they may call other
// instrumented functions.
- if (F.getName().find(" load]") != std::string::npos) {
+ if (F.getName().contains(" load]")) {
FunctionCallee AsanInitFunction =
declareSanitizerInitFunction(*F.getParent(), kAsanInitName, {});
IRBuilder<> IRB(&F.front(), F.front().begin());
diff --git a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
index 539b7441d24b..2236e9cd44c5 100644
--- a/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
+++ b/llvm/lib/Transforms/Instrumentation/MemProfiler.cpp
@@ -535,7 +535,7 @@ bool MemProfiler::maybeInsertMemProfInitAtFunctionEntry(Function &F) {
// the shadow memory.
// We cannot just ignore these methods, because they may call other
// instrumented functions.
- if (F.getName().find(" load]") != std::string::npos) {
+ if (F.getName().contains(" load]")) {
FunctionCallee MemProfInitFunction =
declareSanitizerInitFunction(*F.getParent(), MemProfInitName, {});
IRBuilder<> IRB(&F.front(), F.front().begin());
diff --git a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
index fe672a4377a1..ce570bdfd8b8 100644
--- a/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
+++ b/llvm/lib/Transforms/Instrumentation/SanitizerCoverage.cpp
@@ -603,7 +603,7 @@ void ModuleSanitizerCoverage::instrumentFunction(
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
if (F.empty())
return;
- if (F.getName().find(".module_ctor") != std::string::npos)
+ if (F.getName().contains(".module_ctor"))
return; // Should not instrument sanitizer init functions.
if (F.getName().starts_with("__sanitizer_"))
return; // Don't instrument __sanitizer_* callbacks.
diff --git a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
index 1fb9d7fff32f..9e40d94dd73c 100644
--- a/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstantHoisting.cpp
@@ -674,8 +674,7 @@ void ConstantHoistingPass::findBaseConstants(GlobalVariable *BaseGV) {
llvm::stable_sort(ConstCandVec, [](const ConstantCandidate &LHS,
const ConstantCandidate &RHS) {
if (LHS.ConstInt->getType() != RHS.ConstInt->getType())
- return LHS.ConstInt->getType()->getBitWidth() <
- RHS.ConstInt->getType()->getBitWidth();
+ return LHS.ConstInt->getBitWidth() < RHS.ConstInt->getBitWidth();
return LHS.ConstInt->getValue().ult(RHS.ConstInt->getValue());
});
@@ -890,7 +889,7 @@ bool ConstantHoistingPass::emitBaseConstants(GlobalVariable *BaseGV) {
Type *Ty = ConstInfo.BaseExpr->getType();
Base = new BitCastInst(ConstInfo.BaseExpr, Ty, "const", IP);
} else {
- IntegerType *Ty = ConstInfo.BaseInt->getType();
+ IntegerType *Ty = ConstInfo.BaseInt->getIntegerType();
Base = new BitCastInst(ConstInfo.BaseInt, Ty, "const", IP);
}
diff --git a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
index 18266ba07898..899d7e0a11e6 100644
--- a/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
+++ b/llvm/lib/Transforms/Scalar/ConstraintElimination.cpp
@@ -273,7 +273,16 @@ class ConstraintInfo {
public:
ConstraintInfo(const DataLayout &DL, ArrayRef<Value *> FunctionArgs)
- : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {}
+ : UnsignedCS(FunctionArgs), SignedCS(FunctionArgs), DL(DL) {
+ auto &Value2Index = getValue2Index(false);
+ // Add Arg > -1 constraints to unsigned system for all function arguments.
+ for (Value *Arg : FunctionArgs) {
+ ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0),
+ false, false, false);
+ VarPos.Coefficients[Value2Index[Arg]] = -1;
+ UnsignedCS.addVariableRow(VarPos.Coefficients);
+ }
+ }
DenseMap<Value *, unsigned> &getValue2Index(bool Signed) {
return Signed ? SignedCS.getValue2Index() : UnsignedCS.getValue2Index();
@@ -1365,18 +1374,34 @@ removeEntryFromStack(const StackEntry &E, ConstraintInfo &Info,
ReproducerCondStack.pop_back();
}
-/// Check if the first condition for an AND implies the second.
-static bool checkAndSecondOpImpliedByFirst(
+/// Check if either the first condition of an AND or OR is implied by the
+/// (negated in case of OR) second condition or vice versa.
+static bool checkOrAndOpImpliedByOther(
FactOrCheck &CB, ConstraintInfo &Info, Module *ReproducerModule,
SmallVectorImpl<ReproducerEntry> &ReproducerCondStack,
SmallVectorImpl<StackEntry> &DFSInStack) {
CmpInst::Predicate Pred;
Value *A, *B;
- Instruction *And = CB.getContextInst();
- if (!match(And->getOperand(0), m_ICmp(Pred, m_Value(A), m_Value(B))))
+ Instruction *JoinOp = CB.getContextInst();
+ CmpInst *CmpToCheck = cast<CmpInst>(CB.getInstructionToSimplify());
+ unsigned OtherOpIdx = JoinOp->getOperand(0) == CmpToCheck ? 1 : 0;
+
+ // Don't try to simplify the first condition of a select by the second, as
+ // this may make the select more poisonous than the original one.
+ // TODO: check if the first operand may be poison.
+ if (OtherOpIdx != 0 && isa<SelectInst>(JoinOp))
return false;
+ if (!match(JoinOp->getOperand(OtherOpIdx),
+ m_ICmp(Pred, m_Value(A), m_Value(B))))
+ return false;
+
+ // For OR, check if the negated condition implies CmpToCheck.
+ bool IsOr = match(JoinOp, m_LogicalOr());
+ if (IsOr)
+ Pred = CmpInst::getInversePredicate(Pred);
+
// Optimistically add fact from first condition.
unsigned OldSize = DFSInStack.size();
Info.addFact(Pred, A, B, CB.NumIn, CB.NumOut, DFSInStack);
@@ -1385,11 +1410,19 @@ static bool checkAndSecondOpImpliedByFirst(
bool Changed = false;
// Check if the second condition can be simplified now.
- 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));
+ if (auto ImpliedCondition =
+ checkCondition(CmpToCheck->getPredicate(), CmpToCheck->getOperand(0),
+ CmpToCheck->getOperand(1), CmpToCheck, Info, CB.NumIn,
+ CB.NumOut, CB.getContextInst())) {
+ if (IsOr && isa<SelectInst>(JoinOp)) {
+ JoinOp->setOperand(
+ OtherOpIdx == 0 ? 2 : 0,
+ ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
+ } else
+ JoinOp->setOperand(
+ 1 - OtherOpIdx,
+ ConstantInt::getBool(JoinOp->getType(), *ImpliedCondition));
+
Changed = true;
}
@@ -1442,6 +1475,17 @@ void ConstraintInfo::addFact(CmpInst::Predicate Pred, Value *A, Value *B,
DFSInStack.emplace_back(NumIn, NumOut, R.IsSigned,
std::move(ValuesToRelease));
+ if (!R.IsSigned) {
+ for (Value *V : NewVariables) {
+ ConstraintTy VarPos(SmallVector<int64_t, 8>(Value2Index.size() + 1, 0),
+ false, false, false);
+ VarPos.Coefficients[Value2Index[V]] = -1;
+ CSToUse.addVariableRow(VarPos.Coefficients);
+ DFSInStack.emplace_back(NumIn, NumOut, R.IsSigned,
+ SmallVector<Value *, 2>());
+ }
+ }
+
if (R.isEq()) {
// Also add the inverted constraint for equality constraints.
for (auto &Coeff : R.Coefficients)
@@ -1609,11 +1653,11 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
bool Simplified = checkAndReplaceCondition(
Cmp, Info, CB.NumIn, CB.NumOut, CB.getContextInst(),
ReproducerModule.get(), ReproducerCondStack, S.DT, ToRemove);
- if (!Simplified && match(CB.getContextInst(),
- m_LogicalAnd(m_Value(), m_Specific(Inst)))) {
+ if (!Simplified &&
+ match(CB.getContextInst(), m_LogicalOp(m_Value(), m_Value()))) {
Simplified =
- checkAndSecondOpImpliedByFirst(CB, Info, ReproducerModule.get(),
- ReproducerCondStack, DFSInStack);
+ checkOrAndOpImpliedByOther(CB, Info, ReproducerModule.get(),
+ ReproducerCondStack, DFSInStack);
}
Changed |= Simplified;
}
@@ -1687,7 +1731,8 @@ static bool eliminateConstraints(Function &F, DominatorTree &DT, LoopInfo &LI,
#ifndef NDEBUG
unsigned SignedEntries =
count_if(DFSInStack, [](const StackEntry &E) { return E.IsSigned; });
- assert(Info.getCS(false).size() == DFSInStack.size() - SignedEntries &&
+ assert(Info.getCS(false).size() - FunctionArgs.size() ==
+ DFSInStack.size() - SignedEntries &&
"updates to CS and DFSInStack are out of sync");
assert(Info.getCS(true).size() == SignedEntries &&
"updates to CS and DFSInStack are out of sync");
diff --git a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
index d2dfc764d042..c44d3748a80d 100644
--- a/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
+++ b/llvm/lib/Transforms/Scalar/CorrelatedValuePropagation.cpp
@@ -935,11 +935,13 @@ static bool processSDiv(BinaryOperator *SDI, const ConstantRange &LCR,
UDiv->setDebugLoc(SDI->getDebugLoc());
UDiv->setIsExact(SDI->isExact());
- Value *Res = UDiv;
+ auto *Res = UDiv;
// If the operands had two different domains, we need to negate the result.
- if (Ops[0].D != Ops[1].D)
+ if (Ops[0].D != Ops[1].D) {
Res = BinaryOperator::CreateNeg(Res, Res->getName() + ".neg", SDI);
+ Res->setDebugLoc(SDI->getDebugLoc());
+ }
SDI->replaceAllUsesWith(Res);
SDI->eraseFromParent();
diff --git a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
index edfeb36f3422..c5bf913cda30 100644
--- a/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
+++ b/llvm/lib/Transforms/Scalar/DFAJumpThreading.cpp
@@ -521,7 +521,7 @@ struct AllSwitchPaths {
const BasicBlock *PrevBB = Path.back();
for (const BasicBlock *BB : Path) {
- if (StateDef.count(BB) != 0) {
+ if (StateDef.contains(BB)) {
const PHINode *Phi = dyn_cast<PHINode>(StateDef[BB]);
assert(Phi && "Expected a state-defining instr to be a phi node.");
diff --git a/llvm/lib/Transforms/Scalar/GVN.cpp b/llvm/lib/Transforms/Scalar/GVN.cpp
index 5e58af0edc15..e36578f3de7a 100644
--- a/llvm/lib/Transforms/Scalar/GVN.cpp
+++ b/llvm/lib/Transforms/Scalar/GVN.cpp
@@ -592,7 +592,7 @@ uint32_t GVNPass::ValueTable::lookupOrAddCall(CallInst *C) {
/// Returns true if a value number exists for the specified value.
bool GVNPass::ValueTable::exists(Value *V) const {
- return valueNumbering.count(V) != 0;
+ return valueNumbering.contains(V);
}
/// lookup_or_add - Returns the value number for the specified value, assigning
diff --git a/llvm/lib/Transforms/Scalar/LoopFlatten.cpp b/llvm/lib/Transforms/Scalar/LoopFlatten.cpp
index b1add3c42976..eef94636578d 100644
--- a/llvm/lib/Transforms/Scalar/LoopFlatten.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopFlatten.cpp
@@ -343,9 +343,8 @@ static bool verifyTripCount(Value *RHS, Loop *L,
// If the RHS of the compare is equal to the backedge taken count we need
// to add one to get the trip count.
if (SCEVRHS == BackedgeTCExt || SCEVRHS == BackedgeTakenCount) {
- ConstantInt *One = ConstantInt::get(ConstantRHS->getType(), 1);
- Value *NewRHS = ConstantInt::get(
- ConstantRHS->getContext(), ConstantRHS->getValue() + One->getValue());
+ Value *NewRHS = ConstantInt::get(ConstantRHS->getContext(),
+ ConstantRHS->getValue() + 1);
return setLoopComponents(NewRHS, TripCount, Increment,
IterationInstructions);
}
diff --git a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
index 39607464dd00..a58bbe318563 100644
--- a/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopStrengthReduce.cpp
@@ -7006,7 +7006,7 @@ static bool ReduceLoopStrength(Loop *L, IVUsers &IU, ScalarEvolution &SE,
LLVM_DEBUG(dbgs() << "Old term-cond:\n"
<< *OldTermCond << "\n"
- << "New term-cond:\b" << *NewTermCond << "\n");
+ << "New term-cond:\n" << *NewTermCond << "\n");
BI->setCondition(NewTermCond);
diff --git a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
index f14541a1a037..7cfeb019af97 100644
--- a/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
+++ b/llvm/lib/Transforms/Scalar/LoopUnrollPass.cpp
@@ -200,6 +200,7 @@ TargetTransformInfo::UnrollingPreferences llvm::gatherUnrollingPreferences(
UP.Count = 0;
UP.DefaultUnrollRuntimeCount = 8;
UP.MaxCount = std::numeric_limits<unsigned>::max();
+ UP.MaxUpperBound = UnrollMaxUpperBound;
UP.FullUnrollMaxCount = std::numeric_limits<unsigned>::max();
UP.BEInsns = 2;
UP.Partial = false;
@@ -237,6 +238,8 @@ TargetTransformInfo::UnrollingPreferences llvm::gatherUnrollingPreferences(
UP.MaxPercentThresholdBoost = UnrollMaxPercentThresholdBoost;
if (UnrollMaxCount.getNumOccurrences() > 0)
UP.MaxCount = UnrollMaxCount;
+ if (UnrollMaxUpperBound.getNumOccurrences() > 0)
+ UP.MaxUpperBound = UnrollMaxUpperBound;
if (UnrollFullMaxCount.getNumOccurrences() > 0)
UP.FullUnrollMaxCount = UnrollFullMaxCount;
if (UnrollAllowPartial.getNumOccurrences() > 0)
@@ -777,7 +780,7 @@ shouldPragmaUnroll(Loop *L, const PragmaInfo &PInfo,
return TripCount;
if (PInfo.PragmaEnableUnroll && !TripCount && MaxTripCount &&
- MaxTripCount <= UnrollMaxUpperBound)
+ MaxTripCount <= UP.MaxUpperBound)
return MaxTripCount;
// if didn't return until here, should continue to other priorties
@@ -952,7 +955,7 @@ bool llvm::computeUnrollCount(
// cost of exact full unrolling. As such, if we have an exact count and
// found it unprofitable, we'll never chose to bounded unroll.
if (!TripCount && MaxTripCount && (UP.UpperBound || MaxOrZero) &&
- MaxTripCount <= UnrollMaxUpperBound) {
+ MaxTripCount <= UP.MaxUpperBound) {
UP.Count = MaxTripCount;
if (auto UnrollFactor = shouldFullUnroll(L, TTI, DT, SE, EphValues,
MaxTripCount, UCE, UP)) {
@@ -1026,7 +1029,7 @@ bool llvm::computeUnrollCount(
}
// Don't unroll a small upper bound loop unless user or TTI asked to do so.
- if (MaxTripCount && !UP.Force && MaxTripCount < UnrollMaxUpperBound) {
+ if (MaxTripCount && !UP.Force && MaxTripCount < UP.MaxUpperBound) {
UP.Count = 0;
return false;
}
diff --git a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
index 40b4ea92e1ff..3f02441b74ba 100644
--- a/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
+++ b/llvm/lib/Transforms/Scalar/RewriteStatepointsForGC.cpp
@@ -2057,7 +2057,7 @@ static void relocationViaAlloca(
for (const auto &Info : Records)
for (auto RematerializedValuePair : Info.RematerializedValues) {
Value *OriginalValue = RematerializedValuePair.second;
- if (AllocaMap.count(OriginalValue) != 0)
+ if (AllocaMap.contains(OriginalValue))
continue;
emitAllocaFor(OriginalValue);
diff --git a/llvm/lib/Transforms/Scalar/SROA.cpp b/llvm/lib/Transforms/Scalar/SROA.cpp
index 24da26c9f0f2..656abdb0abbf 100644
--- a/llvm/lib/Transforms/Scalar/SROA.cpp
+++ b/llvm/lib/Transforms/Scalar/SROA.cpp
@@ -3285,6 +3285,7 @@ private:
(BeginOffset > NewAllocaBeginOffset || EndOffset < NewAllocaEndOffset ||
SliceSize !=
DL.getTypeStoreSize(NewAI.getAllocatedType()).getFixedValue() ||
+ !DL.typeSizeEqualsStoreSize(NewAI.getAllocatedType()) ||
!NewAI.getAllocatedType()->isSingleValueType());
// If we're just going to emit a memcpy, the alloca hasn't changed, and the
diff --git a/llvm/lib/Transforms/Utils/DXILUpgrade.cpp b/llvm/lib/Transforms/Utils/DXILUpgrade.cpp
index 735686ddce38..09991f628224 100644
--- a/llvm/lib/Transforms/Utils/DXILUpgrade.cpp
+++ b/llvm/lib/Transforms/Utils/DXILUpgrade.cpp
@@ -7,14 +7,26 @@
//===----------------------------------------------------------------------===//
#include "llvm/Transforms/Utils/DXILUpgrade.h"
+#include "llvm/IR/Constants.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+#include "llvm/Support/Debug.h"
using namespace llvm;
+#define DEBUG_TYPE "dxil-upgrade"
+
static bool handleValVerMetadata(Module &M) {
NamedMDNode *ValVer = M.getNamedMetadata("dx.valver");
if (!ValVer)
return false;
+ LLVM_DEBUG({
+ MDNode *N = ValVer->getOperand(0);
+ auto X = mdconst::extract<ConstantInt>(N->getOperand(0))->getZExtValue();
+ auto Y = mdconst::extract<ConstantInt>(N->getOperand(1))->getZExtValue();
+ dbgs() << "DXIL: validation version: " << X << "." << Y << "\n";
+ });
// We don't need the validation version internally, so we drop it.
ValVer->dropAllReferences();
ValVer->eraseFromParent();
diff --git a/llvm/lib/Transforms/Utils/FunctionComparator.cpp b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
index 79ca99d1566c..09e19be0d293 100644
--- a/llvm/lib/Transforms/Utils/FunctionComparator.cpp
+++ b/llvm/lib/Transforms/Utils/FunctionComparator.cpp
@@ -405,6 +405,8 @@ int FunctionComparator::cmpConstants(const Constant *L,
case Value::ConstantExprVal: {
const ConstantExpr *LE = cast<ConstantExpr>(L);
const ConstantExpr *RE = cast<ConstantExpr>(R);
+ if (int Res = cmpNumbers(LE->getOpcode(), RE->getOpcode()))
+ return Res;
unsigned NumOperandsL = LE->getNumOperands();
unsigned NumOperandsR = RE->getNumOperands();
if (int Res = cmpNumbers(NumOperandsL, NumOperandsR))
@@ -414,6 +416,29 @@ int FunctionComparator::cmpConstants(const Constant *L,
cast<Constant>(RE->getOperand(i))))
return Res;
}
+ if (LE->isCompare())
+ if (int Res = cmpNumbers(LE->getPredicate(), RE->getPredicate()))
+ return Res;
+ if (auto *GEPL = dyn_cast<GEPOperator>(LE)) {
+ auto *GEPR = cast<GEPOperator>(RE);
+ if (int Res = cmpTypes(GEPL->getSourceElementType(),
+ GEPR->getSourceElementType()))
+ return Res;
+ if (int Res = cmpNumbers(GEPL->isInBounds(), GEPR->isInBounds()))
+ return Res;
+ if (int Res = cmpNumbers(GEPL->getInRangeIndex().value_or(unsigned(-1)),
+ GEPR->getInRangeIndex().value_or(unsigned(-1))))
+ return Res;
+ }
+ if (auto *OBOL = dyn_cast<OverflowingBinaryOperator>(LE)) {
+ auto *OBOR = cast<OverflowingBinaryOperator>(RE);
+ if (int Res =
+ cmpNumbers(OBOL->hasNoUnsignedWrap(), OBOR->hasNoUnsignedWrap()))
+ return Res;
+ if (int Res =
+ cmpNumbers(OBOL->hasNoSignedWrap(), OBOR->hasNoSignedWrap()))
+ return Res;
+ }
return 0;
}
case Value::BlockAddressVal: {
diff --git a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
index 1e42d7491676..f94047633022 100644
--- a/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
+++ b/llvm/lib/Transforms/Utils/MemoryTaggingSupport.cpp
@@ -64,7 +64,7 @@ bool forAllReachableExits(const DominatorTree &DT, const PostDominatorTree &PDT,
// sure that the return is covered. Otherwise, we can check whether there
// is a way to reach the RI from the start of the lifetime without passing
// through an end.
- if (EndBlocks.count(RI->getParent()) > 0 ||
+ if (EndBlocks.contains(RI->getParent()) ||
!isPotentiallyReachable(Start, RI, &EndBlocks, &DT, &LI)) {
++NumCoveredExits;
}
diff --git a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
index 89494a7f6497..55e375670cc6 100644
--- a/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyCFG.cpp
@@ -6293,7 +6293,7 @@ Value *SwitchLookupTable::BuildLookup(Value *Index, IRBuilder<> &Builder) {
}
case BitMapKind: {
// Type of the bitmap (e.g. i59).
- IntegerType *MapTy = BitMap->getType();
+ IntegerType *MapTy = BitMap->getIntegerType();
// Cast Index to the same type as the bitmap.
// Note: The Index is <= the number of elements in the table, so
@@ -6668,7 +6668,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
Value *TableIndex;
ConstantInt *TableIndexOffset;
if (UseSwitchConditionAsTableIndex) {
- TableIndexOffset = ConstantInt::get(MaxCaseVal->getType(), 0);
+ TableIndexOffset = ConstantInt::get(MaxCaseVal->getIntegerType(), 0);
TableIndex = SI->getCondition();
} else {
TableIndexOffset = MinCaseVal;
@@ -6752,7 +6752,7 @@ static bool SwitchToLookupTable(SwitchInst *SI, IRBuilder<> &Builder,
// Get the TableIndex'th bit of the bitmask.
// If this bit is 0 (meaning hole) jump to the default destination,
// else continue with table lookup.
- IntegerType *MapTy = TableMask->getType();
+ IntegerType *MapTy = TableMask->getIntegerType();
Value *MaskIndex =
Builder.CreateZExtOrTrunc(TableIndex, MapTy, "switch.maskindex");
Value *Shifted = Builder.CreateLShr(TableMask, MaskIndex, "switch.shifted");
@@ -6975,7 +6975,7 @@ static bool simplifySwitchOfPowersOfTwo(SwitchInst *SI, IRBuilder<> &Builder,
// Replace each case with its trailing zeros number.
for (auto &Case : SI->cases()) {
auto *OrigValue = Case.getCaseValue();
- Case.setValue(ConstantInt::get(OrigValue->getType(),
+ Case.setValue(ConstantInt::get(OrigValue->getIntegerType(),
OrigValue->getValue().countr_zero()));
}
diff --git a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
index 722ed03db3de..42e7c4006b42 100644
--- a/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
+++ b/llvm/lib/Transforms/Utils/SimplifyIndVar.cpp
@@ -27,6 +27,7 @@
#include "llvm/Transforms/Utils/ScalarEvolutionExpander.h"
using namespace llvm;
+using namespace llvm::PatternMatch;
#define DEBUG_TYPE "indvars"
@@ -786,8 +787,6 @@ bool SimplifyIndvar::strengthenOverflowingOperation(BinaryOperator *BO,
/// otherwise.
bool SimplifyIndvar::strengthenRightShift(BinaryOperator *BO,
Instruction *IVOperand) {
- using namespace llvm::PatternMatch;
-
if (BO->getOpcode() == Instruction::Shl) {
bool Changed = false;
ConstantRange IVRange = SE->getUnsignedRange(SE->getSCEV(IVOperand));
@@ -1763,7 +1762,7 @@ Instruction *WidenIV::widenIVUse(WidenIV::NarrowIVDefUse DU, SCEVExpander &Rewri
};
// Our raison d'etre! Eliminate sign and zero extension.
- if ((isa<SExtInst>(DU.NarrowUse) && canWidenBySExt()) ||
+ if ((match(DU.NarrowUse, m_SExtLike(m_Value())) && canWidenBySExt()) ||
(isa<ZExtInst>(DU.NarrowUse) && canWidenByZExt())) {
Value *NewDef = DU.WideDef;
if (DU.NarrowUse->getType() != WideType) {
@@ -2011,8 +2010,6 @@ PHINode *WidenIV::createWideIV(SCEVExpander &Rewriter) {
/// by looking at dominating conditions inside of the loop
void WidenIV::calculatePostIncRange(Instruction *NarrowDef,
Instruction *NarrowUser) {
- using namespace llvm::PatternMatch;
-
Value *NarrowDefLHS;
const APInt *NarrowDefRHS;
if (!match(NarrowDef, m_NSWAdd(m_Value(NarrowDefLHS),
diff --git a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
index 9d799124074c..32913b3f5569 100644
--- a/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
+++ b/llvm/lib/Transforms/Vectorize/SLPVectorizer.cpp
@@ -3760,40 +3760,7 @@ BoUpSLP::findReusedOrderedScalars(const BoUpSLP::TreeEntry &TE) {
OrdersType CurrentOrder(NumScalars, NumScalars);
SmallVector<int> Positions;
SmallBitVector UsedPositions(NumScalars);
- DenseMap<const TreeEntry *, unsigned> UsedEntries;
- DenseMap<Value *, std::pair<const TreeEntry *, unsigned>> ValueToEntryPos;
- for (Value *V : TE.Scalars) {
- if (!isa<LoadInst, ExtractElementInst, ExtractValueInst>(V))
- continue;
- const auto *LocalSTE = getTreeEntry(V);
- if (!LocalSTE)
- continue;
- unsigned Lane =
- std::distance(LocalSTE->Scalars.begin(), find(LocalSTE->Scalars, V));
- if (Lane >= NumScalars)
- continue;
- ++UsedEntries.try_emplace(LocalSTE, 0).first->getSecond();
- ValueToEntryPos.try_emplace(V, LocalSTE, Lane);
- }
- if (UsedEntries.empty())
- return std::nullopt;
- const TreeEntry &BestSTE =
- *std::max_element(UsedEntries.begin(), UsedEntries.end(),
- [](const std::pair<const TreeEntry *, unsigned> &P1,
- const std::pair<const TreeEntry *, unsigned> &P2) {
- return P1.second < P2.second;
- })
- ->first;
- UsedEntries.erase(&BestSTE);
- const TreeEntry *SecondBestSTE = nullptr;
- if (!UsedEntries.empty())
- SecondBestSTE =
- std::max_element(UsedEntries.begin(), UsedEntries.end(),
- [](const std::pair<const TreeEntry *, unsigned> &P1,
- const std::pair<const TreeEntry *, unsigned> &P2) {
- return P1.second < P2.second;
- })
- ->first;
+ const TreeEntry *STE = nullptr;
// Try to find all gathered scalars that are gets vectorized in other
// vectorize node. Here we can have only one single tree vector node to
// correctly identify order of the gathered scalars.
@@ -3801,46 +3768,53 @@ BoUpSLP::findReusedOrderedScalars(const BoUpSLP::TreeEntry &TE) {
Value *V = TE.Scalars[I];
if (!isa<LoadInst, ExtractElementInst, ExtractValueInst>(V))
continue;
- const auto [LocalSTE, Lane] = ValueToEntryPos.lookup(V);
- if (!LocalSTE || (LocalSTE != &BestSTE && LocalSTE != SecondBestSTE))
- continue;
- if (CurrentOrder[Lane] != NumScalars) {
- if ((CurrentOrder[Lane] >= BestSTE.Scalars.size() ||
- BestSTE.Scalars[CurrentOrder[Lane]] == V) &&
- (Lane != I || LocalSTE == SecondBestSTE))
- continue;
- UsedPositions.reset(CurrentOrder[Lane]);
+ if (const auto *LocalSTE = getTreeEntry(V)) {
+ if (!STE)
+ STE = LocalSTE;
+ else if (STE != LocalSTE)
+ // Take the order only from the single vector node.
+ return std::nullopt;
+ unsigned Lane =
+ std::distance(STE->Scalars.begin(), find(STE->Scalars, V));
+ if (Lane >= NumScalars)
+ return std::nullopt;
+ if (CurrentOrder[Lane] != NumScalars) {
+ if (Lane != I)
+ continue;
+ UsedPositions.reset(CurrentOrder[Lane]);
+ }
+ // The partial identity (where only some elements of the gather node are
+ // in the identity order) is good.
+ CurrentOrder[Lane] = I;
+ UsedPositions.set(I);
}
- // The partial identity (where only some elements of the gather node are
- // in the identity order) is good.
- CurrentOrder[Lane] = I;
- UsedPositions.set(I);
}
// Need to keep the order if we have a vector entry and at least 2 scalars or
// the vectorized entry has just 2 scalars.
- if (BestSTE.Scalars.size() != 2 && UsedPositions.count() <= 1)
- return std::nullopt;
- auto IsIdentityOrder = [&](ArrayRef<unsigned> CurrentOrder) {
- for (unsigned I = 0; I < NumScalars; ++I)
- if (CurrentOrder[I] != I && CurrentOrder[I] != NumScalars)
- return false;
- return true;
- };
- if (IsIdentityOrder(CurrentOrder))
- return OrdersType();
- auto *It = CurrentOrder.begin();
- for (unsigned I = 0; I < NumScalars;) {
- if (UsedPositions.test(I)) {
- ++I;
- continue;
- }
- if (*It == NumScalars) {
- *It = I;
- ++I;
+ if (STE && (UsedPositions.count() > 1 || STE->Scalars.size() == 2)) {
+ auto &&IsIdentityOrder = [NumScalars](ArrayRef<unsigned> CurrentOrder) {
+ for (unsigned I = 0; I < NumScalars; ++I)
+ if (CurrentOrder[I] != I && CurrentOrder[I] != NumScalars)
+ return false;
+ return true;
+ };
+ if (IsIdentityOrder(CurrentOrder))
+ return OrdersType();
+ auto *It = CurrentOrder.begin();
+ for (unsigned I = 0; I < NumScalars;) {
+ if (UsedPositions.test(I)) {
+ ++I;
+ continue;
+ }
+ if (*It == NumScalars) {
+ *It = I;
+ ++I;
+ }
+ ++It;
}
- ++It;
+ return std::move(CurrentOrder);
}
- return std::move(CurrentOrder);
+ return std::nullopt;
}
namespace {
@@ -6469,7 +6443,7 @@ bool BoUpSLP::areAllUsersVectorized(
Instruction *I, const SmallDenseSet<Value *> *VectorizedVals) const {
return (I->hasOneUse() && (!VectorizedVals || VectorizedVals->contains(I))) ||
all_of(I->users(), [this](User *U) {
- return ScalarToTreeEntry.count(U) > 0 ||
+ return ScalarToTreeEntry.contains(U) ||
isVectorLikeInstWithConstOps(U) ||
(isa<ExtractElementInst>(U) && MustGather.contains(U));
});
@@ -11498,7 +11472,7 @@ Value *BoUpSLP::vectorizeTree(TreeEntry *E, bool PostponedPHIs) {
Value *V = Builder.CreateBinOp(
static_cast<Instruction::BinaryOps>(E->getOpcode()), LHS,
RHS);
- propagateIRFlags(V, E->Scalars, VL0);
+ propagateIRFlags(V, E->Scalars, VL0, !MinBWs.contains(E));
if (auto *I = dyn_cast<Instruction>(V))
V = propagateMetadata(I, E->Scalars);
@@ -15730,6 +15704,8 @@ static bool compareCmp(Value *V, Value *V2, TargetLibraryInfo &TLI,
assert(isValidElementType(V->getType()) &&
isValidElementType(V2->getType()) &&
"Expected valid element types only.");
+ if (V == V2)
+ return IsCompatibility;
auto *CI1 = cast<CmpInst>(V);
auto *CI2 = cast<CmpInst>(V2);
if (CI1->getOperand(0)->getType()->getTypeID() <
@@ -15754,6 +15730,8 @@ static bool compareCmp(Value *V, Value *V2, TargetLibraryInfo &TLI,
for (int I = 0, E = CI1->getNumOperands(); I < E; ++I) {
auto *Op1 = CI1->getOperand(CI1Preds ? I : E - I - 1);
auto *Op2 = CI2->getOperand(CI2Preds ? I : E - I - 1);
+ if (Op1 == Op2)
+ continue;
if (Op1->getValueID() < Op2->getValueID())
return !IsCompatibility;
if (Op1->getValueID() > Op2->getValueID())
@@ -15780,7 +15758,10 @@ static bool compareCmp(Value *V, Value *V2, TargetLibraryInfo &TLI,
InstructionsState S = getSameOpcode({I1, I2}, TLI);
if (S.getOpcode() && (IsCompatibility || !S.isAltShuffle()))
continue;
- return !IsCompatibility && I1->getOpcode() < I2->getOpcode();
+ if (IsCompatibility)
+ return false;
+ if (I1->getOpcode() != I2->getOpcode())
+ return I1->getOpcode() < I2->getOpcode();
}
}
return IsCompatibility;