Skip to content

[clang][bytecode] Implement logical operators for vector type #107678

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
Sep 8, 2024

Conversation

yronglin
Copy link
Contributor

@yronglin yronglin commented Sep 7, 2024

Implement &&, || logical operators for vector type.

@yronglin yronglin requested a review from tbaederr September 7, 2024 08:54
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Sep 7, 2024
@llvmbot
Copy link
Member

llvmbot commented Sep 7, 2024

@llvm/pr-subscribers-clang

Author: None (yronglin)

Changes

Implement &&, || logical operators for vector type.


Full diff: https://github.com/llvm/llvm-project/pull/107678.diff

2 Files Affected:

  • (modified) clang/lib/AST/ByteCode/Compiler.cpp (+21-2)
  • (modified) clang/test/AST/ByteCode/constexpr-vectors.cpp (+90)
diff --git a/clang/lib/AST/ByteCode/Compiler.cpp b/clang/lib/AST/ByteCode/Compiler.cpp
index eea77c2f0a9bb4..0dd690a69dca71 100644
--- a/clang/lib/AST/ByteCode/Compiler.cpp
+++ b/clang/lib/AST/ByteCode/Compiler.cpp
@@ -15,6 +15,7 @@
 #include "PrimType.h"
 #include "Program.h"
 #include "clang/AST/Attr.h"
+#include "clang/AST/OperationKinds.h"
 
 using namespace clang;
 using namespace clang::interp;
@@ -1232,7 +1233,7 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
 
   // FIXME: Current only support comparison binary operator, add support for
   // other binary operator.
-  if (!E->isComparisonOp())
+  if (!E->isComparisonOp() && !E->isLogicalOp())
     return this->emitInvalid(E);
   // Prepare storage for result.
   if (!Initializing) {
@@ -1267,7 +1268,15 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
   auto getElem = [=](unsigned Offset, unsigned Index) {
     if (!this->emitGetLocal(PT_Ptr, Offset, E))
       return false;
-    return this->emitArrayElemPop(ElemT, Index, E);
+    if (!this->emitArrayElemPop(ElemT, Index, E))
+      return false;
+    if (E->isLogicalOp()) {
+      if (!this->emitPrimCast(ElemT, PT_Bool, Ctx.getASTContext().BoolTy, E))
+        return false;
+      if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))
+        return false;
+    }
+    return true;
   };
 
   for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
@@ -1300,6 +1309,16 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
       if (!this->emitGT(ElemT, E))
         return false;
       break;
+    case BO_LAnd:
+      // a && b is equivalent to a!=0 & b!=0
+      if (!this->emitBitAnd(ResultElemT, E))
+        return false;
+      break;
+    case BO_LOr:
+      // a || b is equivalent to a!=0 | b!=0
+      if (!this->emitBitOr(ResultElemT, E))
+        return false;
+      break;
     default:
       llvm_unreachable("Unsupported binary operator");
     }
diff --git a/clang/test/AST/ByteCode/constexpr-vectors.cpp b/clang/test/AST/ByteCode/constexpr-vectors.cpp
index 684c5810702cc3..7a65b263784586 100644
--- a/clang/test/AST/ByteCode/constexpr-vectors.cpp
+++ b/clang/test/AST/ByteCode/constexpr-vectors.cpp
@@ -57,6 +57,20 @@ void CharUsage() {
   constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3;
   static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
 
+  constexpr auto O = FourCharsVecSize{5, 0, 6, 0} &&
+                     FourCharsVecSize{5, 5, 0, 0};
+  static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, "");
+
+  constexpr auto P = FourCharsVecSize{5, 0, 6, 0} ||
+                     FourCharsVecSize{5, 5, 0, 0};
+  static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, "");
+
+  constexpr auto Q = FourCharsVecSize{5, 0, 6, 0} && 3;
+  static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, "");
+
+  constexpr auto R = FourCharsVecSize{5, 0, 6, 0} || 3;
+  static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, "");
+
   constexpr auto H1 = FourCharsVecSize{-1, -1, 0, -1};
   constexpr auto InvH = -H1;
   static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, "");
@@ -111,6 +125,21 @@ void CharExtVecUsage() {
   constexpr auto H = FourCharsExtVec{1, 2, 3, 4} != 3;
   static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
 
+  constexpr auto O = FourCharsExtVec{5, 0, 6, 0} &&
+                     FourCharsExtVec{5, 5, 0, 0};
+  static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, "");
+
+  constexpr auto P = FourCharsExtVec{5, 0, 6, 0} ||
+                     FourCharsExtVec{5, 5, 0, 0};
+  static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, "");
+
+  constexpr auto Q = FourCharsExtVec{5, 0, 6, 0} && 3;
+  static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, "");
+
+  constexpr auto R = FourCharsExtVec{5, 0, 6, 0} || 3;
+  static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, "");
+
+
   constexpr auto H1 = FourCharsExtVec{-1, -1, 0, -1};
   constexpr auto InvH = -H1;
   static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, "");
