2014-07-15 18:46:51 +08:00
|
|
|
; RUN: opt -mergefunc -S < %s | FileCheck %s
|
|
|
|
|
|
|
|
define i8 @call_with_range() {
|
|
|
|
bitcast i8 0 to i8 ; dummy to make the function large enough
|
|
|
|
%out = call i8 @dummy(), !range !0
|
|
|
|
ret i8 %out
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @call_no_range() {
|
|
|
|
; CHECK-LABEL: @call_no_range
|
|
|
|
; CHECK-NEXT: bitcast i8 0 to i8
|
|
|
|
; CHECK-NEXT: %out = call i8 @dummy()
|
|
|
|
; CHECK-NEXT: ret i8 %out
|
|
|
|
bitcast i8 0 to i8
|
|
|
|
%out = call i8 @dummy()
|
|
|
|
ret i8 %out
|
|
|
|
}
|
|
|
|
|
|
|
|
define i8 @call_different_range() {
|
|
|
|
; CHECK-LABEL: @call_different_range
|
|
|
|
; CHECK-NEXT: bitcast i8 0 to i8
|
|
|
|
; CHECK-NEXT: %out = call i8 @dummy(), !range !1
|
|
|
|
; CHECK-NEXT: ret i8 %out
|
|
|
|
bitcast i8 0 to i8
|
|
|
|
%out = call i8 @dummy(), !range !1
|
|
|
|
ret i8 %out
|
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
define i8 @invoke_with_range() personality i8* undef {
|
2014-07-15 18:46:51 +08:00
|
|
|
%out = invoke i8 @dummy() to label %next unwind label %lpad, !range !0
|
|
|
|
|
|
|
|
next:
|
|
|
|
ret i8 %out
|
|
|
|
|
|
|
|
lpad:
|
2015-06-18 04:52:32 +08:00
|
|
|
%pad = landingpad { i8*, i32 } cleanup
|
2014-07-15 18:46:51 +08:00
|
|
|
resume { i8*, i32 } zeroinitializer
|
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
define i8 @invoke_no_range() personality i8* undef {
|
2014-07-15 18:46:51 +08:00
|
|
|
; CHECK-LABEL: @invoke_no_range()
|
|
|
|
; CHECK-NEXT: invoke i8 @dummy
|
|
|
|
%out = invoke i8 @dummy() to label %next unwind label %lpad
|
|
|
|
|
|
|
|
next:
|
|
|
|
ret i8 %out
|
|
|
|
|
|
|
|
lpad:
|
2015-06-18 04:52:32 +08:00
|
|
|
%pad = landingpad { i8*, i32 } cleanup
|
2014-07-15 18:46:51 +08:00
|
|
|
resume { i8*, i32 } zeroinitializer
|
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
define i8 @invoke_different_range() personality i8* undef {
|
2014-07-15 18:46:51 +08:00
|
|
|
; CHECK-LABEL: @invoke_different_range()
|
|
|
|
; CHECK-NEXT: invoke i8 @dummy
|
|
|
|
%out = invoke i8 @dummy() to label %next unwind label %lpad, !range !1
|
|
|
|
|
|
|
|
next:
|
|
|
|
ret i8 %out
|
|
|
|
|
|
|
|
lpad:
|
2015-06-18 04:52:32 +08:00
|
|
|
%pad = landingpad { i8*, i32 } cleanup
|
2014-07-15 18:46:51 +08:00
|
|
|
resume { i8*, i32 } zeroinitializer
|
|
|
|
}
|
|
|
|
|
2015-06-18 04:52:32 +08:00
|
|
|
define i8 @invoke_with_same_range() personality i8* undef {
|
2015-06-09 08:03:29 +08:00
|
|
|
; CHECK-LABEL: @invoke_with_same_range()
|
2014-07-15 18:46:51 +08:00
|
|
|
; CHECK: tail call i8 @invoke_with_range()
|
|
|
|
%out = invoke i8 @dummy() to label %next unwind label %lpad, !range !0
|
|
|
|
|
|
|
|
next:
|
|
|
|
ret i8 %out
|
|
|
|
|
|
|
|
lpad:
|
2015-06-18 04:52:32 +08:00
|
|
|
%pad = landingpad { i8*, i32 } cleanup
|
2014-07-15 18:46:51 +08:00
|
|
|
resume { i8*, i32 } zeroinitializer
|
|
|
|
}
|
|
|
|
|
2015-12-15 02:34:23 +08:00
|
|
|
define i8 @call_with_same_range() {
|
|
|
|
; CHECK-LABEL: @call_with_same_range
|
|
|
|
; CHECK: tail call i8 @call_with_range
|
|
|
|
bitcast i8 0 to i8
|
|
|
|
%out = call i8 @dummy(), !range !0
|
|
|
|
ret i8 %out
|
|
|
|
}
|
|
|
|
|
Accelerate MergeFunctions with hashing
This patch makes the Merge Functions pass faster by calculating and comparing
a hash value which captures the essential structure of a function before
performing a full function comparison.
The hash is calculated by hashing the function signature, then walking the basic
blocks of the function in the same order as the main comparison function. The
opcode of each instruction is hashed in sequence, which means that different
functions according to the existing total order cannot have the same hash, as
the comparison requires the opcodes of the two functions to be the same order.
The hash function is a static member of the FunctionComparator class because it
is tightly coupled to the exact comparison function used. For example, functions
which are equivalent modulo a single variant callsite might be merged by a more
aggressive MergeFunctions, and the hash function would need to be insensitive to
these differences in order to exploit this.
The hashing function uses a utility class which accumulates the values into an
internal state using a standard bit-mixing function. Note that this is a different interface
than a regular hashing routine, because the values to be hashed are scattered
amongst the properties of a llvm::Function, not linear in memory. This scheme is
fast because only one word of state needs to be kept, and the mixing function is
a few instructions.
The main runOnModule function first computes the hash of each function, and only
further processes functions which do not have a unique function hash. The hash
is also used to order the sorted function set. If the hashes differ, their
values are used to order the functions, otherwise the full comparison is done.
Both of these are helpful in speeding up MergeFunctions. Together they result in
speedups of 9% for mysqld (a mostly C application with little redundancy), 46%
for libxul in Firefox, and 117% for Chromium. (These are all LTO builds.) In all
three cases, the new speed of MergeFunctions is about half that of the module
verifier, making it relatively inexpensive even for large LTO builds with
hundreds of thousands of functions. The same functions are merged, so this
change is free performance.
Author: jrkoenig
Reviewers: nlewycky, dschuff, jfb
Subscribers: llvm-commits, aemerson
Differential revision: http://reviews.llvm.org/D11923
llvm-svn: 245140
2015-08-15 09:18:18 +08:00
|
|
|
|
|
|
|
|
2014-07-15 18:46:51 +08:00
|
|
|
declare i8 @dummy();
|
|
|
|
declare i32 @__gxx_personality_v0(...)
|
|
|
|
|
IR: Make metadata typeless in assembly
Now that `Metadata` is typeless, reflect that in the assembly. These
are the matching assembly changes for the metadata/value split in
r223802.
- Only use the `metadata` type when referencing metadata from a call
intrinsic -- i.e., only when it's used as a `Value`.
- Stop pretending that `ValueAsMetadata` is wrapped in an `MDNode`
when referencing it from call intrinsics.
So, assembly like this:
define @foo(i32 %v) {
call void @llvm.foo(metadata !{i32 %v}, metadata !0)
call void @llvm.foo(metadata !{i32 7}, metadata !0)
call void @llvm.foo(metadata !1, metadata !0)
call void @llvm.foo(metadata !3, metadata !0)
call void @llvm.foo(metadata !{metadata !3}, metadata !0)
ret void, !bar !2
}
!0 = metadata !{metadata !2}
!1 = metadata !{i32* @global}
!2 = metadata !{metadata !3}
!3 = metadata !{}
turns into this:
define @foo(i32 %v) {
call void @llvm.foo(metadata i32 %v, metadata !0)
call void @llvm.foo(metadata i32 7, metadata !0)
call void @llvm.foo(metadata i32* @global, metadata !0)
call void @llvm.foo(metadata !3, metadata !0)
call void @llvm.foo(metadata !{!3}, metadata !0)
ret void, !bar !2
}
!0 = !{!2}
!1 = !{i32* @global}
!2 = !{!3}
!3 = !{}
I wrote an upgrade script that handled almost all of the tests in llvm
and many of the tests in cfe (even handling many `CHECK` lines). I've
attached it (or will attach it in a moment if you're speedy) to PR21532
to help everyone update their out-of-tree testcases.
This is part of PR21532.
llvm-svn: 224257
2014-12-16 03:07:53 +08:00
|
|
|
!0 = !{i8 0, i8 2}
|
|
|
|
!1 = !{i8 5, i8 7}
|