Skip to content

Commit 67f9183

Browse files
authored
[clang][bytecode] Implement comparsion operators for vector type (#107258)
Implement ==, !=, <, <=, >, >= comparsion operators for vector type. --------- Signed-off-by: yronglin <[email protected]>
1 parent 6ec889e commit 67f9183

File tree

3 files changed

+310
-5
lines changed

3 files changed

+310
-5
lines changed

clang/lib/AST/ByteCode/Compiler.cpp

Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -687,6 +687,8 @@ bool Compiler<Emitter>::VisitParenExpr(const ParenExpr *E) {
687687
template <class Emitter>
688688
bool Compiler<Emitter>::VisitBinaryOperator(const BinaryOperator *BO) {
689689
// Need short-circuiting for these.
690+
if (BO->getType()->isVectorType())
691+
return this->VisitVectorBinOp(BO);
690692
if (BO->isLogicalOp())
691693
return this->VisitLogicalBinOp(BO);
692694

@@ -1222,6 +1224,105 @@ bool Compiler<Emitter>::VisitComplexBinOp(const BinaryOperator *E) {
12221224
return true;
12231225
}
12241226

1227+
template <class Emitter>
1228+
bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1229+
assert(E->getType()->isVectorType());
1230+
assert(E->getLHS()->getType()->isVectorType());
1231+
assert(E->getRHS()->getType()->isVectorType());
1232+
1233+
// FIXME: Current only support comparison binary operator, add support for
1234+
// other binary operator.
1235+
if (!E->isComparisonOp())
1236+
return this->emitInvalid(E);
1237+
// Prepare storage for result.
1238+
if (!Initializing) {
1239+
unsigned LocalIndex = allocateTemporary(E);
1240+
if (!this->emitGetPtrLocal(LocalIndex, E))
1241+
return false;
1242+
}
1243+
1244+
const Expr *LHS = E->getLHS();
1245+
const Expr *RHS = E->getRHS();
1246+
const auto *VecTy = E->getType()->getAs<VectorType>();
1247+
1248+
// The LHS and RHS of a comparison operator must have the same type. So we
1249+
// just use LHS vector element type here.
1250+
PrimType ElemT = this->classifyVectorElementType(LHS->getType());
1251+
PrimType ResultElemT = this->classifyVectorElementType(E->getType());
1252+
1253+
// Evaluate LHS and save value to LHSOffset.
1254+
unsigned LHSOffset = this->allocateLocalPrimitive(LHS, PT_Ptr, true, false);
1255+
if (!this->visit(LHS))
1256+
return false;
1257+
if (!this->emitSetLocal(PT_Ptr, LHSOffset, E))
1258+
return false;
1259+
1260+
// Evaluate RHS and save value to RHSOffset.
1261+
unsigned RHSOffset = this->allocateLocalPrimitive(RHS, PT_Ptr, true, false);
1262+
if (!this->visit(RHS))
1263+
return false;
1264+
if (!this->emitSetLocal(PT_Ptr, RHSOffset, E))
1265+
return false;
1266+
1267+
auto getElem = [=](unsigned Offset, unsigned Index) {
1268+
if (!this->emitGetLocal(PT_Ptr, Offset, E))
1269+
return false;
1270+
return this->emitArrayElemPop(ElemT, Index, E);
1271+
};
1272+
1273+
for (unsigned I = 0; I != VecTy->getNumElements(); ++I) {
1274+
if (!getElem(LHSOffset, I))
1275+
return false;
1276+
if (!getElem(RHSOffset, I))
1277+
return false;
1278+
switch (E->getOpcode()) {
1279+
case BO_EQ:
1280+
if (!this->emitEQ(ElemT, E))
1281+
return false;
1282+
break;
1283+
case BO_NE:
1284+
if (!this->emitNE(ElemT, E))
1285+
return false;
1286+
break;
1287+
case BO_LE:
1288+
if (!this->emitLE(ElemT, E))
1289+
return false;
1290+
break;
1291+
case BO_LT:
1292+
if (!this->emitLT(ElemT, E))
1293+
return false;
1294+
break;
1295+
case BO_GE:
1296+
if (!this->emitGE(ElemT, E))
1297+
return false;
1298+
break;
1299+
case BO_GT:
1300+
if (!this->emitGT(ElemT, E))
1301+
return false;
1302+
break;
1303+
default:
1304+
llvm_unreachable("Unsupported binary operator");
1305+
}
1306+
1307+
// The result of the comparison is a vector of the same width and number
1308+
// of elements as the comparison operands with a signed integral element
1309+
// type.
1310+
//
1311+
// https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html
1312+
if (E->isComparisonOp()) {
1313+
if (!this->emitPrimCast(PT_Bool, ResultElemT, VecTy->getElementType(), E))
1314+
return false;
1315+
if (!this->emitNeg(ResultElemT, E))
1316+
return false;
1317+
}
1318+
1319+
// Initialize array element with the value we just computed.
1320+
if (!this->emitInitElem(ResultElemT, I, E))
1321+
return false;
1322+
}
1323+
return true;
1324+
}
1325+
12251326
template <class Emitter>
12261327
bool Compiler<Emitter>::VisitImplicitValueInitExpr(
12271328
const ImplicitValueInitExpr *E) {

clang/lib/AST/ByteCode/Compiler.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
130130
bool VisitLogicalBinOp(const BinaryOperator *E);
131131
bool VisitPointerArithBinOp(const BinaryOperator *E);
132132
bool VisitComplexBinOp(const BinaryOperator *E);
133+
bool VisitVectorBinOp(const BinaryOperator *E);
133134
bool VisitCXXDefaultArgExpr(const CXXDefaultArgExpr *E);
134135
bool VisitCallExpr(const CallExpr *E);
135136
bool VisitBuiltinCallExpr(const CallExpr *E);
@@ -363,7 +364,6 @@ class Compiler : public ConstStmtVisitor<Compiler<Emitter>, bool>,
363364
bool emitComplexBoolCast(const Expr *E);
364365
bool emitComplexComparison(const Expr *LHS, const Expr *RHS,
365366
const BinaryOperator *E);
366-
367367
bool emitRecordDestruction(const Record *R);
368368
bool emitDestruction(const Descriptor *Desc);
369369
unsigned collectBaseOffset(const QualType BaseType,

clang/test/AST/ByteCode/constexpr-vectors.cpp

Lines changed: 208 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,50 @@ using FourI128ExtVec __attribute__((ext_vector_type(4))) = __int128;
1515
// Only int vs float makes a difference here, so we only need to test 1 of each.
1616
// Test Char to make sure the mixed-nature of shifts around char is evident.
1717
void CharUsage() {
18-
constexpr auto H = FourCharsVecSize{-1, -1, 0, -1};
19-
constexpr auto InvH = -H;
18+
constexpr auto w = FourCharsVecSize{1, 2, 3, 4} <
19+
FourCharsVecSize{4, 3, 2, 1};
20+
static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, "");
21+
22+
constexpr auto x = FourCharsVecSize{1, 2, 3, 4} >
23+
FourCharsVecSize{4, 3, 2, 1};
24+
static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[3] == -1, "");
25+
26+
constexpr auto y = FourCharsVecSize{1, 2, 3, 4} <=
27+
FourCharsVecSize{4, 3, 3, 1};
28+
static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, "");
29+
30+
constexpr auto z = FourCharsVecSize{1, 2, 3, 4} >=
31+
FourCharsVecSize{4, 3, 3, 1};
32+
static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, "");
33+
34+
constexpr auto A = FourCharsVecSize{1, 2, 3, 4} ==
35+
FourCharsVecSize{4, 3, 3, 1};
36+
static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, "");
37+
38+
constexpr auto B = FourCharsVecSize{1, 2, 3, 4} !=
39+
FourCharsVecSize{4, 3, 3, 1};
40+
static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, "");
41+
42+
constexpr auto C = FourCharsVecSize{1, 2, 3, 4} < 3;
43+
static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, "");
44+
45+
constexpr auto D = FourCharsVecSize{1, 2, 3, 4} > 3;
46+
static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, "");
47+
48+
constexpr auto E = FourCharsVecSize{1, 2, 3, 4} <= 3;
49+
static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, "");
50+
51+
constexpr auto F = FourCharsVecSize{1, 2, 3, 4} >= 3;
52+
static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, "");
53+
54+
constexpr auto G = FourCharsVecSize{1, 2, 3, 4} == 3;
55+
static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, "");
56+
57+
constexpr auto H = FourCharsVecSize{1, 2, 3, 4} != 3;
58+
static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
59+
60+
constexpr auto H1 = FourCharsVecSize{-1, -1, 0, -1};
61+
constexpr auto InvH = -H1;
2062
static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, "");
2163

