[llvm-commits] [llvm] r151620 - in /llvm/trunk: lib/Transforms/Scalar/DeadStoreElimination.cpp test/Transforms/DeadStoreElimination/OverwriteStoreStart.ll
Peter Cooper
peter_cooper at apple.com
Tue Feb 28 10:01:29 PST 2012
Hi Duncan
Thanks for all the comments. I'd been looking for a better way to test an intrinsic being a memset. I didn't realize isa<> had a check for that. I'll integrate all your suggestions into round 2 of this work once i've worked out all the buildbot failures.
Cheers,
Pete
On Feb 28, 2012, at 2:35 AM, Duncan Sands <baldrick at free.fr> wrote:
> Hi Peter,
>
>> --- llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp (original)
>> +++ llvm/trunk/lib/Transforms/Scalar/DeadStoreElimination.cpp Mon Feb 27 22:27:10 2012
>> @@ -259,6 +259,13 @@
>> }
>> }
>>
>> +
>> +/// isMemset - Returns true if this instruction is an intrinsic memset
>> +static bool isMemset(Instruction *I) {
>> + IntrinsicInst *II = dyn_cast<IntrinsicInst>(I);
>> + return II&& II->getIntrinsicID() == Intrinsic::memset;
>> +}
>
> instead of this you should include IntrinsicInst.h; you can then use
> isa<MemSetInst> to test for a memset intrinsic.
>
>> @@ -418,6 +428,21 @@
>> LaterOff< int64_t(EarlierOff + Earlier.Size)&&
>> int64_t(LaterOff + Later.Size)>= int64_t(EarlierOff + Earlier.Size))
>> return OverwriteEnd;
>> +
>> + // The other interesting case is if the later store overwrites the end of
>> + // the earlier store
>> + //
>> + // |--earlier--|
>> + // |-- later --|
>> + //
>> + // In this case we may want to trim the size of earlier to avoid generating
>> + // writes to addresses which will definitely be overwritten later
>> + if (EarlierOff>= LaterOff&&
>> + EarlierOff< int64_t(LaterOff + Later.Size)&&
>> + int64_t(EarlierOff + Earlier.Size)>= int64_t(LaterOff + Later.Size)) {
>
> Do you want > in this line? If there is equality then the memset can be
> discarded.
>
>> + LaterOff = LaterOff + Later.Size;
>> + return OverwriteStart;
>> + }
>>
>> // Otherwise, they don't completely overlap.
>> return OverwriteUnknown;
>> @@ -589,6 +614,45 @@
>> DepIntrinsic->setLength(TrimmedLength);
>> MadeChange = true;
>> }
>> + } else if (OR == OverwriteStart&& isMemset(DepWrite)) {
>> + // TODO: base this on the target vector size so that if the earlier
>> + // store was too small to get vector writes anyway then its likely
>> + // a good idea to shorten it
>> + // Power of 2 vector writes are probably always a bad idea to optimize
>> + // as any store/memset/memcpy is likely using vector instructions so
>> + // shortening it to not vector size is likely to be slower
>> + // TODO: shorten memcpy and memmove by offsetting the source address.
>> + MemIntrinsic* DepIntrinsic = cast<MemIntrinsic>(DepWrite);
>
> You could cast to a MemSetInst here.
>
>> + unsigned DepWriteAlign = DepIntrinsic->getAlignment();
>> + if (llvm::isPowerOf2_64(InstWriteOffset) ||
>
> Why do you accept any power of 2 (eg: 1) here? If you don't want to reduce
> alignment then shouldn't you only do the check below (is DepWriteAlign really
> allowed to be zero? If so, what does it mean?). If you are happy to reduce
> alignment, why do any alignment check at all?
>
>> + ((DepWriteAlign != 0)&& InstWriteOffset % DepWriteAlign == 0)) {
>> +
>> + DEBUG(dbgs()<< "DSE: Remove Dead Store:\n OW START:"
>> +<< *DepWrite<< "\n KILLER (offset "
>> +<< InstWriteOffset<< ", "
>> +<< DepWriteOffset<< ", "
>> +<< DepLoc.Size<< ")"
>> +<< *Inst<< '\n');
>> +
>> + Value* DepWriteLength = DepIntrinsic->getLength();
>> + Value* TrimmedLength = ConstantInt::get(DepWriteLength->getType(),
>> + DepLoc.Size -
>> + (InstWriteOffset -
>> + DepWriteOffset));
>
> Should this be DepWriteLength rather than DepLoc.Size? Are they guaranteed to
> be the same? Also, what happens if the new length is zero? Finally, is it
> guaranteed that this computation doesn't underflow? If so, maybe you should add
> an assert checking that.
>
>> + DepIntrinsic->setLength(TrimmedLength);
>> + const TargetData *TD = AA->getTargetData();
>> + Type *IntPtrTy = TD->getIntPtrType(BB.getContext());
>> + Value* Offset = ConstantInt::get(IntPtrTy,
>> + InstWriteOffset - DepWriteOffset);
>> + // Offset the start of the memset with a GEP. As the memset type is
>> + // i8* a GEP will do this without needing to use ptrtoint, etc.
>
> I don't think you can rely on it being an i8*, so you should bitcast it to an
> i8* first.
>
>> + Value *Dest = GetElementPtrInst::Create(DepIntrinsic->getRawDest(),
>> + Offset,
>> + "",
>> + DepWrite);
>> + DepIntrinsic->setDest(Dest);
>> + MadeChange = true;
>> + }
>> }
>> }
>
> Ciao, Duncan.
> _______________________________________________
> llvm-commits mailing list
> llvm-commits at cs.uiuc.edu
> http://lists.cs.uiuc.edu/mailman/listinfo/llvm-commits
More information about the llvm-commits
mailing list