Home | History | Annotate | Download | only in InstCombine
      1 ; RUN: opt < %s -instcombine -S | FileCheck %s
      2 
      3 declare void @bar({i32, i32} %a)
      4 declare i32 @baz(i32 %a)
      5 
      6 ; CHECK-LABEL: define i32 @foo(
      7 ; CHECK-NOT: extractvalue
      8 define 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, i32 0, i32 1
     44 ; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load 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]]
     51 define i32 @extract2gep({i32, 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 {i32, i32}* %pair
     56         store i32 0, i32* %P
     57         br label %loop
     58 
     59 loop:
     60         %E = extractvalue {i32, 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 
     66 end:
     67         ret i32 %E
     68 }
     69 
     70 ; CHECK-LABEL: define i32 @doubleextract2gep(
     71 ; CHECK-NEXT: [[GEP:%[a-z0-9]+]] = getelementptr inbounds {{.*}}* %arg, i32 0, i32 1, i32 1
     72 ; CHECK-NEXT: [[LOAD:%[A-Za-z0-9]+]] = load i32* [[GEP]]
     73 ; CHECK-NEXT: ret i32 [[LOAD]]
     74 define i32 @doubleextract2gep({i32, {i32, i32}}* %arg) {
     75         ; The load + extractvalues should be converted
     76         ; to a 3-index inbounds gep + smaller load.
     77         %L = load {i32, {i32, i32}}* %arg
     78         %E1 = extractvalue {i32, {i32, i32}} %L, 1
     79         %E2 = extractvalue {i32, i32} %E1, 1
     80         ret i32 %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
     89 define i32 @nogep-multiuse({i32, i32}* %pair) {
     90         ; The load should be left unchanged since both parts are needed.
     91         %L = load volatile {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
    102 define i32 @nogep-volatile({i32, i32}* %pair) {
    103         ; The load volatile should be left unchanged.
    104         %L = load volatile {i32, i32}* %pair
    105         %E = extractvalue {i32, i32} %L, 1
    106         ret i32 %E
    107 }
    108