Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -2912,22 +2912,22 @@ default: llvm_unreachable("unsupported binary operator"); case BO_EQ: - Result = (LHSValue == RHSValue); + Result = -(LHSValue == RHSValue); break; case BO_NE: - Result = (LHSValue != RHSValue); + Result = -(LHSValue != RHSValue); break; case BO_LT: - Result = (LHSValue < RHSValue); + Result = -(LHSValue < RHSValue); break; case BO_GT: - Result = (LHSValue > RHSValue); + Result = -(LHSValue > RHSValue); break; case BO_LE: - Result = (LHSValue <= RHSValue); + Result = -(LHSValue <= RHSValue); break; case BO_GE: - Result = (LHSValue >= RHSValue); + Result = -(LHSValue >= RHSValue); break; } @@ -10179,7 +10179,8 @@ bool VisitInitListExpr(const InitListExpr *E); bool VisitUnaryImag(const UnaryOperator *E); bool VisitBinaryOperator(const BinaryOperator *E); - // FIXME: Missing: unary -, unary ~, conditional operator (for GNU + bool VisitUnaryOperator(const UnaryOperator *E); + // FIXME: Missing: unary ~, conditional operator (for GNU // conditional select), shufflevector, ExtVectorElementExpr }; } // end anonymous namespace @@ -10364,6 +10365,43 @@ return Success(LHSValue, E); } +bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + Expr *SubExpr = E->getSubExpr(); + const auto *VD = SubExpr->getType()->castAs(); + UnaryOperatorKind Op = E->getOpcode(); + + APValue SubExprValue; + if (!Evaluate(SubExprValue, Info, SubExpr)) + return false; + + assert(SubExprValue.getVectorLength() == VD->getNumElements() && + "Vector length doesn't match type?"); + + switch (Op) { + default: + // FIXME: Implement the rest of the unary operators. + return false; + case UO_Minus: { + for (unsigned EltNum = 0; EltNum < VD->getNumElements(); ++EltNum) { + APValue &Elt = SubExprValue.getVectorElt(EltNum); + if (Elt.getKind() == APValue::Int) { + Elt.setInt(-Elt.getInt()); + } else { + assert(Elt.getKind() == APValue::Float && + "Vector can only be int or float type"); + Elt.setFloat(-Elt.getFloat()); + } + } + break; + } + case UO_Plus: + // Do nothing, Unary plus is a no-op. + break; + } + + return Success(SubExprValue, E); +} + //===----------------------------------------------------------------------===// // Array Evaluation //===----------------------------------------------------------------------===// Index: clang/test/SemaCXX/constexpr-vectors.cpp =================================================================== --- clang/test/SemaCXX/constexpr-vectors.cpp +++ clang/test/SemaCXX/constexpr-vectors.cpp @@ -204,35 +204,35 @@ constexpr auto w = FourCharsVecSize{1, 2, 3, 4} < FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto x = FourCharsVecSize{1, 2, 3, 4} > FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto y = FourCharsVecSize{1, 2, 3, 4} <= FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto z = FourCharsVecSize{1, 2, 3, 4} >= FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto A = FourCharsVecSize{1, 2, 3, 4} == FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto B = FourCharsVecSize{1, 2, 3, 4} != FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto I = FourCharsVecSize{1, 2, 3, 4} & FourCharsVecSize{4, 3, 2, 1}; @@ -277,10 +277,12 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x i8> - constexpr auto Z = CmpLSH(a, H); + constexpr auto InvH = -H; + // CHECK: store <4 x i8> + constexpr auto Z = CmpLSH(a, InvH); // CHECK: store <4 x i8> - constexpr auto aa = CmpRSH(a, H); + constexpr auto aa = CmpRSH(a, InvH); // CHECK: store <4 x i8> constexpr auto ab = CmpBinAnd(a, b); @@ -348,35 +350,35 @@ constexpr auto w = FourCharsExtVec{1, 2, 3, 4} < FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto x = FourCharsExtVec{1, 2, 3, 4} > FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto y = FourCharsExtVec{1, 2, 3, 4} <= FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto z = FourCharsExtVec{1, 2, 3, 4} >= FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto A = FourCharsExtVec{1, 2, 3, 4} == FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto B = FourCharsExtVec{1, 2, 3, 4} != FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto C = FourCharsExtVec{1, 2, 3, 4} < 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto D = FourCharsExtVec{1, 2, 3, 4} > 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto E = FourCharsExtVec{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto F = FourCharsExtVec{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto G = FourCharsExtVec{1, 2, 3, 4} == 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto H = FourCharsExtVec{1, 2, 3, 4} != 3; - // CHECK: store <4 x i8> + // CHECK: store <4 x i8> constexpr auto I = FourCharsExtVec{1, 2, 3, 4} & FourCharsExtVec{4, 3, 2, 1}; @@ -421,10 +423,13 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x i8> - constexpr auto Z = CmpLSH(a, H); + constexpr auto InvH = -H; + // CHECK: store <4 x i8> + + constexpr auto Z = CmpLSH(a, InvH); // CHECK: store <4 x i8> - constexpr auto aa = CmpRSH(a, H); + constexpr auto aa = CmpRSH(a, InvH); // CHECK: store <4 x i8> constexpr auto ab = CmpBinAnd(a, b); @@ -471,35 +476,35 @@ constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} < FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} > FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} == FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} != FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} && FourFloatsVecSize{5, 5, 0, 0}; @@ -524,6 +529,9 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x float> + + constexpr auto Z = -Y; + // CHECK: store <4 x float> } void FloatVecUsage() { @@ -560,35 +568,35 @@ constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} < FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} > FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} == FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} != FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i32> + // CHECK: store <4 x i32> constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} && FourFloatsVecSize{5, 5, 0, 0}; @@ -613,4 +621,7 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x float> + + constexpr auto Z = -Y; + // CHECK: store <4 x float> }