Transform sprintf(dst, "%s", str) -> strcpy(dst, str) if result is unused
Avoid sprintf(dest, "%s", str) -> llvm.memcpy(align 1 dest, align 1 str, strlen(str)+1) if optimizing for size.
Details
Diff Detail
- Repository
- rG LLVM Github Monorepo
Event Timeline
In the case where we need the return value, there are a couple possible modifications:
- Maybe worth checking if the length of the string is a known constant.
- We could consider using stpcpy on targets where it's available.
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | ||
---|---|---|
2501 | I don't think I've seen this hasOptSize() || shouldOptimizeForSize() pattern before; is there documentation anywhere? |
Implemented suggested transformations.
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | ||
---|---|---|
2501 | Also used eg in “optimizeFputs” It was introducted as part of PGSO. |
llvm/test/Transforms/InstCombine/sprintf-1.ll | ||
---|---|---|
169 | Should we do this under minsize or not? Extra sub in asm should be ok, but IR has sub and 2x ptrtoints now. |
LGTM
llvm/lib/Transforms/Utils/SimplifyLibCalls.cpp | ||
---|---|---|
2507 | This is basically the first place we're generating stpcpy "from scratch". That's probably okay, since gcc does it, but we should watch out for bug reports. | |
llvm/test/Transforms/InstCombine/sprintf-1.ll | ||
169 | The ptrtoints are free at the assembly level; the total number of IR instructions isn't important. |
This change still causes failed asserts when building source like e.g. this:
$ cat sprintf-strcpy.c char *ptr; void func(void) { ptr += sprintf(ptr, "%s", ""); } $ clang -c sprintf-strcpy.c -O2 -target x86_64-linux-gnu clang: ../lib/IR/Value.cpp:473: void llvm::Value::doRAUW(llvm::Value*, llvm::Value::ReplaceMetadataUses): Assertion `New->getType() == getType() && "replaceAllUses of value with new value of different type!"' failed.
Will revert it shortly.
I don't think I've seen this hasOptSize() || shouldOptimizeForSize() pattern before; is there documentation anywhere?