@@ -2664,6 +2664,155 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E,
26642664 return true;
26652665}
26662666
2667+ static bool handleLogicalOpForVector(const APInt &LHSValue,
2668+ BinaryOperatorKind Opcode,
2669+ const APInt &RHSValue, APInt &Result) {
2670+ bool LHS = (LHSValue != 0);
2671+ bool RHS = (RHSValue != 0);
2672+
2673+ if (Opcode == BO_LAnd)
2674+ Result = LHS && RHS;
2675+ else
2676+ Result = LHS || RHS;
2677+ return true;
2678+ }
2679+ static bool handleLogicalOpForVector(const APFloat &LHSValue,
2680+ BinaryOperatorKind Opcode,
2681+ const APFloat &RHSValue, APInt &Result) {
2682+ bool LHS = !LHSValue.isZero();
2683+ bool RHS = !RHSValue.isZero();
2684+
2685+ if (Opcode == BO_LAnd)
2686+ Result = LHS && RHS;
2687+ else
2688+ Result = LHS || RHS;
2689+ return true;
2690+ }
2691+
2692+ static bool handleLogicalOpForVector(const APValue &LHSValue,
2693+ BinaryOperatorKind Opcode,
2694+ const APValue &RHSValue, APInt &Result) {
2695+ // The result is always an int type, however operands match the first.
2696+ if (LHSValue.getKind() == APValue::Int)
2697+ return handleLogicalOpForVector(LHSValue.getInt(), Opcode,
2698+ RHSValue.getInt(), Result);
2699+ assert(LHSValue.getKind() == APValue::Float && "Should be no other options");
2700+ return handleLogicalOpForVector(LHSValue.getFloat(), Opcode,
2701+ RHSValue.getFloat(), Result);
2702+ }
2703+
2704+ template <typename APTy>
2705+ static bool
2706+ handleCompareOpForVectorHelper(const APTy &LHSValue, BinaryOperatorKind Opcode,
2707+ const APTy &RHSValue, APInt &Result) {
2708+ switch (Opcode) {
2709+ default:
2710+ llvm_unreachable("unsupported binary operator");
2711+ case BO_EQ:
2712+ Result = (LHSValue == RHSValue);
2713+ break;
2714+ case BO_NE:
2715+ Result = (LHSValue != RHSValue);
2716+ break;
2717+ case BO_LT:
2718+ Result = (LHSValue < RHSValue);
2719+ break;
2720+ case BO_GT:
2721+ Result = (LHSValue > RHSValue);
2722+ break;
2723+ case BO_LE:
2724+ Result = (LHSValue <= RHSValue);
2725+ break;
2726+ case BO_GE:
2727+ Result = (LHSValue >= RHSValue);
2728+ break;
2729+ }
2730+
2731+ return true;
2732+ }
2733+
2734+ static bool handleCompareOpForVector(const APValue &LHSValue,
2735+ BinaryOperatorKind Opcode,
2736+ const APValue &RHSValue, APInt &Result) {
2737+ // The result is always an int type, however operands match the first.
2738+ if (LHSValue.getKind() == APValue::Int)
2739+ return handleCompareOpForVectorHelper(LHSValue.getInt(), Opcode,
2740+ RHSValue.getInt(), Result);
2741+ assert(LHSValue.getKind() == APValue::Float && "Should be no other options");
2742+ return handleCompareOpForVectorHelper(LHSValue.getFloat(), Opcode,
2743+ RHSValue.getFloat(), Result);
2744+ }
2745+
2746+ // Perform binary operations for vector types, in place on the LHS.
2747+ static bool handleVectorVectorBinOp(EvalInfo &Info, const Expr *E,
2748+ BinaryOperatorKind Opcode,
2749+ APValue &LHSValue,
2750+ const APValue &RHSValue) {
2751+ assert(Opcode != BO_PtrMemD && Opcode != BO_PtrMemI &&
2752+ "Operation not supported on vector types");
2753+
2754+ const auto *VT = E->getType()->castAs<VectorType>();
2755+ unsigned NumElements = VT->getNumElements();
2756+ QualType EltTy = VT->getElementType();
2757+
2758+ // In the cases (typically C as I've observed) where we aren't evaluating
2759+ // constexpr but are checking for cases where the LHS isn't yet evaluatable,
2760+ // just give up.
2761+ if (!LHSValue.isVector()) {
2762+ assert(LHSValue.isLValue() &&
2763+ "A vector result that isn't a vector OR uncalculated LValue");
2764+ Info.FFDiag(E);
2765+ return false;
2766+ }
2767+
2768+ assert(LHSValue.getVectorLength() == NumElements &&
2769+ RHSValue.getVectorLength() == NumElements && "Different vector sizes");
2770+
2771+ SmallVector<APValue, 4> ResultElements;
2772+
2773+ for (unsigned EltNum = 0; EltNum < NumElements; ++EltNum) {
2774+ APValue LHSElt = LHSValue.getVectorElt(EltNum);
2775+ APValue RHSElt = RHSValue.getVectorElt(EltNum);
2776+
2777+ if (EltTy->isIntegerType()) {
2778+ APSInt EltResult{Info.Ctx.getIntWidth(EltTy),
2779+ EltTy->isUnsignedIntegerType()};
2780+ bool Success = true;
2781+
2782+ if (BinaryOperator::isLogicalOp(Opcode))
2783+ Success = handleLogicalOpForVector(LHSElt, Opcode, RHSElt, EltResult);
2784+ else if (BinaryOperator::isComparisonOp(Opcode))
2785+ Success = handleCompareOpForVector(LHSElt, Opcode, RHSElt, EltResult);
2786+ else
2787+ Success = handleIntIntBinOp(Info, E, LHSElt.getInt(), Opcode,
2788+ RHSElt.getInt(), EltResult);
2789+
2790+ if (!Success) {
2791+ Info.FFDiag(E);
2792+ return false;
2793+ }
2794+ ResultElements.emplace_back(EltResult);
2795+
2796+ } else if (EltTy->isFloatingType()) {
2797+ assert(LHSElt.getKind() == APValue::Float &&
2798+ RHSElt.getKind() == APValue::Float &&
2799+ "Mismatched LHS/RHS/Result Type");
2800+ APFloat LHSFloat = LHSElt.getFloat();
2801+
2802+ if (!handleFloatFloatBinOp(Info, E, LHSFloat, Opcode,
2803+ RHSElt.getFloat())) {
2804+ Info.FFDiag(E);
2805+ return false;
2806+ }
2807+
2808+ ResultElements.emplace_back(LHSFloat);
2809+ }
2810+ }
2811+
2812+ LHSValue = APValue(ResultElements.data(), ResultElements.size());
2813+ return true;
2814+ }
2815+
26672816/// Cast an lvalue referring to a base subobject to a derived class, by
26682817/// truncating the lvalue's path to the given length.
26692818static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result,
@@ -3910,12 +4059,26 @@ struct CompoundAssignSubobjectHandler {
39104059 return false;
39114060 case APValue::LValue:
39124061 return foundPointer(Subobj, SubobjType);
4062+ case APValue::Vector:
4063+ return foundVector(Subobj, SubobjType);
39134064 default:
39144065 // FIXME: can this happen?
39154066 Info.FFDiag(E);
39164067 return false;
39174068 }
39184069 }
4070+
4071+ bool foundVector(APValue &Value, QualType SubobjType) {
4072+ if (!checkConst(SubobjType))
4073+ return false;
4074+
4075+ if (!SubobjType->isVectorType()) {
4076+ Info.FFDiag(E);
4077+ return false;
4078+ }
4079+ return handleVectorVectorBinOp(Info, E, Opcode, Value, RHS);
4080+ }
4081+
39194082 bool found(APSInt &Value, QualType SubobjType) {
39204083 if (!checkConst(SubobjType))
39214084 return false;
@@ -9516,10 +9679,9 @@ namespace {
95169679 bool VisitCastExpr(const CastExpr* E);
95179680 bool VisitInitListExpr(const InitListExpr *E);
95189681 bool VisitUnaryImag(const UnaryOperator *E);
9519- // FIXME: Missing: unary -, unary ~, binary add/sub/mul/div,
9520- // binary comparisons, binary and/or/xor,
9521- // conditional operator (for GNU conditional select),
9522- // shufflevector, ExtVectorElementExpr
9682+ bool VisitBinaryOperator(const BinaryOperator *E);
9683+ // FIXME: Missing: unary -, unary ~, conditional operator (for GNU
9684+ // conditional select), shufflevector, ExtVectorElementExpr
95239685 };
95249686} // end anonymous namespace
95259687
@@ -9667,6 +9829,41 @@ bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
96679829 return ZeroInitialization(E);
96689830}
96699831
9832+ bool VectorExprEvaluator::VisitBinaryOperator(const BinaryOperator *E) {
9833+ BinaryOperatorKind Op = E->getOpcode();
9834+ assert(Op != BO_PtrMemD && Op != BO_PtrMemI && Op != BO_Cmp &&
9835+ "Operation not supported on vector types");
9836+
9837+ if (Op == BO_Comma)
9838+ return ExprEvaluatorBaseTy::VisitBinaryOperator(E);
9839+
9840+ Expr *LHS = E->getLHS();
9841+ Expr *RHS = E->getRHS();
9842+
9843+ assert(LHS->getType()->isVectorType() && RHS->getType()->isVectorType() &&
9844+ "Must both be vector types");
9845+ // Checking JUST the types are the same would be fine, except shifts don't
9846+ // need to have their types be the same (since you always shift by an int).
9847+ assert(LHS->getType()->getAs<VectorType>()->getNumElements() ==
9848+ E->getType()->getAs<VectorType>()->getNumElements() &&
9849+ RHS->getType()->getAs<VectorType>()->getNumElements() ==
9850+ E->getType()->getAs<VectorType>()->getNumElements() &&
9851+ "All operands must be the same size.");
9852+
9853+ APValue LHSValue;
9854+ APValue RHSValue;
9855+ bool LHSOK = Evaluate(LHSValue, Info, LHS);
9856+ if (!LHSOK && !Info.noteFailure())
9857+ return false;
9858+ if (!Evaluate(RHSValue, Info, RHS) || !LHSOK)
9859+ return false;
9860+
9861+ if (!handleVectorVectorBinOp(Info, E, Op, LHSValue, RHSValue))
9862+ return false;
9863+
9864+ return Success(LHSValue, E);
9865+ }
9866+
96709867//===----------------------------------------------------------------------===//
96719868// Array Evaluation
96729869//===----------------------------------------------------------------------===//
0 commit comments