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?