mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-13 14:36:18 +03:00
Merge pull request #1393 from kinke/nullArray
Optimize array comparisons against null
This commit is contained in:
commit
209b6fc2b0
6 changed files with 67 additions and 42 deletions
|
@ -207,9 +207,9 @@ LLValue *DtoAAEquals(Loc &loc, TOK op, DValue *l, DValue *r) {
|
|||
LLValue *res =
|
||||
gIR->CreateCallOrInvoke(func, aaTypeInfo, aaval, abval, "aaEqRes")
|
||||
.getInstruction();
|
||||
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0));
|
||||
if (op == TOKnotequal) {
|
||||
res = gIR->ir->CreateNot(res);
|
||||
}
|
||||
|
||||
const auto predicate = eqTokToICmpPred(op, /* invert = */ true);
|
||||
res = gIR->ir->CreateICmp(predicate, res, DtoConstInt(0));
|
||||
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -943,10 +943,16 @@ static LLValue *DtoArrayEqCmp_impl(Loc &loc, const char *func, DValue *l,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
LLValue *DtoArrayEquals(Loc &loc, TOK op, DValue *l, DValue *r) {
|
||||
LLValue *res = DtoArrayEqCmp_impl(loc, "_adEq2", l, r, true);
|
||||
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0));
|
||||
if (op == TOKnotequal) {
|
||||
res = gIR->ir->CreateNot(res);
|
||||
LLValue *res = nullptr;
|
||||
|
||||
// optimize comparisons against null by rewriting to `l.length op 0`
|
||||
if (r->isNull()) {
|
||||
const auto predicate = eqTokToICmpPred(op);
|
||||
res = gIR->ir->CreateICmp(predicate, DtoArrayLen(l), DtoConstSize_t(0));
|
||||
} else {
|
||||
res = DtoArrayEqCmp_impl(loc, "_adEq2", l, r, true);
|
||||
const auto predicate = eqTokToICmpPred(op, /* invert = */ true);
|
||||
res = gIR->ir->CreateICmp(predicate, res, DtoConstInt(0));
|
||||
}
|
||||
|
||||
return res;
|
||||
|
@ -956,7 +962,7 @@ LLValue *DtoArrayEquals(Loc &loc, TOK op, DValue *l, DValue *r) {
|
|||
LLValue *DtoArrayCompare(Loc &loc, TOK op, DValue *l, DValue *r) {
|
||||
LLValue *res = nullptr;
|
||||
llvm::ICmpInst::Predicate cmpop;
|
||||
tokToIcmpPred(op, false, &cmpop, &res);
|
||||
tokToICmpPred(op, false, &cmpop, &res);
|
||||
|
||||
if (!res) {
|
||||
Type *t = l->getType()->toBasetype()->nextOf()->toBasetype();
|
||||
|
@ -997,26 +1003,16 @@ LLValue *DtoArrayCastLength(Loc &loc, LLValue *len, LLType *elemty,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
LLValue *DtoDynArrayIs(TOK op, DValue *l, DValue *r) {
|
||||
LLValue *len1, *ptr1, *len2, *ptr2;
|
||||
|
||||
assert(l);
|
||||
assert(r);
|
||||
|
||||
// compare lengths
|
||||
len1 = DtoArrayLen(l);
|
||||
len2 = DtoArrayLen(r);
|
||||
LLValue *b1 = gIR->ir->CreateICmpEQ(len1, len2);
|
||||
LLValue *len1 = DtoArrayLen(l);
|
||||
LLValue *ptr1 = DtoArrayPtr(l);
|
||||
|
||||
// compare pointers
|
||||
ptr1 = DtoArrayPtr(l);
|
||||
ptr2 = DtoArrayPtr(r);
|
||||
LLValue *b2 = gIR->ir->CreateICmpEQ(ptr1, ptr2);
|
||||
LLValue *len2 = DtoArrayLen(r);
|
||||
LLValue *ptr2 = DtoArrayPtr(r);
|
||||
|
||||
// combine
|
||||
LLValue *res = gIR->ir->CreateAnd(b1, b2);
|
||||
|
||||
// return result
|
||||
return (op == TOKnotidentity) ? gIR->ir->CreateNot(res) : res;
|
||||
return createIPairCmp(op, len1, ptr1, len2, ptr2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
|
@ -1451,7 +1451,7 @@ void AppendFunctionToLLVMGlobalCtorsDtors(llvm::Function *func,
|
|||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void tokToIcmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate *outPred,
|
||||
void tokToICmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate *outPred,
|
||||
llvm::Value **outConst) {
|
||||
switch (op) {
|
||||
case TOKlt:
|
||||
|
@ -1487,6 +1487,35 @@ void tokToIcmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate *outPred,
|
|||
}
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
llvm::ICmpInst::Predicate eqTokToICmpPred(TOK op, bool invert) {
|
||||
assert(op == TOKequal || op == TOKnotequal || op == TOKidentity ||
|
||||
op == TOKnotidentity);
|
||||
|
||||
bool isEquality = (op == TOKequal || op == TOKidentity);
|
||||
if (invert)
|
||||
isEquality = !isEquality;
|
||||
|
||||
return (isEquality ? llvm::ICmpInst::ICMP_EQ : llvm::ICmpInst::ICMP_NE);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
LLValue *createIPairCmp(TOK op, LLValue *lhs1, LLValue *lhs2, LLValue *rhs1,
|
||||
LLValue *rhs2) {
|
||||
const auto predicate = eqTokToICmpPred(op);
|
||||
|
||||
LLValue *r1 = gIR->ir->CreateICmp(predicate, lhs1, rhs1);
|
||||
LLValue *r2 = gIR->ir->CreateICmp(predicate, lhs2, rhs2);
|
||||
|
||||
LLValue *r =
|
||||
(predicate == llvm::ICmpInst::ICMP_EQ ? gIR->ir->CreateAnd(r1, r2)
|
||||
: gIR->ir->CreateOr(r1, r2));
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////
|
||||
DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
|
||||
IF_LOG Logger::println("DtoSymbolAddress ('%s' of type '%s')",
|
||||
|
|
|
@ -180,9 +180,18 @@ bool isLLVMUnsigned(Type *t);
|
|||
///
|
||||
/// For some operations, the result can be a constant. In this case outConst is
|
||||
/// set to it, otherwise outPred is set to the predicate to use.
|
||||
void tokToIcmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate *outPred,
|
||||
void tokToICmpPred(TOK op, bool isUnsigned, llvm::ICmpInst::Predicate *outPred,
|
||||
llvm::Value **outConst);
|
||||
|
||||
/// Converts a DMD equality/identity operation token into the corresponding LLVM
|
||||
/// icmp predicate.
|
||||
llvm::ICmpInst::Predicate eqTokToICmpPred(TOK op, bool invert = false);
|
||||
|
||||
/// For equality/identity operations, returns `(lhs1 == rhs1) & (lhs2 == rhs2)`.
|
||||
/// `(lhs1 != rhs1) | (lhs2 != rhs2)` for inequality/not-identity.
|
||||
LLValue *createIPairCmp(TOK op, LLValue *lhs1, LLValue *lhs2, LLValue *rhs1,
|
||||
LLValue *rhs2);
|
||||
|
||||
////////////////////////////////////////////
|
||||
// gen/tocall.cpp stuff below
|
||||
////////////////////////////////////////////
|
||||
|
|
|
@ -1416,7 +1416,7 @@ public:
|
|||
|
||||
if (t->isintegral() || t->ty == Tpointer || t->ty == Tnull) {
|
||||
llvm::ICmpInst::Predicate icmpPred;
|
||||
tokToIcmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
||||
tokToICmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
||||
|
||||
if (!eval) {
|
||||
LLValue *a = l->getRVal();
|
||||
|
@ -1481,7 +1481,7 @@ public:
|
|||
eval = LLConstantInt::getFalse(gIR->context());
|
||||
} else if (t->ty == Tdelegate) {
|
||||
llvm::ICmpInst::Predicate icmpPred;
|
||||
tokToIcmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
||||
tokToICmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
||||
|
||||
if (!eval) {
|
||||
// First compare the function pointers, then the context ones. This is
|
||||
|
|
|
@ -221,26 +221,17 @@ LLType *i1ToI8(LLType *t) {
|
|||
|
||||
LLValue *DtoDelegateEquals(TOK op, LLValue *lhs, LLValue *rhs) {
|
||||
Logger::println("Doing delegate equality");
|
||||
llvm::Value *b1, *b2;
|
||||
if (rhs == nullptr) {
|
||||
rhs = LLConstant::getNullValue(lhs->getType());
|
||||
}
|
||||
|
||||
LLValue *l = gIR->ir->CreateExtractValue(lhs, 0);
|
||||
LLValue *r = gIR->ir->CreateExtractValue(rhs, 0);
|
||||
b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ, l, r);
|
||||
LLValue *l1 = gIR->ir->CreateExtractValue(lhs, 0);
|
||||
LLValue *l2 = gIR->ir->CreateExtractValue(lhs, 1);
|
||||
|
||||
l = gIR->ir->CreateExtractValue(lhs, 1);
|
||||
r = gIR->ir->CreateExtractValue(rhs, 1);
|
||||
b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ, l, r);
|
||||
LLValue *r1 = gIR->ir->CreateExtractValue(rhs, 0);
|
||||
LLValue *r2 = gIR->ir->CreateExtractValue(rhs, 1);
|
||||
|
||||
LLValue *b = gIR->ir->CreateAnd(b1, b2);
|
||||
|
||||
if (op == TOKnotequal || op == TOKnotidentity) {
|
||||
return gIR->ir->CreateNot(b);
|
||||
}
|
||||
|
||||
return b;
|
||||
return createIPairCmp(op, l1, l2, r1, r2);
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue