Skip to content

Commit 6e52283

Browse files
authored
[clang] VectorExprEvaluator::VisitCallExpr - use APSInt callback instead of repeated switch statement (#157137)
Create a EvaluateBinOpExpr helper that each related group of elementwise binop builtins can use with their own custom callback, to help reduce the amount of duplication and avoid too much code bloat as more builtins are added. This also handles builtins which have a elementwise LHS operand and a scalar RHS operand. Similar to #155891 which did the same thing for the new ByteCode eval.
1 parent 54ed459 commit 6e52283

File tree

1 file changed

+86
-195
lines changed

1 file changed

+86
-195
lines changed

clang/lib/AST/ExprConstant.cpp

Lines changed: 86 additions & 195 deletions
Original file line numberDiff line numberDiff line change
@@ -11597,6 +11597,38 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1159711597
if (!IsConstantEvaluatedBuiltinCall(E))
1159811598
return ExprEvaluatorBaseTy::VisitCallExpr(E);
1159911599

11600+
auto EvaluateBinOpExpr =
11601+
[&](llvm::function_ref<APInt(const APSInt &, const APSInt &)> Fn) {
11602+
APValue SourceLHS, SourceRHS;
11603+
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
11604+
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
11605+
return false;
11606+
11607+
auto *DestTy = E->getType()->castAs<VectorType>();
11608+
QualType DestEltTy = DestTy->getElementType();
11609+
bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType();
11610+
unsigned SourceLen = SourceLHS.getVectorLength();
11611+
SmallVector<APValue, 4> ResultElements;
11612+
ResultElements.reserve(SourceLen);
11613+
11614+
if (SourceRHS.isInt()) {
11615+
const APSInt &RHS = SourceRHS.getInt();
11616+
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11617+
const APSInt &LHS = SourceLHS.getVectorElt(EltNum).getInt();
11618+
ResultElements.push_back(
11619+
APValue(APSInt(Fn(LHS, RHS), DestUnsigned)));
11620+
}
11621+
} else {
11622+
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11623+
const APSInt &LHS = SourceLHS.getVectorElt(EltNum).getInt();
11624+
const APSInt &RHS = SourceRHS.getVectorElt(EltNum).getInt();
11625+
ResultElements.push_back(
11626+
APValue(APSInt(Fn(LHS, RHS), DestUnsigned)));
11627+
}
11628+
}
11629+
return Success(APValue(ResultElements.data(), SourceLen), E);
11630+
};
11631+
1160011632
switch (E->getBuiltinCallee()) {
1160111633
default:
1160211634
return false;
@@ -11653,27 +11685,30 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1165311685
}
1165411686

1165511687
case Builtin::BI__builtin_elementwise_add_sat:
11688+
return EvaluateBinOpExpr([](const APSInt &LHS, const APSInt &RHS) {
11689+
return LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS);
11690+
});
11691+
1165611692
case Builtin::BI__builtin_elementwise_sub_sat:
11693+
return EvaluateBinOpExpr([](const APSInt &LHS, const APSInt &RHS) {
11694+
return LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS);
11695+
});
11696+
1165711697
case clang::X86::BI__builtin_ia32_pmulhuw128:
1165811698
case clang::X86::BI__builtin_ia32_pmulhuw256:
1165911699
case clang::X86::BI__builtin_ia32_pmulhuw512:
11700+
return EvaluateBinOpExpr(llvm::APIntOps::mulhu);
11701+
1166011702
case clang::X86::BI__builtin_ia32_pmulhw128:
1166111703
case clang::X86::BI__builtin_ia32_pmulhw256:
1166211704
case clang::X86::BI__builtin_ia32_pmulhw512:
11705+
return EvaluateBinOpExpr(llvm::APIntOps::mulhs);
11706+
1166311707
case clang::X86::BI__builtin_ia32_psllv2di:
1166411708
case clang::X86::BI__builtin_ia32_psllv4di:
1166511709
case clang::X86::BI__builtin_ia32_psllv4si:
1166611710
case clang::X86::BI__builtin_ia32_psllv8si:
1166711711
case clang::X86::BI__builtin_ia32_psllv16si:
11668-
case clang::X86::BI__builtin_ia32_psrav4si:
11669-
case clang::X86::BI__builtin_ia32_psrav8si:
11670-
case clang::X86::BI__builtin_ia32_psrav16si:
11671-
case clang::X86::BI__builtin_ia32_psrlv2di:
11672-
case clang::X86::BI__builtin_ia32_psrlv4di:
11673-
case clang::X86::BI__builtin_ia32_psrlv4si:
11674-
case clang::X86::BI__builtin_ia32_psrlv8si:
11675-
case clang::X86::BI__builtin_ia32_psrlv16si:
11676-
1167711712
case clang::X86::BI__builtin_ia32_psllwi128:
1167811713
case clang::X86::BI__builtin_ia32_pslldi128:
1167911714
case clang::X86::BI__builtin_ia32_psllqi128:
@@ -11683,17 +11718,16 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1168311718
case clang::X86::BI__builtin_ia32_psllwi512:
1168411719
case clang::X86::BI__builtin_ia32_pslldi512:
1168511720
case clang::X86::BI__builtin_ia32_psllqi512:
11721+
return EvaluateBinOpExpr([](const APSInt &LHS, const APSInt &RHS) {
11722+
if (RHS.uge(LHS.getBitWidth())) {
11723+
return APInt::getZero(LHS.getBitWidth());
11724+
}
11725+
return LHS.shl(RHS.getZExtValue());
11726+
});
1168611727