@@ -165,10 +194,33 @@ void FloatUsage() {
   constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3;
   static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
 
+  constexpr auto O1 = FourFloatsVecSize{5, 0, 6, 0} &&
+                     FourFloatsVecSize{5, 5, 0, 0};
+  static_assert(O1[0] == 1 && O1[1] == 0 && O1[2] == 0 && O1[3] == 0, "");
+
+  constexpr auto P1 = FourFloatsVecSize{5, 0, 6, 0} ||
+                     FourFloatsVecSize{5, 5, 0, 0};
+  static_assert(P1[0] == 1 && P1[1] == 1 && P1[2] == 1 && P1[3] == 0, "");
+
+  constexpr auto Q = FourFloatsVecSize{5, 0, 6, 0} && 3;
+  static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, "");
+
+  constexpr auto R = FourFloatsVecSize{5, 0, 6, 0} || 3;
+  static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, "");
+
+
   constexpr auto Y = FourFloatsVecSize{1.200000e+01, 1.700000e+01, -1.000000e+00, -1.000000e+00};
   constexpr auto Z = -Y;
   static_assert(Z[0] == -1.200000e+01 && Z[1] == -1.700000e+01 && Z[2] == 1.000000e+00 && Z[3] == 1.000000e+00, "");
 
+  constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} &&
+                     FourFloatsVecSize{5, 5, 0, 0};
+  static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, "");
+
+  constexpr auto P = FourFloatsVecSize{5, 0, 6, 0} ||
+                     FourFloatsVecSize{5, 5, 0, 0};
+  static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, "");
+
   // Operator ~ is illegal on floats.
   constexpr auto ae = ~FourFloatsVecSize{0, 1, 8, -1}; // expected-error {{invalid argument type}}
 
@@ -219,6 +271,20 @@ void FloatVecUsage() {
   constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3;
   static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
 
+  constexpr auto O = FourFloatsVecSize{5, 0, 6, 0} &&
+                     FourFloatsVecSize{5, 5, 0, 0};
+  static_assert(O[0] == 1 && O[1] == 0 && O[2] == 0 && O[3] == 0, "");
+
+  constexpr auto P = FourFloatsVecSize{5, 0, 6, 0} ||
+                     FourFloatsVecSize{5, 5, 0, 0};
+  static_assert(P[0] == 1 && P[1] == 1 && P[2] == 1 && P[3] == 0, "");
+
+  constexpr auto Q = FourFloatsVecSize{5, 0, 6, 0} && 3;
+  static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, "");
+
+  constexpr auto R = FourFloatsVecSize{5, 0, 6, 0} || 3;
+  static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, "");
+
   constexpr auto Y = FourFloatsVecSize{1.200000e+01, 1.700000e+01, -1.000000e+00, -1.000000e+00};
   constexpr auto Z = -Y;
   static_assert(Z[0] == -1.200000e+01 && Z[1] == -1.700000e+01 && Z[2] == 1.000000e+00 && Z[3] == 1.000000e+00, "");
@@ -234,6 +300,18 @@ void I128Usage() {
   constexpr auto a = FourI128VecSize{1, 2, 3, 4};
   static_assert(a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4, "");
 
+  constexpr auto a1 = FourI128VecSize{5, 0, 6, 0} && FourI128VecSize{5, 5, 0, 0};
+  static_assert(a1[0] == 1 && a1[1] == 0 && a1[2] == 0 && a1[3] == 0, "");
+
+  constexpr auto a2 = FourI128VecSize{5, 0, 6, 0} || FourI128VecSize{5, 5, 0, 0};
+  static_assert(a2[0] == 1 && a2[1] == 1 && a2[2] == 1 && a2[3] == 0, "");
+
+  constexpr auto Q = FourI128VecSize{5, 0, 6, 0} && 3;
+  static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, "");
+
+  constexpr auto R = FourI128VecSize{5, 0, 6, 0} || 3;
+  static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, "");
+
   constexpr auto b = a < 3;
   static_assert(b[0] == -1 && b[1] == -1 && b[2] == 0 && b[3] == 0, "");
 
@@ -249,6 +327,18 @@ void I128VecUsage() {
   constexpr auto a = FourI128ExtVec{1, 2, 3, 4};
   static_assert(a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4, "");
 
+  constexpr auto a1 = FourI128ExtVec{5, 0, 6, 0} && FourI128ExtVec{5, 5, 0, 0};
+  static_assert(a1[0] == 1 && a1[1] == 0 && a1[2] == 0 && a1[3] == 0, "");
+
+  constexpr auto a2 = FourI128ExtVec{5, 0, 6, 0} || FourI128ExtVec{5, 5, 0, 0};
+  static_assert(a2[0] == 1 && a2[1] == 1 && a2[2] == 1 && a2[3] == 0, "");
+
+  constexpr auto Q = FourI128ExtVec{5, 0, 6, 0} && 3;
+  static_assert(Q[0] == 1 && Q[1] == 0 && Q[2] == 1 && Q[3] == 0, "");
+
+  constexpr auto R = FourI128ExtVec{5, 0, 6, 0} || 3;
+  static_assert(R[0] == 1 && R[1] == 1 && R[2] == 1 && R[3] == 1, "");
+
   constexpr auto b = a < 3;
   static_assert(b[0] == -1 && b[1] == -1 && b[2] == 0 && b[3] == 0, "");
 

@yronglin
Copy link
Contributor Author

yronglin commented Sep 8, 2024

Thanks for the review!

@yronglin yronglin merged commit cf11eb6 into llvm:main Sep 8, 2024
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants