aboutsummaryrefslogtreecommitdiff
path: root/clang/lib/AST/ExprConstant.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/AST/ExprConstant.cpp')
-rw-r--r--clang/lib/AST/ExprConstant.cpp315
1 files changed, 155 insertions, 160 deletions
diff --git a/clang/lib/AST/ExprConstant.cpp b/clang/lib/AST/ExprConstant.cpp
index 972d9fe..1bfea24 100644
--- a/clang/lib/AST/ExprConstant.cpp
+++ b/clang/lib/AST/ExprConstant.cpp
@@ -12090,24 +12090,46 @@ static bool evalShuffleGeneric(
unsigned ShuffleMask = 0;
APValue A, MaskVector, B;
bool IsVectorMask = false;
-
- QualType Arg2Type = Call->getArg(2)->getType();
- if (Arg2Type->isVectorType()) {
- IsVectorMask = true;
- if (!EvaluateAsRValue(Info, Call->getArg(0), A) ||
- !EvaluateAsRValue(Info, Call->getArg(1), MaskVector) ||
- !EvaluateAsRValue(Info, Call->getArg(2), B))
- return false;
- } else if (Arg2Type->isIntegerType()) {
- APSInt MaskImm;
- if (!EvaluateInteger(Call->getArg(2), MaskImm, Info))
- return false;
- ShuffleMask = static_cast<unsigned>(MaskImm.getZExtValue());
- if (!EvaluateAsRValue(Info, Call->getArg(0), A) ||
- !EvaluateAsRValue(Info, Call->getArg(1), B))
+ bool IsSingleOperand = (Call->getNumArgs() == 2);
+
+ if (IsSingleOperand) {
+ QualType MaskType = Call->getArg(1)->getType();
+ if (MaskType->isVectorType()) {
+ IsVectorMask = true;
+ if (!EvaluateAsRValue(Info, Call->getArg(0), A) ||
+ !EvaluateAsRValue(Info, Call->getArg(1), MaskVector))
+ return false;
+ B = A;
+ } else if (MaskType->isIntegerType()) {
+ APSInt MaskImm;
+ if (!EvaluateInteger(Call->getArg(1), MaskImm, Info))
+ return false;
+ ShuffleMask = static_cast<unsigned>(MaskImm.getZExtValue());
+ if (!EvaluateAsRValue(Info, Call->getArg(0), A))
+ return false;
+ B = A;
+ } else {
return false;
+ }
} else {
- return false;
+ QualType Arg2Type = Call->getArg(2)->getType();
+ if (Arg2Type->isVectorType()) {
+ IsVectorMask = true;
+ if (!EvaluateAsRValue(Info, Call->getArg(0), A) ||
+ !EvaluateAsRValue(Info, Call->getArg(1), MaskVector) ||
+ !EvaluateAsRValue(Info, Call->getArg(2), B))
+ return false;
+ } else if (Arg2Type->isIntegerType()) {
+ APSInt MaskImm;
+ if (!EvaluateInteger(Call->getArg(2), MaskImm, Info))
+ return false;
+ ShuffleMask = static_cast<unsigned>(MaskImm.getZExtValue());
+ if (!EvaluateAsRValue(Info, Call->getArg(0), A) ||
+ !EvaluateAsRValue(Info, Call->getArg(1), B))
+ return false;
+ } else {
+ return false;
+ }
}
unsigned NumElts = VT->getNumElements();
@@ -12124,8 +12146,16 @@ static bool evalShuffleGeneric(
if (SrcIdx < 0) {
// Zero out this element
QualType ElemTy = VT->getElementType();
- ResultElements.push_back(
- APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy))));
+ if (ElemTy->isRealFloatingType()) {
+ ResultElements.push_back(
+ APValue(APFloat::getZero(Info.Ctx.getFloatTypeSemantics(ElemTy))));
+ } else if (ElemTy->isIntegerType()) {
+ APValue Zero(Info.Ctx.MakeIntValue(0, ElemTy));
+ ResultElements.push_back(APValue(Zero));
+ } else {
+ // Other types of fallback logic
+ ResultElements.push_back(APValue());
+ }
} else {
const APValue &Src = (SrcVecIdx == 0) ? A : B;
ResultElements.push_back(Src.getVectorElt(SrcIdx));
@@ -12136,98 +12166,6 @@ static bool evalShuffleGeneric(
return true;
}
-static bool evalPshufbBuiltin(EvalInfo &Info, const CallExpr *Call,
- APValue &Out) {
- APValue SrcVec, ControlVec;
- if (!EvaluateAsRValue(Info, Call->getArg(0), SrcVec))
- return false;
- if (!EvaluateAsRValue(Info, Call->getArg(1), ControlVec))
- return false;
-
- const auto *VT = Call->getType()->getAs<VectorType>();
- if (!VT)
- return false;
-
- QualType ElemT = VT->getElementType();
- unsigned NumElts = VT->getNumElements();
-
- SmallVector<APValue, 64> ResultElements;
- ResultElements.reserve(NumElts);
-
- for (unsigned Idx = 0; Idx != NumElts; ++Idx) {
- APValue CtlVal = ControlVec.getVectorElt(Idx);
- APSInt CtlByte = CtlVal.getInt();
- uint8_t Ctl = static_cast<uint8_t>(CtlByte.getZExtValue());
-
- if (Ctl & 0x80) {
- APValue Zero(Info.Ctx.MakeIntValue(0, ElemT));
- ResultElements.push_back(Zero);
- } else {
- unsigned LaneBase = (Idx / 16) * 16;
- unsigned SrcOffset = Ctl & 0x0F;
- unsigned SrcIdx = LaneBase + SrcOffset;
-
- ResultElements.push_back(SrcVec.getVectorElt(SrcIdx));
- }
- }
- Out = APValue(ResultElements.data(), ResultElements.size());
- return true;
-}
-
-static bool evalPshufBuiltin(EvalInfo &Info, const CallExpr *Call,
- bool IsShufHW, APValue &Out) {
- APValue Vec;
- APSInt Imm;
- if (!EvaluateAsRValue(Info, Call->getArg(0), Vec))
- return false;
- if (!EvaluateInteger(Call->getArg(1), Imm, Info))
- return false;
-
- const auto *VT = Call->getType()->getAs<VectorType>();
- if (!VT)
- return false;
-
- QualType ElemT = VT->getElementType();
- unsigned ElemBits = Info.Ctx.getTypeSize(ElemT);
- unsigned NumElts = VT->getNumElements();
-
- unsigned LaneBits = 128u;
- unsigned LaneElts = LaneBits / ElemBits;
- if (!LaneElts || (NumElts % LaneElts) != 0)
- return false;
-
- uint8_t Ctl = static_cast<uint8_t>(Imm.getZExtValue());
-
- SmallVector<APValue, 32> ResultElements;
- ResultElements.reserve(NumElts);
-
- for (unsigned Idx = 0; Idx != NumElts; Idx++) {
- unsigned LaneBase = (Idx / LaneElts) * LaneElts;
- unsigned LaneIdx = Idx % LaneElts;
- unsigned SrcIdx = Idx;
- unsigned Sel = (Ctl >> (2 * LaneIdx)) & 0x3;
-
- if (ElemBits == 32) {
- SrcIdx = LaneBase + Sel;
- } else {
- constexpr unsigned HalfSize = 4;
- bool InHigh = LaneIdx >= HalfSize;
- if (!IsShufHW && !InHigh) {
- SrcIdx = LaneBase + Sel;
- } else if (IsShufHW && InHigh) {
- unsigned Rel = LaneIdx - HalfSize;
- Sel = (Ctl >> (2 * Rel)) & 0x3;
- SrcIdx = LaneBase + HalfSize + Sel;
- }
- }
-
- ResultElements.push_back(Vec.getVectorElt(SrcIdx));
- }
-
- Out = APValue(ResultElements.data(), ResultElements.size());
- return true;
-}
-
bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
if (!IsConstantEvaluatedBuiltinCall(E))
return ExprEvaluatorBaseTy::VisitCallExpr(E);
@@ -12993,7 +12931,19 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case X86::BI__builtin_ia32_pshufb256:
case X86::BI__builtin_ia32_pshufb512: {
APValue R;
- if (!evalPshufbBuiltin(Info, E, R))
+ if (!evalShuffleGeneric(
+ Info, E, R,
+ [](unsigned DstIdx,
+ unsigned ShuffleMask) -> std::pair<unsigned, int> {
+ uint8_t Ctlb = static_cast<uint8_t>(ShuffleMask);
+ if (Ctlb & 0x80)
+ return std::make_pair(0, -1);
+
+ unsigned LaneBase = (DstIdx / 16) * 16;
+ unsigned SrcOffset = Ctlb & 0x0F;
+ unsigned SrcIdx = LaneBase + SrcOffset;
+ return std::make_pair(0, static_cast<int>(SrcIdx));
+ }))
return false;
return Success(R, E);
}
@@ -13002,7 +12952,21 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case X86::BI__builtin_ia32_pshuflw256:
case X86::BI__builtin_ia32_pshuflw512: {
APValue R;
- if (!evalPshufBuiltin(Info, E, false, R))
+ if (!evalShuffleGeneric(
+ Info, E, R,
+ [](unsigned DstIdx, unsigned Mask) -> std::pair<unsigned, int> {
+ constexpr unsigned LaneBits = 128u;
+ constexpr unsigned ElemBits = 16u;
+ constexpr unsigned LaneElts = LaneBits / ElemBits;
+ constexpr unsigned HalfSize = 4;
+ unsigned LaneBase = (DstIdx / LaneElts) * LaneElts;
+ unsigned LaneIdx = DstIdx % LaneElts;
+ if (LaneIdx < HalfSize) {
+ unsigned Sel = (Mask >> (2 * LaneIdx)) & 0x3;
+ return std::make_pair(0, static_cast<int>(LaneBase + Sel));
+ }
+ return std::make_pair(0, static_cast<int>(DstIdx));
+ }))
return false;
return Success(R, E);
}
@@ -13011,7 +12975,23 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case X86::BI__builtin_ia32_pshufhw256:
case X86::BI__builtin_ia32_pshufhw512: {
APValue R;
- if (!evalPshufBuiltin(Info, E, true, R))
+ if (!evalShuffleGeneric(
+ Info, E, R,
+ [](unsigned DstIdx, unsigned Mask) -> std::pair<unsigned, int> {
+ constexpr unsigned LaneBits = 128u;
+ constexpr unsigned ElemBits = 16u;
+ constexpr unsigned LaneElts = LaneBits / ElemBits;
+ constexpr unsigned HalfSize = 4;
+ unsigned LaneBase = (DstIdx / LaneElts) * LaneElts;
+ unsigned LaneIdx = DstIdx % LaneElts;
+ if (LaneIdx >= HalfSize) {
+ unsigned Rel = LaneIdx - HalfSize;
+ unsigned Sel = (Mask >> (2 * Rel)) & 0x3;
+ return std::make_pair(
+ 0, static_cast<int>(LaneBase + HalfSize + Sel));
+ }
+ return std::make_pair(0, static_cast<int>(DstIdx));
+ }))
return false;
return Success(R, E);
}
@@ -13020,7 +13000,17 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case X86::BI__builtin_ia32_pshufd256:
case X86::BI__builtin_ia32_pshufd512: {
APValue R;
- if (!evalPshufBuiltin(Info, E, false, R))
+ if (!evalShuffleGeneric(
+ Info, E, R,
+ [](unsigned DstIdx, unsigned Mask) -> std::pair<unsigned, int> {
+ constexpr unsigned LaneBits = 128u;
+ constexpr unsigned ElemBits = 32u;
+ constexpr unsigned LaneElts = LaneBits / ElemBits;
+ unsigned LaneBase = (DstIdx / LaneElts) * LaneElts;
+ unsigned LaneIdx = DstIdx % LaneElts;
+ unsigned Sel = (Mask >> (2 * LaneIdx)) & 0x3;
+ return std::make_pair(0, static_cast<int>(LaneBase + Sel));
+ }))
return false;
return Success(R, E);
}
@@ -13500,61 +13490,66 @@ bool VectorExprEvaluator::VisitCallExpr(const CallExpr *E) {
case X86::BI__builtin_ia32_pslldqi128_byteshift:
case X86::BI__builtin_ia32_pslldqi256_byteshift:
case X86::BI__builtin_ia32_pslldqi512_byteshift: {
- assert(E->getNumArgs() == 2);
-
- APValue Src;
- APSInt Imm;
- if (!EvaluateAsRValue(Info, E->getArg(0), Src) ||
- !EvaluateInteger(E->getArg(1), Imm, Info))
+ APValue R;
+ if (!evalShuffleGeneric(
+ Info, E, R,
+ [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
+ unsigned LaneBase = (DstIdx / 16) * 16;
+ unsigned LaneIdx = DstIdx % 16;
+ if (LaneIdx < Shift)
+ return std::make_pair(0, -1);
+
+ return std::make_pair(
+ 0, static_cast<int>(LaneBase + LaneIdx - Shift));
+ }))
return false;
-
- unsigned VecLen = Src.getVectorLength();
- unsigned Shift = Imm.getZExtValue() & 0xff;
-
- SmallVector<APValue> ResultElements;
- for (unsigned Lane = 0; Lane != VecLen; Lane += 16) {
- for (unsigned I = 0; I != 16; ++I) {
- if (I < Shift) {
- APSInt Zero(8, /*isUnsigned=*/true);
- Zero = 0;
- ResultElements.push_back(APValue(Zero));
- } else {
- ResultElements.push_back(Src.getVectorElt(Lane + I - Shift));
- }
- }
- }
-
- return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+ return Success(R, E);
}
case X86::BI__builtin_ia32_psrldqi128_byteshift:
case X86::BI__builtin_ia32_psrldqi256_byteshift:
case X86::BI__builtin_ia32_psrldqi512_byteshift: {
- assert(E->getNumArgs() == 2);
-
- APValue Src;
- APSInt Imm;
- if (!EvaluateAsRValue(Info, E->getArg(0), Src) ||
- !EvaluateInteger(E->getArg(1), Imm, Info))
+ APValue R;
+ if (!evalShuffleGeneric(
+ Info, E, R,
+ [](unsigned DstIdx, unsigned Shift) -> std::pair<unsigned, int> {
+ unsigned LaneBase = (DstIdx / 16) * 16;
+ unsigned LaneIdx = DstIdx % 16;
+ if (LaneIdx + Shift < 16)
+ return std::make_pair(
+ 0, static_cast<int>(LaneBase + LaneIdx + Shift));
+
+ return std::make_pair(0, -1);
+ }))
return false;
+ return Success(R, E);
+ }
- unsigned VecLen = Src.getVectorLength();
- unsigned Shift = Imm.getZExtValue() & 0xff;
-
- SmallVector<APValue> ResultElements;
- for (unsigned Lane = 0; Lane != VecLen; Lane += 16) {
- for (unsigned I = 0; I != 16; ++I) {
- if (I + Shift < 16) {
- ResultElements.push_back(Src.getVectorElt(Lane + I + Shift));
- } else {
- APSInt Zero(8, /*isUnsigned=*/true);
- Zero = 0;
- ResultElements.push_back(APValue(Zero));
- }
- }
- }
+ case X86::BI__builtin_ia32_palignr128:
+ case X86::BI__builtin_ia32_palignr256:
+ case X86::BI__builtin_ia32_palignr512: {
+ APValue R;
+ if (!evalShuffleGeneric(Info, E, R, [](unsigned DstIdx, unsigned Shift) {
+ // Default to -1 → zero-fill this destination element
+ unsigned VecIdx = 1;
+ int ElemIdx = -1;
+
+ int Lane = DstIdx / 16;
+ int Offset = DstIdx % 16;
+
+ // Elements come from VecB first, then VecA after the shift boundary
+ unsigned ShiftedIdx = Offset + (Shift & 0xFF);
+ if (ShiftedIdx < 16) { // from VecB
+ ElemIdx = ShiftedIdx + (Lane * 16);
+ } else if (ShiftedIdx < 32) { // from VecA
+ VecIdx = 0;
+ ElemIdx = (ShiftedIdx - 16) + (Lane * 16);
+ }
- return Success(APValue(ResultElements.data(), ResultElements.size()), E);
+ return std::pair<unsigned, int>{VecIdx, ElemIdx};
+ }))
+ return false;
+ return Success(R, E);
}
case X86::BI__builtin_ia32_vpermi2varq128:
case X86::BI__builtin_ia32_vpermi2varpd128: {