This is an archive of the discontinued LLVM Phabricator instance.

[CodeGen] Emit a helper function for __builtin_os_log_format to reduce code size
ClosedPublic

Authored by ahatanak on Oct 5 2017, 4:00 PM.

Details

Summary

We found that the IR IRGen emits when expanding __builtin_os_log_format is quite big and has a lot of redundancy.

For example, when clang compiles the following code:

void foo1(void *buf) {
  __builtin_os_log_format(buf, "%d %d", 11, 22);
}

The IR looks like this:

define void @foo1(i8* %buf) #0 {
entry:
  %buf.addr = alloca i8*, align 8
  store i8* %buf, i8** %buf.addr, align 8
  %0 = load i8*, i8** %buf.addr, align 8
  %summary = getelementptr i8, i8* %0, i64 0
  store i8 0, i8* %summary, align 1
  %numArgs = getelementptr i8, i8* %0, i64 1
  store i8 2, i8* %numArgs, align 1
  %argDescriptor = getelementptr i8, i8* %0, i64 2
  store i8 0, i8* %argDescriptor, align 1
  %argSize = getelementptr i8, i8* %0, i64 3
  store i8 4, i8* %argSize, align 1
  %1 = getelementptr i8, i8* %0, i64 4
  %2 = bitcast i8* %1 to i32*
  store i32 11, i32* %2, align 1
  %argDescriptor1 = getelementptr i8, i8* %0, i64 8
  store i8 0, i8* %argDescriptor1, align 1
  %argSize2 = getelementptr i8, i8* %0, i64 9
  store i8 4, i8* %argSize2, align 1
  %3 = getelementptr i8, i8* %0, i64 10
  %4 = bitcast i8* %3 to i32*
  store i32 22, i32* %4, align 1
  ret void
}

The IR generated when compiling a similar call like "__builtin_os_log_format(buf, "%d %d", 33, 44)" is almost the same except for the values of the integer constants stored, so there is an opportunity for code reductionton here.

To reduce code size, this patch modifies IRGen to emit a helper function that can be used by different call sites that call __builtin_os_log_format in a program. When compiling with -Oz, the generated helper function is marked as linkonce_odr, hidden, and noinline so that the linker can merge identical helper functions from different translation units. When compiling with other optimization levels, the function is marked as 'internal' and the generated IR should look mostly the same after inlining.

This patch also fixes a bug where the generated IR writes past the buffer when %m is the last directive. For example, the size of 'buf' in the following code is 4 but IRGen emits a store that writes a 4-byte value at buf+4.

char buf[__builtin_os_log_format_buffer_size("%m")];
__builtin_os_log_format(buf, "%m");

Original patch was written by Duncan.

rdar://problem/34065973
dar://problem/34196543

Diff Detail

Repository
rL LLVM

Event Timeline

ahatanak created this revision.Oct 5 2017, 4:00 PM
rjmccall edited edge metadata.Oct 5 2017, 8:16 PM

I don't see any reason not to use linkonce_odr + hidden even outside of -Oz. Otherwise LGTM.

ahatanak updated this revision to Diff 117955.Oct 5 2017, 11:35 PM

Always mark the helper function as linkonce_odr and hidden.

I think you are right. The linkage should be linkonce_odr even when not compiling with -Oz. I've fixed it in the latest patch.

rjmccall accepted this revision.Oct 5 2017, 11:51 PM

Thanks. LGTM.

This revision is now accepted and ready to land.Oct 5 2017, 11:51 PM
This revision was automatically updated to reflect the committed changes.
thakis added a subscriber: thakis.Feb 11 2019, 8:47 AM
thakis added inline comments.
cfe/trunk/test/CodeGenObjC/os_log.m
53

Zombie comment: This is missing a ':' and hence doesn't check anything.

Herald added a project: Restricted Project. · View Herald TranscriptFeb 11 2019, 8:47 AM