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:
parent
c24c869cf0
commit
fd77171a96
@ -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 }
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 %{{.*}})
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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 }
|
||||
|
@ -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", ""()
|
||||
|
@ -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
@ -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
|
||||
|
@ -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: }
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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
|
||||
}
|
||||
|
@ -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, ...)
|
||||
|
Loading…
x
Reference in New Issue
Block a user