Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

memchr("", 0, 1) optimized incorrectly #31472

Closed
alexcrichton opened this issue Mar 3, 2017 · 9 comments
Closed

memchr("", 0, 1) optimized incorrectly #31472

alexcrichton opened this issue Mar 3, 2017 · 9 comments
Assignees
Labels
bugzilla Issues migrated from bugzilla

Comments

@alexcrichton
Copy link
Contributor

Bugzilla Link 32124
Resolution FIXED
Resolved on May 19, 2017 15:48
Version 4.0
OS Windows NT
CC @compnerd,@MatzeB,@sanjoy

Extended Description

We've got an upstream rust-lang/rust bug at rust-lang/rust#40165 which is exhibiting some odd behavior! I've managed to reduce it to a small snippet of IR which optimizes oddly:

@​s = internal constant [1 x i8] [i8 0], align 1

define i8* @​foo() {
entry-block:
%0 = tail call i8* @​memchr(i8* getelementptr ([1 x i8], [1 x i8]* @​s, i64 0, i64 0), i32 0, i64 1)
ret i8* %0
}

declare i8* @​memchr(i8*, i32, i64)

When optimized,that entire function optimizes to returning null, but I'd expect it to return @​s itself (as the first byte is zero)

@alexcrichton
Copy link
Contributor Author

assigned to @MatzeB

@alexcrichton
Copy link
Contributor Author

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 3, 2017

I believe the minimal diff for fixing this to be:

  • if (GV->getInitializer()->isNullValue()) {
  • if (GV->getInitializer()->isNullValue() && TrimAtNul) {

This will remove the ability to optimize certain libcalls on all-zero static buffers, but at least it won't be incorrect.
The ideal fix would probably be to allocate an all-zero string buffer if TrimAtNul is false.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 3, 2017

Checking https://godbolt.org/g/QroaoK against various versions of clang suggests this bug has been around since LLVM 3.7, and is not present in other compilers.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 3, 2017

I haven't stepped throught with a debugger, but you may want to confirm that SimplifyLibCall doesn't do anything hazy with memchr()

Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B)

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 4, 2017

You may want to try this patch (at least as stopgap solution).

diff --git a/lib/Transforms/Utils/SimplifyLibCalls.cpp b/lib/Transforms/Utils/SimplifyLibCalls.cpp
index ec33679..5553d5c 100644
--- a/lib/Transforms/Utils/SimplifyLibCalls.cpp
+++ b/lib/Transforms/Utils/SimplifyLibCalls.cpp
@@ -666,6 +666,10 @@ Value *LibCallSimplifier::optimizeMemChr(CallInst *CI, IRBuilder<> &B) {
// return null if we don't find the char.
Str = Str.substr(0, LenC->getZExtValue());

  • // memchr("", 0, y) -> ""
  • if (Str.empty() && CharC->isNullValue())
  • return CI->getArgOperand(0);
  • // If the char is variable but the input str and length are not we can turn
    // this memchr call into a simple bit field test. Of course this only works
    // when the return value is only checked against null.

@llvmbot
Copy link
Collaborator

llvmbot commented Mar 4, 2017

IMO this should be fixed (even as an workaround) in getConstantStringInfo (see my mini-diff above), because memchr is unlikely to be the only affected function.

@MatzeB
Copy link
Contributor

MatzeB commented May 5, 2017

For the record: Looks like Eli found the (existing) bug while reading my review at https://reviews.llvm.org/D32839#inline-284908

The latest version of that patch fixes this issue as a side effect of some refactoring.

@MatzeB
Copy link
Contributor

MatzeB commented May 19, 2017

Fixed by r303461

@llvmbot llvmbot transferred this issue from llvm/llvm-bugzilla-archive Dec 10, 2021
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bugzilla Issues migrated from bugzilla
Projects
None yet
Development

No branches or pull requests

3 participants