1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2025-01-31 12:41:49 +01:00

[ArgPromo][Tests] Run update_test_checks on all ArgumentPromotion tests

Summary:
In preparation of D65531 as well as the reuse of these tests for the
Attributor, we modernize them and use the update_test_checks to simplify
updates.

This was done with the update_test_checks after D68819 and D68850.

Reviewers: hfinkel, vsk, dblaikie, davidxl, tejohnson, tstellar, echristo, chandlerc, efriedma, lebedev.ri

Subscribers: bollu, arphaman, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D68766
This commit is contained in:
Johannes Doerfert 2019-10-10 02:10:51 -05:00
parent c24c869cf0
commit fd77171a96
32 changed files with 1477 additions and 872 deletions

View File

@ -1,19 +1,30 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; CHECK: define internal i32 @deref(i32 %x.val) #0 {
define internal i32 @deref(i32* %x) nounwind {
; CHECK-LABEL: define {{[^@]+}}@deref
; CHECK-SAME: (i32 [[X_VAL:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 [[X_VAL]]
;
entry:
%tmp2 = load i32, i32* %x, align 4
ret i32 %tmp2
}
define i32 @f(i32 %x) {
; CHECK-LABEL: define {{[^@]+}}@f
; CHECK-SAME: (i32 [[X:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X_ADDR:%.*]] = alloca i32
; CHECK-NEXT: store i32 [[X]], i32* [[X_ADDR]], align 4
; CHECK-NEXT: [[X_ADDR_VAL:%.*]] = load i32, i32* [[X_ADDR]], align 4
; CHECK-NEXT: [[TMP1:%.*]] = call i32 @deref(i32 [[X_ADDR_VAL]])
; CHECK-NEXT: ret i32 [[TMP1]]
;
entry:
%x_addr = alloca i32
store i32 %x, i32* %x_addr, align 4
; CHECK: %tmp1 = call i32 @deref(i32 %x_addr.val) [[NUW:#[0-9]+]]
%tmp1 = call i32 @deref( i32* %x_addr ) nounwind
ret i32 %tmp1
}
; CHECK: attributes [[NUW]] = { nounwind }

View File

@ -1,11 +1,22 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; PR2498
; This test tries to convince argpromotion about promoting the load from %A + 2,
; This test tries to convince CHECK about promoting the load from %A + 2,
; because there is a load of %A in the entry block
define internal i32 @callee(i1 %C, i32* %A) {
; CHECK-LABEL: define internal i32 @callee(
; CHECK: i1 %C, i32* %A)
; CHECK-LABEL: define {{[^@]+}}@callee
; CHECK-SAME: (i1 [[C:%.*]], i32* [[A:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A_0:%.*]] = load i32, i32* [[A]]
; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CHECK: T:
; CHECK-NEXT: ret i32 [[A_0]]
; CHECK: F:
; CHECK-NEXT: [[A_2:%.*]] = getelementptr i32, i32* [[A]], i32 2
; CHECK-NEXT: [[R:%.*]] = load i32, i32* [[A_2]]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
; Unconditonally load the element at %A
%A.0 = load i32, i32* %A
@ -22,9 +33,11 @@ F:
}
define i32 @foo() {
; CHECK-LABEL: define i32 @foo
%X = call i32 @callee(i1 false, i32* null) ; <i32> [#uses=1]
; CHECK: call i32 @callee(i1 false, i32* null)
ret i32 %X
; CHECK-LABEL: define {{[^@]+}}@foo()
; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32* null)
; CHECK-NEXT: ret i32 [[X]]
;
%X = call i32 @callee(i1 false, i32* null) ; <i32> [#uses=1]
ret i32 %X
}

View File

@ -1,12 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -inline -argpromotion -disable-output
define internal fastcc i32 @hash(i32* %ts, i32 %mod) nounwind {
entry:
unreachable
unreachable
}
define void @encode(i32* %m, i32* %ts, i32* %new) nounwind {
entry:
%0 = call fastcc i32 @hash( i32* %ts, i32 0 ) nounwind ; <i32> [#uses=0]
unreachable
%0 = call fastcc i32 @hash( i32* %ts, i32 0 ) nounwind ; <i32> [#uses=0]
unreachable
}

View File

@ -1,25 +1,26 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -disable-output
define internal fastcc i32 @term_SharingList(i32* %Term, i32* %List) nounwind {
entry:
br i1 false, label %bb, label %bb5
br i1 false, label %bb, label %bb5
bb: ; preds = %entry
%0 = call fastcc i32 @term_SharingList( i32* null, i32* %List ) nounwind ; <i32> [#uses=0]
unreachable
%0 = call fastcc i32 @term_SharingList( i32* null, i32* %List ) nounwind ; <i32> [#uses=0]
unreachable
bb5: ; preds = %entry
ret i32 0
ret i32 0
}
define i32 @term_Sharing(i32* %Term) nounwind {
entry:
br i1 false, label %bb.i, label %bb14
br i1 false, label %bb.i, label %bb14
bb.i: ; preds = %entry
%0 = call fastcc i32 @term_SharingList( i32* null, i32* null ) nounwind ; <i32> [#uses=0]
ret i32 1
%0 = call fastcc i32 @term_SharingList( i32* null, i32* null ) nounwind ; <i32> [#uses=0]
ret i32 1
bb14: ; preds = %entry
ret i32 0
ret i32 0
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -S -argpromotion < %s | FileCheck %s
; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
; Test that we only promote arguments when the caller/callee have compatible
@ -5,8 +6,14 @@
target triple = "x86_64-unknown-linux-gnu"
; CHECK-LABEL: @no_promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1)
define internal fastcc void @no_promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1) #0 {
; CHECK-LABEL: define {{[^@]+}}@no_promote_avx2
; CHECK-SAME: (<4 x i64>* [[ARG:%.*]], <4 x i64>* readonly [[ARG1:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = load <4 x i64>, <4 x i64>* [[ARG1]]
; CHECK-NEXT: store <4 x i64> [[TMP]], <4 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <4 x i64>, <4 x i64>* %arg1
store <4 x i64> %tmp, <4 x i64>* %arg
@ -14,6 +21,18 @@ bb:
}
define void @no_promote(<4 x i64>* %arg) #1 {
; CHECK-LABEL: define {{[^@]+}}@no_promote
; CHECK-SAME: (<4 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: call fastcc void @no_promote_avx2(<4 x i64>* [[TMP2]], <4 x i64>* [[TMP]])
; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <4 x i64>, align 32
%tmp2 = alloca <4 x i64>, align 32
@ -25,8 +44,13 @@ bb:
ret void
}
; CHECK-LABEL: @promote_avx2(<4 x i64>* %arg, <4 x i64> %
define internal fastcc void @promote_avx2(<4 x i64>* %arg, <4 x i64>* readonly %arg1) #0 {
; CHECK-LABEL: define {{[^@]+}}@promote_avx2
; CHECK-SAME: (<4 x i64>* [[ARG:%.*]], <4 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <4 x i64> [[ARG1_VAL]], <4 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <4 x i64>, <4 x i64>* %arg1
store <4 x i64> %tmp, <4 x i64>* %arg
@ -34,6 +58,19 @@ bb:
}
define void @promote(<4 x i64>* %arg) #0 {
; CHECK-LABEL: define {{[^@]+}}@promote
; CHECK-SAME: (<4 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <4 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <4 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <4 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <4 x i64>, <4 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @promote_avx2(<4 x i64>* [[TMP2]], <4 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <4 x i64>, <4 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <4 x i64> [[TMP4]], <4 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <4 x i64>, align 32
%tmp2 = alloca <4 x i64>, align 32

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -S -argpromotion < %s | FileCheck %s
; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
; Test that we only promote arguments when the caller/callee have compatible
@ -6,8 +7,13 @@
target triple = "x86_64-unknown-linux-gnu"
; This should promote
; CHECK-LABEL: @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* %arg, <8 x i64> %arg1.val)
define internal fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #0 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <8 x i64> [[ARG1_VAL]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -15,6 +21,19 @@ bb:
}
define void @avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* %arg) #0 {
; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer512
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer512(<8 x i64>* [[TMP2]], <8 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -27,8 +46,13 @@ bb:
}
; This should promote
; CHECK-LABEL: @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64> %arg1.val)
define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #1 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <8 x i64> [[ARG1_VAL]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -36,6 +60,19 @@ bb:
}
define void @avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg) #1 {
; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer256(<8 x i64>* [[TMP2]], <8 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -48,8 +85,13 @@ bb:
}
; This should promote
; CHECK-LABEL: @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64> %arg1.val)
define internal fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #1 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <8 x i64> [[ARG1_VAL]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -57,6 +99,19 @@ bb:
}
define void @avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* %arg) #0 {
; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer512_call_avx512_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer512_call_avx512_legal512_prefer256(<8 x i64>* [[TMP2]], <8 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -69,8 +124,13 @@ bb:
}
; This should promote
; CHECK-LABEL: @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* %arg, <8 x i64> %arg1.val)
define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #0 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <8 x i64> [[ARG1_VAL]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -78,6 +138,19 @@ bb:
}
define void @avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* %arg) #1 {
; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal512_prefer512
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal512_prefer512(<8 x i64>* [[TMP2]], <8 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -90,8 +163,14 @@ bb:
}
; This should not promote
; CHECK-LABEL: @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1)
define internal fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #1 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64>* readonly [[ARG1:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]]
; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -99,6 +178,18 @@ bb:
}
define void @avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* %arg) #2 {
; CHECK-LABEL: define {{[^@]+}}@avx512_legal256_prefer256_call_avx512_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: call fastcc void @callee_avx512_legal256_prefer256_call_avx512_legal512_prefer256(<8 x i64>* [[TMP2]], <8 x i64>* [[TMP]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -111,8 +202,14 @@ bb:
}
; This should not promote
; CHECK-LABEL: @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1)
define internal fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #2 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64>* readonly [[ARG1:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = load <8 x i64>, <8 x i64>* [[ARG1]]
; CHECK-NEXT: store <8 x i64> [[TMP]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -120,6 +217,18 @@ bb:
}
define void @avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* %arg) #1 {
; CHECK-LABEL: define {{[^@]+}}@avx512_legal512_prefer256_call_avx512_legal256_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: call fastcc void @callee_avx512_legal512_prefer256_call_avx512_legal256_prefer256(<8 x i64>* [[TMP2]], <8 x i64>* [[TMP]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -132,8 +241,13 @@ bb:
}
; This should promote
; CHECK-LABEL: @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* %arg, <8 x i64> %arg1.val)
define internal fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #3 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <8 x i64> [[ARG1_VAL]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -141,6 +255,19 @@ bb:
}
define void @avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* %arg) #4 {
; CHECK-LABEL: define {{[^@]+}}@avx2_legal256_prefer256_call_avx2_legal512_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @callee_avx2_legal256_prefer256_call_avx2_legal512_prefer256(<8 x i64>* [[TMP2]], <8 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32
@ -153,8 +280,13 @@ bb:
}
; This should promote
; CHECK-LABEL: @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* %arg, <8 x i64> %arg1.val)
define internal fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* %arg, <8 x i64>* readonly %arg1) #4 {
; CHECK-LABEL: define {{[^@]+}}@callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]], <8 x i64> [[ARG1_VAL:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: store <8 x i64> [[ARG1_VAL]], <8 x i64>* [[ARG]]
; CHECK-NEXT: ret void
;
bb:
%tmp = load <8 x i64>, <8 x i64>* %arg1
store <8 x i64> %tmp, <8 x i64>* %arg
@ -162,6 +294,19 @@ bb:
}
define void @avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* %arg) #3 {
; CHECK-LABEL: define {{[^@]+}}@avx2_legal512_prefer256_call_avx2_legal256_prefer256
; CHECK-SAME: (<8 x i64>* [[ARG:%.*]])
; CHECK-NEXT: bb:
; CHECK-NEXT: [[TMP:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP2:%.*]] = alloca <8 x i64>, align 32
; CHECK-NEXT: [[TMP3:%.*]] = bitcast <8 x i64>* [[TMP]] to i8*
; CHECK-NEXT: call void @llvm.memset.p0i8.i64(i8* align 32 [[TMP3]], i8 0, i64 32, i1 false)
; CHECK-NEXT: [[TMP_VAL:%.*]] = load <8 x i64>, <8 x i64>* [[TMP]]
; CHECK-NEXT: call fastcc void @callee_avx2_legal512_prefer256_call_avx2_legal256_prefer256(<8 x i64>* [[TMP2]], <8 x i64> [[TMP_VAL]])
; CHECK-NEXT: [[TMP4:%.*]] = load <8 x i64>, <8 x i64>* [[TMP2]], align 32
; CHECK-NEXT: store <8 x i64> [[TMP4]], <8 x i64>* [[ARG]], align 2
; CHECK-NEXT: ret void
;
bb:
%tmp = alloca <8 x i64>, align 32
%tmp2 = alloca <8 x i64>, align 32

View File

@ -1,12 +1,11 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; In PR41658, argpromotion put an inalloca in a position that per the
; calling convention is passed in a register. This test verifies that
; we don't do that anymore. It also verifies that the combination of
; globalopt and argpromotion is able to optimize the call safely.
;
; RUN: opt -S -argpromotion %s | FileCheck --check-prefix=THIS %s
; RUN: opt -S -globalopt -argpromotion %s | FileCheck --check-prefix=OPT %s
; THIS: define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a
; OPT: define internal fastcc void @internalfun(<{ %struct.a }>* %0)
; RUN: opt -S -argpromotion %s | FileCheck %s --check-prefix=ARGPROMOTION
; RUN: opt -S -globalopt -argpromotion %s | FileCheck %s --check-prefix=GLOBALOPT_ARGPROMOTION
target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
target triple = "i386-pc-windows-msvc19.11.0"
@ -14,6 +13,26 @@ target triple = "i386-pc-windows-msvc19.11.0"
%struct.a = type { i8 }
define internal x86_thiscallcc void @internalfun(%struct.a* %this, <{ %struct.a }>* inalloca) {
; ARGPROMOTION-LABEL: define {{[^@]+}}@internalfun
; ARGPROMOTION-SAME: (%struct.a* [[THIS:%.*]], <{ [[STRUCT_A:%.*]] }>* inalloca [[TMP0:%.*]])
; ARGPROMOTION-NEXT: entry:
; ARGPROMOTION-NEXT: [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0
; ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4
; ARGPROMOTION-NEXT: [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0
; ARGPROMOTION-NEXT: [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* [[TMP1]], %struct.a* dereferenceable(1) [[A]])
; ARGPROMOTION-NEXT: call void @ext(<{ [[STRUCT_A]] }>* inalloca [[ARGMEM]])
; ARGPROMOTION-NEXT: ret void
;
; GLOBALOPT_ARGPROMOTION-LABEL: define {{[^@]+}}@internalfun
; GLOBALOPT_ARGPROMOTION-SAME: (<{ [[STRUCT_A:%.*]] }>* [[TMP0:%.*]]) unnamed_addr
; GLOBALOPT_ARGPROMOTION-NEXT: entry:
; GLOBALOPT_ARGPROMOTION-NEXT: [[A:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[TMP0]], i32 0, i32 0
; GLOBALOPT_ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A]] }>, align 4
; GLOBALOPT_ARGPROMOTION-NEXT: [[TMP1:%.*]] = getelementptr inbounds <{ [[STRUCT_A]] }>, <{ [[STRUCT_A]] }>* [[ARGMEM]], i32 0, i32 0
; GLOBALOPT_ARGPROMOTION-NEXT: [[CALL:%.*]] = call x86_thiscallcc %struct.a* @copy_ctor(%struct.a* [[TMP1]], %struct.a* dereferenceable(1) [[A]])
; GLOBALOPT_ARGPROMOTION-NEXT: call void @ext(<{ [[STRUCT_A]] }>* inalloca [[ARGMEM]])
; GLOBALOPT_ARGPROMOTION-NEXT: ret void
;
entry:
%a = getelementptr inbounds <{ %struct.a }>, <{ %struct.a }>* %0, i32 0, i32 0
%argmem = alloca inalloca <{ %struct.a }>, align 4
@ -25,6 +44,22 @@ entry:
; This is here to ensure @internalfun is live.
define void @exportedfun(%struct.a* %a) {
; ARGPROMOTION-LABEL: define {{[^@]+}}@exportedfun
; ARGPROMOTION-SAME: (%struct.a* [[A:%.*]])
; ARGPROMOTION-NEXT: [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave()
; ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4
; ARGPROMOTION-NEXT: call x86_thiscallcc void @internalfun(%struct.a* [[A]], <{ [[STRUCT_A]] }>* inalloca [[ARGMEM]])
; ARGPROMOTION-NEXT: call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]])
; ARGPROMOTION-NEXT: ret void
;
; GLOBALOPT_ARGPROMOTION-LABEL: define {{[^@]+}}@exportedfun
; GLOBALOPT_ARGPROMOTION-SAME: (%struct.a* [[A:%.*]]) local_unnamed_addr
; GLOBALOPT_ARGPROMOTION-NEXT: [[INALLOCA_SAVE:%.*]] = tail call i8* @llvm.stacksave()
; GLOBALOPT_ARGPROMOTION-NEXT: [[ARGMEM:%.*]] = alloca inalloca <{ [[STRUCT_A:%.*]] }>, align 4
; GLOBALOPT_ARGPROMOTION-NEXT: call fastcc void @internalfun(<{ [[STRUCT_A]] }>* [[ARGMEM]])
; GLOBALOPT_ARGPROMOTION-NEXT: call void @llvm.stackrestore(i8* [[INALLOCA_SAVE]])
; GLOBALOPT_ARGPROMOTION-NEXT: ret void
;
%inalloca.save = tail call i8* @llvm.stacksave()
%argmem = alloca inalloca <{ %struct.a }>, align 4
call x86_thiscallcc void @internalfun(%struct.a* %a, <{ %struct.a }>* inalloca %argmem)

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -5,27 +6,32 @@
@G = constant %T { i32 0, i32 0, i32 17, i32 25 }
define internal i32 @test(%T* %p) {
; CHECK-LABEL: define internal i32 @test(
; CHECK: i32 %{{.*}}, i32 %{{.*}})
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32 [[P_0_2_VAL:%.*]], i32 [[P_0_3_VAL:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[V:%.*]] = add i32 [[P_0_3_VAL]], [[P_0_2_VAL]]
; CHECK-NEXT: ret i32 [[V]]
;
entry:
%a.gep = getelementptr %T, %T* %p, i64 0, i32 3
%b.gep = getelementptr %T, %T* %p, i64 0, i32 2
%a = load i32, i32* %a.gep
%b = load i32, i32* %b.gep
; CHECK-NOT: load
%v = add i32 %a, %b
ret i32 %v
; CHECK: ret i32
}
define i32 @caller() {
; CHECK-LABEL: define i32 @caller(
; CHECK-LABEL: define {{[^@]+}}@caller()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[G_IDX:%.*]] = getelementptr [[T:%.*]], %T* @G, i64 0, i32 2
; CHECK-NEXT: [[G_IDX_VAL:%.*]] = load i32, i32* [[G_IDX]]
; CHECK-NEXT: [[G_IDX1:%.*]] = getelementptr [[T]], %T* @G, i64 0, i32 3
; CHECK-NEXT: [[G_IDX1_VAL:%.*]] = load i32, i32* [[G_IDX1]]
; CHECK-NEXT: [[V:%.*]] = call i32 @test(i32 [[G_IDX_VAL]], i32 [[G_IDX1_VAL]])
; CHECK-NEXT: ret i32 [[V]]
;
entry:
%v = call i32 @test(%T* @G)
; CHECK: %[[B_GEP:.*]] = getelementptr %T, %T* @G, i64 0, i32 2
; CHECK: %[[B:.*]] = load i32, i32* %[[B_GEP]]
; CHECK: %[[A_GEP:.*]] = getelementptr %T, %T* @G, i64 0, i32 3
; CHECK: %[[A:.*]] = load i32, i32* %[[A_GEP]]
; CHECK: call i32 @test(i32 %[[B]], i32 %[[A]])
ret i32 %v
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -5,48 +6,57 @@
; Don't drop 'byval' on %X here.
define internal void @f(%struct.ss* byval %b, i32* byval %X, i32 %i) nounwind {
; CHECK-LABEL: define internal void @f(
; CHECK: i32 %[[B0:.*]], i64 %[[B1:.*]], i32* byval %X, i32 %i)
; CHECK-LABEL: define {{[^@]+}}@f
; CHECK-SAME: (i32 [[B_0:%.*]], i64 [[B_1:%.*]], i32* byval [[X:%.*]], i32 [[I:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: store i32 [[B_0]], i32* [[DOT0]]
; CHECK-NEXT: [[DOT1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 1
; CHECK-NEXT: store i64 [[B_1]], i64* [[DOT1]]
; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4
; CHECK-NEXT: store i32 0, i32* [[X]]
; CHECK-NEXT: ret void
;
entry:
; CHECK: %[[B:.*]] = alloca %struct.ss
; CHECK: %[[B_GEP0:.*]] = getelementptr %struct.ss, %struct.ss* %[[B]], i32 0, i32 0
; CHECK: store i32 %[[B0]], i32* %[[B_GEP0]]
; CHECK: %[[B_GEP1:.*]] = getelementptr %struct.ss, %struct.ss* %[[B]], i32 0, i32 1
; CHECK: store i64 %[[B1]], i64* %[[B_GEP1]]
%tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
; CHECK: %[[TMP:.*]] = getelementptr %struct.ss, %struct.ss* %[[B]], i32 0, i32 0
%tmp1 = load i32, i32* %tmp, align 4
; CHECK: %[[TMP1:.*]] = load i32, i32* %[[TMP]]
%tmp2 = add i32 %tmp1, 1
; CHECK: %[[TMP2:.*]] = add i32 %[[TMP1]], 1
store i32 %tmp2, i32* %tmp, align 4
; CHECK: store i32 %[[TMP2]], i32* %[[TMP]]
store i32 0, i32* %X
; CHECK: store i32 0, i32* %X
ret void
}
; Also make sure we don't drop the call zeroext attribute.
define i32 @test(i32* %X) {
; CHECK-LABEL: define i32 @test(
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32* [[X:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: store i64 2, i64* [[TMP4]], align 4
; CHECK-NEXT: [[S_0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: [[S_0_VAL:%.*]] = load i32, i32* [[S_0]]
; CHECK-NEXT: [[S_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: [[S_1_VAL:%.*]] = load i64, i64* [[S_1]]
; CHECK-NEXT: call void @f(i32 [[S_0_VAL]], i64 [[S_1_VAL]], i32* byval [[X]], i32 zeroext 0)
; CHECK-NEXT: ret i32 0
;
entry:
%S = alloca %struct.ss
; CHECK: %[[S:.*]] = alloca %struct.ss
%tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
store i32 1, i32* %tmp1, align 8
; CHECK: store i32 1
%tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
store i64 2, i64* %tmp4, align 4
; CHECK: store i64 2
call void @f( %struct.ss* byval %S, i32* byval %X, i32 zeroext 0)
; CHECK: %[[S_GEP0:.*]] = getelementptr %struct.ss, %struct.ss* %[[S]], i32 0, i32 0
; CHECK: %[[S0:.*]] = load i32, i32* %[[S_GEP0]]
; CHECK: %[[S_GEP1:.*]] = getelementptr %struct.ss, %struct.ss* %[[S]], i32 0, i32 1
; CHECK: %[[S1:.*]] = load i64, i64* %[[S_GEP1]]
; CHECK: call void @f(i32 %[[S0]], i64 %[[S1]], i32* byval %X, i32 zeroext 0)
ret i32 0
}

View File

@ -1,8 +1,13 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -basicaa -argpromotion -mem2reg -S | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
define internal i32 @test(i32* %X, i32* %Y) {
; CHECK-LABEL: define internal i32 @test(i32 %X.val, i32 %Y.val)
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32 [[X_VAL:%.*]], i32 [[Y_VAL:%.*]])
; CHECK-NEXT: [[C:%.*]] = add i32 [[X_VAL]], [[Y_VAL]]
; CHECK-NEXT: ret i32 [[C]]
;
%A = load i32, i32* %X
%B = load i32, i32* %Y
%C = add i32 %A, %B
@ -10,20 +15,25 @@ define internal i32 @test(i32* %X, i32* %Y) {
}
define internal i32 @caller(i32* %B) {
; CHECK-LABEL: define internal i32 @caller(i32 %B.val1)
; CHECK-LABEL: define {{[^@]+}}@caller
; CHECK-SAME: (i32 [[B_VAL1:%.*]])
; CHECK-NEXT: [[C:%.*]] = call i32 @test(i32 1, i32 [[B_VAL1]])
; CHECK-NEXT: ret i32 [[C]]
;
%A = alloca i32
store i32 1, i32* %A
%C = call i32 @test(i32* %A, i32* %B)
; CHECK: call i32 @test(i32 1, i32 %B.val1)
ret i32 %C
}
define i32 @callercaller() {
; CHECK-LABEL: define i32 @callercaller()
; CHECK-LABEL: define {{[^@]+}}@callercaller()
; CHECK-NEXT: [[X:%.*]] = call i32 @caller(i32 2)
; CHECK-NEXT: ret i32 [[X]]
;
%B = alloca i32
store i32 2, i32* %B
%X = call i32 @caller(i32* %B)
; CHECK: call i32 @caller(i32 2)
ret i32 %X
}

View File

@ -1,13 +1,28 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
; Arg promotion eliminates the struct argument.
; FIXME: Should it eliminate the i32* argument?
; FIXME: We should eliminate the i32* argument.
%struct.ss = type { i32, i64 }
define internal void @f(%struct.ss* byval %b, i32* byval %X) nounwind {
; CHECK-LABEL: define internal void @f(i32 %b.0, i64 %b.1, i32* byval %X)
; CHECK-LABEL: define {{[^@]+}}@f
; CHECK-SAME: (i32 [[B_0:%.*]], i64 [[B_1:%.*]], i32* byval [[X:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: store i32 [[B_0]], i32* [[DOT0]]
; CHECK-NEXT: [[DOT1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 1
; CHECK-NEXT: store i64 [[B_1]], i64* [[DOT1]]
; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4
; CHECK-NEXT: store i32 0, i32* [[X]]
; CHECK-NEXT: ret void
;
entry:
%tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
%tmp1 = load i32, i32* %tmp, align 4
@ -19,7 +34,21 @@ entry:
}
define i32 @test(i32* %X) {
; CHECK-LABEL: define i32 @test
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32* [[X:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: store i64 2, i64* [[TMP4]], align 4
; CHECK-NEXT: [[S_0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: [[S_0_VAL:%.*]] = load i32, i32* [[S_0]]
; CHECK-NEXT: [[S_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: [[S_1_VAL:%.*]] = load i64, i64* [[S_1]]
; CHECK-NEXT: call void @f(i32 [[S_0_VAL]], i64 [[S_1_VAL]], i32* byval [[X]])
; CHECK-NEXT: ret i32 0
;
entry:
%S = alloca %struct.ss
%tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
@ -27,6 +56,5 @@ entry:
%tmp4 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 1
store i64 2, i64* %tmp4, align 4
call void @f( %struct.ss* byval %S, i32* byval %X)
; CHECK: call void @f(i32 %{{.*}}, i64 %{{.*}}, i32* byval %{{.*}})
ret i32 0
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -6,6 +7,20 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1
%struct.ss = type { i32, i64 }
define internal void @f(%struct.ss* byval %b) nounwind {
; CHECK-LABEL: define {{[^@]+}}@f
; CHECK-SAME: (i32 [[B_0:%.*]], i64 [[B_1:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: store i32 [[B_0]], i32* [[DOT0]]
; CHECK-NEXT: [[DOT1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 1
; CHECK-NEXT: store i64 [[B_1]], i64* [[DOT1]]
; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4
; CHECK-NEXT: ret void
;
entry:
%tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
%tmp1 = load i32, i32* %tmp, align 4
@ -14,12 +29,22 @@ entry:
ret void
}
; CHECK-LABEL: define internal void @f(i32 %b.0, i64 %b.1)
; CHECK: alloca %struct.ss{{$}}
; CHECK: store i32 %b.0
; CHECK: store i64 %b.1
define internal void @g(%struct.ss* byval align 32 %b) nounwind {
; CHECK-LABEL: define {{[^@]+}}@g
; CHECK-SAME: (i32 [[B_0:%.*]], i64 [[B_1:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[B:%.*]] = alloca [[STRUCT_SS:%.*]], align 32
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: store i32 [[B_0]], i32* [[DOT0]]
; CHECK-NEXT: [[DOT1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 1
; CHECK-NEXT: store i64 [[B_1]], i64* [[DOT1]]
; CHECK-NEXT: [[TMP:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[B]], i32 0, i32 0
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* [[TMP]], align 4
; CHECK-NEXT: [[TMP2:%.*]] = add i32 [[TMP1]], 1
; CHECK-NEXT: store i32 [[TMP2]], i32* [[TMP]], align 4
; CHECK-NEXT: ret void
;
entry:
%tmp = getelementptr %struct.ss, %struct.ss* %b, i32 0, i32 0
%tmp1 = load i32, i32* %tmp, align 4
@ -28,12 +53,27 @@ entry:
ret void
}
; CHECK-LABEL: define internal void @g(i32 %b.0, i64 %b.1)
; CHECK: alloca %struct.ss, align 32
; CHECK: store i32 %b.0
; CHECK: store i64 %b.1
define i32 @main() nounwind {
; CHECK-LABEL: define {{[^@]+}}@main()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = alloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[TMP1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 8
; CHECK-NEXT: [[TMP4:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: store i64 2, i64* [[TMP4]], align 4
; CHECK-NEXT: [[S_0:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: [[S_0_VAL:%.*]] = load i32, i32* [[S_0]]
; CHECK-NEXT: [[S_1:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: [[S_1_VAL:%.*]] = load i64, i64* [[S_1]]
; CHECK-NEXT: call void @f(i32 [[S_0_VAL]], i64 [[S_1_VAL]])
; CHECK-NEXT: [[S_01:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 0
; CHECK-NEXT: [[S_01_VAL:%.*]] = load i32, i32* [[S_01]]
; CHECK-NEXT: [[S_12:%.*]] = getelementptr [[STRUCT_SS]], %struct.ss* [[S]], i32 0, i32 1
; CHECK-NEXT: [[S_12_VAL:%.*]] = load i64, i64* [[S_12]]
; CHECK-NEXT: call void @g(i32 [[S_01_VAL]], i64 [[S_12_VAL]])
; CHECK-NEXT: ret i32 0
;
entry:
%S = alloca %struct.ss
%tmp1 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
@ -45,6 +85,4 @@ entry:
ret i32 0
}
; CHECK-LABEL: define i32 @main
; CHECK: call void @f(i32 %{{.*}}, i64 %{{.*}})
; CHECK: call void @g(i32 %{{.*}}, i64 %{{.*}})

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -5,23 +6,27 @@
@G2 = constant i32* @G1
define internal i32 @test(i32** %x) {
; CHECK-LABEL: define internal i32 @test(
; CHECK: i32 %{{.*}})
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32 [[X_VAL_VAL:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 [[X_VAL_VAL]]
;
entry:
%y = load i32*, i32** %x
%z = load i32, i32* %y
; CHECK-NOT: load
ret i32 %z
; CHECK: ret i32
}
define i32 @caller() {
; CHECK-LABEL: define i32 @caller()
; CHECK-LABEL: define {{[^@]+}}@caller()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[G2_VAL:%.*]] = load i32*, i32** @G2
; CHECK-NEXT: [[G2_VAL_VAL:%.*]] = load i32, i32* [[G2_VAL]]
; CHECK-NEXT: [[X:%.*]] = call i32 @test(i32 [[G2_VAL_VAL]])
; CHECK-NEXT: ret i32 [[X]]
;
entry:
%x = call i32 @test(i32** @G2)
; CHECK: %[[Y:.*]] = load i32*, i32** @G2
; CHECK: %[[Z:.*]] = load i32, i32* %[[Y]]
; CHECK: call i32 @test(i32 %[[Z]])
ret i32 %x
}

View File

@ -1,10 +1,19 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
; Don't promote around control flow.
define internal i32 @callee(i1 %C, i32* %P) {
; CHECK-LABEL: define internal i32 @callee(
; CHECK: i1 %C, i32* %P)
; CHECK-LABEL: define {{[^@]+}}@callee
; CHECK-SAME: (i1 [[C:%.*]], i32* [[P:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CHECK: T:
; CHECK-NEXT: ret i32 17
; CHECK: F:
; CHECK-NEXT: [[X:%.*]] = load i32, i32* [[P]]
; CHECK-NEXT: ret i32 [[X]]
;
entry:
br i1 %C, label %T, label %F
@ -17,11 +26,13 @@ F:
}
define i32 @foo() {
; CHECK-LABEL: define i32 @foo(
; CHECK-LABEL: define {{[^@]+}}@foo()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 true, i32* null)
; CHECK-NEXT: ret i32 [[X]]
;
entry:
; CHECK-NOT: load i32, i32* null
%X = call i32 @callee(i1 true, i32* null)
; CHECK: call i32 @callee(i1 true, i32* null)
ret i32 %X
}

View File

@ -1,24 +1,39 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
; CHECK: load i32, i32* %A
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
define internal i32 @callee(i1 %C, i32* %P) {
br i1 %C, label %T, label %F
; CHECK-LABEL: define {{[^@]+}}@callee
; CHECK-SAME: (i1 [[C:%.*]], i32 [[P_VAL:%.*]])
; CHECK-NEXT: br i1 [[C]], label [[T:%.*]], label [[F:%.*]]
; CHECK: T:
; CHECK-NEXT: ret i32 17
; CHECK: F:
; CHECK-NEXT: ret i32 [[P_VAL]]
;
br i1 %C, label %T, label %F
T: ; preds = %0
ret i32 17
ret i32 17
F: ; preds = %0
%X = load i32, i32* %P ; <i32> [#uses=1]
ret i32 %X
%X = load i32, i32* %P ; <i32> [#uses=1]
ret i32 %X
}
define i32 @foo() {
%A = alloca i32 ; <i32*> [#uses=2]
store i32 17, i32* %A
%X = call i32 @callee( i1 false, i32* %A ) ; <i32> [#uses=1]
ret i32 %X
; CHECK-LABEL: define {{[^@]+}}@foo()
; CHECK-NEXT: [[A:%.*]] = alloca i32
; CHECK-NEXT: store i32 17, i32* [[A]]
; CHECK-NEXT: [[A_VAL:%.*]] = load i32, i32* [[A]]
; CHECK-NEXT: [[X:%.*]] = call i32 @callee(i1 false, i32 [[A_VAL]])
; CHECK-NEXT: ret i32 [[X]]
;
%A = alloca i32 ; <i32*> [#uses=2]
store i32 17, i32* %A
%X = call i32 @callee( i1 false, i32* %A ) ; <i32> [#uses=1]
ret i32 %X
}

View File

@ -1,24 +1,34 @@
; RUN: opt -S < %s -inline -argpromotion | FileCheck %s
; RUN: opt -S < %s -passes=inline,argpromotion | FileCheck %s
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -S < %s -inline -argpromotion | FileCheck %s --check-prefixes=ARGPROMOTION,ALL_OLDPM
; RUN: opt -S < %s -passes=inline,argpromotion | FileCheck %s --check-prefixes=ARGPROMOTION,ALL_NEWPM
%S = type { %S* }
; Inlining should nuke the invoke (and any inlined calls) here even with
; argument promotion running along with it.
define void @zot() personality i32 (...)* @wibble {
; CHECK-LABEL: define void @zot() personality i32 (...)* @wibble
; CHECK-NOT: call
; CHECK-NOT: invoke
; ARGPROMOTION-LABEL: define {{[^@]+}}@zot() personality i32 (...)* @wibble
; ARGPROMOTION-NEXT: bb:
; ARGPROMOTION-NEXT: unreachable
; ARGPROMOTION: hoge.exit:
; ARGPROMOTION-NEXT: br label [[BB1:%.*]]
; ARGPROMOTION: bb1:
; ARGPROMOTION-NEXT: unreachable
; ARGPROMOTION: bb2:
; ARGPROMOTION-NEXT: [[TMP:%.*]] = landingpad { i8*, i32 }
; ARGPROMOTION-NEXT: cleanup
; ARGPROMOTION-NEXT: unreachable
;
bb:
invoke void @hoge()
to label %bb1 unwind label %bb2
to label %bb1 unwind label %bb2
bb1:
unreachable
bb2:
%tmp = landingpad { i8*, i32 }
cleanup
cleanup
unreachable
}
@ -35,6 +45,10 @@ bb:
}
define internal i1 @eggs(i8* %arg) {
; ALL_NEWPM-LABEL: define {{[^@]+}}@eggs()
; ALL_NEWPM-NEXT: bb:
; ALL_NEWPM-NEXT: unreachable
;
bb:
%tmp = call zeroext i1 @barney(i8* %arg)
unreachable
@ -46,26 +60,39 @@ bb:
}
define i32 @test_inf_promote_caller(i32 %arg) {
; CHECK-LABEL: define i32 @test_inf_promote_caller(
; ARGPROMOTION-LABEL: define {{[^@]+}}@test_inf_promote_caller
; ARGPROMOTION-SAME: (i32 [[ARG:%.*]])
; ARGPROMOTION-NEXT: bb:
; ARGPROMOTION-NEXT: [[TMP:%.*]] = alloca [[S:%.*]]
; ARGPROMOTION-NEXT: [[TMP1:%.*]] = alloca [[S]]
; ARGPROMOTION-NEXT: [[TMP2:%.*]] = call i32 @test_inf_promote_callee(%S* [[TMP]], %S* [[TMP1]])
; ARGPROMOTION-NEXT: ret i32 0
;
bb:
%tmp = alloca %S
%tmp1 = alloca %S
%tmp2 = call i32 @test_inf_promote_callee(%S* %tmp, %S* %tmp1)
; CHECK: call i32 @test_inf_promote_callee(%S* %{{.*}}, %S* %{{.*}})
ret i32 0
}
define internal i32 @test_inf_promote_callee(%S* %arg, %S* %arg1) {
; CHECK-LABEL: define internal i32 @test_inf_promote_callee(
; CHECK: %S* %{{.*}}, %S* %{{.*}})
; ARGPROMOTION-LABEL: define {{[^@]+}}@test_inf_promote_callee
; ARGPROMOTION-SAME: (%S* [[ARG:%.*]], %S* [[ARG1:%.*]])
; ARGPROMOTION-NEXT: bb:
; ARGPROMOTION-NEXT: [[TMP:%.*]] = getelementptr [[S:%.*]], %S* [[ARG1]], i32 0, i32 0
; ARGPROMOTION-NEXT: [[TMP2:%.*]] = load %S*, %S** [[TMP]]
; ARGPROMOTION-NEXT: [[TMP3:%.*]] = getelementptr [[S]], %S* [[ARG]], i32 0, i32 0
; ARGPROMOTION-NEXT: [[TMP4:%.*]] = load %S*, %S** [[TMP3]]
; ARGPROMOTION-NEXT: [[TMP5:%.*]] = call i32 @test_inf_promote_callee(%S* [[TMP4]], %S* [[TMP2]])
; ARGPROMOTION-NEXT: ret i32 0
;
bb:
%tmp = getelementptr %S, %S* %arg1, i32 0, i32 0
%tmp2 = load %S*, %S** %tmp
%tmp3 = getelementptr %S, %S* %arg, i32 0, i32 0
%tmp4 = load %S*, %S** %tmp3
%tmp5 = call i32 @test_inf_promote_callee(%S* %tmp4, %S* %tmp2)
; CHECK: call i32 @test_inf_promote_callee(%S* %{{.*}}, %S* %{{.*}})
ret i32 0
}

View File

@ -1,10 +1,15 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
declare void @sink(i32)
; CHECK: define internal void @test({{.*}} !dbg [[SP:![0-9]+]]
define internal void @test(i32** %X) !dbg !2 {
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (i32 [[X_VAL_VAL:%.*]]) !dbg !3
; CHECK-NEXT: call void @sink(i32 [[X_VAL_VAL]])
; CHECK-NEXT: ret void
;
%1 = load i32*, i32** %X, align 8
%2 = load i32, i32* %1, align 8
call void @sink(i32 %2)
@ -13,30 +18,38 @@ define internal void @test(i32** %X) !dbg !2 {
%struct.pair = type { i32, i32 }
; CHECK: define internal void @test_byval(i32 %{{.*}}, i32 %{{.*}})
define internal void @test_byval(%struct.pair* byval %P) {
; CHECK-LABEL: define {{[^@]+}}@test_byval
; CHECK-SAME: (i32 [[P_0:%.*]], i32 [[P_1:%.*]])
; CHECK-NEXT: [[P:%.*]] = alloca [[STRUCT_PAIR:%.*]]
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[STRUCT_PAIR]], %struct.pair* [[P]], i32 0, i32 0
; CHECK-NEXT: store i32 [[P_0]], i32* [[DOT0]]
; CHECK-NEXT: [[DOT1:%.*]] = getelementptr [[STRUCT_PAIR]], %struct.pair* [[P]], i32 0, i32 1
; CHECK-NEXT: store i32 [[P_1]], i32* [[DOT1]]
; CHECK-NEXT: ret void
;
ret void
}
; CHECK-LABEL: define {{.*}} @caller(
define void @caller(i32** %Y, %struct.pair* %P) {
; CHECK: load i32*, {{.*}} !dbg [[LOC_1:![0-9]+]]
; CHECK-NEXT: load i32, {{.*}} !dbg [[LOC_1]]
; CHECK-NEXT: call void @test(i32 %{{.*}}), !dbg [[LOC_1]]
; CHECK-LABEL: define {{[^@]+}}@caller
; CHECK-SAME: (i32** [[Y:%.*]], %struct.pair* [[P:%.*]])
; CHECK-NEXT: [[Y_VAL:%.*]] = load i32*, i32** [[Y]], align 8, !dbg !4
; CHECK-NEXT: [[Y_VAL_VAL:%.*]] = load i32, i32* [[Y_VAL]], align 8, !dbg !4
; CHECK-NEXT: call void @test(i32 [[Y_VAL_VAL]]), !dbg !4
; CHECK-NEXT: [[P_0:%.*]] = getelementptr [[STRUCT_PAIR:%.*]], %struct.pair* [[P]], i32 0, i32 0, !dbg !5
; CHECK-NEXT: [[P_0_VAL:%.*]] = load i32, i32* [[P_0]], !dbg !5
; CHECK-NEXT: [[P_1:%.*]] = getelementptr [[STRUCT_PAIR]], %struct.pair* [[P]], i32 0, i32 1, !dbg !5
; CHECK-NEXT: [[P_1_VAL:%.*]] = load i32, i32* [[P_1]], !dbg !5
; CHECK-NEXT: call void @test_byval(i32 [[P_0_VAL]], i32 [[P_1_VAL]]), !dbg !5
; CHECK-NEXT: ret void
;
call void @test(i32** %Y), !dbg !1
; CHECK: getelementptr %struct.pair, {{.*}} !dbg [[LOC_2:![0-9]+]]
; CHECK-NEXT: load i32, i32* {{.*}} !dbg [[LOC_2]]
; CHECK-NEXT: getelementptr %struct.pair, {{.*}} !dbg [[LOC_2]]
; CHECK-NEXT: load i32, i32* {{.*}} !dbg [[LOC_2]]
; CHECK-NEXT: call void @test_byval(i32 %{{.*}}, i32 %{{.*}}), !dbg [[LOC_2]]
call void @test_byval(%struct.pair* %P), !dbg !6
ret void
}
; CHECK: [[SP]] = distinct !DISubprogram(name: "test",
; CHECK: [[LOC_1]] = !DILocation(line: 8
; CHECK: [[LOC_2]] = !DILocation(line: 9
!llvm.module.flags = !{!0}
!llvm.dbg.cu = !{!3}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -13,6 +14,16 @@ target triple = "x86_64-unknown-linux-gnu"
@a = internal global %struct.Foo { i32 1, i64 2 }, align 8
define void @run() {
; CHECK-LABEL: define {{[^@]+}}@run()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = tail call i8 @UseLongDoubleUnsafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*))
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[UNION_U:%.*]], %union.u* bitcast (%struct.s* @b to %union.u*), i32 0, i32 0
; CHECK-NEXT: [[DOT0_VAL:%.*]] = load x86_fp80, x86_fp80* [[DOT0]]
; CHECK-NEXT: [[TMP1:%.*]] = tail call x86_fp80 @UseLongDoubleSafely(x86_fp80 [[DOT0_VAL]])
; CHECK-NEXT: [[TMP2:%.*]] = call i64 @AccessPaddingOfStruct(%struct.Foo* @a)
; CHECK-NEXT: [[TMP3:%.*]] = call i64 @CaptureAStruct(%struct.Foo* @a)
; CHECK-NEXT: ret void
;
entry:
tail call i8 @UseLongDoubleUnsafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*))
tail call x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 bitcast (%struct.s* @b to %union.u*))
@ -21,8 +32,15 @@ entry:
ret void
}
; CHECK: internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) {
define internal i8 @UseLongDoubleUnsafely(%union.u* byval align 16 %arg) {
; CHECK-LABEL: define {{[^@]+}}@UseLongDoubleUnsafely
; CHECK-SAME: (%union.u* byval align 16 [[ARG:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[BITCAST:%.*]] = bitcast %union.u* [[ARG]] to %struct.s*
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[STRUCT_S:%.*]], %struct.s* [[BITCAST]], i64 0, i32 2
; CHECK-NEXT: [[RESULT:%.*]] = load i8, i8* [[GEP]]
; CHECK-NEXT: ret i8 [[RESULT]]
;
entry:
%bitcast = bitcast %union.u* %arg to %struct.s*
%gep = getelementptr inbounds %struct.s, %struct.s* %bitcast, i64 0, i32 2
@ -30,22 +48,46 @@ entry:
ret i8 %result
}
; CHECK: internal x86_fp80 @UseLongDoubleSafely(x86_fp80 {{%.*}}) {
define internal x86_fp80 @UseLongDoubleSafely(%union.u* byval align 16 %arg) {
; CHECK-LABEL: define {{[^@]+}}@UseLongDoubleSafely
; CHECK-SAME: (x86_fp80 [[ARG_0:%.*]])
; CHECK-NEXT: [[ARG:%.*]] = alloca [[UNION_U:%.*]], align 16
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[UNION_U]], %union.u* [[ARG]], i32 0, i32 0
; CHECK-NEXT: store x86_fp80 [[ARG_0]], x86_fp80* [[DOT0]]
; CHECK-NEXT: [[GEP:%.*]] = getelementptr inbounds [[UNION_U]], %union.u* [[ARG]], i64 0, i32 0
; CHECK-NEXT: [[FP80:%.*]] = load x86_fp80, x86_fp80* [[GEP]]
; CHECK-NEXT: ret x86_fp80 [[FP80]]
;
%gep = getelementptr inbounds %union.u, %union.u* %arg, i64 0, i32 0
%fp80 = load x86_fp80, x86_fp80* %gep
ret x86_fp80 %fp80
}
; CHECK: define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) {
define internal i64 @AccessPaddingOfStruct(%struct.Foo* byval %a) {
; CHECK-LABEL: define {{[^@]+}}@AccessPaddingOfStruct
; CHECK-SAME: (%struct.Foo* byval [[A:%.*]])
; CHECK-NEXT: [[P:%.*]] = bitcast %struct.Foo* [[A]] to i64*
; CHECK-NEXT: [[V:%.*]] = load i64, i64* [[P]]
; CHECK-NEXT: ret i64 [[V]]
;
%p = bitcast %struct.Foo* %a to i64*
%v = load i64, i64* %p
ret i64 %v
}
; CHECK: define internal i64 @CaptureAStruct(%struct.Foo* byval %a) {
define internal i64 @CaptureAStruct(%struct.Foo* byval %a) {
; CHECK-LABEL: define {{[^@]+}}@CaptureAStruct
; CHECK-SAME: (%struct.Foo* byval [[A:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[A_PTR:%.*]] = alloca %struct.Foo*
; CHECK-NEXT: br label [[LOOP:%.*]]
; CHECK: loop:
; CHECK-NEXT: [[PHI:%.*]] = phi %struct.Foo* [ null, [[ENTRY:%.*]] ], [ [[GEP:%.*]], [[LOOP]] ]
; CHECK-NEXT: [[TMP0:%.*]] = phi %struct.Foo* [ [[A]], [[ENTRY]] ], [ [[TMP0]], [[LOOP]] ]
; CHECK-NEXT: store %struct.Foo* [[PHI]], %struct.Foo** [[A_PTR]]
; CHECK-NEXT: [[GEP]] = getelementptr [[STRUCT_FOO:%.*]], %struct.Foo* [[A]], i64 0
; CHECK-NEXT: br label [[LOOP]]
;
entry:
%a_ptr = alloca %struct.Foo*
br label %loop

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt %s -globalopt -argpromotion -sroa -S | FileCheck %s
; RUN: opt %s -passes='module(globalopt),cgscc(argpromotion),function(sroa)' -S | FileCheck %s
@ -7,6 +8,12 @@ target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:1
; Argpromote + sroa should change this to passing the two integers by value.
define internal i32 @f(%struct.ss* inalloca %s) {
; CHECK-LABEL: define {{[^@]+}}@f
; CHECK-SAME: (i32 [[S_0_0_VAL:%.*]], i32 [[S_0_1_VAL:%.*]]) unnamed_addr
; CHECK-NEXT: entry:
; CHECK-NEXT: [[R:%.*]] = add i32 [[S_0_0_VAL]], [[S_0_1_VAL]]
; CHECK-NEXT: ret i32 [[R]]
;
entry:
%f0 = getelementptr %struct.ss, %struct.ss* %s, i32 0, i32 0
%f1 = getelementptr %struct.ss, %struct.ss* %s, i32 0, i32 1
@ -15,11 +22,13 @@ entry:
%r = add i32 %a, %b
ret i32 %r
}
; CHECK-LABEL: define internal fastcc i32 @f
; CHECK-NOT: load
; CHECK: ret
define i32 @main() {
; CHECK-LABEL: define {{[^@]+}}@main() local_unnamed_addr
; CHECK-NEXT: entry:
; CHECK-NEXT: [[R:%.*]] = call fastcc i32 @f(i32 1, i32 2)
; CHECK-NEXT: ret i32 [[R]]
;
entry:
%S = alloca inalloca %struct.ss
%f0 = getelementptr %struct.ss, %struct.ss* %S, i32 0, i32 0
@ -29,22 +38,29 @@ entry:
%r = call i32 @f(%struct.ss* inalloca %S)
ret i32 %r
}
; CHECK-LABEL: define i32 @main
; CHECK-NOT: load
; CHECK: ret
; Argpromote can't promote %a because of the icmp use.
define internal i1 @g(%struct.ss* %a, %struct.ss* inalloca %b) nounwind {
; CHECK: define internal fastcc i1 @g(%struct.ss* %a, %struct.ss* %b)
; CHECK-LABEL: define {{[^@]+}}@g
; CHECK-SAME: (%struct.ss* [[A:%.*]], %struct.ss* [[B:%.*]]) unnamed_addr
; CHECK-NEXT: entry:
; CHECK-NEXT: [[C:%.*]] = icmp eq %struct.ss* [[A]], [[B]]
; CHECK-NEXT: ret i1 [[C]]
;
entry:
%c = icmp eq %struct.ss* %a, %b
ret i1 %c
}
define i32 @test() {
; CHECK-LABEL: define {{[^@]+}}@test() local_unnamed_addr
; CHECK-NEXT: entry:
; CHECK-NEXT: [[S:%.*]] = alloca inalloca [[STRUCT_SS:%.*]]
; CHECK-NEXT: [[C:%.*]] = call fastcc i1 @g(%struct.ss* [[S]], %struct.ss* [[S]])
; CHECK-NEXT: ret i32 0
;
entry:
%S = alloca inalloca %struct.ss
%c = call i1 @g(%struct.ss* %S, %struct.ss* inalloca %S)
; CHECK: call fastcc i1 @g(%struct.ss* %S, %struct.ss* %S)
ret i32 0
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; Check that when argument promotion changes a function in some parent node of
; the call graph, any analyses that happened to be cached for that function are
; actually invalidated. We are using `demanded-bits` here because when printed
@ -11,37 +12,37 @@
@G = constant i32 0
define internal i32 @a(i32* %x) {
; CHECK-LABEL: define internal i32 @a(
; CHECK-SAME: i32 %[[V:.*]]) {
; CHECK-LABEL: define {{[^@]+}}@a
; CHECK-SAME: (i32 [[X_VAL:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: ret i32 %[[V]]
; CHECK-NEXT: }
; CHECK-NEXT: ret i32 [[X_VAL]]
;
entry:
%v = load i32, i32* %x
ret i32 %v
}
define i32 @b() {
; CHECK-LABEL: define i32 @b()
; CHECK-LABEL: define {{[^@]+}}@b()
; CHECK-NEXT: entry:
; CHECK-NEXT: %[[L:.*]] = load i32, i32* @G
; CHECK-NEXT: %[[V:.*]] = call i32 @a(i32 %[[L]])
; CHECK-NEXT: ret i32 %[[V]]
; CHECK-NEXT: }
; CHECK-NEXT: [[G_VAL:%.*]] = load i32, i32* @G
; CHECK-NEXT: [[V:%.*]] = call i32 @a(i32 [[G_VAL]])
; CHECK-NEXT: ret i32 [[V]]
;
entry:
%v = call i32 @a(i32* @G)
ret i32 %v
}
define i32 @c() {
; CHECK-LABEL: define i32 @c()
; CHECK-LABEL: define {{[^@]+}}@c()
; CHECK-NEXT: entry:
; CHECK-NEXT: %[[L:.*]] = load i32, i32* @G
; CHECK-NEXT: %[[V1:.*]] = call i32 @a(i32 %[[L]])
; CHECK-NEXT: %[[V2:.*]] = call i32 @b()
; CHECK-NEXT: %[[RESULT:.*]] = add i32 %[[V1]], %[[V2]]
; CHECK-NEXT: ret i32 %[[RESULT]]
; CHECK-NEXT: }
; CHECK-NEXT: [[G_VAL:%.*]] = load i32, i32* @G
; CHECK-NEXT: [[V1:%.*]] = call i32 @a(i32 [[G_VAL]])
; CHECK-NEXT: [[V2:%.*]] = call i32 @b()
; CHECK-NEXT: [[RESULT:%.*]] = add i32 [[V1]], [[V2]]
; CHECK-NEXT: ret i32 [[RESULT]]
;
entry:
%v1 = call i32 @a(i32* @G)
%v2 = call i32 @b()

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; PR36543
@ -5,8 +6,16 @@
%T = type { i32, i32, i32, i32 }
; CHECK-LABEL: define internal i32 @test(%T* %p)
define internal i32 @test(%T* %p) {
; CHECK-LABEL: define {{[^@]+}}@test
; CHECK-SAME: (%T* [[P:%.*]])
; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3
; CHECK-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2
; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]]
; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]]
; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
; CHECK-NEXT: ret i32 [[V]]
;
%a.gep = getelementptr %T, %T* %p, i64 0, i32 3
%b.gep = getelementptr %T, %T* %p, i64 0, i32 2
%a = load i32, i32* %a.gep
@ -15,8 +24,12 @@ define internal i32 @test(%T* %p) {
ret i32 %v
}
; CHECK-LABEL: define i32 @caller(%T* %p)
define i32 @caller(%T* %p) {
; CHECK-LABEL: define {{[^@]+}}@caller
; CHECK-SAME: (%T* [[P:%.*]])
; CHECK-NEXT: [[V:%.*]] = musttail call i32 @test(%T* [[P]])
; CHECK-NEXT: ret i32 [[V]]
;
%v = musttail call i32 @test(%T* %p)
ret i32 %v
}
@ -24,11 +37,24 @@ define i32 @caller(%T* %p) {
; Don't promote arguments of musttail caller
define i32 @foo(%T* %p, i32 %v) {
; CHECK-LABEL: define {{[^@]+}}@foo
; CHECK-SAME: (%T* [[P:%.*]], i32 [[V:%.*]])
; CHECK-NEXT: ret i32 0
;
ret i32 0
}
; CHECK-LABEL: define internal i32 @test2(%T* %p, i32 %p2)
define internal i32 @test2(%T* %p, i32 %p2) {
; CHECK-LABEL: define {{[^@]+}}@test2
; CHECK-SAME: (%T* [[P:%.*]], i32 [[P2:%.*]])
; CHECK-NEXT: [[A_GEP:%.*]] = getelementptr [[T:%.*]], %T* [[P]], i64 0, i32 3
; CHECK-NEXT: [[B_GEP:%.*]] = getelementptr [[T]], %T* [[P]], i64 0, i32 2
; CHECK-NEXT: [[A:%.*]] = load i32, i32* [[A_GEP]]
; CHECK-NEXT: [[B:%.*]] = load i32, i32* [[B_GEP]]
; CHECK-NEXT: [[V:%.*]] = add i32 [[A]], [[B]]
; CHECK-NEXT: [[CA:%.*]] = musttail call i32 @foo(%T* undef, i32 [[V]])
; CHECK-NEXT: ret i32 [[CA]]
;
%a.gep = getelementptr %T, %T* %p, i64 0, i32 3
%b.gep = getelementptr %T, %T* %p, i64 0, i32 2
%a = load i32, i32* %a.gep
@ -38,8 +64,12 @@ define internal i32 @test2(%T* %p, i32 %p2) {
ret i32 %ca
}
; CHECK-LABEL: define i32 @caller2(%T* %g)
define i32 @caller2(%T* %g) {
; CHECK-LABEL: define {{[^@]+}}@caller2
; CHECK-SAME: (%T* [[G:%.*]])
; CHECK-NEXT: [[V:%.*]] = call i32 @test2(%T* [[G]], i32 0)
; CHECK-NEXT: ret i32 [[V]]
;
%v = call i32 @test2(%T* %g, i32 0)
ret i32 %v
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; Don't promote paramaters of/arguments to naked functions
@ -5,19 +6,29 @@
@g = common global i32 0, align 4
define i32 @bar() {
; CHECK-LABEL: define {{[^@]+}}@bar()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = call i32 @foo(i32* @g)
; CHECK-NEXT: ret i32 [[CALL]]
;
entry:
%call = call i32 @foo(i32* @g)
; CHECK: %call = call i32 @foo(i32* @g)
ret i32 %call
}
define internal i32 @foo(i32*) #0 {
; CHECK-LABEL: define {{[^@]+}}@foo
; CHECK-SAME: (i32* [[TMP0:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
; CHECK-NEXT: call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
; CHECK-NEXT: unreachable
;
entry:
%retval = alloca i32, align 4
call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
unreachable
}
; CHECK: define internal i32 @foo(i32* %0)
attributes #0 = { naked }

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; ArgumentPromotion should preserve the default function address space
@ -8,14 +9,24 @@ target datalayout = "e-P1-p:16:8-i8:8-i16:8-i32:8-i64:8-f32:8-f64:8-n8-a:8"
@g = common global i32 0, align 4
define i32 @bar() {
; CHECK-LABEL: define {{[^@]+}}@bar() addrspace(1)
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CALL:%.*]] = call addrspace(1) i32 @foo()
; CHECK-NEXT: ret i32 [[CALL]]
;
entry:
%call = call i32 @foo(i32* @g)
; CHECK: %call = call addrspace(1) i32 @foo()
ret i32 %call
}
; CHECK: define internal i32 @foo() addrspace(1)
define internal i32 @foo(i32*) {
; CHECK-LABEL: define {{[^@]+}}@foo() addrspace(1)
; CHECK-NEXT: entry:
; CHECK-NEXT: [[RETVAL:%.*]] = alloca i32, align 4
; CHECK-NEXT: call addrspace(0) void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()
; CHECK-NEXT: unreachable
;
entry:
%retval = alloca i32, align 4
call void asm sideeffect "ldr r0, [r0] \0Abx lr \0A", ""()

View File

@ -1,18 +1,35 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -S -argpromotion < %s | FileCheck %s
; RUN: opt -S -passes=argpromotion < %s | FileCheck %s
; RUN: opt -S -debugify -o /dev/null < %s
target triple = "x86_64-pc-windows-msvc"
define internal void @callee(i8*) {
; CHECK-LABEL: define {{[^@]+}}@callee()
; CHECK-NEXT: entry:
; CHECK-NEXT: call void @thunk()
; CHECK-NEXT: ret void
;
entry:
call void @thunk()
ret void
}
define void @test1() personality i32 (...)* @__CxxFrameHandler3 {
; CHECK-LABEL: define {{[^@]+}}@test1() personality i32 (...)* @__CxxFrameHandler3
; CHECK-NEXT: entry:
; CHECK-NEXT: invoke void @thunk()
; CHECK-NEXT: to label [[OUT:%.*]] unwind label [[CPAD:%.*]]
; CHECK: out:
; CHECK-NEXT: ret void
; CHECK: cpad:
; CHECK-NEXT: [[PAD:%.*]] = cleanuppad within none []
; CHECK-NEXT: call void @callee() [ "funclet"(token [[PAD]]) ]
; CHECK-NEXT: cleanupret from [[PAD]] unwind to caller
;
entry:
invoke void @thunk()
to label %out unwind label %cpad
to label %out unwind label %cpad
out:
ret void
@ -23,10 +40,6 @@ cpad:
cleanupret from %pad unwind to caller
}
; CHECK-LABEL: define void @test1(
; CHECK: %[[pad:.*]] = cleanuppad within none []
; CHECK-NEXT: call void @callee() [ "funclet"(token %[[pad]]) ]
; CHECK-NEXT: cleanupret from %[[pad]] unwind to caller
declare void @thunk()

File diff suppressed because it is too large Load Diff

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; PR 32917
@ -5,6 +6,15 @@
@a = common local_unnamed_addr global i32 0, align 4
define i32 @fn2() local_unnamed_addr {
; CHECK-LABEL: define {{[^@]+}}@fn2() local_unnamed_addr
; CHECK-NEXT: [[TMP1:%.*]] = load i32, i32* @b, align 4
; CHECK-NEXT: [[TMP2:%.*]] = sext i32 [[TMP1]] to i64
; CHECK-NEXT: [[TMP3:%.*]] = inttoptr i64 [[TMP2]] to i32*
; CHECK-NEXT: [[DOTIDX:%.*]] = getelementptr i32, i32* [[TMP3]], i64 -1
; CHECK-NEXT: [[DOTIDX_VAL:%.*]] = load i32, i32* [[DOTIDX]], align 4
; CHECK-NEXT: call fastcc void @fn1(i32 [[DOTIDX_VAL]])
; CHECK-NEXT: ret i32 undef
;
%1 = load i32, i32* @b, align 4
%2 = sext i32 %1 to i64
%3 = inttoptr i64 %2 to i32*
@ -13,11 +23,13 @@ define i32 @fn2() local_unnamed_addr {
}
define internal fastcc void @fn1(i32* nocapture readonly) unnamed_addr {
; CHECK-LABEL: define {{[^@]+}}@fn1
; CHECK-SAME: (i32 [[DOT18446744073709551615_VAL:%.*]]) unnamed_addr
; CHECK-NEXT: store i32 [[DOT18446744073709551615_VAL]], i32* @a, align 4
; CHECK-NEXT: ret void
;
%2 = getelementptr inbounds i32, i32* %0, i64 -1
%3 = load i32, i32* %2, align 4
store i32 %3, i32* @a, align 4
ret void
}
; CHECK: getelementptr {{.*}} -1
; CHECK-NOT: getelementptr {{.*}} 4294967295

View File

@ -1,18 +1,29 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -argpromotion -verify -dse -S %s -o - | FileCheck %s
; Fix for PR33641. ArgumentPromotion removed the argument to bar but left the call to
; dbg.value which still used the removed argument.
; The %p argument should be removed, and the use of it in dbg.value should be
; changed to undef.
%p_t = type i16*
%fun_t = type void (%p_t)*
define void @foo() {
; CHECK-LABEL: define {{[^@]+}}@foo()
; CHECK-NEXT: ret void
;
%tmp = alloca %fun_t
store %fun_t @bar, %fun_t* %tmp
ret void
}
define internal void @bar(%p_t %p) {
; CHECK-LABEL: define {{[^@]+}}@bar()
; CHECK-NEXT: call void @llvm.dbg.value(metadata i16* undef, metadata !3, metadata !DIExpression()), !dbg !5
; CHECK-NEXT: ret void
;
call void @llvm.dbg.value(metadata %p_t %p, metadata !4, metadata !5), !dbg !6
ret void
}
@ -29,10 +40,3 @@ declare void @llvm.dbg.value(metadata, metadata, metadata)
!4 = !DILocalVariable(name: "p", scope: !3)
!5 = !DIExpression()
!6 = !DILocation(line: 1, column: 1, scope: !3)
; The %p argument should be removed, and the use of it in dbg.value should be
; changed to undef.
; CHECK: define internal void @bar() {
; CHECK-NEXT: call void @llvm.dbg.value(metadata i16* undef
; CHECK-NEXT: ret void
; CHECK-NEXT: }

View File

@ -1,17 +1,26 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt -argpromotion -mem2reg -S < %s | FileCheck %s
target datalayout = "E-p:64:64:64-a0:0:8-f32:32:32-f64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:32:64-v64:64:64-v128:128:128"
; Checks if !prof metadata is corret in deadargelim.
define void @caller() #0 {
; CHECK-LABEL: define {{[^@]+}}@caller()
; CHECK-NEXT: call void @promote_i32_ptr(i32 42), !prof !0
; CHECK-NEXT: ret void
;
%x = alloca i32
store i32 42, i32* %x
call void @promote_i32_ptr(i32* %x), !prof !0
; CHECK: call void @promote_i32_ptr(i32 42), !prof ![[PROF:[0-9]]]
ret void
}
define internal void @promote_i32_ptr(i32* %xp) {
; CHECK-LABEL: define {{[^@]+}}@promote_i32_ptr
; CHECK-SAME: (i32 [[XP_VAL:%.*]])
; CHECK-NEXT: call void @use_i32(i32 [[XP_VAL]])
; CHECK-NEXT: ret void
;
%x = load i32, i32* %xp
call void @use_i32(i32 %x)
ret void
@ -19,5 +28,4 @@ define internal void @promote_i32_ptr(i32* %xp) {
declare void @use_i32(i32)
; CHECK: ![[PROF]] = !{!"branch_weights", i32 30}
!0 = !{!"branch_weights", i32 30}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -14,6 +15,14 @@
@d = global i8 0, align 1
define internal fastcc void @fn(i32* nocapture readonly %p1, i64* nocapture readonly %p2) {
; CHECK-LABEL: define {{[^@]+}}@fn
; CHECK-SAME: (i32 [[P1_VAL:%.*]], i64 [[P2_VAL:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: [[CONV:%.*]] = trunc i64 [[P2_VAL]] to i32
; CHECK-NEXT: [[CONV1:%.*]] = trunc i32 [[P1_VAL]] to i8
; CHECK-NEXT: store i8 [[CONV1]], i8* @d, align 1, !tbaa !0
; CHECK-NEXT: ret void
;
entry:
%0 = load i64, i64* %p2, align 8, !tbaa !1
%conv = trunc i64 %0 to i32
@ -24,11 +33,18 @@ entry:
}
define i32 @main() {
; CHECK-LABEL: define {{[^@]+}}@main()
; CHECK-NEXT: entry:
; CHECK-NEXT: [[TMP0:%.*]] = load i32**, i32*** @e, align 8, !tbaa !3
; CHECK-NEXT: store i32* @g, i32** [[TMP0]], align 8, !tbaa !3
; CHECK-NEXT: [[TMP1:%.*]] = load i32*, i32** @a, align 8, !tbaa !3
; CHECK-NEXT: store i32 1, i32* [[TMP1]], align 4, !tbaa !5
; CHECK-NEXT: [[G_VAL:%.*]] = load i32, i32* @g, align 4, !tbaa !5
; CHECK-NEXT: [[C_VAL:%.*]] = load i64, i64* @c, align 8, !tbaa !7
; CHECK-NEXT: call fastcc void @fn(i32 [[G_VAL]], i64 [[C_VAL]])
; CHECK-NEXT: ret i32 0
;
entry:
; CHECK-LABEL: main
; CHECK: store i32 1, i32* %{{.*}}, align 4, !tbaa ![[I32:[0-9]+]]
; CHECK: %g.val = load i32, i32* @g, align 4, !tbaa ![[I32]]
; CHECK: %c.val = load i64, i64* @c, align 8, !tbaa ![[LONG:[0-9]+]]
%0 = load i32**, i32*** @e, align 8, !tbaa !8
store i32* @g, i32** %0, align 8, !tbaa !8
%1 = load i32*, i32** @a, align 8, !tbaa !8
@ -47,7 +63,4 @@ entry:
!7 = !{!3, !3, i64 0}
!8 = !{!9, !9, i64 0}
!9 = !{!"any pointer", !3, i64 0}
; CHECK: ![[I32]] = !{![[I32_TYPE:[0-9]+]], ![[I32_TYPE]], i64 0}
; CHECK: ![[I32_TYPE]] = !{!"int", !{{.*}}, i64 0}
; CHECK: ![[LONG]] = !{![[LONG_TYPE:[0-9]+]], ![[LONG_TYPE]], i64 0}
; CHECK: ![[LONG_TYPE]] = !{!"long", !{{.*}}, i64 0}

View File

@ -1,29 +1,40 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
target triple = "x86_64-pc-windows-msvc"
; CHECK: define internal void @add(i32 %[[THIS1:.*]], i32 %[[THIS2:.*]], i32* noalias %[[SR:.*]])
define internal void @add({i32, i32}* %this, i32* sret %r) {
; CHECK-LABEL: define {{[^@]+}}@add
; CHECK-SAME: (i32 [[THIS_0_0_VAL:%.*]], i32 [[THIS_0_1_VAL:%.*]], i32* noalias [[R:%.*]])
; CHECK-NEXT: [[AB:%.*]] = add i32 [[THIS_0_0_VAL]], [[THIS_0_1_VAL]]
; CHECK-NEXT: store i32 [[AB]], i32* [[R]]
; CHECK-NEXT: ret void
;
%ap = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 0
%bp = getelementptr {i32, i32}, {i32, i32}* %this, i32 0, i32 1
%a = load i32, i32* %ap
%b = load i32, i32* %bp
; CHECK: %[[AB:.*]] = add i32 %[[THIS1]], %[[THIS2]]
%ab = add i32 %a, %b
; CHECK: store i32 %[[AB]], i32* %[[SR]]
store i32 %ab, i32* %r
ret void
}
; CHECK: define void @f()
define void @f() {
; CHECK: %[[R:.*]] = alloca i32
; CHECK-LABEL: define {{[^@]+}}@f()
; CHECK-NEXT: [[R:%.*]] = alloca i32
; CHECK-NEXT: [[PAIR:%.*]] = alloca { i32, i32 }
; CHECK-NEXT: [[PAIR_IDX:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[PAIR]], i64 0, i32 0
; CHECK-NEXT: [[PAIR_IDX_VAL:%.*]] = load i32, i32* [[PAIR_IDX]]
; CHECK-NEXT: [[PAIR_IDX1:%.*]] = getelementptr { i32, i32 }, { i32, i32 }* [[PAIR]], i64 0, i32 1
; CHECK-NEXT: [[PAIR_IDX1_VAL:%.*]] = load i32, i32* [[PAIR_IDX1]]
; CHECK-NEXT: call void @add(i32 [[PAIR_IDX_VAL]], i32 [[PAIR_IDX1_VAL]], i32* noalias [[R]])
; CHECK-NEXT: ret void
;
%r = alloca i32
%pair = alloca {i32, i32}
; CHECK: call void @add(i32 %{{.*}}, i32 %{{.*}}, i32* noalias %[[R]])
call void @add({i32, i32}* %pair, i32* sret %r)
ret void
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt %s -argpromotion -S -o - | FileCheck %s
; RUN: opt %s -passes=argpromotion -S -o - | FileCheck %s
; PR14710
@ -9,15 +10,30 @@ target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
declare i8* @foo(%pair*)
define internal void @bar(%pair* byval %Data) {
; CHECK: define internal void @bar(i32 %Data.0, i32 %Data.1)
; CHECK: %Data = alloca %pair
; CHECK-NOT: tail
; CHECK: call i8* @foo(%pair* %Data)
; CHECK-LABEL: define {{[^@]+}}@bar
; CHECK-SAME: (i32 [[DATA_0:%.*]], i32 [[DATA_1:%.*]])
; CHECK-NEXT: [[DATA:%.*]] = alloca [[PAIR:%.*]]
; CHECK-NEXT: [[DOT0:%.*]] = getelementptr [[PAIR]], %pair* [[DATA]], i32 0, i32 0
; CHECK-NEXT: store i32 [[DATA_0]], i32* [[DOT0]]
; CHECK-NEXT: [[DOT1:%.*]] = getelementptr [[PAIR]], %pair* [[DATA]], i32 0, i32 1
; CHECK-NEXT: store i32 [[DATA_1]], i32* [[DOT1]]
; CHECK-NEXT: [[TMP1:%.*]] = call i8* @foo(%pair* [[DATA]])
; CHECK-NEXT: ret void
;
tail call i8* @foo(%pair* %Data)
ret void
}
define void @zed(%pair* byval %Data) {
; CHECK-LABEL: define {{[^@]+}}@zed
; CHECK-SAME: (%pair* byval [[DATA:%.*]])
; CHECK-NEXT: [[DATA_0:%.*]] = getelementptr [[PAIR:%.*]], %pair* [[DATA]], i32 0, i32 0
; CHECK-NEXT: [[DATA_0_VAL:%.*]] = load i32, i32* [[DATA_0]]
; CHECK-NEXT: [[DATA_1:%.*]] = getelementptr [[PAIR]], %pair* [[DATA]], i32 0, i32 1
; CHECK-NEXT: [[DATA_1_VAL:%.*]] = load i32, i32* [[DATA_1]]
; CHECK-NEXT: call void @bar(i32 [[DATA_0_VAL]], i32 [[DATA_1_VAL]])
; CHECK-NEXT: ret void
;
call void @bar(%pair* byval %Data)
ret void
}

View File

@ -1,3 +1,4 @@
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature --scrub-attributes
; RUN: opt < %s -argpromotion -S | FileCheck %s
; RUN: opt < %s -passes=argpromotion -S | FileCheck %s
@ -15,6 +16,12 @@ target triple = "x86_64-unknown-linux-gnu"
; Function Attrs: nounwind uwtable
define i32 @main(i32 %argc, i8** nocapture readnone %argv) #0 {
; CHECK-LABEL: define {{[^@]+}}@main
; CHECK-SAME: (i32 [[ARGC:%.*]], i8** nocapture readnone [[ARGV:%.*]])
; CHECK-NEXT: entry:
; CHECK-NEXT: tail call void (i8*, i8*, i8*, i8*, i8*, ...) @callee_t0f(i8* undef, i8* undef, i8* undef, i8* undef, i8* undef, %struct.tt0* byval align 8 @t45)
; CHECK-NEXT: ret i32 0
;
entry:
tail call void (i8*, i8*, i8*, i8*, i8*, ...) @callee_t0f(i8* undef, i8* undef, i8* undef, i8* undef, i8* undef, %struct.tt0* byval align 8 @t45)
ret i32 0
@ -22,8 +29,11 @@ entry:
; Function Attrs: nounwind uwtable
define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...) {
; CHECK-LABEL: define {{[^@]+}}@callee_t0f
; CHECK-SAME: (i8* nocapture readnone [[TP13:%.*]], i8* nocapture readnone [[TP14:%.*]], i8* nocapture readnone [[TP15:%.*]], i8* nocapture readnone [[TP16:%.*]], i8* nocapture readnone [[TP17:%.*]], ...)
; CHECK-NEXT: entry:
; CHECK-NEXT: ret void
;
entry:
ret void
}
; CHECK-LABEL: define internal void @callee_t0f(i8* nocapture readnone %tp13, i8* nocapture readnone %tp14, i8* nocapture readnone %tp15, i8* nocapture readnone %tp16, i8* nocapture readnone %tp17, ...)