2264
constexpr auto ae = ~FourCharsVecSize{1, 2, 10, 20};
@@ -27,8 +69,50 @@ void CharUsage() {
2769
}
2870

2971
void CharExtVecUsage() {
30-
constexpr auto H = FourCharsExtVec{-1, -1, 0, -1};
31-
constexpr auto InvH = -H;
72+
constexpr auto w = FourCharsExtVec{1, 2, 3, 4} <
73+
FourCharsExtVec{4, 3, 2, 1};
74+
static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, "");
75+
76+
constexpr auto x = FourCharsExtVec{1, 2, 3, 4} >
77+
FourCharsExtVec{4, 3, 2, 1};
78+
static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[3] == -1, "");
79+
80+
constexpr auto y = FourCharsExtVec{1, 2, 3, 4} <=
81+
FourCharsExtVec{4, 3, 3, 1};
82+
static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, "");
83+
84+
constexpr auto z = FourCharsExtVec{1, 2, 3, 4} >=
85+
FourCharsExtVec{4, 3, 3, 1};
86+
static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, "");
87+
88+
constexpr auto A = FourCharsExtVec{1, 2, 3, 4} ==
89+
FourCharsExtVec{4, 3, 3, 1};
90+
static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, "");
91+
92+
constexpr auto B = FourCharsExtVec{1, 2, 3, 4} !=
93+
FourCharsExtVec{4, 3, 3, 1};
94+
static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, "");
95+
96+
constexpr auto C = FourCharsExtVec{1, 2, 3, 4} < 3;
97+
static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, "");
98+
99+
constexpr auto D = FourCharsExtVec{1, 2, 3, 4} > 3;
100+
static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, "");
101+
102+
constexpr auto E = FourCharsExtVec{1, 2, 3, 4} <= 3;
103+
static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, "");
104+
105+
constexpr auto F = FourCharsExtVec{1, 2, 3, 4} >= 3;
106+
static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, "");
107+
108+
constexpr auto G = FourCharsExtVec{1, 2, 3, 4} == 3;
109+
static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, "");
110+
111+
constexpr auto H = FourCharsExtVec{1, 2, 3, 4} != 3;
112+
static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
113+
114+
constexpr auto H1 = FourCharsExtVec{-1, -1, 0, -1};
115+
constexpr auto InvH = -H1;
32116
static_assert(InvH[0] == 1 && InvH[1] == 1 && InvH[2] == 0 && InvH[3] == 1, "");
33117

34118
constexpr auto ae = ~FourCharsExtVec{1, 2, 10, 20};
@@ -39,6 +123,48 @@ void CharExtVecUsage() {
39123
}
40124

41125
void FloatUsage() {
126+
constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} <
127+
FourFloatsVecSize{4, 3, 2, 1};
128+
static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, "");
129+
130+
constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} >
131+
FourFloatsVecSize{4, 3, 2, 1};
132+
static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[3] == -1, "");
133+
134+
constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <=
135+
FourFloatsVecSize{4, 3, 3, 1};
136+
static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, "");
137+
138+
constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >=
139+
FourFloatsVecSize{4, 3, 3, 1};
140+
static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, "");
141+
142+
constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} ==
143+
FourFloatsVecSize{4, 3, 3, 1};
144+
static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, "");
145+
146+
constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} !=
147+
FourFloatsVecSize{4, 3, 3, 1};
148+
static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, "");
149+
150+
constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3;
151+
static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, "");
152+
153+
constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3;
154+
static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, "");
155+
156+
constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3;
157+
static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, "");
158+
159+
constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3;
160+
static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, "");
161+
162+
constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3;
163+
static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, "");
164+
165+
constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3;
166+
static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
167+
42168
constexpr auto Y = FourFloatsVecSize{1.200000e+01, 1.700000e+01, -1.000000e+00, -1.000000e+00};
43169
constexpr auto Z = -Y;
44170
static_assert(Z[0] == -1.200000e+01 && Z[1] == -1.700000e+01 && Z[2] == 1.000000e+00 && Z[3] == 1.000000e+00, "");
@@ -51,6 +177,48 @@ void FloatUsage() {
51177
}
52178

