xref: /llvm-project/llvm/test/Transforms/InstCombine/demorgan-sink-not-into-xor.ll (revision b7c0f79926ad0e4f4abe193c82dad8468855eb81)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --prefix-filecheck-ir-name V
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3
4; https://bugs.llvm.org/show_bug.cgi?id=38446
5
6; Pattern:
7;   ~(x ^ y)
8; Should be transformed into:
9;   (~x) ^ y
10; or into
11;   x ^ (~y)
12
13; While -passes=reassociate does handle this simple pattern, it does not handle
14; the more complicated motivating pattern.
15
16; ============================================================================ ;
17; Basic positive tests
18; ============================================================================ ;
19
20; If the operand is easily-invertible, fold into it.
21declare i1 @gen1()
22
23define i1 @positive_easyinvert(i16 %x, i8 %y) {
24; CHECK-LABEL: @positive_easyinvert(
25; CHECK-NEXT:    [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
26; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[X:%.*]], -1
27; CHECK-NEXT:    [[VTMP4:%.*]] = xor i1 [[VTMP2]], [[TMP1]]
28; CHECK-NEXT:    ret i1 [[VTMP4]]
29;
30  %tmp1 = icmp slt i16 %x, 0
31  %tmp2 = icmp slt i8 %y, 0
32  %tmp3 = xor i1 %tmp2, %tmp1
33  %tmp4 = xor i1 %tmp3, true
34  ret i1 %tmp4
35}
36
37define i1 @positive_easyinvert0(i8 %y) {
38; CHECK-LABEL: @positive_easyinvert0(
39; CHECK-NEXT:    [[VTMP1:%.*]] = call i1 @gen1()
40; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i8 [[Y:%.*]], -1
41; CHECK-NEXT:    [[VTMP4:%.*]] = xor i1 [[TMP1]], [[VTMP1]]
42; CHECK-NEXT:    ret i1 [[VTMP4]]
43;
44  %tmp1 = call i1 @gen1()
45  %cond = icmp slt i8 %y, 0
46  %tmp3 = xor i1 %cond, %tmp1
47  %tmp4 = xor i1 %tmp3, true
48  ret i1 %tmp4
49}
50
51define i1 @positive_easyinvert1(i8 %y) {
52; CHECK-LABEL: @positive_easyinvert1(
53; CHECK-NEXT:    [[VTMP1:%.*]] = call i1 @gen1()
54; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i8 [[Y:%.*]], -1
55; CHECK-NEXT:    [[VTMP4:%.*]] = xor i1 [[VTMP1]], [[TMP1]]
56; CHECK-NEXT:    ret i1 [[VTMP4]]
57;
58  %tmp1 = call i1 @gen1()
59  %tmp2 = icmp slt i8 %y, 0
60  %tmp3 = xor i1 %tmp1, %tmp2
61  %tmp4 = xor i1 %tmp3, true
62  ret i1 %tmp4
63}
64
65; ============================================================================ ;
66; One-use tests with easily-invertible operand.
67; ============================================================================ ;
68
69declare void @use1(i1)
70
71define i1 @oneuse_easyinvert_0(i8 %y) {
72; CHECK-LABEL: @oneuse_easyinvert_0(
73; CHECK-NEXT:    [[VTMP1:%.*]] = call i1 @gen1()
74; CHECK-NEXT:    [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
75; CHECK-NEXT:    call void @use1(i1 [[VTMP2]])
76; CHECK-NEXT:    [[VTMP3:%.*]] = xor i1 [[VTMP1]], [[VTMP2]]
77; CHECK-NEXT:    [[VTMP4:%.*]] = xor i1 [[VTMP3]], true
78; CHECK-NEXT:    ret i1 [[VTMP4]]
79;
80  %tmp1 = call i1 @gen1()
81  %tmp2 = icmp slt i8 %y, 0
82  call void @use1(i1 %tmp2)
83  %tmp3 = xor i1 %tmp1, %tmp2
84  %tmp4 = xor i1 %tmp3, true
85  ret i1 %tmp4
86}
87
88define i1 @oneuse_easyinvert_1(i8 %y) {
89; CHECK-LABEL: @oneuse_easyinvert_1(
90; CHECK-NEXT:    [[VTMP1:%.*]] = call i1 @gen1()
91; CHECK-NEXT:    [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
92; CHECK-NEXT:    [[VTMP3:%.*]] = xor i1 [[VTMP1]], [[VTMP2]]
93; CHECK-NEXT:    call void @use1(i1 [[VTMP3]])
94; CHECK-NEXT:    [[VTMP4:%.*]] = xor i1 [[VTMP3]], true
95; CHECK-NEXT:    ret i1 [[VTMP4]]
96;
97  %tmp1 = call i1 @gen1()
98  %tmp2 = icmp slt i8 %y, 0
99  %tmp3 = xor i1 %tmp1, %tmp2
100  call void @use1(i1 %tmp3)
101  %tmp4 = xor i1 %tmp3, true
102  ret i1 %tmp4
103}
104
105define i1 @oneuse_easyinvert_2(i8 %y) {
106; CHECK-LABEL: @oneuse_easyinvert_2(
107; CHECK-NEXT:    [[VTMP1:%.*]] = call i1 @gen1()
108; CHECK-NEXT:    [[VTMP2:%.*]] = icmp slt i8 [[Y:%.*]], 0
109; CHECK-NEXT:    call void @use1(i1 [[VTMP2]])
110; CHECK-NEXT:    [[VTMP3:%.*]] = xor i1 [[VTMP1]], [[VTMP2]]
111; CHECK-NEXT:    call void @use1(i1 [[VTMP3]])
112; CHECK-NEXT:    [[VTMP4:%.*]] = xor i1 [[VTMP3]], true
113; CHECK-NEXT:    ret i1 [[VTMP4]]
114;
115  %tmp1 = call i1 @gen1()
116  %tmp2 = icmp slt i8 %y, 0
117  call void @use1(i1 %tmp2)
118  %tmp3 = xor i1 %tmp1, %tmp2
119  call void @use1(i1 %tmp3)
120  %tmp4 = xor i1 %tmp3, true
121  ret i1 %tmp4
122}
123
124; ============================================================================ ;
125; Negative tests
126; ============================================================================ ;
127
128; Not easily invertible.
129define i32 @negative(i32 %x, i32 %y) {
130; CHECK-LABEL: @negative(
131; CHECK-NEXT:    [[VTMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
132; CHECK-NEXT:    [[VTMP2:%.*]] = xor i32 [[VTMP1]], -1
133; CHECK-NEXT:    ret i32 [[VTMP2]]
134;
135  %tmp1 = xor i32 %x, %y
136  %tmp2 = xor i32 %tmp1, -1
137  ret i32 %tmp2
138}
139