Index: llvm/lib/Analysis/ValueTracking.cpp =================================================================== --- llvm/lib/Analysis/ValueTracking.cpp +++ llvm/lib/Analysis/ValueTracking.cpp @@ -2018,13 +2018,27 @@ return true; if (match(V, m_Power2())) return true; - if (Q.CxtI && - (match(V, m_VScale()) || match(V, m_Shl(m_VScale(), m_Value())))) { + if (Q.CxtI && match(V, m_VScale())) { const Function *F = Q.CxtI->getFunction(); // The vscale_range indicates vscale is a power-of-two. return F->hasFnAttribute(Attribute::VScaleRange); } + const APInt *Shift; + if (Q.CxtI && match(V, m_Shl(m_VScale(), m_APInt(Shift)))) { + const Function *F = Q.CxtI->getFunction(); + // The vscale_range indicates vscale is a power-of-two. + if (F->hasFnAttribute(Attribute::VScaleRange)) { + Attribute Attr = F->getFnAttribute(Attribute::VScaleRange); + if (std::optional MaxVScale = Attr.getVScaleRangeMax()) { + unsigned Bitwidth = V->getType()->getScalarSizeInBits(); + // Make sure the value don't get shifted out + if (Log2_32(*MaxVScale) + Shift->getZExtValue() < Bitwidth) + return true; + } + } + } + // 1 << X is clearly a power of two if the one is not shifted off the end. If // it is shifted off the end then the result is undefined. if (match(V, m_Shl(m_One(), m_Value())))