xref: /llvm-project/llvm/test/Transforms/IROutliner/outlining-isomorphic-predicates.ll (revision f4b925ee7078f058602fd323e25f45f1ae91ca34)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -S -passes=verify,iroutliner -ir-outlining-no-cost < %s | FileCheck %s
3
4; This test checks the isomorphic comparisons can be outlined together into one
5; function.
6
7; The following three function are identical, except that in the third, the
8; operand order, and predicate are swapped, meaning it is structurally the same
9; and should be outlined together.
10
11define void @outline_slt1() {
12; CHECK-LABEL: @outline_slt1(
13; CHECK-NEXT:  entry:
14; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
15; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
16; CHECK-NEXT:    call void @outlined_ir_func_1(ptr [[A]], ptr [[B]])
17; CHECK-NEXT:    ret void
18;
19entry:
20  %a = alloca i32, align 4
21  %b = alloca i32, align 4
22  store i32 2, ptr %a, align 4
23  store i32 3, ptr %b, align 4
24  %al = load i32, ptr %a
25  %bl = load i32, ptr %b
26  %0 = icmp slt i32 %al, %bl
27  ret void
28}
29
30define void @outline_slt2() {
31; CHECK-LABEL: @outline_slt2(
32; CHECK-NEXT:  entry:
33; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
34; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
35; CHECK-NEXT:    call void @outlined_ir_func_1(ptr [[A]], ptr [[B]])
36; CHECK-NEXT:    ret void
37;
38entry:
39  %a = alloca i32, align 4
40  %b = alloca i32, align 4
41  store i32 2, ptr %a, align 4
42  store i32 3, ptr %b, align 4
43  %al = load i32, ptr %a
44  %bl = load i32, ptr %b
45  %0 = icmp slt i32 %al, %bl
46  ret void
47}
48
49define void @outline_sgt() {
50; CHECK-LABEL: @outline_sgt(
51; CHECK-NEXT:  entry:
52; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
53; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
54; CHECK-NEXT:    call void @outlined_ir_func_1(ptr [[A]], ptr [[B]])
55; CHECK-NEXT:    ret void
56;
57entry:
58  %a = alloca i32, align 4
59  %b = alloca i32, align 4
60  store i32 2, ptr %a, align 4
61  store i32 3, ptr %b, align 4
62  %al = load i32, ptr %a
63  %bl = load i32, ptr %b
64  %0 = icmp sgt i32 %bl, %al
65  ret void
66}
67
68; This has a swapped predicate, but not swapped operands, so it cannot use
69; the same outlined function as the ones above.
70
71define void @dontoutline_sgt() {
72; CHECK-LABEL: @dontoutline_sgt(
73; CHECK-NEXT:  entry:
74; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
75; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
76; CHECK-NEXT:    store i32 2, ptr [[A]], align 4
77; CHECK-NEXT:    store i32 3, ptr [[B]], align 4
78; CHECK-NEXT:    [[AL:%.*]] = load i32, ptr [[A]], align 4
79; CHECK-NEXT:    [[BL:%.*]] = load i32, ptr [[B]], align 4
80; CHECK-NEXT:    [[TMP0:%.*]] = icmp sgt i32 [[AL]], [[BL]]
81; CHECK-NEXT:    ret void
82;
83entry:
84  %a = alloca i32, align 4
85  %b = alloca i32, align 4
86  store i32 2, ptr %a, align 4
87  store i32 3, ptr %b, align 4
88  %al = load i32, ptr %a
89  %bl = load i32, ptr %b
90  %0 = icmp sgt i32 %al, %bl
91  ret void
92}
93
94; The below functions use a different kind of predicate that is not compatible
95; with the ones above, and should use a different outlined function.
96; The other difference here is that the predicate with swapped operands comes
97; first this time.
98
99define void @outline_ugt1() {
100; CHECK-LABEL: @outline_ugt1(
101; CHECK-NEXT:  entry:
102; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
103; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
104; CHECK-NEXT:    call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
105; CHECK-NEXT:    ret void
106;
107entry:
108  %a = alloca i32, align 4
109  %b = alloca i32, align 4
110  store i32 2, ptr %a, align 4
111  store i32 3, ptr %b, align 4
112  %al = load i32, ptr %a
113  %bl = load i32, ptr %b
114  %0 = icmp ugt i32 %al, %bl
115  ret void
116}
117
118define void @outline_ugt2() {
119; CHECK-LABEL: @outline_ugt2(
120; CHECK-NEXT:  entry:
121; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
122; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
123; CHECK-NEXT:    call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
124; CHECK-NEXT:    ret void
125;
126entry:
127  %a = alloca i32, align 4
128  %b = alloca i32, align 4
129  store i32 2, ptr %a, align 4
130  store i32 3, ptr %b, align 4
131  %al = load i32, ptr %a
132  %bl = load i32, ptr %b
133  %0 = icmp ugt i32 %al, %bl
134  ret void
135}
136
137define void @outline_ult() {
138; CHECK-LABEL: @outline_ult(
139; CHECK-NEXT:  entry:
140; CHECK-NEXT:    [[A:%.*]] = alloca i32, align 4
141; CHECK-NEXT:    [[B:%.*]] = alloca i32, align 4
142; CHECK-NEXT:    call void @outlined_ir_func_0(ptr [[A]], ptr [[B]])
143; CHECK-NEXT:    ret void
144;
145entry:
146  %a = alloca i32, align 4
147  %b = alloca i32, align 4
148  store i32 2, ptr %a, align 4
149  store i32 3, ptr %b, align 4
150  %al = load i32, ptr %a
151  %bl = load i32, ptr %b
152  %0 = icmp ult i32 %bl, %al
153  ret void
154}
155
156; CHECK: define internal void @outlined_ir_func_0(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]]) #0 {
157; CHECK: entry_to_outline:
158; CHECK-NEXT:    store i32 2, ptr [[ARG0]], align 4
159; CHECK-NEXT:    store i32 3, ptr [[ARG1]], align 4
160; CHECK-NEXT:    [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
161; CHECK-NEXT:    [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
162; CHECK-NEXT:    [[TMP0:%.*]] = icmp ugt i32 [[AL]], [[BL]]
163
164; CHECK: define internal void @outlined_ir_func_1(ptr [[ARG0:%.*]], ptr [[ARG1:%.*]]) #0 {
165; CHECK: entry_to_outline:
166; CHECK-NEXT:    store i32 2, ptr [[ARG0]], align 4
167; CHECK-NEXT:    store i32 3, ptr [[ARG1]], align 4
168; CHECK-NEXT:    [[AL:%.*]] = load i32, ptr [[ARG0]], align 4
169; CHECK-NEXT:    [[BL:%.*]] = load i32, ptr [[ARG1]], align 4
170; CHECK-NEXT:    [[TMP0:%.*]] = icmp slt i32 [[AL]], [[BL]]
171