53179
void FloatVecUsage() {
180+
constexpr auto w = FourFloatsVecSize{1, 2, 3, 4} <
181+
FourFloatsVecSize{4, 3, 2, 1};
182+
static_assert(w[0] == -1 && w[1] == -1 && w[2] == 0 && w[3] == 0, "");
183+
184+
constexpr auto x = FourFloatsVecSize{1, 2, 3, 4} >
185+
FourFloatsVecSize{4, 3, 2, 1};
186+
static_assert(x[0] == 0 && x[1] == 0 && x[2] == -1 && x[2] == -1, "");
187+
188+
constexpr auto y = FourFloatsVecSize{1, 2, 3, 4} <=
189+
FourFloatsVecSize{4, 3, 3, 1};
190+
static_assert(y[0] == -1 && y[1] == -1 && y[2] == -1 && y[3] == 0, "");
191+
192+
constexpr auto z = FourFloatsVecSize{1, 2, 3, 4} >=
193+
FourFloatsVecSize{4, 3, 3, 1};
194+
static_assert(z[0] == 0 && z[1] == 0 && z[2] == -1 && z[3] == -1, "");
195+
196+
constexpr auto A = FourFloatsVecSize{1, 2, 3, 4} ==
197+
FourFloatsVecSize{4, 3, 3, 1};
198+
static_assert(A[0] == 0 && A[1] == 0 && A[2] == -1 && A[3] == 0, "");
199+
200+
constexpr auto B = FourFloatsVecSize{1, 2, 3, 4} !=
201+
FourFloatsVecSize{4, 3, 3, 1};
202+
static_assert(B[0] == -1 && B[1] == -1 && B[2] == 0 && B[3] == -1, "");
203+
204+
constexpr auto C = FourFloatsVecSize{1, 2, 3, 4} < 3;
205+
static_assert(C[0] == -1 && C[1] == -1 && C[2] == 0 && C[3] == 0, "");
206+
207+
constexpr auto D = FourFloatsVecSize{1, 2, 3, 4} > 3;
208+
static_assert(D[0] == 0 && D[1] == 0 && D[2] == 0 && D[3] == -1, "");
209+
210+
constexpr auto E = FourFloatsVecSize{1, 2, 3, 4} <= 3;
211+
static_assert(E[0] == -1 && E[1] == -1 && E[2] == -1 && E[3] == 0, "");
212+
213+
constexpr auto F = FourFloatsVecSize{1, 2, 3, 4} >= 3;
214+
static_assert(F[0] == 0 && F[1] == 0 && F[2] == -1 && F[3] == -1, "");
215+
216+
constexpr auto G = FourFloatsVecSize{1, 2, 3, 4} == 3;
217+
static_assert(G[0] == 0 && G[1] == 0 && G[2] == -1 && G[3] == 0, "");
218+
219+
constexpr auto H = FourFloatsVecSize{1, 2, 3, 4} != 3;
220+
static_assert(H[0] == -1 && H[1] == -1 && H[2] == 0 && H[3] == -1, "");
221+
54222
constexpr auto Y = FourFloatsVecSize{1.200000e+01, 1.700000e+01, -1.000000e+00, -1.000000e+00};
55223
constexpr auto Z = -Y;
56224
static_assert(Z[0] == -1.200000e+01 && Z[1] == -1.700000e+01 && Z[2] == 1.000000e+00 && Z[3] == 1.000000e+00, "");
@@ -63,6 +231,12 @@ void FloatVecUsage() {
63231
}
64232

65233
void I128Usage() {
234+
constexpr auto a = FourI128VecSize{1, 2, 3, 4};
235+
static_assert(a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4, "");
236+
237+
constexpr auto b = a < 3;
238+
static_assert(b[0] == -1 && b[1] == -1 && b[2] == 0 && b[3] == 0, "");
239+
66240
// Operator ~ is illegal on floats, so no test for that.
67241
constexpr auto c = ~FourI128VecSize{1, 2, 10, 20};
68242
static_assert(c[0] == -2 && c[1] == -3 && c[2] == -11 && c[3] == -21, "");
@@ -72,6 +246,12 @@ void I128Usage() {
72246
}
73247

74248
void I128VecUsage() {
249+
constexpr auto a = FourI128ExtVec{1, 2, 3, 4};
250+
static_assert(a[0] == 1 && a[1] == 2 && a[2] == 3 && a[3] == 4, "");
251+
252+
constexpr auto b = a < 3;
253+
static_assert(b[0] == -1 && b[1] == -1 && b[2] == 0 && b[3] == 0, "");
254+
75255
// Operator ~ is illegal on floats, so no test for that.
76256
constexpr auto c = ~FourI128ExtVec{1, 2, 10, 20};
77257
static_assert(c[0] == -2 && c[1] == -3 && c[2] == -11 && c[3] == -21, "");
@@ -82,6 +262,30 @@ void I128VecUsage() {
82262

83263
using FourBoolsExtVec __attribute__((ext_vector_type(4))) = bool;
84264
void BoolVecUsage() {
265+
constexpr auto a = FourBoolsExtVec{true, false, true, false} <
266+
FourBoolsExtVec{false, false, true, true};
267+
static_assert(a[0] == false && a[1] == false && a[2] == false && a[3] == true, "");
268+
269+
constexpr auto b = FourBoolsExtVec{true, false, true, false} <=
270+
FourBoolsExtVec{false, false, true, true};
271+
static_assert(b[0] == false && b[1] == true && b[2] == true && b[3] == true, "");
272+
273+
constexpr auto c = FourBoolsExtVec{true, false, true, false} ==
274+
FourBoolsExtVec{false, false, true, true};
275+
static_assert(c[0] == false && c[1] == true && c[2] == true && c[3] == false, "");
276+
277+
constexpr auto d = FourBoolsExtVec{true, false, true, false} !=
278+
FourBoolsExtVec{false, false, true, true};
279+
static_assert(d[0] == true && d[1] == false && d[2] == false && d[3] == true, "");
280+
281+
constexpr auto e = FourBoolsExtVec{true, false, true, false} >=
282+
FourBoolsExtVec{false, false, true, true};
283+
static_assert(e[0] == true && e[1] == true && e[2] == true && e[3] == false, "");
284+
285+
constexpr auto f = FourBoolsExtVec{true, false, true, false} >
286+
FourBoolsExtVec{false, false, true, true};
287+
static_assert(f[0] == true && f[1] == false && f[2] == false && f[3] == false, "");
288+
85289
constexpr auto j = !FourBoolsExtVec{true, false, true, false};
86290
static_assert(j[0] == false && j[1] == true && j[2] == false && j[3] == true, "");
87291

0 commit comments

Comments
 (0)