Optimize some slice copies

Cache length & ptr in DSliceValue, so that e.g. a pair constructed from
a constant length and some ptr keeps returning a constant length instead
of an extractvalue instruction every time the length is needed.

This enables checking for matching constant lengths when copying slices
and makes `test1()` in runnable/betterc.d work (memcpy instead of
_d_array_slice_copy call):

```
int[10] a1 = void;
int[10] a2 = void;
a1[] = a2[];
```

(more or less equivalent to `a1 = a2`, which is already optimized)
This commit is contained in:
Martin Kinkelin 2019-01-09 23:50:41 +01:00
parent a911e72c86
commit 2fb5098f48
3 changed files with 34 additions and 6 deletions

View file

@ -275,8 +275,18 @@ void DtoArrayAssign(Loc &loc, DValue *lhs, DValue *rhs, int op,
LLValue *lhsSize = computeSize(lhsLength, elementSize); LLValue *lhsSize = computeSize(lhsLength, elementSize);
DtoMemSetZero(lhsPtr, lhsSize); DtoMemSetZero(lhsPtr, lhsSize);
} else { } else {
const bool knownInBounds = bool knownInBounds =
isConstructing || (t->ty == Tsarray && t2->ty == Tsarray); isConstructing || (t->ty == Tsarray && t2->ty == Tsarray);
if (!knownInBounds) {
if (auto constLhsLength = llvm::dyn_cast<LLConstantInt>(lhsLength)) {
if (auto constRhsLength =
llvm::dyn_cast<LLConstantInt>(rhsLength)) {
if (constLhsLength->getValue() == constRhsLength->getValue()) {
knownInBounds = true;
}
}
}
}
copySlice(loc, lhsPtr, lhsLength, rhsPtr, rhsLength, elementSize, copySlice(loc, lhsPtr, lhsLength, rhsPtr, rhsLength, elementSize,
knownInBounds); knownInBounds);
} }
@ -1194,7 +1204,9 @@ LLValue *DtoArrayLen(DValue *v) {
if (v->isLVal()) { if (v->isLVal()) {
return DtoLoad(DtoGEPi(DtoLVal(v), 0, 0), ".len"); return DtoLoad(DtoGEPi(DtoLVal(v), 0, 0), ".len");
} }
return gIR->ir->CreateExtractValue(DtoRVal(v), 0, ".len"); auto slice = v->isSlice();
assert(slice);
return slice->getLength();
} }
if (t->ty == Tsarray) { if (t->ty == Tsarray) {
assert(!v->isSlice()); assert(!v->isSlice());
@ -1222,7 +1234,9 @@ LLValue *DtoArrayPtr(DValue *v) {
} else if (v->isLVal()) { } else if (v->isLVal()) {
ptr = DtoLoad(DtoGEPi(DtoLVal(v), 0, 1), ".ptr"); ptr = DtoLoad(DtoGEPi(DtoLVal(v), 0, 1), ".ptr");
} else { } else {
ptr = gIR->ir->CreateExtractValue(DtoRVal(v), 1, ".ptr"); auto slice = v->isSlice();
assert(slice);
ptr = slice->getPtr();
} }
} else if (t->ty == Tsarray) { } else if (t->ty == Tsarray) {
assert(!v->isSlice()); assert(!v->isSlice());

View file

@ -87,11 +87,22 @@ DSliceValue::DSliceValue(Type *t, LLValue *pair) : DRValue(t, pair) {
} }
DSliceValue::DSliceValue(Type *t, LLValue *length, LLValue *ptr) DSliceValue::DSliceValue(Type *t, LLValue *length, LLValue *ptr)
: DSliceValue(t, DtoAggrPair(length, ptr)) {} : DSliceValue(t, DtoAggrPair(length, ptr)) {
cachedLength = length;
cachedPtr = ptr;
}
LLValue *DSliceValue::getLength() { return DtoExtractValue(val, 0, ".len"); } LLValue *DSliceValue::getLength() {
if (!cachedLength)
cachedLength = DtoExtractValue(val, 0, ".len");
return cachedLength;
}
LLValue *DSliceValue::getPtr() { return DtoExtractValue(val, 1, ".ptr"); } LLValue *DSliceValue::getPtr() {
if (!cachedPtr)
cachedPtr = DtoExtractValue(val, 1, ".ptr");
return cachedPtr;
}
//////////////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////////////

View file

@ -117,6 +117,9 @@ public:
/// Represents a D slice (dynamic array). /// Represents a D slice (dynamic array).
class DSliceValue : public DRValue { class DSliceValue : public DRValue {
llvm::Value *cachedLength = nullptr;
llvm::Value *cachedPtr = nullptr;
public: public:
DSliceValue(Type *t, llvm::Value *pair); DSliceValue(Type *t, llvm::Value *pair);
DSliceValue(Type *t, llvm::Value *length, llvm::Value *ptr); DSliceValue(Type *t, llvm::Value *length, llvm::Value *ptr);