Allow vectors to be compared for (not-)equality

I don't know how much sense that makes, as the front-end expects a result
expression of a single bool.
LLVM returns a vector of i1 values, the pair-wise results.
From my experience with SIMD on x86_64, what's mostly needed is a vector
bit mask, as that's what the CPU returns and which is later used to mask
accesses/writes.

Anyway, due to new `Target.isVectorOpSupported()` simply allowing all ops,
(not-)equality comparisons of vectors now land here, and I reduce the
pair-wise results via integer bitcast and an additional integer
comparison.
This commit is contained in:
Martin 2017-08-04 21:32:25 +02:00
parent 988444c899
commit db8797e1ce
4 changed files with 40 additions and 12 deletions

View file

@ -324,18 +324,17 @@ LLValue *DtoBinNumericEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op) {
LLValue *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op) { LLValue *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op) {
LLValue *res = nullptr; LLValue *res = nullptr;
if (op == TOKequal) { if (op == TOKequal || op == TOKnotequal) {
res = gIR->ir->CreateFCmpOEQ(DtoRVal(lhs), DtoRVal(rhs)); LLValue *l = DtoRVal(lhs);
} else if (op == TOKnotequal) { LLValue *r = DtoRVal(rhs);
res = gIR->ir->CreateFCmpUNE(DtoRVal(lhs), DtoRVal(rhs)); res = (op == TOKequal ? gIR->ir->CreateFCmpOEQ(l, r)
} else { : gIR->ir->CreateFCmpUNE(l, r));
llvm::ICmpInst::Predicate cmpop; if (lhs->type->toBasetype()->ty == Tvector) {
if (op == TOKidentity) { res = mergeVectorEquals(res, op);
cmpop = llvm::ICmpInst::ICMP_EQ;
} else {
cmpop = llvm::ICmpInst::ICMP_NE;
} }
} else {
const auto cmpop =
op == TOKidentity ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
LLValue *sz = DtoConstSize_t(getTypeStoreSize(DtoType(lhs->type))); LLValue *sz = DtoConstSize_t(getTypeStoreSize(DtoType(lhs->type)));
LLValue *val = DtoMemCmp(makeLValue(loc, lhs), makeLValue(loc, rhs), sz); LLValue *val = DtoMemCmp(makeLValue(loc, lhs), makeLValue(loc, rhs), sz);
res = gIR->ir->CreateICmp(cmpop, val, res = gIR->ir->CreateICmp(cmpop, val,
@ -344,3 +343,28 @@ LLValue *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op) {
assert(res); assert(res);
return res; return res;
} }
//////////////////////////////////////////////////////////////////////////////
LLValue *mergeVectorEquals(LLValue *resultsVector, TOK op) {
// `resultsVector` is a vector of i1 values, the pair-wise results.
// Bitcast to an integer and checks the bits via additional integer
// comparison.
const auto sizeInBits = getTypeBitSize(resultsVector->getType());
LLType *integerType = LLType::getIntNTy(gIR->context(), sizeInBits);
LLValue *v = DtoBitCast(resultsVector, integerType);
if (op == TOKequal) {
// all pairs must be equal for the vectors to be equal
LLConstant *allEqual =
LLConstantInt::get(integerType, (1 << sizeInBits) - 1);
return gIR->ir->CreateICmpEQ(v, allEqual);
} else if (op == TOKnotequal) {
// any not-equal pair suffices for the vectors to be not-equal
LLConstant *noneNotEqual = LLConstantInt::get(integerType, 0);
return gIR->ir->CreateICmpNE(v, noneNotEqual);
}
llvm_unreachable("Unsupported operator.");
return nullptr;
}

View file

@ -57,5 +57,6 @@ DValue *binUshr(Loc &loc, Type *type, DValue *lhs, Expression *rhs,
llvm::Value *DtoBinNumericEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op); llvm::Value *DtoBinNumericEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op);
llvm::Value *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op); llvm::Value *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op);
llvm::Value *mergeVectorEquals(llvm::Value *resultsVector, TOK op);
dinteger_t undoStrideMul(Loc &loc, Type *t, dinteger_t offset); dinteger_t undoStrideMul(Loc &loc, Type *t, dinteger_t offset);

View file

@ -1343,6 +1343,9 @@ public:
Logger::cout() << "rv: " << *rv << '\n'; Logger::cout() << "rv: " << *rv << '\n';
} }
eval = p->ir->CreateICmp(cmpop, lv, rv); eval = p->ir->CreateICmp(cmpop, lv, rv);
if (t->ty == Tvector) {
eval = mergeVectorEquals(eval, e->op);
}
} else if (t->isfloating()) // includes iscomplex } else if (t->isfloating()) // includes iscomplex
{ {
eval = DtoBinNumericEquals(e->loc, l, r, e->op); eval = DtoBinNumericEquals(e->loc, l, r, e->op);

@ -1 +1 @@
Subproject commit 0889fc7ce6f2148e1278e6f04e28ca50399d431b Subproject commit cdf6195c9ca07b8e02e284f4581723c322f9c69d