1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --function-signature
2; RUN: opt < %s -ipsccp -S | FileCheck %s
3; PR36485
4; musttail call result can\'t be replaced with a constant, unless the call
5; can be removed
6
7declare i32 @external()
8
9define i8* @start(i8 %v) {
10; CHECK-LABEL: define {{[^@]+}}@start
11; CHECK-SAME: (i8 [[V:%.*]]) {
12; CHECK-NEXT:    [[C1:%.*]] = icmp eq i8 [[V]], 0
13; CHECK-NEXT:    br i1 [[C1]], label [[TRUE:%.*]], label [[FALSE:%.*]]
14; CHECK:       true:
15; CHECK-NEXT:    [[CA:%.*]] = musttail call i8* @side_effects(i8 0)
16; CHECK-NEXT:    ret i8* [[CA]]
17; CHECK:       false:
18; CHECK-NEXT:    [[C2:%.*]] = icmp eq i8 [[V]], 1
19; CHECK-NEXT:    br i1 [[C2]], label [[C2_TRUE:%.*]], label [[C2_FALSE:%.*]]
20; CHECK:       c2_true:
21; CHECK-NEXT:    ret i8* null
22; CHECK:       c2_false:
23; CHECK-NEXT:    [[CA2:%.*]] = musttail call i8* @dont_zap_me(i8 [[V]])
24; CHECK-NEXT:    ret i8* [[CA2]]
25;
26  %c1 = icmp eq i8 %v, 0
27  br i1 %c1, label %true, label %false
28true:
29  %ca = musttail call i8* @side_effects(i8 %v)
30  ret i8* %ca
31false:
32  %c2 = icmp eq i8 %v, 1
33  br i1 %c2, label %c2_true, label %c2_false
34c2_true:
35  %ca1 = musttail call i8* @no_side_effects(i8 %v)
36  ret i8* %ca1
37c2_false:
38  %ca2 = musttail call i8* @dont_zap_me(i8 %v)
39  ret i8* %ca2
40}
41
42define internal i8* @side_effects(i8 %v) {
43; CHECK-LABEL: define {{[^@]+}}@side_effects
44; CHECK-SAME: (i8 [[V:%.*]]) {
45; CHECK-NEXT:    [[I1:%.*]] = call i32 @external()
46; CHECK-NEXT:    [[CA:%.*]] = musttail call i8* @start(i8 0)
47; CHECK-NEXT:    ret i8* [[CA]]
48;
49  %i1 = call i32 @external()
50
51  ; since this goes back to `start` the SCPP should be see that the return value
52  ; is always `null`.
53  ; The call can't be removed due to `external` call above, though.
54
55  %ca = musttail call i8* @start(i8 %v)
56
57  ; Thus the result must be returned anyway
58  ret i8* %ca
59}
60
61; The call to this function is removed, so the return value must be zapped
62define internal i8* @no_side_effects(i8 %v) readonly nounwind willreturn {
63; CHECK-LABEL: define {{[^@]+}}@no_side_effects
64; CHECK-SAME: (i8 [[V:%.*]]) #[[ATTR0:[0-9]+]] {
65; CHECK-NEXT:    ret i8* undef
66;
67  ret i8* null
68}
69
70; The call to this function cannot be removed due to side effects. Thus the
71; return value should stay as it is, and should not be zapped.
72define internal i8* @dont_zap_me(i8 %v) {
73; CHECK-LABEL: define {{[^@]+}}@dont_zap_me
74; CHECK-SAME: (i8 [[V:%.*]]) {
75; CHECK-NEXT:    [[I1:%.*]] = call i32 @external()
76; CHECK-NEXT:    ret i8* null
77;
78  %i1 = call i32 @external()
79  ret i8* null
80}
81