Files
clang-p2996/llvm/test/Transforms/SCCP/constant-range-struct.ll
Florian Hahn 352b612a71 [SCCP] Drop unnecessary early exit for ExtractValueInst.
visitExtractValueInst uses mergeInValue, so it already can handle
constant ranges. Initially the early exit was using isOverdefined to
keep things as NFC during the initial move to ValueLatticeElement.
As the function already supports constant ranges, it can just use
ValueState[&I].isOverdefined.

Reviewers: efriedma, mssimpso, davide

Reviewed By: efriedma

Differential Revision: https://reviews.llvm.org/D78393
2020-04-22 22:07:59 +01:00

164 lines
5.2 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: [[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: [[F_1:%.*]] = icmp eq i64 [[V1]], 10
; CHECK-NEXT: call void @use(i1 [[F_1]])
; CHECK-NEXT: [[F_2:%.*]] = icmp ult i64 [[V1]], 19
; CHECK-NEXT: call void @use(i1 [[F_2]])
; CHECK-NEXT: [[F_3:%.*]] = icmp eq i64 [[V2]], 50
; CHECK-NEXT: call void @use(i1 [[F_3]])
; CHECK-NEXT: [[F_4:%.*]] = icmp ugt i64 [[V2]], 301
; CHECK-NEXT: call void @use(i1 [[F_4]])
; 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
}