@@ -1267,12 +1267,8 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1267
1267
assert (E->getLHS ()->getType ()->isVectorType ());
1268
1268
assert (E->getRHS ()->getType ()->isVectorType ());
1269
1269
1270
- // FIXME: Current only support comparison binary operator, add support for
1271
- // other binary operator.
1272
- if (!E->isComparisonOp () && !E->isLogicalOp ())
1273
- return this ->emitInvalid (E);
1274
1270
// Prepare storage for result.
1275
- if (!Initializing) {
1271
+ if (!Initializing && !E-> isCompoundAssignmentOp () ) {
1276
1272
unsigned LocalIndex = allocateTemporary (E);
1277
1273
if (!this ->emitGetPtrLocal (LocalIndex, E))
1278
1274
return false ;
@@ -1281,6 +1277,9 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1281
1277
const Expr *LHS = E->getLHS ();
1282
1278
const Expr *RHS = E->getRHS ();
1283
1279
const auto *VecTy = E->getType ()->getAs <VectorType>();
1280
+ auto Op = E->isCompoundAssignmentOp ()
1281
+ ? BinaryOperator::getOpForCompoundAssignment (E->getOpcode ())
1282
+ : E->getOpcode ();
1284
1283
1285
1284
// The LHS and RHS of a comparison operator must have the same type. So we
1286
1285
// just use LHS vector element type here.
@@ -1301,6 +1300,17 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1301
1300
if (!this ->emitSetLocal (PT_Ptr, RHSOffset, E))
1302
1301
return false ;
1303
1302
1303
+ if (E->isCompoundAssignmentOp () && !this ->emitGetLocal (PT_Ptr, LHSOffset, E))
1304
+ return false ;
1305
+
1306
+ // BitAdd/BitOr/BitXor/Shl/Shr doesn't support bool type, we need perform the
1307
+ // integer promotion.
1308
+ bool NeedIntPromot = ElemT == PT_Bool && (E->isBitwiseOp () || E->isShiftOp ());
1309
+ QualType PromotTy =
1310
+ Ctx.getASTContext ().getPromotedIntegerType (Ctx.getASTContext ().BoolTy );
1311
+ PrimType PromotT = classifyPrim (PromotTy);
1312
+ PrimType OpT = NeedIntPromot ? PromotT : ElemT;
1313
+
1304
1314
auto getElem = [=](unsigned Offset, unsigned Index) {
1305
1315
if (!this ->emitGetLocal (PT_Ptr, Offset, E))
1306
1316
return false ;
@@ -1311,16 +1321,63 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1311
1321
return false ;
1312
1322
if (!this ->emitPrimCast (PT_Bool, ResultElemT, VecTy->getElementType (), E))
1313
1323
return false ;
1324
+ } else if (NeedIntPromot) {
1325
+ if (!this ->emitPrimCast (ElemT, PromotT, PromotTy, E))
1326
+ return false ;
1314
1327
}
1315
1328
return true ;
1316
1329
};
1317
1330
1331
+ #define EMIT_ARITH_OP (OP ) \
1332
+ { \
1333
+ if (ElemT == PT_Float) { \
1334
+ if (!this ->emit ##OP##f (getFPOptions (E), E)) \
1335
+ return false ; \
1336
+ } else { \
1337
+ if (!this ->emit ##OP (ElemT, E)) \
1338
+ return false ; \
1339
+ } \
1340
+ break ; \
1341
+ }
1342
+
1318
1343
for (unsigned I = 0 ; I != VecTy->getNumElements (); ++I) {
1319
1344
if (!getElem (LHSOffset, I))
1320
1345
return false ;
1321
1346
if (!getElem (RHSOffset, I))
1322
1347
return false ;
1323
- switch (E->getOpcode ()) {
1348
+ switch (Op) {
1349
+ case BO_Add:
1350
+ EMIT_ARITH_OP (Add)
1351
+ case BO_Sub:
1352
+ EMIT_ARITH_OP (Sub)
1353
+ case BO_Mul:
1354
+ EMIT_ARITH_OP (Mul)
1355
+ case BO_Div:
1356
+ EMIT_ARITH_OP (Div)
1357
+ case BO_Rem:
1358
+ if (!this ->emitRem (ElemT, E))
1359
+ return false ;
1360
+ break ;
1361
+ case BO_And:
1362
+ if (!this ->emitBitAnd (OpT, E))
1363
+ return false ;
1364
+ break ;
1365
+ case BO_Or:
1366
+ if (!this ->emitBitOr (OpT, E))
1367
+ return false ;
1368
+ break ;
1369
+ case BO_Xor:
1370
+ if (!this ->emitBitXor (OpT, E))
1371
+ return false ;
1372
+ break ;
1373
+ case BO_Shl:
1374
+ if (!this ->emitShl (OpT, ElemT, E))
1375
+ return false ;
1376
+ break ;
1377
+ case BO_Shr:
1378
+ if (!this ->emitShr (OpT, ElemT, E))
1379
+ return false ;
1380
+ break ;
1324
1381
case BO_EQ:
1325
1382
if (!this ->emitEQ (ElemT, E))
1326
1383
return false ;
@@ -1356,7 +1413,7 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1356
1413
return false ;
1357
1414
break ;
1358
1415
default :
1359
- llvm_unreachable ( " Unsupported binary operator " );
1416
+ return this -> emitInvalid (E );
1360
1417
}
1361
1418
1362
1419
// The result of the comparison is a vector of the same width and number
@@ -1371,10 +1428,19 @@ bool Compiler<Emitter>::VisitVectorBinOp(const BinaryOperator *E) {
1371
1428
return false ;
1372
1429
}
1373
1430
1431
+ // If we performed an integer promotion, we need to cast the compute result
1432
+ // into result vector element type.
1433
+ if (NeedIntPromot &&
1434
+ !this ->emitPrimCast (PromotT, ResultElemT, VecTy->getElementType (), E))
1435
+ return false ;
1436
+
1374
1437
// Initialize array element with the value we just computed.
1375
1438
if (!this ->emitInitElem (ResultElemT, I, E))
1376
1439
return false ;
1377
1440
}
1441
+
1442
+ if (DiscardResult && E->isCompoundAssignmentOp () && !this ->emitPopPtr (E))
1443
+ return false ;
1378
1444
return true ;
1379
1445
}
1380
1446
@@ -2294,6 +2360,8 @@ bool Compiler<Emitter>::VisitPointerCompoundAssignOperator(
2294
2360
template <class Emitter >
2295
2361
bool Compiler<Emitter>::VisitCompoundAssignOperator(
2296
2362
const CompoundAssignOperator *E) {
2363
+ if (E->getType ()->isVectorType ())
2364
+ return VisitVectorBinOp (E);
2297
2365
2298
2366
const Expr *LHS = E->getLHS ();
2299
2367
const Expr *RHS = E->getRHS ();
0 commit comments