mirror of
https://github.com/ldc-developers/ldc.git
synced 2025-05-14 07:09:50 +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 =
|
LLValue *res =
|
||||||
gIR->CreateCallOrInvoke(func, aaTypeInfo, aaval, abval, "aaEqRes")
|
gIR->CreateCallOrInvoke(func, aaTypeInfo, aaval, abval, "aaEqRes")
|
||||||
.getInstruction();
|
.getInstruction();
|
||||||
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0));
|
|
||||||
if (op == TOKnotequal) {
|
const auto predicate = eqTokToICmpPred(op, /* invert = */ true);
|
||||||
res = gIR->ir->CreateNot(res);
|
res = gIR->ir->CreateICmp(predicate, res, DtoConstInt(0));
|
||||||
}
|
|
||||||
return res;
|
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 *DtoArrayEquals(Loc &loc, TOK op, DValue *l, DValue *r) {
|
||||||
LLValue *res = DtoArrayEqCmp_impl(loc, "_adEq2", l, r, true);
|
LLValue *res = nullptr;
|
||||||
res = gIR->ir->CreateICmpNE(res, DtoConstInt(0));
|
|
||||||
if (op == TOKnotequal) {
|
// optimize comparisons against null by rewriting to `l.length op 0`
|
||||||
res = gIR->ir->CreateNot(res);
|
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;
|
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 *DtoArrayCompare(Loc &loc, TOK op, DValue *l, DValue *r) {
|
||||||
LLValue *res = nullptr;
|
LLValue *res = nullptr;
|
||||||
llvm::ICmpInst::Predicate cmpop;
|
llvm::ICmpInst::Predicate cmpop;
|
||||||
tokToIcmpPred(op, false, &cmpop, &res);
|
tokToICmpPred(op, false, &cmpop, &res);
|
||||||
|
|
||||||
if (!res) {
|
if (!res) {
|
||||||
Type *t = l->getType()->toBasetype()->nextOf()->toBasetype();
|
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 *DtoDynArrayIs(TOK op, DValue *l, DValue *r) {
|
||||||
LLValue *len1, *ptr1, *len2, *ptr2;
|
|
||||||
|
|
||||||
assert(l);
|
assert(l);
|
||||||
assert(r);
|
assert(r);
|
||||||
|
|
||||||
// compare lengths
|
LLValue *len1 = DtoArrayLen(l);
|
||||||
len1 = DtoArrayLen(l);
|
LLValue *ptr1 = DtoArrayPtr(l);
|
||||||
len2 = DtoArrayLen(r);
|
|
||||||
LLValue *b1 = gIR->ir->CreateICmpEQ(len1, len2);
|
|
||||||
|
|
||||||
// compare pointers
|
LLValue *len2 = DtoArrayLen(r);
|
||||||
ptr1 = DtoArrayPtr(l);
|
LLValue *ptr2 = DtoArrayPtr(r);
|
||||||
ptr2 = DtoArrayPtr(r);
|
|
||||||
LLValue *b2 = gIR->ir->CreateICmpEQ(ptr1, ptr2);
|
|
||||||
|
|
||||||
// combine
|
return createIPairCmp(op, len1, ptr1, len2, ptr2);
|
||||||
LLValue *res = gIR->ir->CreateAnd(b1, b2);
|
|
||||||
|
|
||||||
// return result
|
|
||||||
return (op == TOKnotidentity) ? gIR->ir->CreateNot(res) : res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
|
@ -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) {
|
llvm::Value **outConst) {
|
||||||
switch (op) {
|
switch (op) {
|
||||||
case TOKlt:
|
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) {
|
DValue *DtoSymbolAddress(Loc &loc, Type *type, Declaration *decl) {
|
||||||
IF_LOG Logger::println("DtoSymbolAddress ('%s' of type '%s')",
|
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
|
/// 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.
|
/// 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);
|
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
|
// gen/tocall.cpp stuff below
|
||||||
////////////////////////////////////////////
|
////////////////////////////////////////////
|
||||||
|
|
|
@ -1416,7 +1416,7 @@ public:
|
||||||
|
|
||||||
if (t->isintegral() || t->ty == Tpointer || t->ty == Tnull) {
|
if (t->isintegral() || t->ty == Tpointer || t->ty == Tnull) {
|
||||||
llvm::ICmpInst::Predicate icmpPred;
|
llvm::ICmpInst::Predicate icmpPred;
|
||||||
tokToIcmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
tokToICmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
||||||
|
|
||||||
if (!eval) {
|
if (!eval) {
|
||||||
LLValue *a = l->getRVal();
|
LLValue *a = l->getRVal();
|
||||||
|
@ -1481,7 +1481,7 @@ public:
|
||||||
eval = LLConstantInt::getFalse(gIR->context());
|
eval = LLConstantInt::getFalse(gIR->context());
|
||||||
} else if (t->ty == Tdelegate) {
|
} else if (t->ty == Tdelegate) {
|
||||||
llvm::ICmpInst::Predicate icmpPred;
|
llvm::ICmpInst::Predicate icmpPred;
|
||||||
tokToIcmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
tokToICmpPred(e->op, isLLVMUnsigned(t), &icmpPred, &eval);
|
||||||
|
|
||||||
if (!eval) {
|
if (!eval) {
|
||||||
// First compare the function pointers, then the context ones. This is
|
// 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) {
|
LLValue *DtoDelegateEquals(TOK op, LLValue *lhs, LLValue *rhs) {
|
||||||
Logger::println("Doing delegate equality");
|
Logger::println("Doing delegate equality");
|
||||||
llvm::Value *b1, *b2;
|
|
||||||
if (rhs == nullptr) {
|
if (rhs == nullptr) {
|
||||||
rhs = LLConstant::getNullValue(lhs->getType());
|
rhs = LLConstant::getNullValue(lhs->getType());
|
||||||
}
|
}
|
||||||
|
|
||||||
LLValue *l = gIR->ir->CreateExtractValue(lhs, 0);
|
LLValue *l1 = gIR->ir->CreateExtractValue(lhs, 0);
|
||||||
LLValue *r = gIR->ir->CreateExtractValue(rhs, 0);
|
LLValue *l2 = gIR->ir->CreateExtractValue(lhs, 1);
|
||||||
b1 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ, l, r);
|
|
||||||
|
|
||||||
l = gIR->ir->CreateExtractValue(lhs, 1);
|
LLValue *r1 = gIR->ir->CreateExtractValue(rhs, 0);
|
||||||
r = gIR->ir->CreateExtractValue(rhs, 1);
|
LLValue *r2 = gIR->ir->CreateExtractValue(rhs, 1);
|
||||||
b2 = gIR->ir->CreateICmp(llvm::ICmpInst::ICMP_EQ, l, r);
|
|
||||||
|
|
||||||
LLValue *b = gIR->ir->CreateAnd(b1, b2);
|
return createIPairCmp(op, l1, l2, r1, r2);
|
||||||
|
|
||||||
if (op == TOKnotequal || op == TOKnotidentity) {
|
|
||||||
return gIR->ir->CreateNot(b);
|
|
||||||
}
|
|
||||||
|
|
||||||
return b;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue