Imported Upstream version 6.0.0.172

Former-commit-id: f3cc9b82f3e5bd8f0fd3ebc098f789556b44e9cd
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2019-04-12 14:10:50 +00:00
parent 8016999e4d
commit 64ac736ec5
32155 changed files with 3981439 additions and 75368 deletions

View File

@@ -0,0 +1,291 @@
; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -o - < %s -inline-threshold=0 | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
declare void @pad()
@glbl = external global i32
define i32 @outer_add1(i32 %a) {
; CHECK-LABEL: @outer_add1(
; CHECK-NOT: call i32 @add
%C = call i32 @add(i32 %a, i32 0)
ret i32 %C
}
define i32 @outer_add2(i32 %a) {
; CHECK-LABEL: @outer_add2(
; CHECK-NOT: call i32 @add
%C = call i32 @add(i32 0, i32 %a)
ret i32 %C
}
define i32 @add(i32 %a, i32 %b) {
%add = add i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %add
}
define i32 @outer_sub1(i32 %a) {
; CHECK-LABEL: @outer_sub1(
; CHECK-NOT: call i32 @sub1
%C = call i32 @sub1(i32 %a, i32 0)
ret i32 %C
}
define i32 @sub1(i32 %a, i32 %b) {
%sub = sub i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %sub
}
define i32 @outer_sub2(i32 %a) {
; CHECK-LABEL: @outer_sub2(
; CHECK-NOT: call i32 @sub2
%C = call i32 @sub2(i32 %a)
ret i32 %C
}
define i32 @sub2(i32 %a) {
%sub = sub i32 %a, %a
call void @pad()
ret i32 %sub
}
define i32 @outer_mul1(i32 %a) {
; CHECK-LABEL: @outer_mul1(
; CHECK-NOT: call i32 @mul
%C = call i32 @mul(i32 %a, i32 0)
ret i32 %C
}
define i32 @outer_mul2(i32 %a) {
; CHECK-LABEL: @outer_mul2(
; CHECK-NOT: call i32 @mul
%C = call i32 @mul(i32 %a, i32 1)
ret i32 %C
}
define i32 @mul(i32 %a, i32 %b) {
%mul = mul i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %mul
}
define i32 @outer_div1(i32 %a) {
; CHECK-LABEL: @outer_div1(
; CHECK-NOT: call i32 @div1
%C = call i32 @div1(i32 0, i32 %a)
ret i32 %C
}
define i32 @outer_div2(i32 %a) {
; CHECK-LABEL: @outer_div2(
; CHECK-NOT: call i32 @div1
%C = call i32 @div1(i32 %a, i32 1)
ret i32 %C
}
define i32 @div1(i32 %a, i32 %b) {
%div = sdiv i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %div
}
define i32 @outer_div3(i32 %a) {
; CHECK-LABEL: @outer_div3(
; CHECK-NOT: call i32 @div
%C = call i32 @div2(i32 %a)
ret i32 %C
}
define i32 @div2(i32 %a) {
%div = sdiv i32 %a, %a
call void @pad()
ret i32 %div
}
define i32 @outer_rem1(i32 %a) {
; CHECK-LABEL: @outer_rem1(
; CHECK-NOT: call i32 @rem
%C = call i32 @rem1(i32 0, i32 %a)
ret i32 %C
}
define i32 @outer_rem2(i32 %a) {
; CHECK-LABEL: @outer_rem2(
; CHECK-NOT: call i32 @rem
%C = call i32 @rem1(i32 %a, i32 1)
ret i32 %C
}
define i32 @rem1(i32 %a, i32 %b) {
%rem = urem i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %rem
}
define i32 @outer_rem3(i32 %a) {
; CHECK-LABEL: @outer_rem3(
; CHECK-NOT: call i32 @rem
%C = call i32 @rem2(i32 %a)
ret i32 %C
}
define i32 @rem2(i32 %a) {
%rem = urem i32 %a, %a
call void @pad()
ret i32 %rem
}
define i32 @outer_shl1(i32 %a) {
; CHECK-LABEL: @outer_shl1(
; CHECK-NOT: call i32 @shl
%C = call i32 @shl(i32 %a, i32 0)
ret i32 %C
}
define i32 @shl(i32 %a, i32 %b) {
%shl = shl i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %shl
}
define i32 @outer_shr1(i32 %a) {
; CHECK-LABEL: @outer_shr1(
; CHECK-NOT: call i32 @shr
%C = call i32 @shr(i32 %a, i32 0)
ret i32 %C
}
define i32 @shr(i32 %a, i32 %b) {
%shr = ashr i32 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i32 %shr
}
define i1 @outer_and1(i1 %a) {
; check-label: @outer_and1(
; check-not: call i1 @and1
%c = call i1 @and1(i1 %a, i1 false)
ret i1 %c
}
define i1 @outer_and2(i1 %a) {
; check-label: @outer_and2(
; check-not: call i1 @and1
%c = call i1 @and1(i1 %a, i1 true)
ret i1 %c
}
define i1 @and1(i1 %a, i1 %b) {
%and = and i1 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i1 %and
}
define i1 @outer_and3(i1 %a) {
; check-label: @outer_and3(
; check-not: call i1 @and2
%c = call i1 @and2(i1 %a)
ret i1 %c
}
define i1 @and2(i1 %a) {
%and = and i1 %a, %a
call void @pad()
ret i1 %and
}
define i1 @outer_or1(i1 %a) {
; check-label: @outer_or1(
; check-not: call i1 @or1
%c = call i1 @or1(i1 %a, i1 false)
ret i1 %c
}
define i1 @outer_or2(i1 %a) {
; check-label: @outer_or2(
; check-not: call i1 @or1
%c = call i1 @or1(i1 %a, i1 true)
ret i1 %c
}
define i1 @or1(i1 %a, i1 %b) {
%or = or i1 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i1 %or
}
define i1 @outer_or3(i1 %a) {
; check-label: @outer_or3(
; check-not: call i1 @or2
%c = call i1 @or2(i1 %a)
ret i1 %c
}
define i1 @or2(i1 %a) {
%or = or i1 %a, %a
call void @pad()
ret i1 %or
}
define i1 @outer_xor1(i1 %a) {
; check-label: @outer_xor1(
; check-not: call i1 @xor
%c = call i1 @xor1(i1 %a, i1 false)
ret i1 %c
}
define i1 @xor1(i1 %a, i1 %b) {
%xor = xor i1 %a, %b
call void @pad()
store i32 0, i32* @glbl
ret i1 %xor
}
define i1 @outer_xor3(i1 %a) {
; check-label: @outer_xor3(
; check-not: call i1 @xor
%c = call i1 @xor2(i1 %a)
ret i1 %c
}
define i1 @xor2(i1 %a) {
%xor = xor i1 %a, %a
call void @pad()
ret i1 %xor
}

View File

@@ -0,0 +1,249 @@
; REQUIRES: asserts
; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
define i32 @outer1(i32* %ptr, i32 %i) {
%C = call i32 @inner1(i32* %ptr, i32 %i)
ret i32 %C
}
; sext can be folded into gep.
; CHECK: Analyzing call of inner1
; CHECK: NumInstructionsSimplified: 3
; CHECK: NumInstructions: 4
define i32 @inner1(i32* %ptr, i32 %i) {
%E = sext i32 %i to i64
%G = getelementptr inbounds i32, i32* %ptr, i64 %E
%L = load i32, i32* %G
ret i32 %L
}
define i32 @outer2(i32* %ptr, i32 %i) {
%C = call i32 @inner2(i32* %ptr, i32 %i)
ret i32 %C
}
; zext from i32 to i64 is free.
; CHECK: Analyzing call of inner2
; CHECK: NumInstructionsSimplified: 3
; CHECK: NumInstructions: 4
define i32 @inner2(i32* %ptr, i32 %i) {
%E = zext i32 %i to i64
%G = getelementptr inbounds i32, i32* %ptr, i64 %E
%L = load i32, i32* %G
ret i32 %L
}
define i32 @outer3(i32* %ptr, i16 %i) {
%C = call i32 @inner3(i32* %ptr, i16 %i)
ret i32 %C
}
; zext can be folded into gep.
; CHECK: Analyzing call of inner3
; CHECK: NumInstructionsSimplified: 3
; CHECK: NumInstructions: 4
define i32 @inner3(i32* %ptr, i16 %i) {
%E = zext i16 %i to i64
%G = getelementptr inbounds i32, i32* %ptr, i64 %E
%L = load i32, i32* %G
ret i32 %L
}
define i16 @outer4(i8* %ptr) {
%C = call i16 @inner4(i8* %ptr)
ret i16 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner4
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i16 @inner4(i8* %ptr) {
%L = load i8, i8* %ptr
%E = zext i8 %L to i16
ret i16 %E
}
define i16 @outer5(i8* %ptr) {
%C = call i16 @inner5(i8* %ptr)
ret i16 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner5
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i16 @inner5(i8* %ptr) {
%L = load i8, i8* %ptr
%E = sext i8 %L to i16
ret i16 %E
}
define i32 @outer6(i8* %ptr) {
%C = call i32 @inner6(i8* %ptr)
ret i32 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner6
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i32 @inner6(i8* %ptr) {
%L = load i8, i8* %ptr
%E = zext i8 %L to i32
ret i32 %E
}
define i32 @outer7(i8* %ptr) {
%C = call i32 @inner7(i8* %ptr)
ret i32 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner7
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i32 @inner7(i8* %ptr) {
%L = load i8, i8* %ptr
%E = sext i8 %L to i32
ret i32 %E
}
define i32 @outer8(i16* %ptr) {
%C = call i32 @inner8(i16* %ptr)
ret i32 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner8
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i32 @inner8(i16* %ptr) {
%L = load i16, i16* %ptr
%E = zext i16 %L to i32
ret i32 %E
}
define i32 @outer9(i16* %ptr) {
%C = call i32 @inner9(i16* %ptr)
ret i32 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner9
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i32 @inner9(i16* %ptr) {
%L = load i16, i16* %ptr
%E = sext i16 %L to i32
ret i32 %E
}
define i64 @outer10(i8* %ptr) {
%C = call i64 @inner10(i8* %ptr)
ret i64 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner10
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i64 @inner10(i8* %ptr) {
%L = load i8, i8* %ptr
%E = zext i8 %L to i64
ret i64 %E
}
define i64 @outer11(i8* %ptr) {
%C = call i64 @inner11(i8* %ptr)
ret i64 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner11
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i64 @inner11(i8* %ptr) {
%L = load i8, i8* %ptr
%E = sext i8 %L to i64
ret i64 %E
}
define i64 @outer12(i16* %ptr) {
%C = call i64 @inner12(i16* %ptr)
ret i64 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner12
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i64 @inner12(i16* %ptr) {
%L = load i16, i16* %ptr
%E = zext i16 %L to i64
ret i64 %E
}
define i64 @outer13(i16* %ptr) {
%C = call i64 @inner13(i16* %ptr)
ret i64 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner13
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i64 @inner13(i16* %ptr) {
%L = load i16, i16* %ptr
%E = sext i16 %L to i64
ret i64 %E
}
define i64 @outer14(i32* %ptr) {
%C = call i64 @inner14(i32* %ptr)
ret i64 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner14
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i64 @inner14(i32* %ptr) {
%L = load i32, i32* %ptr
%E = zext i32 %L to i64
ret i64 %E
}
define i64 @outer15(i32* %ptr) {
%C = call i64 @inner15(i32* %ptr)
ret i64 %C
}
; It is an ExtLoad.
; CHECK: Analyzing call of inner15
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 3
define i64 @inner15(i32* %ptr) {
%L = load i32, i32* %ptr
%E = sext i32 %L to i64
ret i64 %E
}
define i64 @outer16(i32 %V1, i64 %V2) {
%C = call i64 @inner16(i32 %V1, i64 %V2)
ret i64 %C
}
; sext can be folded into shl.
; CHECK: Analyzing call of inner16
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 4
define i64 @inner16(i32 %V1, i64 %V2) {
%E = sext i32 %V1 to i64
%S = shl i64 %E, 3
%A = add i64 %V2, %S
ret i64 %A
}

View File

@@ -0,0 +1,51 @@
; REQUIRES: asserts
; RUN: opt -inline -mtriple=aarch64--linux-gnu -mcpu=kryo -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
define void @outer1([4 x i32]* %ptr, i32 %i) {
call void @inner1([4 x i32]* %ptr, i32 %i)
ret void
}
define void @outer2([4 x i32]* %ptr, i32 %i) {
call void @inner2([4 x i32]* %ptr, i32 %i)
ret void
}
define void @outer3([4 x i32]* %ptr, i32 %j) {
call void @inner3([4 x i32]* %ptr, i32 0, i32 %j)
ret void
}
; The gep in inner1() is reg+reg, which is a legal addressing mode for AArch64.
; Thus, both the gep and ret can be simplified.
; CHECK: Analyzing call of inner1
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 2
define void @inner1([4 x i32]* %ptr, i32 %i) {
%G = getelementptr inbounds [4 x i32], [4 x i32]* %ptr, i32 0, i32 %i
ret void
}
; The gep in inner2() is reg+imm+reg, which is not a legal addressing mode for
; AArch64. Thus, only the ret can be simplified and not the gep.
; CHECK: Analyzing call of inner2
; CHECK: NumInstructionsSimplified: 1
; CHECK: NumInstructions: 2
define void @inner2([4 x i32]* %ptr, i32 %i) {
%G = getelementptr inbounds [4 x i32], [4 x i32]* %ptr, i32 1, i32 %i
ret void
}
; The gep in inner3() is reg+reg because %i is a known constant from the
; callsite. This case is a legal addressing mode for AArch64. Thus, both the
; gep and ret can be simplified.
; CHECK: Analyzing call of inner3
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 2
define void @inner3([4 x i32]* %ptr, i32 %i, i32 %j) {
%G = getelementptr inbounds [4 x i32], [4 x i32]* %ptr, i32 %i, i32 %j
ret void
}

View File

@@ -0,0 +1,40 @@
; RUN: opt < %s -mtriple=aarch64-unknown-linux-gnu -S -inline | FileCheck %s
; RUN: opt < %s -mtriple=aarch64-unknown-linux-gnu -S -passes='cgscc(inline)' | FileCheck %s
; Check that we only inline when we have compatible target attributes.
define i32 @foo() #0 {
entry:
%call = call i32 (...) @baz()
ret i32 %call
; CHECK-LABEL: foo
; CHECK: call i32 (...) @baz()
}
declare i32 @baz(...) #0
define i32 @bar() #1 {
entry:
%call = call i32 @foo()
ret i32 %call
; CHECK-LABEL: bar
; CHECK: call i32 (...) @baz()
}
define i32 @qux() #0 {
entry:
%call = call i32 @bar()
ret i32 %call
; CHECK-LABEL: qux
; CHECK: call i32 @bar()
}
define i32 @strict_align() #2 {
entry:
%call = call i32 @foo()
ret i32 %call
; CHECK-LABEL: strict_align
; CHECK: call i32 (...) @baz()
}
attributes #0 = { "target-cpu"="generic" "target-features"="+crc,+neon" }
attributes #1 = { "target-cpu"="generic" "target-features"="+crc,+neon,+crypto" }
attributes #2 = { "target-cpu"="generic" "target-features"="+crc,+neon,+strict-align" }

View File

@@ -0,0 +1,2 @@
if not 'AArch64' in config.root.targets:
config.unsupported = True

View File

@@ -0,0 +1,94 @@
; REQUIRES: asserts
; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -debug-only=inline-cost < %s 2>&1 | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
; FIXME: Once the 'or' or 'and' is simplified the second compare is dead, but
; the inline cost model has already added the cost.
define i1 @outer1(i32 %a) {
%C = call i1 @inner1(i32 0, i32 %a)
ret i1 %C
}
; CHECK: Analyzing call of inner1
; CHECK: NumInstructionsSimplified: 3
; CHECK: NumInstructions: 4
define i1 @inner1(i32 %a, i32 %b) {
%tobool = icmp eq i32 %a, 0 ; Simplifies to true
%tobool1 = icmp eq i32 %b, 0 ; Should be dead once 'or' is simplified
%or.cond = or i1 %tobool, %tobool1 ; Simplifies to true
ret i1 %or.cond ; Simplifies to ret i1 true
}
define i1 @outer2(i32 %a) {
%C = call i1 @inner2(i32 1, i32 %a)
ret i1 %C
}
; CHECK: Analyzing call of inner2
; CHECK: NumInstructionsSimplified: 3
; CHECK: NumInstructions: 4
define i1 @inner2(i32 %a, i32 %b) {
%tobool = icmp eq i32 %a, 0 ; Simplifies to false
%tobool1 = icmp eq i32 %b, 0 ; Should be dead once 'and' is simplified
%and.cond = and i1 %tobool, %tobool1 ; Simplifies to false
ret i1 %and.cond ; Simplifies to ret i1 false
}
define i32 @outer3(i32 %a) {
%C = call i32 @inner3(i32 4294967295, i32 %a)
ret i32 %C
}
; CHECK: Analyzing call of inner3
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 2
define i32 @inner3(i32 %a, i32 %b) {
%or.cond = or i32 %a, %b ; Simplifies to 4294967295
ret i32 %or.cond ; Simplifies to ret i32 4294967295
}
define i32 @outer4(i32 %a) {
%C = call i32 @inner4(i32 0, i32 %a)
ret i32 %C
}
; CHECK: Analyzing call of inner4
; CHECK: NumInstructionsSimplified: 2
; CHECK: NumInstructions: 2
define i32 @inner4(i32 %a, i32 %b) {
%and.cond = and i32 %a, %b ; Simplifies to 0
ret i32 %and.cond ; Simplifies to ret i32 0
}
define i1 @outer5(i32 %a) {
%C = call i1 @inner5(i32 0, i32 %a)
ret i1 %C
}
; CHECK: Analyzing call of inner5
; CHECK: NumInstructionsSimplified: 4
; CHECK: NumInstructions: 5
define i1 @inner5(i32 %a, i32 %b) {
%tobool = icmp eq i32 %a, 0 ; Simplifies to true
%tobool1 = icmp eq i32 %b, 0 ; Should be dead once 'or' is simplified
%or.cond = or i1 %tobool, %tobool1 ; Simplifies to true
br i1 %or.cond, label %end, label %isfalse ; Simplifies to br label %end
isfalse: ; This block is unreachable once inlined
call void @dead()
call void @dead()
call void @dead()
call void @dead()
call void @dead()
br label %end
end:
ret i1 %or.cond ; Simplifies to ret i1 true
}
declare void @dead()

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,251 @@
; RUN: opt -inline -mtriple=aarch64--linux-gnu -S -o - < %s -inline-threshold=0 | FileCheck %s
target datalayout = "e-m:e-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128"
target triple = "aarch64--linux-gnu"
declare void @pad()
@glbl = external global i32
define i32 @outer1(i1 %cond) {
; CHECK-LABEL: @outer1(
; CHECK-NOT: call i32 @inner1
%C = call i32 @inner1(i1 %cond, i32 1)
ret i32 %C
}
define i32 @inner1(i1 %cond, i32 %val) {
%select = select i1 %cond, i32 1, i32 %val ; Simplified to 1
call void @pad()
store i32 0, i32* @glbl
ret i32 %select ; Simplifies to ret i32 1
}
define i32 @outer2(i32 %val) {
; CHECK-LABEL: @outer2(
; CHECK-NOT: call i32 @inner2
%C = call i32 @inner2(i1 true, i32 %val)
ret i32 %C
}
define i32 @inner2(i1 %cond, i32 %val) {
%select = select i1 %cond, i32 1, i32 %val ; Simplifies to 1
call void @pad()
store i32 0, i32* @glbl
ret i32 %select ; Simplifies to ret i32 1
}
define i32 @outer3(i32 %val) {
; CHECK-LABEL: @outer3(
; CHECK-NOT: call i32 @inner3
%C = call i32 @inner3(i1 false, i32 %val)
ret i32 %C
}
define i32 @inner3(i1 %cond, i32 %val) {
%select = select i1 %cond, i32 %val, i32 -1 ; Simplifies to -1
call void @pad()
store i32 0, i32* @glbl
ret i32 %select ; Simplifies to ret i32 -1
}
define i32 @outer4() {
; CHECK-LABEL: @outer4(
; CHECK-NOT: call i32 @inner4
%C = call i32 @inner4(i1 true, i32 1, i32 -1)
ret i32 %C
}
define i32 @inner4(i1 %cond, i32 %val1, i32 %val2) {
%select = select i1 %cond, i32 %val1, i32 %val2 ; Simplifies to 1
call void @pad()
store i32 0, i32* @glbl
store i32 1, i32* @glbl
ret i32 %select ; Simplifies to ret i32 1
}
define i1 @outer5() {
; CHECK-LABEL: @outer5(
; CHECK-NOT: call i1 @inner5
%C = call i1 @inner5(i1 true, i1 true, i1 false)
ret i1 %C
}
declare void @dead()
define i1 @inner5(i1 %cond, i1 %val1, i1 %val2) {
%select = select i1 %cond, i1 %val1, i1 %val2 ; Simplifies to true
br i1 %select, label %exit, label %isfalse ; Simplifies to br label %end
isfalse: ; This block is unreachable once inlined
call void @dead()
br label %exit
exit:
store i32 0, i32* @glbl
ret i1 %select ; Simplifies to ret i1 true
}
define i32 @outer6(i1 %cond) {
; CHECK-LABEL: @outer6(
; CHECK-NOT: call i32 @inner6
%A = alloca i32
%C = call i32 @inner6(i1 %cond, i32* %A)
ret i32 %C
}
define i32 @inner6(i1 %cond, i32* %ptr) {
%G1 = getelementptr inbounds i32, i32* %ptr, i32 1
%G2 = getelementptr inbounds i32, i32* %G1, i32 1
%G3 = getelementptr inbounds i32, i32* %ptr, i32 2
%select = select i1 %cond, i32* %G2, i32* %G3 ; Simplified to %A[2]
%load = load i32, i32* %select ; SROA'ed
call void @pad()
ret i32 %load ; Simplified
}
define i32 @outer7(i32* %ptr) {
; CHECK-LABEL: @outer7(
; CHECK-NOT: call i32 @inner7
%A = alloca i32
%C = call i32 @inner7(i1 true, i32* %A, i32* %ptr)
ret i32 %C
}
define i32 @inner7(i1 %cond, i32* %p1, i32* %p2) {
%select = select i1 %cond, i32* %p1, i32* %p2 ; Simplifies to %A
%load = load i32, i32* %select ; SROA'ed
call void @pad()
store i32 0, i32* @glbl
ret i32 %load ; Simplified
}
define i32 @outer8(i32* %ptr) {
; CHECK-LABEL: @outer8(
; CHECK-NOT: call i32 @inner8
%A = alloca i32
%C = call i32 @inner8(i1 false, i32* %ptr, i32* %A)
ret i32 %C
}
define i32 @inner8(i1 %cond, i32* %p1, i32* %p2) {
%select = select i1 %cond, i32* %p1, i32* %p2 ; Simplifies to %A
%load = load i32, i32* %select ; SROA'ed
call void @pad()
store i32 0, i32* @glbl
ret i32 %load ; Simplified
}
define <2 x i32> @outer9(<2 x i32> %val) {
; CHECK-LABEL: @outer9(
; CHECK-NOT: call <2 x i32> @inner9
%C = call <2 x i32> @inner9(<2 x i1> <i1 true, i1 true>, <2 x i32> %val)
ret <2 x i32> %C
}
define <2 x i32> @inner9(<2 x i1> %cond, <2 x i32> %val) {
%select = select <2 x i1> %cond, <2 x i32> <i32 1, i32 1>, <2 x i32> %val ; Simplifies to <1, 1>
call void @pad()
store i32 0, i32* @glbl
ret <2 x i32> %select ; Simplifies to ret <2 x i32> <1, 1>
}
define <2 x i32> @outer10(<2 x i32> %val) {
; CHECK-LABEL: @outer10(
; CHECK-NOT: call <2 x i32> @inner10
%C = call <2 x i32> @inner10(<2 x i1> <i1 false, i1 false>, <2 x i32> %val)
ret <2 x i32> %C
}
define <2 x i32> @inner10(<2 x i1> %cond, <2 x i32> %val) {
%select = select <2 x i1> %cond, < 2 x i32> %val, <2 x i32> <i32 -1, i32 -1> ; Simplifies to <-1, -1>
call void @pad()
store i32 0, i32* @glbl
ret <2 x i32> %select ; Simplifies to ret <2 x i32> <-1, -1>
}
define <2 x i32> @outer11() {
; CHECK-LABEL: @outer11(
; CHECK-NOT: call <2 x i32> @inner11
%C = call <2 x i32> @inner11(<2 x i1> <i1 true, i1 false>)
ret <2 x i32> %C
}
define <2 x i32> @inner11(<2 x i1> %cond) {
%select = select <2 x i1> %cond, <2 x i32> <i32 1, i32 1>, < 2 x i32> <i32 -1, i32 -1> ; Simplifies to <1, -1>
call void @pad()
ret <2 x i32> %select ; Simplifies to ret <2 x i32> <1, -1>
}
define i1 @outer12(i32* %ptr) {
; CHECK-LABEL: @outer12(
; CHECK-NOT: call i1 @inner12
%C = call i1 @inner12(i1 true, i32* @glbl, i32* %ptr)
ret i1 %C
}
define i1 @inner12(i1 %cond, i32* %ptr1, i32* %ptr2) {
%select = select i1 %cond, i32* %ptr1, i32* %ptr2 ; Simplified to @glbl
%cmp = icmp eq i32* %select, @glbl ; Simplified to true
call void @pad()
store i32 0, i32* @glbl
ret i1 %cmp ; Simplifies to ret i1 true
}
define <2 x i32> @outer13(<2 x i32> %val1, <2 x i32> %val2) {
; CHECK-LABEL: @outer13(
; CHECK: call <2 x i32> @inner13
%C = call <2 x i32> @inner13(<2 x i1> <i1 true, i1 false>, <2 x i32> %val1, <2 x i32> %val2)
ret <2 x i32> %C
}
define <2 x i32> @inner13(<2 x i1> %cond, <2 x i32> %val1, < 2 x i32> %val2) {
%select = select <2 x i1> %cond, <2 x i32> %val1, < 2 x i32> %val2 ; Cannot be Simplified
call void @pad()
store i32 0, i32* @glbl
store i32 1, i32* @glbl
ret <2 x i32> %select ; Simplified
}
define i32 @outer14(i32 %val1, i32 %val2) {
; CHECK-LABEL: @outer14(
; CHECK-NOT: call i32 @inner14
%C = call i32 @inner14(i1 true, i32 %val1, i32 %val2)
ret i32 %C
}
define i32 @inner14(i1 %cond, i32 %val1, i32 %val2) {
%select = select i1 %cond, i32 %val1, i32 %val2 ; Simplified to %val1
call void @pad()
store i32 0, i32* @glbl
store i32 1, i32* @glbl
ret i32 %select ; Simplifies to ret i32 %val1
}
define i32 @outer15(i32 %val1, i32 %val2) {
; CHECK-LABEL: @outer15(
; CHECK-NOT: call i32 @inner15
%C = call i32 @inner15(i1 false, i32 %val1, i32 %val2)
ret i32 %C
}
define i32 @inner15(i1 %cond, i32 %val1, i32 %val2) {
%select = select i1 %cond, i32 %val1, i32 %val2 ; Simplified to %val2
call void @pad()
store i32 0, i32* @glbl
store i32 1, i32* @glbl
ret i32 %select ; Simplifies to ret i32 %val2
}

View File

@@ -0,0 +1,160 @@
; RUN: opt < %s -inline -inline-threshold=20 -S -mtriple=aarch64-none-linux | FileCheck %s
; RUN: opt < %s -passes='cgscc(inline)' -inline-threshold=20 -S -mtriple=aarch64-none-linux | FileCheck %s
define i32 @callee_range(i32 %a, i32* %P) {
switch i32 %a, label %sw.default [
i32 0, label %sw.bb0
i32 1000, label %sw.bb1
i32 2000, label %sw.bb1
i32 3000, label %sw.bb1
i32 4000, label %sw.bb1
i32 5000, label %sw.bb1
i32 6000, label %sw.bb1
i32 7000, label %sw.bb1
i32 8000, label %sw.bb1
i32 9000, label %sw.bb1
]
sw.default:
store volatile i32 %a, i32* %P
br label %return
sw.bb0:
store volatile i32 %a, i32* %P
br label %return
sw.bb1:
store volatile i32 %a, i32* %P
br label %return
return:
ret i32 42
}
define i32 @caller_range(i32 %a, i32* %P) {
; CHECK-LABEL: @caller_range(
; CHECK: call i32 @callee_range
%r = call i32 @callee_range(i32 %a, i32* %P)
ret i32 %r
}
define i32 @callee_bittest(i32 %a, i32* %P) {
switch i32 %a, label %sw.default [
i32 0, label %sw.bb0
i32 1, label %sw.bb1
i32 2, label %sw.bb2
i32 3, label %sw.bb0
i32 4, label %sw.bb1
i32 5, label %sw.bb2
i32 6, label %sw.bb0
i32 7, label %sw.bb1
i32 8, label %sw.bb2
]
sw.default:
store volatile i32 %a, i32* %P
br label %return
sw.bb0:
store volatile i32 %a, i32* %P
br label %return
sw.bb1:
store volatile i32 %a, i32* %P
br label %return
sw.bb2:
br label %return
return:
ret i32 42
}
define i32 @caller_bittest(i32 %a, i32* %P) {
; CHECK-LABEL: @caller_bittest(
; CHECK-NOT: call i32 @callee_bittest
%r= call i32 @callee_bittest(i32 %a, i32* %P)
ret i32 %r
}
define i32 @callee_jumptable(i32 %a, i32* %P) {
switch i32 %a, label %sw.default [
i32 1001, label %sw.bb101
i32 1002, label %sw.bb102
i32 1003, label %sw.bb103
i32 1004, label %sw.bb104
i32 1005, label %sw.bb101
i32 1006, label %sw.bb102
i32 1007, label %sw.bb103
i32 1008, label %sw.bb104
i32 1009, label %sw.bb101
i32 1010, label %sw.bb102
i32 1011, label %sw.bb103
i32 1012, label %sw.bb104
]
sw.default:
br label %return
sw.bb101:
store volatile i32 %a, i32* %P
br label %return
sw.bb102:
store volatile i32 %a, i32* %P
br label %return
sw.bb103:
store volatile i32 %a, i32* %P
br label %return
sw.bb104:
store volatile i32 %a, i32* %P
br label %return
return:
ret i32 42
}
define i32 @caller_jumptable(i32 %a, i32 %b, i32* %P) {
; CHECK-LABEL: @caller_jumptable(
; CHECK: call i32 @callee_jumptable
%r = call i32 @callee_jumptable(i32 %b, i32* %P)
ret i32 %r
}
define internal i32 @callee_negativeCost(i32 %t) {
entry:
switch i32 %t, label %sw.default [
i32 1, label %sw.bb
i32 0, label %sw.bb1
i32 42, label %sw.bb2
i32 43, label %sw.bb3
]
sw.bb: ; preds = %entry
br label %cleanup
sw.bb1: ; preds = %entry
br label %cleanup
sw.bb2: ; preds = %entry
br label %cleanup
sw.bb3: ; preds = %entry
br label %cleanup
sw.default: ; preds = %entry
br label %cleanup
cleanup: ; preds = %sw.default, %sw.bb3, %sw.bb2, %sw.bb1, %sw.bb
%retval.0 = phi i32 [ 1, %sw.default ], [ 3, %sw.bb3 ], [ 2, %sw.bb2 ], [ 0, %sw.bb1 ], [ 0, %sw.bb ]
ret i32 %retval.0
}
define i32 @caller_negativeCost(i32 %t) {
; CHECK-LABEL: @caller_negativeCost(
; CHECK-NOT: call i32 @callee_negativeCost
entry:
%call = call i32 @callee_negativeCost(i32 %t)
ret i32 %call
}