Imported Upstream version 5.18.0.225

Former-commit-id: 10196d987d5fc5564b9d3b33b1fdf13190f4d0b5
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2018-12-21 19:01:49 +00:00
parent 32d52ae4ca
commit f32dbaf0b2
28477 changed files with 3866961 additions and 38 deletions

View File

@@ -0,0 +1,49 @@
; RUN: opt -S -adce < %s | FileCheck %s
; While it is normally okay to DCE out calls to @readonly_function and
; @readnone_function, we cannot do that if they're carrying operand
; bundles since the presence of unknown operand bundles implies
; arbitrary memory effects.
declare void @readonly_function() readonly nounwind
declare void @readnone_function() readnone nounwind
define void @test0() {
; CHECK-LABEL: @test0(
entry:
call void @readonly_function() [ "tag"() ]
; CHECK: call void @readonly_function
ret void
}
define void @test1() {
; CHECK-LABEL: @test1(
entry:
call void @readnone_function() [ "tag"() ]
; CHECK: call void @readnone_function
ret void
}
define void @test2() {
; CHECK-LABEL: @test2(
entry:
; CHECK-NOT: @readonly_function(
call void @readonly_function() readonly [ "tag"() ]
ret void
}
define void @test3() {
; CHECK-LABEL: @test3(
entry:
; CHECK-NOT: @readnone_function(
call void @readnone_function() readnone [ "tag"() ]
ret void
}
define void @test4() {
; CHECK-LABEL: @test4(
entry:
; CHECK-NOT: @readonly_function()
call void @readonly_function() [ "deopt"() ]
ret void
}

View File

@@ -0,0 +1,51 @@
; RUN: opt -S -basicaa -gvn < %s | FileCheck %s
declare void @argmemonly_function(i32 *) argmemonly
define i32 @test0(i32* %P, i32* noalias %P2) {
; CHECK-LABEL: @test0(
%v1 = load i32, i32* %P
; CHECK: %v1 = load i32, i32* %P
call void @argmemonly_function(i32* %P2) [ "tag"() ]
; CHECK: call void @argmemonly_function(
%v2 = load i32, i32* %P
; CHECK: %v2 = load i32, i32* %P
%diff = sub i32 %v1, %v2
; CHECK: %diff = sub i32 %v1, %v2
ret i32 %diff
; CHECK: ret i32 %diff
}
define i32 @test1(i32* %P, i32* noalias %P2) {
; CHECK-LABEL: @test1(
%v1 = load i32, i32* %P
call void @argmemonly_function(i32* %P2) argmemonly [ "tag"() ]
; CHECK: call void @argmemonly_function(
%v2 = load i32, i32* %P
%diff = sub i32 %v1, %v2
ret i32 %diff
; CHECK: ret i32 0
}
define i32 @test2(i32* %P, i32* noalias %P2) {
; Note: in this test we //can// GVN %v1 and %v2 into one value in theory. Calls
; with deopt operand bundles are not argmemonly because they *read* the entire
; heap, but they don't write to any location in the heap if the callee does not
; deoptimize the caller. This fact, combined with the fact that
; @argmemonly_function is, well, an argmemonly function, can be used to conclude
; that %P is not written to at the callsite. However LLVM currently cannot
; describe the "does not write to non-args, and reads the entire heap" effect on
; a callsite.
; CHECK-LABEL: @test2(
%v1 = load i32, i32* %P
; CHECK: %v1 = load i32, i32* %P
call void @argmemonly_function(i32* %P2) [ "deopt"() ]
; CHECK: call void @argmemonly_function(
%v2 = load i32, i32* %P
; CHECK: %v2 = load i32, i32* %P
%diff = sub i32 %v1, %v2
; CHECK: %diff = sub i32 %v1, %v2
ret i32 %diff
; CHECK: ret i32 %diff
}

View File

@@ -0,0 +1,62 @@
; RUN: opt -S -dse < %s | FileCheck %s
declare void @f()
declare noalias i8* @malloc(i32) nounwind
define void @test_0() {
; CHECK-LABEL: @test_0(
%m = call i8* @malloc(i32 24)
tail call void @f() [ "unknown"(i8* %m) ]
; CHECK: store i8 -19, i8* %m
store i8 -19, i8* %m
ret void
}
define i8* @test_1() {
; CHECK-LABEL: @test_1(
%m = call i8* @malloc(i32 24)
tail call void @f() [ "unknown"(i8* %m) ]
store i8 -19, i8* %m
tail call void @f()
store i8 101, i8* %m
; CHECK: tail call void @f() [ "unknown"(i8* %m) ]
; CHECK: store i8 -19, i8* %m
; CHECK: tail call void @f()
; CHECK: store i8 101, i8* %m
ret i8* %m
}
define void @test_2() {
; Since the deopt operand bundle does not escape %m (see caveat below), it is
; legal to elide the final store that location.
; CHECK-LABEL: @test_2(
%m = call i8* @malloc(i32 24)
tail call void @f() [ "deopt"(i8* %m) ]
store i8 -19, i8* %m
ret void
; CHECK: tail call void @f() [ "deopt"(i8* %m) ]
; CHECK-NEXT: ret void
}
define i8* @test_3() {
; Since the deopt operand bundle does not escape %m (see caveat below), @f
; cannot observe the stores to %m
; CHECK-LABEL: @test_3(
%m = call i8* @malloc(i32 24)
tail call void @f() [ "deopt"(i8* %m) ]
store i8 -19, i8* %m
tail call void @f()
store i8 101, i8* %m
ret i8* %m
}
; Caveat: technically, %m can only escape if the calling function is deoptimized
; at the call site (i.e. the call returns to the "deopt" continuation). Since
; the calling function body will be invalidated in that case, the calling
; function can be optimized under the assumption that %m does not escape.

View File

@@ -0,0 +1,89 @@
; RUN: opt -S -early-cse < %s | FileCheck %s
; While it is normally okay to do memory optimizations over calls to
; @readonly_function and @readnone_function, we cannot do that if
; they're carrying unknown operand bundles since the presence of
; unknown operand bundles implies arbitrary memory effects.
declare void @readonly_function() readonly nounwind
declare void @readnone_function() readnone nounwind
define i32 @test0(i32* %x) {
; CHECK-LABEL: @test0(
entry:
store i32 100, i32* %x
; CHECK: store i32 100, i32* %x
call void @readonly_function() [ "tag"() ]
; CHECK: call void @readonly_function()
%v = load i32, i32* %x
; CHECK: %v = load i32, i32* %x
; CHECK: ret i32 %v
ret i32 %v
}
define i32 @test1(i32* %x) {
; CHECK: @test1(
entry:
store i32 100, i32* %x
; CHECK: store i32 100, i32* %x
call void @readonly_function() readonly [ "tag"() ]
; CHECK-NOT: call void @readonly_function
%v = load i32, i32* %x
ret i32 %v
; CHECK: ret i32 100
}
define i32 @test3(i32* %x) {
; CHECK-LABEL: @test3(
entry:
store i32 100, i32* %x
; CHECK: store i32 100, i32* %x
call void @readonly_function()
; CHECK-NOT: call void @readonly_function
%v = load i32, i32* %x
ret i32 %v
; CHECK: ret i32 100
}
define void @test4(i32* %x) {
; CHECK-LABEL: @test4(
entry:
store i32 100, i32* %x
; CHECK: store i32 100, i32* %x
call void @readnone_function() [ "tag"() ]
; CHECK: call void @readnone_function
store i32 200, i32* %x
; CHECK: store i32 200, i32* %x
ret void
}
define void @test5(i32* %x) {
; CHECK-LABEL: @test5(
entry:
store i32 100, i32* %x
; CHECK-NOT: store i32 100, i32* %x
; CHECK-NOT: call void @readnone_function
call void @readnone_function() readnone [ "tag"() ]
store i32 200, i32* %x
; CHECK: store i32 200, i32* %x
ret void
}
define void @test6(i32* %x) {
; The "deopt" operand bundle does not make the call to
; @readonly_function read-write; and so the nounwind readonly call can
; be deleted.
; CHECK-LABEL: @test6(
entry:
; CHECK-NEXT: entry:
; CHECK-NEXT: store i32 200, i32* %x
; CHECK-NEXT: ret void
store i32 100, i32* %x
call void @readonly_function() [ "deopt"() ]
store i32 200, i32* %x
ret void
}

View File

@@ -0,0 +1,33 @@
; RUN: opt -S -functionattrs < %s | FileCheck %s
declare void @f_readonly() readonly
declare void @f_readnone() readnone
define void @test_0(i32* %x) {
; FunctionAttrs must not infer readonly / readnone for %x
; CHECK-LABEL: define void @test_0(i32* %x) {
entry:
; CHECK: call void @f_readonly() [ "foo"(i32* %x) ]
call void @f_readonly() [ "foo"(i32* %x) ]
ret void
}
define void @test_1(i32* %x) {
; FunctionAttrs must not infer readonly / readnone for %x
; CHECK-LABEL: define void @test_1(i32* %x) {
entry:
; CHECK: call void @f_readnone() [ "foo"(i32* %x) ]
call void @f_readnone() [ "foo"(i32* %x) ]
ret void
}
define void @test_2(i32* %x) {
; The "deopt" operand bundle does not capture or write to %x.
; CHECK-LABEL: define void @test_2(i32* nocapture readonly %x)
entry:
call void @f_readonly() [ "deopt"(i32* %x) ]
ret void
}

View File

@@ -0,0 +1,17 @@
; RUN: opt -S -inline < %s | FileCheck %s
; Check that the inliner does not inline through arbitrary unknown
; operand bundles.
define i32 @callee() {
entry:
ret i32 2
}
define i32 @caller() {
; CHECK: @caller(
entry:
; CHECK: call i32 @callee() [ "unknown"() ]
%x = call i32 @callee() [ "unknown"() ]
ret i32 %x
}

View File

@@ -0,0 +1,64 @@
; RUN: opt -S -mergefunc < %s | FileCheck %s
; Minor note: functions need to be at least three instructions long
; to be considered by -mergefunc.
declare i32 @foo(...)
define i32 @f() {
; CHECK-LABEL: @f(
entry:
%v0 = call i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
%v1 = call i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
%v2 = call i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
; CHECK: %v0 = call i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
; CHECK: %v1 = call i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
; CHECK: %v2 = call i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
ret i32 %v2
}
define i32 @g() {
; CHECK-LABEL: @g(
entry:
%v0 = call i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
%v1 = call i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
%v2 = call i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
; CHECK: %v0 = call i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
; CHECK: %v1 = call i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
; CHECK: %v2 = call i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
ret i32 %v2
}
define i32 @f.invoke() personality i8 3 {
; CHECK-LABEL: @f.invoke(
entry:
; CHECK: %v0 = invoke i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
%v0 = invoke i32 (...) @foo(i32 10) [ "foo"(i32 20) ]
to label %normal unwind label %exception
normal:
ret i32 %v0
exception:
%cleanup = landingpad i8 cleanup
ret i32 0
}
define i32 @g.invoke() personality i8 3 {
; CHECK-LABEL: @g.invoke(
entry:
; CHECK: %v0 = invoke i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
%v0 = invoke i32 (...) @foo() [ "foo"(i32 10, i32 20) ]
to label %normal unwind label %exception
normal:
ret i32 %v0
exception:
%cleanup = landingpad i8 cleanup
ret i32 0
}

View File

@@ -0,0 +1,27 @@
; RUN: opt -S -globals-aa -functionattrs < %s | FileCheck %s
; RUN: opt -S -O3 < %s | FileCheck %s
; Apart from checking for the direct cause of the bug, we also check
; if any problematic aliasing rules have accidentally snuck into -O3.
;
; Since the "abc" operand bundle is not a special operand bundle that
; LLVM knows about, all of the stores and loads in @test below have to
; stay.
declare void @foo() readnone
; CHECK-LABEL: define i8* @test(i8* %p)
; CHECK: %a = alloca i8*, align 8
; CHECK: store i8* %p, i8** %a, align 8
; CHECK: call void @foo() [ "abc"(i8** %a) ]
; CHECK: %reload = load i8*, i8** %a, align 8
; CHECK: ret i8* %reload
; CHECK: }
define i8* @test(i8* %p) {
%a = alloca i8*, align 8
store i8* %p, i8** %a, align 8
call void @foo() ["abc" (i8** %a)]
%reload = load i8*, i8** %a, align 8
ret i8* %reload
}

View File

@@ -0,0 +1,21 @@
; RUN: opt -S -early-cse < %s | FileCheck %s
; This test isn't directly related to EarlyCSE or varargs. It is just
; using these as a vehicle for testing the correctness of
; haveSameSpecialState around operand bundles.
declare i32 @foo(...)
define i32 @f() {
; CHECK-LABEL: @f(
entry:
; CHECK: %v0 = call i32 (...) @foo(
; CHECK: %v1 = call i32 (...) @foo(
; CHECK: %v = add i32 %v0, %v1
; CHECK: ret i32 %v
%v0 = call i32 (...) @foo(i32 10) readonly [ "foo"(i32 20) ]
%v1 = call i32 (...) @foo() readonly [ "foo"(i32 10, i32 20) ]
%v = add i32 %v0, %v1
ret i32 %v
}