|  | ; RUN: opt < %s -instcombine -S | FileCheck %s | 
|  |  | 
|  | declare void @bar({i32, i32} %a) | 
|  | declare i32 @baz(i32 %a) | 
|  |  | 
|  | ; CHECK: define i32 @foo | 
|  | ; CHECK-NOT: extractvalue | 
|  | define i32 @foo(i32 %a, i32 %b) { | 
|  | ; Instcombine should fold various combinations of insertvalue and extractvalue | 
|  | ; together | 
|  | ; Build a simple struct and pull values out again | 
|  | %s1.1 = insertvalue {i32, i32} undef, i32 %a, 0 | 
|  | %s1 = insertvalue {i32, i32} %s1.1, i32 %b, 1 | 
|  | %v1 = extractvalue {i32, i32} %s1, 0 | 
|  | %v2 = extractvalue {i32, i32} %s1, 1 | 
|  |  | 
|  | ; Build a nested struct and pull a sub struct out of it | 
|  | ; This requires instcombine to insert a few insertvalue instructions | 
|  | %ns1.1 = insertvalue {i32, {i32, i32}} undef, i32 %v1, 0 | 
|  | %ns1.2 = insertvalue {i32, {i32, i32}} %ns1.1, i32 %v1, 1, 0 | 
|  | %ns1   = insertvalue {i32, {i32, i32}} %ns1.2, i32 %v2, 1, 1 | 
|  | %s2    = extractvalue {i32, {i32, i32}} %ns1, 1 | 
|  | %v3    = extractvalue {i32, {i32, i32}} %ns1, 1, 1 | 
|  | call void @bar({i32, i32} %s2) | 
|  |  | 
|  | ; Use nested extractvalues to get to a value | 
|  | %s3    = extractvalue {i32, {i32, i32}} %ns1, 1 | 
|  | %v4    = extractvalue {i32, i32} %s3, 1 | 
|  | call void @bar({i32, i32} %s3) | 
|  |  | 
|  | ; Use nested insertvalues to build a nested struct | 
|  | %s4.1 = insertvalue {i32, i32} undef, i32 %v3, 0 | 
|  | %s4   = insertvalue {i32, i32} %s4.1, i32 %v4, 1 | 
|  | %ns2  = insertvalue {i32, {i32, i32}} undef, {i32, i32} %s4, 1 | 
|  |  | 
|  | ; And now extract a single value from there | 
|  | %v5   = extractvalue {i32, {i32, i32}} %ns2, 1, 1 | 
|  |  | 
|  | ret i32 %v5 | 
|  | } | 
|  |  | 
|  | ; CHECK: define i32 @extract2gep | 
|  | ; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}* %pair, i32 0, i32 1 | 
|  | ; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32* [[GEP]] | 
|  | ; CHECK-NEXT: store | 
|  | ; CHECK-NEXT: br label %loop | 
|  | ; CHECK-NOT: extractvalue | 
|  | ; CHECK: call {{.*}}(i32 [[LOAD]]) | 
|  | ; CHECK-NOT: extractvalue | 
|  | ; CHECK: ret i32 [[LOAD]] | 
|  | define i32 @extract2gep({i32, i32}* %pair, i32* %P) { | 
|  | ; The load + extractvalue should be converted | 
|  | ; to an inbounds gep + smaller load. | 
|  | ; The new load should be in the same spot as the old load. | 
|  | %L = load {i32, i32}* %pair | 
|  | store i32 0, i32* %P | 
|  | br label %loop | 
|  |  | 
|  | loop: | 
|  | %E = extractvalue {i32, i32} %L, 1 | 
|  | %C = call i32 @baz(i32 %E) | 
|  | store i32 %C, i32* %P | 
|  | %cond = icmp eq i32 %C, 0 | 
|  | br i1 %cond, label %end, label %loop | 
|  |  | 
|  | end: | 
|  | ret i32 %E | 
|  | } | 
|  |  | 
|  | ; CHECK: define i32 @doubleextract2gep | 
|  | ; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}* %arg, i32 0, i32 1, i32 1 | 
|  | ; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32* [[GEP]] | 
|  | ; CHECK-NEXT: ret i32 [[LOAD]] | 
|  | define i32 @doubleextract2gep({i32, {i32, i32}}* %arg) { | 
|  | ; The load + extractvalues should be converted | 
|  | ; to a 3-index inbounds gep + smaller load. | 
|  | %L = load {i32, {i32, i32}}* %arg | 
|  | %E1 = extractvalue {i32, {i32, i32}} %L, 1 | 
|  | %E2 = extractvalue {i32, i32} %E1, 1 | 
|  | ret i32 %E2 | 
|  | } | 
|  |  | 
|  | ; CHECK: define i32 @nogep-multiuse | 
|  | ; CHECK-NEXT: load {{.*}} %pair | 
|  | ; CHECK-NEXT: extractvalue | 
|  | ; CHECK-NEXT: extractvalue | 
|  | ; CHECK-NEXT: add | 
|  | ; CHECK-NEXT: ret | 
|  | define i32 @nogep-multiuse({i32, i32}* %pair) { | 
|  | ; The load should be left unchanged since both parts are needed. | 
|  | %L = volatile load {i32, i32}* %pair | 
|  | %LHS = extractvalue {i32, i32} %L, 0 | 
|  | %RHS = extractvalue {i32, i32} %L, 1 | 
|  | %R = add i32 %LHS, %RHS | 
|  | ret i32 %R | 
|  | } | 
|  |  | 
|  | ; CHECK: define i32 @nogep-volatile | 
|  | ; CHECK-NEXT: load volatile {{.*}} %pair | 
|  | ; CHECK-NEXT: extractvalue | 
|  | ; CHECK-NEXT: ret | 
|  | define i32 @nogep-volatile({i32, i32}* %pair) { | 
|  | ; The volatile load should be left unchanged. | 
|  | %L = volatile load {i32, i32}* %pair | 
|  | %E = extractvalue {i32, i32} %L, 1 | 
|  | ret i32 %E | 
|  | } |