11687-
case clang::X86::BI__builtin_ia32_psrlwi128:
11688-
case clang::X86::BI__builtin_ia32_psrldi128:
11689-
case clang::X86::BI__builtin_ia32_psrlqi128:
11690-
case clang::X86::BI__builtin_ia32_psrlwi256:
11691-
case clang::X86::BI__builtin_ia32_psrldi256:
11692-
case clang::X86::BI__builtin_ia32_psrlqi256:
11693-
case clang::X86::BI__builtin_ia32_psrlwi512:
11694-
case clang::X86::BI__builtin_ia32_psrldi512:
11695-
case clang::X86::BI__builtin_ia32_psrlqi512:
11696-
11728+
case clang::X86::BI__builtin_ia32_psrav4si:
11729+
case clang::X86::BI__builtin_ia32_psrav8si:
11730+
case clang::X86::BI__builtin_ia32_psrav16si:
1169711731
case clang::X86::BI__builtin_ia32_psrawi128:
1169811732
case clang::X86::BI__builtin_ia32_psradi128:
1169911733
case clang::X86::BI__builtin_ia32_psraqi128:
@@ -11702,145 +11736,35 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1170211736
case clang::X86::BI__builtin_ia32_psraqi256:
1170311737
case clang::X86::BI__builtin_ia32_psrawi512:
1170411738
case clang::X86::BI__builtin_ia32_psradi512:
11705-
case clang::X86::BI__builtin_ia32_psraqi512: {
11706-
11707-
APValue SourceLHS, SourceRHS;
11708-
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
11709-
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
11710-
return false;
11711-
11712-
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
11713-
bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType();
11714-
unsigned SourceLen = SourceLHS.getVectorLength();
11715-
SmallVector<APValue, 4> ResultElements;
11716-
ResultElements.reserve(SourceLen);
11717-
11718-
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11719-
APSInt LHS = SourceLHS.getVectorElt(EltNum).getInt();
11720-
11721-
if (SourceRHS.isInt()) {
11722-
const unsigned LaneBitWidth = LHS.getBitWidth();
11723-
const unsigned ShiftAmount = SourceRHS.getInt().getZExtValue();
11724-
11725-
switch (E->getBuiltinCallee()) {
11726-
case clang::X86::BI__builtin_ia32_psllwi128:
11727-
case clang::X86::BI__builtin_ia32_psllwi256:
11728-
case clang::X86::BI__builtin_ia32_psllwi512:
11729-
case clang::X86::BI__builtin_ia32_pslldi128:
11730-
case clang::X86::BI__builtin_ia32_pslldi256:
11731-
case clang::X86::BI__builtin_ia32_pslldi512:
11732-
case clang::X86::BI__builtin_ia32_psllqi128:
11733-
case clang::X86::BI__builtin_ia32_psllqi256:
11734-
case clang::X86::BI__builtin_ia32_psllqi512:
11735-
if (ShiftAmount >= LaneBitWidth) {
11736-
ResultElements.push_back(
11737-
APValue(APSInt(APInt::getZero(LaneBitWidth), DestUnsigned)));
11738-
} else {
11739-
ResultElements.push_back(
11740-
APValue(APSInt(LHS.shl(ShiftAmount), DestUnsigned)));
11741-
}
11742-
break;
11743-
case clang::X86::BI__builtin_ia32_psrlwi128:
11744-
case clang::X86::BI__builtin_ia32_psrlwi256:
11745-
case clang::X86::BI__builtin_ia32_psrlwi512:
11746-
case clang::X86::BI__builtin_ia32_psrldi128:
11747-
case clang::X86::BI__builtin_ia32_psrldi256:
11748-
case clang::X86::BI__builtin_ia32_psrldi512:
11749-
case clang::X86::BI__builtin_ia32_psrlqi128:
11750-
case clang::X86::BI__builtin_ia32_psrlqi256:
11751-
case clang::X86::BI__builtin_ia32_psrlqi512:
11752-
if (ShiftAmount >= LaneBitWidth) {
11753-
ResultElements.push_back(
11754-
APValue(APSInt(APInt::getZero(LaneBitWidth), DestUnsigned)));
11755-
} else {
11756-
ResultElements.push_back(
11757-
APValue(APSInt(LHS.lshr(ShiftAmount), DestUnsigned)));
11758-
}
11759-
break;
11760-
case clang::X86::BI__builtin_ia32_psrawi128:
11761-
case clang::X86::BI__builtin_ia32_psrawi256:
11762-
case clang::X86::BI__builtin_ia32_psrawi512:
11763-
case clang::X86::BI__builtin_ia32_psradi128:
11764-
case clang::X86::BI__builtin_ia32_psradi256:
11765-
case clang::X86::BI__builtin_ia32_psradi512:
11766-
case clang::X86::BI__builtin_ia32_psraqi128:
11767-
case clang::X86::BI__builtin_ia32_psraqi256:
11768-
case clang::X86::BI__builtin_ia32_psraqi512:
11769-
ResultElements.push_back(
11770-
APValue(APSInt(LHS.ashr(std::min(ShiftAmount, LaneBitWidth - 1)),
11771-
DestUnsigned)));
11772-
break;
11773-
default:
11774-
llvm_unreachable("Unexpected builtin callee");
11775-
}
11776-
continue;
11739+
case clang::X86::BI__builtin_ia32_psraqi512:
11740+
return EvaluateBinOpExpr([](const APSInt &LHS, const APSInt &RHS) {
11741+
if (RHS.uge(LHS.getBitWidth())) {
11742+
return LHS.ashr(LHS.getBitWidth() - 1);
1177711743
}
11778-
APSInt RHS = SourceRHS.getVectorElt(EltNum).getInt();
11779-
switch (E->getBuiltinCallee()) {
11780-
case Builtin::BI__builtin_elementwise_add_sat:
11781-
ResultElements.push_back(APValue(
11782-
APSInt(LHS.isSigned() ? LHS.sadd_sat(RHS) : LHS.uadd_sat(RHS),
11783-
DestUnsigned)));
11784-
break;
11785-
case Builtin::BI__builtin_elementwise_sub_sat:
11786-
ResultElements.push_back(APValue(
11787-
APSInt(LHS.isSigned() ? LHS.ssub_sat(RHS) : LHS.usub_sat(RHS),
11788-
DestUnsigned)));
11789-
break;
11790-
case clang::X86::BI__builtin_ia32_pmulhuw128:
11791-
case clang::X86::BI__builtin_ia32_pmulhuw256:
11792-
case clang::X86::BI__builtin_ia32_pmulhuw512:
11793-
ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhu(LHS, RHS),
11794-
/*isUnsigned=*/true)));
11795-
break;
11796-
case clang::X86::BI__builtin_ia32_pmulhw128:
11797-
case clang::X86::BI__builtin_ia32_pmulhw256:
11798-
case clang::X86::BI__builtin_ia32_pmulhw512:
11799-
ResultElements.push_back(APValue(APSInt(llvm::APIntOps::mulhs(LHS, RHS),
11800-
/*isUnsigned=*/false)));
11801-
break;
11802-
case clang::X86::BI__builtin_ia32_psllv2di:
11803-
case clang::X86::BI__builtin_ia32_psllv4di:
11804-
case clang::X86::BI__builtin_ia32_psllv4si:
11805-
case clang::X86::BI__builtin_ia32_psllv8si:
11806-
case clang::X86::BI__builtin_ia32_psllv16si:
11807-
if (RHS.uge(RHS.getBitWidth())) {
11808-
ResultElements.push_back(
11809-
APValue(APSInt(APInt::getZero(RHS.getBitWidth()), DestUnsigned)));
11810-
break;
11811-
}
11812-
ResultElements.push_back(
11813-
APValue(APSInt(LHS.shl(RHS.getZExtValue()), DestUnsigned)));
11814-
break;
11815-
case clang::X86::BI__builtin_ia32_psrav4si:
11816-
case clang::X86::BI__builtin_ia32_psrav8si:
11817-
case clang::X86::BI__builtin_ia32_psrav16si:
11818-
if (RHS.uge(RHS.getBitWidth())) {
11819-
ResultElements.push_back(
11820-
APValue(APSInt(LHS.ashr(RHS.getBitWidth() - 1), DestUnsigned)));
11821-
break;
11822-
}
11823-
ResultElements.push_back(
11824-
APValue(APSInt(LHS.ashr(RHS.getZExtValue()), DestUnsigned)));
11825-
break;
11826-
case clang::X86::BI__builtin_ia32_psrlv2di:
11827-
case clang::X86::BI__builtin_ia32_psrlv4di:
11828-
case clang::X86::BI__builtin_ia32_psrlv4si:
11829-
case clang::X86::BI__builtin_ia32_psrlv8si:
11830-
case clang::X86::BI__builtin_ia32_psrlv16si:
11831-
if (RHS.uge(RHS.getBitWidth())) {
11832-
ResultElements.push_back(
11833-
APValue(APSInt(APInt::getZero(RHS.getBitWidth()), DestUnsigned)));
11834-
break;
11835-
}
11836-
ResultElements.push_back(
11837-
APValue(APSInt(LHS.lshr(RHS.getZExtValue()), DestUnsigned)));
11838-
break;
11744+
return LHS.ashr(RHS.getZExtValue());
11745+
});
11746+
11747+
case clang::X86::BI__builtin_ia32_psrlv2di:
11748+
case clang::X86::BI__builtin_ia32_psrlv4di:
11749+
case clang::X86::BI__builtin_ia32_psrlv4si:
11750+
case clang::X86::BI__builtin_ia32_psrlv8si:
11751+
case clang::X86::BI__builtin_ia32_psrlv16si:
11752+
case clang::X86::BI__builtin_ia32_psrlwi128:
11753+
case clang::X86::BI__builtin_ia32_psrldi128:
11754+
case clang::X86::BI__builtin_ia32_psrlqi128:
11755+
case clang::X86::BI__builtin_ia32_psrlwi256:
11756+
case clang::X86::BI__builtin_ia32_psrldi256:
11757+
case clang::X86::BI__builtin_ia32_psrlqi256:
11758+
case clang::X86::BI__builtin_ia32_psrlwi512:
11759+
case clang::X86::BI__builtin_ia32_psrldi512:
11760+
case clang::X86::BI__builtin_ia32_psrlqi512:
11761+
return EvaluateBinOpExpr([](const APSInt &LHS, const APSInt &RHS) {
11762+
if (RHS.uge(LHS.getBitWidth())) {
11763+
return APInt::getZero(LHS.getBitWidth());
1183911764
}
11840-
}
11765+
return LHS.lshr(RHS.getZExtValue());
11766+
});
1184111767

