[LLVMdev] [PATCH] PR2218
Chris Lattner
clattner at apple.com
Fri Aug 7 14:40:20 PDT 2009
On Jul 25, 2009, at 4:48 PM, Jakub Staszak wrote:
> Hello,
>
> Sorry for my stupid mistakes. I hope that everything is fine now.
> This patch fixes PR2218. There are no loads in example, however
> "instcombine" changes memcpy() into store/load.
Hi Jakub,
Sorry for the delay, I'm way behind on code review. Generally if you
respond quickly, I'll remember enough about the previous email that I
can respond quickly too. If it gets out of my brain then it takes me
a while to get back to it. I'll try to be better in the future :(
This patch is looking like a great improvement. Some comments on
formatting:
Please pull this out to a helper function:
+ CallSite CS = CallSite::get(C);
+
+ // Pointer must be a parameter (case 1)
+ for (argI = 0; argI < CS.arg_size(); ++argI)
+ if (CS.getArgument(argI)->stripPointerCasts() == pointer)
+ break;
+
+ if (argI == CS.arg_size())
+ return false;
per http://llvm.org/docs/CodingStandards.html#hl_predicateloops
+ // Store cannot be volatile (case 2) and must-alias with our
pointer.
+ if (S->isVolatile()) {
+ return false;
+ } else {
no need for the 'else after return': http://llvm.org/docs/CodingStandards.html#hl_else_after_return
+ AliasAnalysis& AA = getAnalysis<AliasAnalysis>();
+ if (AA.alias(S->getPointerOperand(), 1, pointer, 1) !=
+ AliasAnalysis::MustAlias)
+ return false;
Knowing that the loaded and stored pointer must alias is important,
but you also need to check that the loaded and stored sizes equal each
other.
+ // Look for a replacement for our pointer. If more than one found,
exit.
+ for (User::use_iterator I = L->use_begin(), E = L->use_end(); I !=
E; ++I) {
+ Instruction *User = cast<Instruction>(*I);
+
+ if (StoreInst *SI = dyn_cast<StoreInst>(User)) {
+ if (SI->isVolatile())
+ return false;
+
+ if (!Repl)
+ Repl = SI->getPointerOperand();
+ else if (Repl != SI->getPointerOperand())
+ return false;
+
+ } else
+ return false;
+ }
Please do something like this:
if (!L->hasOneUse()) return false;
StoreInst *StoreOfLoad = dyn_cast<StoreInst>(L->use_back());
if (StoreOfLoad == 0 || ...)
...
Actually, I see now that the code actually allows multiple stores as
long as they are to the same pointer. That also seems reasonable to
me, but please update the comment above the loop to make it really
clear what it is doing. It is probably also reasonable to factor this
out to a static helper function.
I'm still not sure that this transformation is safe (it seems like we
need another dependence query). In particular, given something like:
%temporary = alloca i8
call void @initialize(i8* noalias sret %temporary)
%tmp = load i8* %temporary
store 42 -> %result
store i8 %tmp, i8* %result
It is not safe to transform this into:
call void @initialize(i8* noalias sret %result)
store 42 -> %result
I think this can be fixed by doing a dependence query from the store,
though I'm not sure what we'd expect. Another option is to see if the
result is only used by the store. In this case, the loop above that
allows multiple stores to the same pointer seems unneeded because we'd
only be able to support one store.
Thanks for working on this!
-Chris
More information about the llvm-dev
mailing list