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 *res = nullptr;
if (op == TOKequal) {
res = gIR->ir->CreateFCmpOEQ(DtoRVal(lhs), DtoRVal(rhs));
} else if (op == TOKnotequal) {
res = gIR->ir->CreateFCmpUNE(DtoRVal(lhs), DtoRVal(rhs));
} else {
llvm::ICmpInst::Predicate cmpop;
if (op == TOKidentity) {
cmpop = llvm::ICmpInst::ICMP_EQ;
} else {
cmpop = llvm::ICmpInst::ICMP_NE;
if (op == TOKequal || op == TOKnotequal) {
LLValue *l = DtoRVal(lhs);
LLValue *r = DtoRVal(rhs);
res = (op == TOKequal ? gIR->ir->CreateFCmpOEQ(l, r)
: gIR->ir->CreateFCmpUNE(l, r));
if (lhs->type->toBasetype()->ty == Tvector) {
res = mergeVectorEquals(res, op);
}
} else {
const auto cmpop =
op == TOKidentity ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE;
LLValue *sz = DtoConstSize_t(getTypeStoreSize(DtoType(lhs->type)));
LLValue *val = DtoMemCmp(makeLValue(loc, lhs), makeLValue(loc, rhs), sz);
res = gIR->ir->CreateICmp(cmpop, val,
@ -344,3 +343,28 @@ LLValue *DtoBinFloatsEquals(Loc &loc, DValue *lhs, DValue *rhs, TOK op) {
assert(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;
}