11842-
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
11843-
}
1184411768
case clang::X86::BI__builtin_ia32_pmuldq128:
1184511769
case clang::X86::BI__builtin_ia32_pmuldq256:
1184611770
case clang::X86::BI__builtin_ia32_pmuldq512:
@@ -11878,6 +11802,7 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1187811802

1187911803
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
1188011804
}
11805+
1188111806
case clang::X86::BI__builtin_ia32_vprotbi:
1188211807
case clang::X86::BI__builtin_ia32_vprotdi:
1188311808
case clang::X86::BI__builtin_ia32_vprotqi:
@@ -11887,53 +11812,19 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
1188711812
case clang::X86::BI__builtin_ia32_prold512:
1188811813
case clang::X86::BI__builtin_ia32_prolq128:
1188911814
case clang::X86::BI__builtin_ia32_prolq256:
11890-
case clang::X86::BI__builtin_ia32_prolq512: {
11891-
APValue SourceLHS, SourceRHS;
11892-
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
11893-
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
11894-
return false;
11895-
11896-
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
11897-
bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType();
11898-
unsigned SourceLen = SourceLHS.getVectorLength();
11899-
SmallVector<APValue, 4> ResultElements;
11900-
ResultElements.reserve(SourceLen);
11901-
11902-
APSInt RHS = SourceRHS.getInt();
11903-
11904-
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11905-
const APSInt &LHS = SourceLHS.getVectorElt(EltNum).getInt();
11906-
ResultElements.push_back(APValue(APSInt(LHS.rotl(RHS), DestUnsigned)));
11907-
}
11815+
case clang::X86::BI__builtin_ia32_prolq512:
11816+
return EvaluateBinOpExpr(
11817+
[](const APSInt &LHS, const APSInt &RHS) { return LHS.rotl(RHS); });
1190811818

