@@ -11827,6 +11827,53 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1182711827
1182811828 return Success(APValue(ResultElements.data(), ResultElements.size()), E);
1182911829 }
11830+ case Builtin::BI__builtin_elementwise_ctlz:
11831+ case Builtin::BI__builtin_elementwise_cttz: {
11832+ APValue SourceLHS;
11833+ std::optional<APValue> Fallback;
11834+ if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS))
11835+ return false;
11836+ if (E->getNumArgs() > 1) {
11837+ APValue FallbackTmp;
11838+ if (!EvaluateAsRValue(Info, E->getArg(1), FallbackTmp))
11839+ return false;
11840+ Fallback = FallbackTmp;
11841+ }
11842+
11843+ QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
11844+ unsigned SourceLen = SourceLHS.getVectorLength();
11845+ SmallVector<APValue, 4> ResultElements;
11846+ ResultElements.reserve(SourceLen);
11847+
11848+ for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11849+ APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt();
11850+ if (!LHS) {
11851+ // Without a fallback, a zero element is undefined
11852+ if (!Fallback) {
11853+ Info.FFDiag(E, diag::note_constexpr_countzeroes_zero)
11854+ << /*IsTrailing=*/(E->getBuiltinCallee() ==
11855+ Builtin::BI__builtin_elementwise_cttz);
11856+ return false;
11857+ }
11858+ ResultElements.push_back(Fallback->getVectorElt(EltNum));
11859+ continue;
11860+ }
11861+ switch (E->getBuiltinCallee()) {
11862+ case Builtin::BI__builtin_elementwise_ctlz:
11863+ ResultElements.push_back(APValue(
11864+ APSInt(APInt(Info.Ctx.getIntWidth(DestEltTy), LHS.countl_zero()),
11865+ DestEltTy->isUnsignedIntegerOrEnumerationType())));
11866+ break;
11867+ case Builtin::BI__builtin_elementwise_cttz:
11868+ ResultElements.push_back(APValue(
11869+ APSInt(APInt(Info.Ctx.getIntWidth(DestEltTy), LHS.countr_zero()),
11870+ DestEltTy->isUnsignedIntegerOrEnumerationType())));
11871+ break;
11872+ }
11873+ }
11874+
11875+ return Success(APValue(ResultElements.data(), ResultElements.size()), E);
11876+ }
1183011877 }
1183111878}
1183211879
@@ -13382,6 +13429,7 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1338213429 case Builtin::BI__builtin_clzll:
1338313430 case Builtin::BI__builtin_clzs:
1338413431 case Builtin::BI__builtin_clzg:
13432+ case Builtin::BI__builtin_elementwise_ctlz:
1338513433 case Builtin::BI__lzcnt16: // Microsoft variants of count leading-zeroes
1338613434 case Builtin::BI__lzcnt:
1338713435 case Builtin::BI__lzcnt64: {
@@ -13390,7 +13438,9 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1339013438 return false;
1339113439
1339213440 std::optional<APSInt> Fallback;
13393- if (BuiltinOp == Builtin::BI__builtin_clzg && E->getNumArgs() > 1) {
13441+ if ((BuiltinOp == Builtin::BI__builtin_clzg ||
13442+ BuiltinOp == Builtin::BI__builtin_elementwise_ctlz) &&
13443+ E->getNumArgs() > 1) {
1339413444 APSInt FallbackTemp;
1339513445 if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info))
1339613446 return false;
@@ -13408,6 +13458,11 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1340813458 BuiltinOp != Builtin::BI__lzcnt &&
1340913459 BuiltinOp != Builtin::BI__lzcnt64;
1341013460
13461+ if (BuiltinOp == Builtin::BI__builtin_elementwise_ctlz) {
13462+ Info.FFDiag(E, diag::note_constexpr_countzeroes_zero)
13463+ << /*IsTrailing=*/false;
13464+ }
13465+
1341113466 if (ZeroIsUndefined)
1341213467 return Error(E);
1341313468 }
@@ -13462,13 +13517,16 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1346213517 case Builtin::BI__builtin_ctzl:
1346313518 case Builtin::BI__builtin_ctzll:
1346413519 case Builtin::BI__builtin_ctzs:
13465- case Builtin::BI__builtin_ctzg: {
13520+ case Builtin::BI__builtin_ctzg:
13521+ case Builtin::BI__builtin_elementwise_cttz: {
1346613522 APSInt Val;
1346713523 if (!EvaluateInteger(E->getArg(0), Val, Info))
1346813524 return false;
1346913525
1347013526 std::optional<APSInt> Fallback;
13471- if (BuiltinOp == Builtin::BI__builtin_ctzg && E->getNumArgs() > 1) {
13527+ if ((BuiltinOp == Builtin::BI__builtin_ctzg ||
13528+ BuiltinOp == Builtin::BI__builtin_elementwise_cttz) &&
13529+ E->getNumArgs() > 1) {
1347213530 APSInt FallbackTemp;
1347313531 if (!EvaluateInteger(E->getArg(1), FallbackTemp, Info))
1347413532 return false;
@@ -13479,6 +13537,10 @@ bool IntExprEvaluator::VisitBuiltinCallExpr(const CallExpr *E,
1347913537 if (Fallback)
1348013538 return Success(*Fallback, E);
1348113539
13540+ if (BuiltinOp == Builtin::BI__builtin_elementwise_cttz) {
13541+ Info.FFDiag(E, diag::note_constexpr_countzeroes_zero)
13542+ << /*IsTrailing=*/true;
13543+ }
1348213544 return Error(E);
1348313545 }
1348413546
0 commit comments