1; RUN: opt < %s -instcombine -S | FileCheck %s
2
3declare void @bar({i32, i32} %a)
4declare i32 @baz(i32 %a)
5
6; CHECK-LABEL: define i32 @foo(
7; CHECK-NOT: extractvalue
8define i32 @foo(i32 %a, i32 %b) {
9; Instcombine should fold various combinations of insertvalue and extractvalue
10; together
11        ; Build a simple struct and pull values out again
12        %s1.1 = insertvalue {i32, i32} undef, i32 %a, 0
13        %s1 = insertvalue {i32, i32} %s1.1, i32 %b, 1
14        %v1 = extractvalue {i32, i32} %s1, 0
15        %v2 = extractvalue {i32, i32} %s1, 1
16
17        ; Build a nested struct and pull a sub struct out of it
18        ; This requires instcombine to insert a few insertvalue instructions
19        %ns1.1 = insertvalue {i32, {i32, i32}} undef, i32 %v1, 0
20        %ns1.2 = insertvalue {i32, {i32, i32}} %ns1.1, i32 %v1, 1, 0
21        %ns1   = insertvalue {i32, {i32, i32}} %ns1.2, i32 %v2, 1, 1
22        %s2    = extractvalue {i32, {i32, i32}} %ns1, 1
23        %v3    = extractvalue {i32, {i32, i32}} %ns1, 1, 1
24        call void @bar({i32, i32} %s2)
25
26        ; Use nested extractvalues to get to a value
27        %s3    = extractvalue {i32, {i32, i32}} %ns1, 1
28        %v4    = extractvalue {i32, i32} %s3, 1
29        call void @bar({i32, i32} %s3)
30
31        ; Use nested insertvalues to build a nested struct
32        %s4.1 = insertvalue {i32, i32} undef, i32 %v3, 0
33        %s4   = insertvalue {i32, i32} %s4.1, i32 %v4, 1
34        %ns2  = insertvalue {i32, {i32, i32}} undef, {i32, i32} %s4, 1
35
36        ; And now extract a single value from there
37        %v5   = extractvalue {i32, {i32, i32}} %ns2, 1, 1
38
39        ret i32 %v5
40}
41
42; CHECK-LABEL: define i32 @extract2gep(
43; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}, {{.*}}* %pair, i64 0, i32 1
44; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32, i32* [[GEP]]
45; CHECK-NEXT: store
46; CHECK-NEXT: br label %loop
47; CHECK-NOT: extractvalue
48; CHECK: call {{.*}}(i32 [[LOAD]])
49; CHECK-NOT: extractvalue
50; CHECK: ret i32 [[LOAD]]
51define i32 @extract2gep({i16, i32}* %pair, i32* %P) {
52        ; The load + extractvalue should be converted
53        ; to an inbounds gep + smaller load.
54        ; The new load should be in the same spot as the old load.
55        %L = load {i16, i32}, {i16, i32}* %pair
56        store i32 0, i32* %P
57        br label %loop
58
59loop:
60        %E = extractvalue {i16, i32} %L, 1
61        %C = call i32 @baz(i32 %E)
62        store i32 %C, i32* %P
63        %cond = icmp eq i32 %C, 0
64        br i1 %cond, label %end, label %loop
65
66end:
67        ret i32 %E
68}
69
70; CHECK-LABEL: define i16 @doubleextract2gep(
71; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}, {{.*}}* %arg, i64 0, i32 1, i32 1
72; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i16, i16* [[GEP]]
73; CHECK-NEXT: ret i16 [[LOAD]]
74define i16 @doubleextract2gep({i16, {i32, i16}}* %arg) {
75        ; The load + extractvalues should be converted
76        ; to a 3-index inbounds gep + smaller load.
77        %L = load {i16, {i32, i16}}, {i16, {i32, i16}}* %arg
78        %E1 = extractvalue {i16, {i32, i16}} %L, 1
79        %E2 = extractvalue {i32, i16} %E1, 1
80        ret i16 %E2
81}
82
83; CHECK: define i32 @nogep-multiuse
84; CHECK-NEXT: load {{.*}} %pair
85; CHECK-NEXT: extractvalue
86; CHECK-NEXT: extractvalue
87; CHECK-NEXT: add
88; CHECK-NEXT: ret
89define i32 @nogep-multiuse({i32, i32}* %pair) {
90        ; The load should be left unchanged since both parts are needed.
91        %L = load volatile {i32, i32}, {i32, i32}* %pair
92        %LHS = extractvalue {i32, i32} %L, 0
93        %RHS = extractvalue {i32, i32} %L, 1
94        %R = add i32 %LHS, %RHS
95        ret i32 %R
96}
97
98; CHECK: define i32 @nogep-volatile
99; CHECK-NEXT: load volatile {{.*}} %pair
100; CHECK-NEXT: extractvalue
101; CHECK-NEXT: ret
102define i32 @nogep-volatile({i32, i32}* %pair) {
103        ; The load volatile should be left unchanged.
104        %L = load volatile {i32, i32}, {i32, i32}* %pair
105        %E = extractvalue {i32, i32} %L, 1
106        ret i32 %E
107}
108