11909-
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
11910-
}
1191111819
case clang::X86::BI__builtin_ia32_prord128:
1191211820
case clang::X86::BI__builtin_ia32_prord256:
1191311821
case clang::X86::BI__builtin_ia32_prord512:
1191411822
case clang::X86::BI__builtin_ia32_prorq128:
1191511823
case clang::X86::BI__builtin_ia32_prorq256:
11916-
case clang::X86::BI__builtin_ia32_prorq512: {
11917-
APValue SourceLHS, SourceRHS;
11918-
if (!EvaluateAsRValue(Info, E->getArg(0), SourceLHS) ||
11919-
!EvaluateAsRValue(Info, E->getArg(1), SourceRHS))
11920-
return false;
11824+
case clang::X86::BI__builtin_ia32_prorq512:
11825+
return EvaluateBinOpExpr(
11826+
[](const APSInt &LHS, const APSInt &RHS) { return LHS.rotr(RHS); });
1192111827

11922-
QualType DestEltTy = E->getType()->castAs<VectorType>()->getElementType();
11923-
bool DestUnsigned = DestEltTy->isUnsignedIntegerOrEnumerationType();
11924-
unsigned SourceLen = SourceLHS.getVectorLength();
11925-
SmallVector<APValue, 4> ResultElements;
11926-
ResultElements.reserve(SourceLen);
11927-
11928-
APSInt RHS = SourceRHS.getInt();
11929-
11930-
for (unsigned EltNum = 0; EltNum < SourceLen; ++EltNum) {
11931-
const APSInt &LHS = SourceLHS.getVectorElt(EltNum).getInt();
11932-
ResultElements.push_back(APValue(APSInt(LHS.rotr(RHS), DestUnsigned)));
11933-
}
11934-
11935-
return Success(APValue(ResultElements.data(), ResultElements.size()), E);
11936-
}
1193711828
case Builtin::BI__builtin_elementwise_max:
1193811829
case Builtin::BI__builtin_elementwise_min: {
1193911830
APValue SourceLHS, SourceRHS;

0 commit comments

Comments
 (0)