156 lines
4.7 KiB
LLVM
156 lines
4.7 KiB
LLVM
|
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
|
||
|
; RUN: opt %s -ipsccp -S | FileCheck %s
|
||
|
|
||
|
declare i1 @cond()
|
||
|
declare void @use(i1)
|
||
|
|
||
|
define internal {i64, i64} @struct1() {
|
||
|
; CHECK-LABEL: @struct1(
|
||
|
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
|
||
|
; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: br label [[EXIT]]
|
||
|
; CHECK: exit:
|
||
|
; CHECK-NEXT: [[R:%.*]] = phi { i64, i64 } [ { i64 20, i64 200 }, [[TRUE]] ], [ { i64 30, i64 300 }, [[FALSE]] ]
|
||
|
; CHECK-NEXT: ret { i64, i64 } [[R]]
|
||
|
;
|
||
|
%c = call i1 @cond()
|
||
|
br i1 %c, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
%s.1 = insertvalue {i64, i64} undef, i64 20, 0
|
||
|
%s.2 = insertvalue {i64, i64} %s.1, i64 200, 1
|
||
|
br label %exit
|
||
|
|
||
|
false:
|
||
|
%s.3 = insertvalue {i64, i64} undef, i64 30, 0
|
||
|
%s.4 = insertvalue {i64, i64} %s.3, i64 300, 1
|
||
|
br label %exit
|
||
|
|
||
|
exit:
|
||
|
%r = phi {i64, i64} [ %s.2, %true], [ %s.4, %false ]
|
||
|
ret {i64, i64} %r
|
||
|
}
|
||
|
|
||
|
define void @struct1_caller() {
|
||
|
; CHECK-LABEL: @struct1_caller(
|
||
|
; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct1()
|
||
|
; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0
|
||
|
; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1
|
||
|
; CHECK-NEXT: [[T_1:%.*]] = icmp ne i64 [[V1]], 10
|
||
|
; CHECK-NEXT: call void @use(i1 [[T_1]])
|
||
|
; CHECK-NEXT: [[T_2:%.*]] = icmp ult i64 [[V1]], 100
|
||
|
; CHECK-NEXT: call void @use(i1 [[T_2]])
|
||
|
; CHECK-NEXT: [[T_3:%.*]] = icmp ne i64 [[V2]], 0
|
||
|
; CHECK-NEXT: call void @use(i1 [[T_3]])
|
||
|
; CHECK-NEXT: [[T_4:%.*]] = icmp ult i64 [[V2]], 301
|
||
|
; CHECK-NEXT: call void @use(i1 [[T_4]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
%s = call {i64, i64} @struct1()
|
||
|
%v1 = extractvalue {i64, i64} %s, 0
|
||
|
%v2 = extractvalue {i64, i64} %s, 1
|
||
|
|
||
|
%t.1 = icmp ne i64 %v1, 10
|
||
|
call void @use(i1 %t.1)
|
||
|
%t.2 = icmp ult i64 %v1, 100
|
||
|
call void @use(i1 %t.2)
|
||
|
%t.3 = icmp ne i64 %v2, 0
|
||
|
call void @use(i1 %t.3)
|
||
|
%t.4 = icmp ult i64 %v2, 301
|
||
|
call void @use(i1 %t.4)
|
||
|
|
||
|
ret void
|
||
|
}
|
||
|
|
||
|
define internal {i64, i64} @struct2() {
|
||
|
; CHECK-LABEL: @struct2(
|
||
|
; CHECK-NEXT: [[C:%.*]] = call i1 @cond()
|
||
|
; CHECK-NEXT: br i1 [[C]], label [[TRUE:%.*]], label [[FALSE:%.*]]
|
||
|
; CHECK: true:
|
||
|
; CHECK-NEXT: br label [[EXIT:%.*]]
|
||
|
; CHECK: false:
|
||
|
; CHECK-NEXT: br label [[EXIT]]
|
||
|
; CHECK: exit:
|
||
|
; CHECK-NEXT: [[V1:%.*]] = phi i64 [ 20, [[TRUE]] ], [ 30, [[FALSE]] ]
|
||
|
; CHECK-NEXT: [[V2:%.*]] = phi i64 [ 200, [[TRUE]] ], [ 300, [[FALSE]] ]
|
||
|
; CHECK-NEXT: [[S_1:%.*]] = insertvalue { i64, i64 } undef, i64 [[V1]], 0
|
||
|
; CHECK-NEXT: [[S_2:%.*]] = insertvalue { i64, i64 } [[S_1]], i64 [[V2]], 1
|
||
|
; CHECK-NEXT: ret { i64, i64 } [[S_2]]
|
||
|
;
|
||
|
%c = call i1 @cond()
|
||
|
br i1 %c, label %true, label %false
|
||
|
|
||
|
true:
|
||
|
br label %exit
|
||
|
|
||
|
false:
|
||
|
br label %exit
|
||
|
|
||
|
exit:
|
||
|
%v1 = phi i64 [ 20, %true ], [ 30, %false ]
|
||
|
%v2 = phi i64 [ 200, %true ], [ 300, %false ]
|
||
|
%s.1 = insertvalue {i64, i64} undef, i64 %v1, 0
|
||
|
%s.2 = insertvalue {i64, i64} %s.1, i64 %v2, 1
|
||
|
ret {i64, i64} %s.2
|
||
|
}
|
||
|
|
||
|
define void @struct2_caller() {
|
||
|
; CHECK-LABEL: @struct2_caller(
|
||
|
; CHECK-NEXT: [[S:%.*]] = call { i64, i64 } @struct2()
|
||
|
; CHECK-NEXT: [[V1:%.*]] = extractvalue { i64, i64 } [[S]], 0
|
||
|
; CHECK-NEXT: [[V2:%.*]] = extractvalue { i64, i64 } [[S]], 1
|
||
|
; CHECK-NEXT: call void @use(i1 true)
|
||
|
; CHECK-NEXT: call void @use(i1 true)
|
||
|
; CHECK-NEXT: call void @use(i1 true)
|
||
|
; CHECK-NEXT: call void @use(i1 true)
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: call void @use(i1 false)
|
||
|
; CHECK-NEXT: [[C_1:%.*]] = icmp eq i64 [[V1]], 25
|
||
|
; CHECK-NEXT: call void @use(i1 [[C_1]])
|
||
|
; CHECK-NEXT: [[C_2:%.*]] = icmp ult i64 [[V1]], 25
|
||
|
; CHECK-NEXT: call void @use(i1 [[C_2]])
|
||
|
; CHECK-NEXT: [[C_3:%.*]] = icmp eq i64 [[V2]], 250
|
||
|
; CHECK-NEXT: call void @use(i1 [[C_3]])
|
||
|
; CHECK-NEXT: [[C_4:%.*]] = icmp ugt i64 [[V2]], 250
|
||
|
; CHECK-NEXT: call void @use(i1 [[C_4]])
|
||
|
; CHECK-NEXT: ret void
|
||
|
;
|
||
|
%s = call {i64, i64} @struct2()
|
||
|
%v1 = extractvalue {i64, i64} %s, 0
|
||
|
%v2 = extractvalue {i64, i64} %s, 1
|
||
|
|
||
|
%t.1 = icmp ne i64 %v1, 10
|
||
|
call void @use(i1 %t.1)
|
||
|
%t.2 = icmp ult i64 %v1, 100
|
||
|
call void @use(i1 %t.2)
|
||
|
%t.3 = icmp ne i64 %v2, 0
|
||
|
call void @use(i1 %t.3)
|
||
|
%t.4 = icmp ult i64 %v2, 301
|
||
|
call void @use(i1 %t.4)
|
||
|
|
||
|
%f.1 = icmp eq i64 %v1, 10
|
||
|
call void @use(i1 %f.1)
|
||
|
%f.2 = icmp ult i64 %v1, 19
|
||
|
call void @use(i1 %f.2)
|
||
|
%f.3 = icmp eq i64 %v2, 50
|
||
|
call void @use(i1 %f.3)
|
||
|
%f.4 = icmp ugt i64 %v2, 301
|
||
|
call void @use(i1 %f.4)
|
||
|
|
||
|
%c.1 = icmp eq i64 %v1, 25
|
||
|
call void @use(i1 %c.1)
|
||
|
%c.2 = icmp ult i64 %v1, 25
|
||
|
call void @use(i1 %c.2)
|
||
|
%c.3 = icmp eq i64 %v2, 250
|
||
|
call void @use(i1 %c.3)
|
||
|
%c.4 = icmp ugt i64 %v2, 250
|
||
|
call void @use(i1 %c.4)
|
||
|
|
||
|
ret void
|
||
|
}
|