diff options
Diffstat (limited to 'test/Transforms/InstCombine/extractvalue.ll')
-rw-r--r-- | test/Transforms/InstCombine/extractvalue.ll | 81 |
1 files changed, 75 insertions, 6 deletions
diff --git a/test/Transforms/InstCombine/extractvalue.ll b/test/Transforms/InstCombine/extractvalue.ll index 875f860..64edc18 100644 --- a/test/Transforms/InstCombine/extractvalue.ll +++ b/test/Transforms/InstCombine/extractvalue.ll @@ -1,13 +1,16 @@ -; RUN: opt < %s -instcombine -S | not grep extractvalue +; RUN: opt < %s -instcombine -S | FileCheck %s -; Instcombine should fold various combinations of insertvalue and extractvalue -; together declare void @bar({i32, i32} %a) +declare i32 @baz(i32 %a) -define i32 @foo() { +; 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 0, 0 - %s1 = insertvalue {i32, i32} %s1.1, i32 1, 1 + %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 @@ -36,3 +39,69 @@ define i32 @foo() { 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: volatile load {{.*}} %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 +} |