mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-26 06:22:56 +02:00
71 lines
2.1 KiB
LLVM
71 lines
2.1 KiB
LLVM
|
; RUN: opt -S -deadargelim %s | FileCheck %s
|
||
|
|
||
|
; Case 0: the basic example: an entire aggregate use is returned, but it's
|
||
|
; actually only used in ways we can eliminate. We gain benefit from analysing
|
||
|
; the "use" and applying its results to all sub-values.
|
||
|
|
||
|
; CHECK-LABEL: define internal void @agguse_dead()
|
||
|
|
||
|
define internal { i32, i32 } @agguse_dead() {
|
||
|
ret { i32, i32 } { i32 0, i32 1 }
|
||
|
}
|
||
|
|
||
|
define internal { i32, i32 } @test_agguse_dead() {
|
||
|
%val = call { i32, i32 } @agguse_dead()
|
||
|
ret { i32, i32 } %val
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
; Case 1: an opaque use of the aggregate exists (in this case dead). Otherwise
|
||
|
; only one value is used, so function can be simplified.
|
||
|
|
||
|
; CHECK-LABEL: define internal i32 @rets_independent_if_agguse_dead()
|
||
|
; CHECK: [[RET:%.*]] = extractvalue { i32, i32 } { i32 0, i32 1 }, 1
|
||
|
; CHECK: ret i32 [[RET]]
|
||
|
|
||
|
define internal { i32, i32 } @rets_independent_if_agguse_dead() {
|
||
|
ret { i32, i32 } { i32 0, i32 1 }
|
||
|
}
|
||
|
|
||
|
define internal { i32, i32 } @test_rets_independent_if_agguse_dead(i1 %tst) {
|
||
|
%val = call { i32, i32 } @rets_independent_if_agguse_dead()
|
||
|
br i1 %tst, label %use_1, label %use_aggregate
|
||
|
|
||
|
use_1:
|
||
|
; This use can be classified as applying only to ret 1.
|
||
|
%val0 = extractvalue { i32, i32 } %val, 1
|
||
|
call void @callee(i32 %val0)
|
||
|
ret { i32, i32 } undef
|
||
|
|
||
|
use_aggregate:
|
||
|
; This use is assumed to apply to both 0 and 1.
|
||
|
ret { i32, i32 } %val
|
||
|
}
|
||
|
|
||
|
; Case 2: an opaque use of the aggregate exists (in this case *live*). Other
|
||
|
; uses shouldn't matter.
|
||
|
|
||
|
; CHECK-LABEL: define internal { i32, i32 } @rets_live_agguse()
|
||
|
; CHECK: ret { i32, i32 } { i32 0, i32 1 }
|
||
|
|
||
|
define internal { i32, i32 } @rets_live_agguse() {
|
||
|
ret { i32, i32} { i32 0, i32 1 }
|
||
|
}
|
||
|
|
||
|
define { i32, i32 } @test_rets_live_aggues(i1 %tst) {
|
||
|
%val = call { i32, i32 } @rets_live_agguse()
|
||
|
br i1 %tst, label %use_1, label %use_aggregate
|
||
|
|
||
|
use_1:
|
||
|
; This use can be classified as applying only to ret 1.
|
||
|
%val0 = extractvalue { i32, i32 } %val, 1
|
||
|
call void @callee(i32 %val0)
|
||
|
ret { i32, i32 } undef
|
||
|
|
||
|
use_aggregate:
|
||
|
; This use is assumed to apply to both 0 and 1.
|
||
|
ret { i32, i32 } %val
|
||
|
}
|
||
|
|
||
|
declare void @callee(i32)
|