Skip to content

Missed optimization of strdup to malloc + memcpy if argument is known at compile time #146742

Open
@BreadTom

Description

@BreadTom

Clang godbolt
GCC godbolt

Clang 20.1 and GCC 15.1 missed optimizing strdup("Hello") to malloc then memcpy "Hello" like f0_fast().
Maybe useful if the string came from -D:

#define HELLO_WORLD "Hello world"

char *f0_slow (void)
{
    return __builtin_strdup (HELLO_WORLD);
}

C source code

char *f0_fast (void)
{
    char *ret_val = __builtin_malloc (strlen ("Hello") + 1);
    if (ret_val)
        __builtin_memcpy (ret_val, "Hello", strlen ("Hello") + 1);
    return ret_val;
}

char *f0_slow (void)
{
    return __builtin_strdup ("Hello");
}

LLVM IR

@.str = private unnamed_addr constant [6 x i8] c"Hello\00", align 1

define dso_local noalias noundef ptr @f0_fast() local_unnamed_addr {
entry:
  %call = tail call dereferenceable_or_null(6) ptr @malloc(i64 noundef 6) #5
  %tobool.not = icmp eq ptr %call, null
  br i1 %tobool.not, label %if.end, label %if.then

if.then:
  tail call void @llvm.memcpy.p0.p0.i64(ptr noundef nonnull align 1 dereferenceable(6) %call, ptr noundef nonnull align 1 dereferenceable(6) @.str, i64 6, i1 false)
  br label %if.end

if.end:
  ret ptr %call
}

declare noalias noundef ptr @malloc(i64 noundef) local_unnamed_addr #1

declare void @llvm.memcpy.p0.p0.i64(ptr noalias nocapture writeonly, ptr noalias nocapture readonly, i64, i1 immarg) #2

define dso_local noalias noundef ptr @f0_slow() local_unnamed_addr {
entry:
  %call = tail call dereferenceable_or_null(6) ptr @strdup(ptr noundef nonnull @.str) #5
  ret ptr %call
}

declare noalias ptr @strdup(ptr nocapture noundef readonly) local_unnamed_addr #4

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions