erichkeane updated this revision to Diff 394604. erichkeane marked 7 inline comments as done. erichkeane added a comment.
Fix Aaron+ Craig's comments. CHANGES SINCE LAST ACTION https://reviews.llvm.org/D115670/new/ https://reviews.llvm.org/D115670 Files: clang/lib/AST/ExprConstant.cpp clang/lib/Sema/SemaExpr.cpp clang/test/SemaCXX/constexpr-vectors.cpp
Index: clang/test/SemaCXX/constexpr-vectors.cpp =================================================================== --- clang/test/SemaCXX/constexpr-vectors.cpp +++ clang/test/SemaCXX/constexpr-vectors.cpp @@ -11,12 +11,15 @@ using FourLongLongsVecSize __attribute__((vector_size(32))) = long long; using FourFloatsVecSize __attribute__((vector_size(16))) = float; using FourDoublesVecSize __attribute__((vector_size(32))) = double; +using FourI128VecSize __attribute__((vector_size(64))) = __int128; using FourCharsExtVec __attribute__((ext_vector_type(4))) = char; using FourIntsExtVec __attribute__((ext_vector_type(4))) = int; using FourLongLongsExtVec __attribute__((ext_vector_type(4))) = long long; using FourFloatsExtVec __attribute__((ext_vector_type(4))) = float; using FourDoublesExtVec __attribute__((ext_vector_type(4))) = double; +using FourI128ExtVec __attribute__((ext_vector_type(4))) = __int128; + // Next a series of tests to make sure these operations are usable in // constexpr functions. Template instantiations don't emit Winvalid-constexpr, @@ -204,35 +207,35 @@ constexpr auto w = FourCharsVecSize{1, 2, 3, 4} < FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0> constexpr auto x = FourCharsVecSize{1, 2, 3, 4} > FourCharsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1> constexpr auto y = FourCharsVecSize{1, 2, 3, 4} <= FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0> constexpr auto z = FourCharsVecSize{1, 2, 3, 4} >= FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1> constexpr auto A = FourCharsVecSize{1, 2, 3, 4} == FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0> constexpr auto B = FourCharsVecSize{1, 2, 3, 4} != FourCharsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1> constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0> constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 -1> constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0> constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1> constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0> constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1> constexpr auto I = FourCharsVecSize{1, 2, 3, 4} & FourCharsVecSize{4, 3, 2, 1}; @@ -277,10 +280,12 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x i8> <i8 12, i8 17, i8 -1, i8 -1> - constexpr auto Z = CmpLSH(a, H); + constexpr auto InvH = -H; + // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1> + constexpr auto Z = CmpLSH(a, InvH); // CHECK: store <4 x i8> <i8 36, i8 36, i8 7, i8 16> - constexpr auto aa = CmpRSH(a, H); + constexpr auto aa = CmpRSH(a, InvH); // CHECK: store <4 x i8> <i8 9, i8 9, i8 7, i8 4> constexpr auto ab = CmpBinAnd(a, b); @@ -291,6 +296,12 @@ constexpr auto ad = CmpBinOr(a, b); // CHECK: store <4 x i8> <i8 22, i8 19, i8 15, i8 9> + + constexpr auto ae = ~FourCharsVecSize{1, 2, 10, 20}; + // CHECK: store <4 x i8> <i8 -2, i8 -3, i8 -11, i8 -21> + + constexpr auto af = !FourCharsVecSize{0, 1, 8, -1}; + // CHECK: store <4 x i8> <i8 -1, i8 0, i8 0, i8 0> } void CharExtVecUsage() { @@ -348,35 +359,35 @@ constexpr auto w = FourCharsExtVec{1, 2, 3, 4} < FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0> constexpr auto x = FourCharsExtVec{1, 2, 3, 4} > FourCharsExtVec{4, 3, 2, 1}; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1> constexpr auto y = FourCharsExtVec{1, 2, 3, 4} <= FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0> constexpr auto z = FourCharsExtVec{1, 2, 3, 4} >= FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1> constexpr auto A = FourCharsExtVec{1, 2, 3, 4} == FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0> constexpr auto B = FourCharsExtVec{1, 2, 3, 4} != FourCharsExtVec{4, 3, 3, 1}; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1> constexpr auto C = FourCharsExtVec{1, 2, 3, 4} < 3; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 0> constexpr auto D = FourCharsExtVec{1, 2, 3, 4} > 3; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 0, i8 -1> constexpr auto E = FourCharsExtVec{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 -1, i8 0> constexpr auto F = FourCharsExtVec{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 1> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 -1> constexpr auto G = FourCharsExtVec{1, 2, 3, 4} == 3; - // CHECK: store <4 x i8> <i8 0, i8 0, i8 1, i8 0> + // CHECK: store <4 x i8> <i8 0, i8 0, i8 -1, i8 0> constexpr auto H = FourCharsExtVec{1, 2, 3, 4} != 3; - // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1> + // CHECK: store <4 x i8> <i8 -1, i8 -1, i8 0, i8 -1> constexpr auto I = FourCharsExtVec{1, 2, 3, 4} & FourCharsExtVec{4, 3, 2, 1}; @@ -421,10 +432,13 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x i8> <i8 12, i8 17, i8 -1, i8 -1> - constexpr auto Z = CmpLSH(a, H); + constexpr auto InvH = -H; + // CHECK: store <4 x i8> <i8 1, i8 1, i8 0, i8 1> + + constexpr auto Z = CmpLSH(a, InvH); // CHECK: store <4 x i8> <i8 36, i8 36, i8 7, i8 16> - constexpr auto aa = CmpRSH(a, H); + constexpr auto aa = CmpRSH(a, InvH); // CHECK: store <4 x i8> <i8 9, i8 9, i8 7, i8 4> constexpr auto ab = CmpBinAnd(a, b); @@ -435,6 +449,12 @@ constexpr auto ad = CmpBinOr(a, b); // CHECK: store <4 x i8> <i8 22, i8 19, i8 15, i8 9> + + constexpr auto ae = ~FourCharsExtVec{1, 2, 10, 20}; + // CHECK: store <4 x i8> <i8 -2, i8 -3, i8 -11, i8 -21> + + constexpr auto af = !FourCharsExtVec{0, 1, 8, -1}; + // CHECK: store <4 x i8> <i8 -1, i8 0, i8 0, i8 0> } void FloatUsage() { @@ -471,35 +491,35 @@ constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} < FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0> constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} > FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1> constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0> constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1> constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} == FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0> constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} != FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1> constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0> constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 -1> constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0> constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1> constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0> constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1> constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} && FourFloatsVecSize{5, 5, 0, 0}; @@ -524,6 +544,13 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x float> <float 1.200000e+01, float 1.700000e+01, float -1.000000e+00, float -1.000000e+00> + + constexpr auto Z = -Y; + // CHECK: store <4 x float> <float -1.200000e+01, float -1.700000e+01, float 1.000000e+00, float 1.000000e+00> + + // Operator ~ is illegal on floats, so no test for that. + constexpr auto af = !FourFloatsVecSize{0, 1, 8, -1}; + // CHECK: store <4 x i32> <i32 -1, i32 0, i32 0, i32 0> } void FloatVecUsage() { @@ -560,35 +587,35 @@ constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} < FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0> constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} > FourFloatsVecSize{4, 3, 2, 1}; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1> constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0> constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >= FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1> constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} == FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0> constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} != FourFloatsVecSize{4, 3, 3, 1}; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1> constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 0> constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 0, i32 -1> constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 -1, i32 0> constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 1> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 -1> constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3; - // CHECK: store <4 x i32> <i32 0, i32 0, i32 1, i32 0> + // CHECK: store <4 x i32> <i32 0, i32 0, i32 -1, i32 0> constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3; - // CHECK: store <4 x i32> <i32 1, i32 1, i32 0, i32 1> + // CHECK: store <4 x i32> <i32 -1, i32 -1, i32 0, i32 -1> constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} && FourFloatsVecSize{5, 5, 0, 0}; @@ -613,4 +640,40 @@ constexpr auto Y = CmpSub(a, b); // CHECK: store <4 x float> <float 1.200000e+01, float 1.700000e+01, float -1.000000e+00, float -1.000000e+00> + + constexpr auto Z = -Y; + // CHECK: store <4 x float> <float -1.200000e+01, float -1.700000e+01, float 1.000000e+00, float 1.000000e+00> + + // Operator ~ is illegal on floats, so no test for that. + constexpr auto af = !FourFloatsVecSize{0, 1, 8, -1}; + // CHECK: store <4 x i32> <i32 -1, i32 0, i32 0, i32 0> +} + +void I128Usage() { + constexpr auto a = FourI128VecSize{1, 2, 3, 4}; + // CHECK: store <4 x i128> <i128 1, i128 2, i128 3, i128 4> + constexpr auto b = a < 3; + // CHECK: store <4 x i128> <i128 -1, i128 -1, i128 0, i128 0> + + // Operator ~ is illegal on floats, so no test for that. + constexpr auto c = ~FourI128VecSize{1, 2, 10, 20}; + // CHECK: store <4 x i128> <i128 -2, i128 -3, i128 -11, i128 -21> + + constexpr auto d = !FourI128VecSize{0, 1, 8, -1}; + // CHECK: store <4 x i128> <i128 -1, i128 0, i128 0, i128 0> +} + +void I128VecUsage() { + constexpr auto a = FourI128ExtVec{1, 2, 3, 4}; + // CHECK: store <4 x i128> <i128 1, i128 2, i128 3, i128 4> + constexpr auto b = a < 3; + // CHECK: store <4 x i128> <i128 -1, i128 -1, i128 0, i128 0> + + // Operator ~ is illegal on floats, so no test for that. + constexpr auto c = ~FourI128ExtVec{1, 2, 10, 20}; + // CHECK: store <4 x i128> <i128 -2, i128 -3, i128 -11, i128 -21> + + constexpr auto d = !FourI128ExtVec{0, 1, 8, -1}; + // CHECK: store <4 x i128> <i128 -1, i128 0, i128 0, i128 0> } + Index: clang/lib/Sema/SemaExpr.cpp =================================================================== --- clang/lib/Sema/SemaExpr.cpp +++ clang/lib/Sema/SemaExpr.cpp @@ -12261,27 +12261,32 @@ if (isa<ExtVectorType>(VTy)) { if (TypeSize == Context.getTypeSize(Context.CharTy)) return Context.getExtVectorType(Context.CharTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + if (TypeSize == Context.getTypeSize(Context.ShortTy)) return Context.getExtVectorType(Context.ShortTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.IntTy)) + if (TypeSize == Context.getTypeSize(Context.IntTy)) return Context.getExtVectorType(Context.IntTy, VTy->getNumElements()); - else if (TypeSize == Context.getTypeSize(Context.LongTy)) + if (TypeSize == Context.getTypeSize(Context.Int128Ty)) + return Context.getExtVectorType(Context.Int128Ty, VTy->getNumElements()); + if (TypeSize == Context.getTypeSize(Context.LongTy)) return Context.getExtVectorType(Context.LongTy, VTy->getNumElements()); assert(TypeSize == Context.getTypeSize(Context.LongLongTy) && "Unhandled vector element size in vector compare"); return Context.getExtVectorType(Context.LongLongTy, VTy->getNumElements()); } + if (TypeSize == Context.getTypeSize(Context.Int128Ty)) + return Context.getVectorType(Context.Int128Ty, VTy->getNumElements(), + VectorType::GenericVector); if (TypeSize == Context.getTypeSize(Context.LongLongTy)) return Context.getVectorType(Context.LongLongTy, VTy->getNumElements(), VectorType::GenericVector); - else if (TypeSize == Context.getTypeSize(Context.LongTy)) + if (TypeSize == Context.getTypeSize(Context.LongTy)) return Context.getVectorType(Context.LongTy, VTy->getNumElements(), VectorType::GenericVector); - else if (TypeSize == Context.getTypeSize(Context.IntTy)) + if (TypeSize == Context.getTypeSize(Context.IntTy)) return Context.getVectorType(Context.IntTy, VTy->getNumElements(), VectorType::GenericVector); - else if (TypeSize == Context.getTypeSize(Context.ShortTy)) + if (TypeSize == Context.getTypeSize(Context.ShortTy)) return Context.getVectorType(Context.ShortTy, VTy->getNumElements(), VectorType::GenericVector); assert(TypeSize == Context.getTypeSize(Context.CharTy) && Index: clang/lib/AST/ExprConstant.cpp =================================================================== --- clang/lib/AST/ExprConstant.cpp +++ clang/lib/AST/ExprConstant.cpp @@ -2931,6 +2931,11 @@ break; } + // The boolean operations on these vector types use an instruction that + // results in a mask of '-1' for the 'truth' value. Ensure that we negate 1 + // to -1 to make sure that we produce the correct value. + Result.negate(); + return true; } @@ -10179,7 +10184,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: conditional operator (for GNU // conditional select), shufflevector, ExtVectorElementExpr }; } // end anonymous namespace @@ -10364,6 +10370,83 @@ return Success(LHSValue, E); } +static llvm::Optional<APValue> handleVectorUnaryOperator(ASTContext &Ctx, + QualType ResultTy, + UnaryOperatorKind Op, + APValue Elt) { + switch (Op) { + case UO_Plus: + // Nothing to do here. + return Elt; + case UO_Minus: + if (Elt.getKind() == APValue::Int) { + Elt.getInt().negate(); + } else { + assert(Elt.getKind() == APValue::Float && + "Vector can only be int or float type"); + Elt.getFloat().changeSign(); + } + return Elt; + case UO_Not: + // This is only valid for integral types anyway, so we don't have to handle + // float here. + assert(Elt.getKind() == APValue::Int && + "Vector operator ~ can only be int"); + Elt.getInt().flipAllBits(); + return Elt; + case UO_LNot: { + if (Elt.getKind() == APValue::Int) { + Elt.getInt() = !Elt.getInt(); + // operator ! on vectors returns -1 for 'truth', so negate it. + Elt.getInt().negate(); + return Elt; + } + assert(Elt.getKind() == APValue::Float && + "Vector can only be int or float type"); + // Float types result in an int of the same size, but -1 for true, or 0 for + // false. + APSInt EltResult{Ctx.getIntWidth(ResultTy), + ResultTy->isUnsignedIntegerType()}; + if (Elt.getFloat().isZero()) + EltResult.setAllBits(); + else + EltResult.clearAllBits(); + + return APValue{EltResult}; + } + default: + // FIXME: Implement the rest of the unary operators. + return llvm::None; + } +} + +bool VectorExprEvaluator::VisitUnaryOperator(const UnaryOperator *E) { + Expr *SubExpr = E->getSubExpr(); + const auto *VD = SubExpr->getType()->castAs<VectorType>(); + // This result element type differs in the case of negating a floating point + // vector, since the result type is the a vector of the equivilant sized + // integer. + const QualType ResultEltTy = VD->getElementType(); + UnaryOperatorKind Op = E->getOpcode(); + + APValue SubExprValue; + if (!Evaluate(SubExprValue, Info, SubExpr)) + return false; + + assert(SubExprValue.getVectorLength() == VD->getNumElements() && + "Vector length doesn't match type?"); + + SmallVector<APValue, 4> ResultElements; + for (unsigned EltNum = 0; EltNum < VD->getNumElements(); ++EltNum) { + llvm::Optional<APValue> Elt = handleVectorUnaryOperator( + Info.Ctx, ResultEltTy, Op, SubExprValue.getVectorElt(EltNum)); + if (!Elt) + return false; + ResultElements.push_back(*Elt); + } + return Success(APValue(ResultElements.data(), ResultElements.size()), E); +} + //===----------------------------------------------------------------------===// // Array Evaluation //===----------------------------------------------------------------------===//
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits