@@ -2664,6 +2664,155 @@ static bool handleFloatFloatBinOp(EvalInfo &Info, const Expr *E,
2664
2664
return true;
2665
2665
}
2666
2666
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
+
2667
2816
/// Cast an lvalue referring to a base subobject to a derived class, by
2668
2817
/// truncating the lvalue's path to the given length.
2669
2818
static bool CastToDerivedClass(EvalInfo &Info, const Expr *E, LValue &Result,
@@ -3910,12 +4059,26 @@ struct CompoundAssignSubobjectHandler {
3910
4059
return false;
3911
4060
case APValue::LValue:
3912
4061
return foundPointer(Subobj, SubobjType);
4062
+ case APValue::Vector:
4063
+ return foundVector(Subobj, SubobjType);
3913
4064
default:
3914
4065
// FIXME: can this happen?
3915
4066
Info.FFDiag(E);
3916
4067
return false;
3917
4068
}
3918
4069
}
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
+
3919
4082
bool found(APSInt &Value, QualType SubobjType) {
3920
4083
if (!checkConst(SubobjType))
3921
4084
return false;
@@ -9516,10 +9679,9 @@ namespace {
9516
9679
bool VisitCastExpr(const CastExpr* E);
9517
9680
bool VisitInitListExpr(const InitListExpr *E);
9518
9681
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
9523
9685
};
9524
9686
} // end anonymous namespace
9525
9687
@@ -9667,6 +9829,41 @@ bool VectorExprEvaluator::VisitUnaryImag(const UnaryOperator *E) {
9667
9829
return ZeroInitialization(E);
9668
9830
}
9669
9831
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
+
9670
9867
//===----------------------------------------------------------------------===//
9671
9868
// Array Evaluation
9672
9869
//===----------------------------------------------------------------------===//
0 commit comments