[llvm-commits] [llvm] r122548 - in /llvm/trunk: lib/Transforms/Scalar/MemCpyOptimizer.cpp test/Transforms/MemCpyOpt/memcpy-to-memset.ll
Frits van Bommel
fvbommel at gmail.com
Fri Dec 24 13:43:22 PST 2010
On Fri, Dec 24, 2010 at 10:17 PM, Benjamin Kramer
<benny.kra at googlemail.com> wrote:
> /// isBytewiseValue - If the specified value can be set by repeating the same
> /// byte in memory, return the i8 value that it is represented with. This is
> @@ -38,6 +40,13 @@
> /// i16 0xF0F0, double 0.0 etc. If the value can't be handled with a repeated
> /// byte store (e.g. i16 0x1234), return null.
> static Value *isBytewiseValue(Value *V) {
> + // Look through constant globals.
> + if (GlobalVariable *GV = dyn_cast<GlobalVariable>(V)) {
> + if (GV->mayBeOverridden() || !GV->isConstant() || !GV->hasInitializer())
> + return 0;
> + V = GV->getInitializer();
> + }
> +
This shouldn't be done here. Putting this here can cause
miscompilation when a pointer to a global is stored somewhere (by
memset'ing the bytewise value of the *initializer* instead).
This should probably be put into a separate function (e.g.
isPointerToBytewiseValue()) that returns
isBytewiseValue(GV->getInitializer()) if the conditions hold.
> + // A ConstantArray is splatable if all its members are equal and also
> + // splatable.
> + if (ConstantArray *CA = dyn_cast<ConstantArray>(V)) {
I notice this function doesn't seem to handle null values. There
should probably be an
if (V->isNullValue()) return Zero;
or similar near here.
Possibly even the same for undefs.
(Currently it doesn't handle all-zero arrays & structs, for instance)
> + // If copying from a constant, try to turn the memcpy into a memset.
> + if (Value *ByteVal = isBytewiseValue(M->getSource())) {
This should use the above-mentioned isPointerToBytewiseValue(...).
> + Value *Ops[] = {
> + M->getRawDest(), ByteVal, // Start, value
> + CopySize, // Size
> + M->getAlignmentCst(), // Alignment
> + ConstantInt::getFalse(M->getContext()), // volatile
> + };
> + const Type *Tys[] = { Ops[0]->getType(), Ops[2]->getType() };
> + Module *Mod = M->getParent()->getParent()->getParent();
> + Function *MemSetF = Intrinsic::getDeclaration(Mod, Intrinsic::memset, Tys, 2);
> + CallInst::Create(MemSetF, Ops, Ops+5, "", M);
This can probably be simplified by using EmitMemSet() from
llvm/Transforms/Utils/BuildLibCalls.h, but the same goes for the
previously existing code in this file.
More information about the llvm-commits
mailing list