xref: /llvm-project/llvm/test/Transforms/InstCombine/phi-with-multiple-unsimplifiable-values.ll (revision 21e3a212c570dc80055742ef8abbd0a306ff9135)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4declare void @use(i8 %value);
5
6; Since we know that any comparison of ucmp/scmp with a constant will result in
7; a comparison of ucmp/scmp's operands, we can propagate such a comparison
8; through the phi node and let the next iteration of instcombine simplify it.
9define i1 @icmp_of_phi_of_scmp_with_constant(i1 %c, i16 %x, i16 %y)
10; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant(
11; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) {
12; CHECK-NEXT:  [[ENTRY:.*:]]
13; CHECK-NEXT:    br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]]
14; CHECK:       [[TRUE]]:
15; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]]
16; CHECK-NEXT:    br label %[[EXIT:.*]]
17; CHECK:       [[FALSE]]:
18; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i16 [[Y]], [[X]]
19; CHECK-NEXT:    br label %[[EXIT]]
20; CHECK:       [[EXIT]]:
21; CHECK-NEXT:    [[R:%.*]] = phi i1 [ [[TMP0]], %[[TRUE]] ], [ [[TMP1]], %[[FALSE]] ]
22; CHECK-NEXT:    ret i1 [[R]]
23;
24{
25entry:
26  br i1 %c, label %true, label %false
27true:
28  %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y)
29  br label %exit
30false:
31  %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x)
32  br label %exit
33exit:
34  %phi = phi i8 [%cmp1, %true], [%cmp2, %false]
35  %r = icmp slt i8 %phi, 0
36  ret i1 %r
37}
38
39; When one of the incoming values is ucmp/scmp and the other is not we can still perform the transformation
40define i1 @icmp_of_phi_of_one_scmp_with_constant(i1 %c, i16 %x, i16 %y, i8 %false_val)
41; CHECK-LABEL: define i1 @icmp_of_phi_of_one_scmp_with_constant(
42; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[FALSE_VAL:%.*]]) {
43; CHECK-NEXT:  [[ENTRY:.*:]]
44; CHECK-NEXT:    br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]]
45; CHECK:       [[TRUE]]:
46; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i16 [[X]], [[Y]]
47; CHECK-NEXT:    br label %[[EXIT:.*]]
48; CHECK:       [[FALSE]]:
49; CHECK-NEXT:    [[TMP1:%.*]] = icmp slt i8 [[FALSE_VAL]], 0
50; CHECK-NEXT:    br label %[[EXIT]]
51; CHECK:       [[EXIT]]:
52; CHECK-NEXT:    [[PHI:%.*]] = phi i1 [ [[TMP0]], %[[TRUE]] ], [ [[TMP1]], %[[FALSE]] ]
53; CHECK-NEXT:    ret i1 [[PHI]]
54;
55{
56entry:
57  br i1 %c, label %true, label %false
58true:
59  %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y)
60  br label %exit
61false:
62  br label %exit
63exit:
64  %phi = phi i8 [%cmp1, %true], [%false_val, %false]
65  %r = icmp slt i8 %phi, 0
66  ret i1 %r
67}
68
69; Negative test: the RHS of comparison that uses the phi node is not constant
70define i1 @icmp_of_phi_of_scmp_with_non_constant(i1 %c, i16 %x, i16 %y, i8 %cmp)
71; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_non_constant(
72; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]], i8 [[CMP:%.*]]) {
73; CHECK-NEXT:  [[ENTRY:.*:]]
74; CHECK-NEXT:    br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]]
75; CHECK:       [[TRUE]]:
76; CHECK-NEXT:    [[CMP1:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[X]], i16 [[Y]])
77; CHECK-NEXT:    br label %[[EXIT:.*]]
78; CHECK:       [[FALSE]]:
79; CHECK-NEXT:    [[CMP2:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[Y]], i16 [[X]])
80; CHECK-NEXT:    br label %[[EXIT]]
81; CHECK:       [[EXIT]]:
82; CHECK-NEXT:    [[PHI:%.*]] = phi i8 [ [[CMP1]], %[[TRUE]] ], [ [[CMP2]], %[[FALSE]] ]
83; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[PHI]], [[CMP]]
84; CHECK-NEXT:    ret i1 [[R]]
85;
86{
87entry:
88  br i1 %c, label %true, label %false
89true:
90  %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y)
91  br label %exit
92false:
93  %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x)
94  br label %exit
95exit:
96  %phi = phi i8 [%cmp1, %true], [%cmp2, %false]
97  %r = icmp slt i8 %phi, %cmp
98  ret i1 %r
99}
100
101; Negative test: more than one incoming value of the phi node is not one-use
102define i1 @icmp_of_phi_of_scmp_with_constant_not_one_use(i1 %c, i16 %x, i16 %y)
103; CHECK-LABEL: define i1 @icmp_of_phi_of_scmp_with_constant_not_one_use(
104; CHECK-SAME: i1 [[C:%.*]], i16 [[X:%.*]], i16 [[Y:%.*]]) {
105; CHECK-NEXT:  [[ENTRY:.*:]]
106; CHECK-NEXT:    br i1 [[C]], label %[[TRUE:.*]], label %[[FALSE:.*]]
107; CHECK:       [[TRUE]]:
108; CHECK-NEXT:    [[CMP1:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[X]], i16 [[Y]])
109; CHECK-NEXT:    call void @use(i8 [[CMP1]])
110; CHECK-NEXT:    br label %[[EXIT:.*]]
111; CHECK:       [[FALSE]]:
112; CHECK-NEXT:    [[CMP2:%.*]] = call i8 @llvm.scmp.i8.i16(i16 [[Y]], i16 [[X]])
113; CHECK-NEXT:    call void @use(i8 [[CMP2]])
114; CHECK-NEXT:    br label %[[EXIT]]
115; CHECK:       [[EXIT]]:
116; CHECK-NEXT:    [[PHI:%.*]] = phi i8 [ [[CMP1]], %[[TRUE]] ], [ [[CMP2]], %[[FALSE]] ]
117; CHECK-NEXT:    [[R:%.*]] = icmp slt i8 [[PHI]], 0
118; CHECK-NEXT:    ret i1 [[R]]
119;
120{
121entry:
122  br i1 %c, label %true, label %false
123true:
124  %cmp1 = call i8 @llvm.scmp(i16 %x, i16 %y)
125  call void @use(i8 %cmp1)
126  br label %exit
127false:
128  %cmp2 = call i8 @llvm.scmp(i16 %y, i16 %x)
129  call void @use(i8 %cmp2)
130  br label %exit
131exit:
132  %phi = phi i8 [%cmp1, %true], [%cmp2, %false]
133  %r = icmp slt i8 %phi, 0
134  ret i1 %r
135}
136