1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt -instcombine -S < %s | FileCheck %s
3
4declare void @use(i32)
5
6define i32 @sub_to_xor(i32 %x, i32 %y) {
7; CHECK-LABEL: @sub_to_xor(
8; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
9; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[TMP1]]
10; CHECK-NEXT:    ret i32 [[SUB]]
11;
12  %or = or i32 %x, %y
13  %and = and i32 %x, %y
14  %sub = sub i32 %and, %or
15  ret i32 %sub
16}
17
18define i32 @sub_to_xor_extra_use_sub(i32 %x, i32 %y) {
19; CHECK-LABEL: @sub_to_xor_extra_use_sub(
20; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
21; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[TMP1]]
22; CHECK-NEXT:    call void @use(i32 [[SUB]])
23; CHECK-NEXT:    ret i32 [[SUB]]
24;
25  %or = or i32 %x, %y
26  %and = and i32 %x, %y
27  %sub = sub i32 %and, %or
28  call void @use(i32 %sub)
29  ret i32 %sub
30}
31
32define i32 @sub_to_xor_extra_use_and(i32 %x, i32 %y) {
33; CHECK-LABEL: @sub_to_xor_extra_use_and(
34; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X:%.*]], [[Y:%.*]]
35; CHECK-NEXT:    call void @use(i32 [[AND]])
36; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X]], [[Y]]
37; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[TMP1]]
38; CHECK-NEXT:    ret i32 [[SUB]]
39;
40  %or = or i32 %x, %y
41  %and = and i32 %x, %y
42  call void @use(i32 %and)
43  %sub = sub i32 %and, %or
44  ret i32 %sub
45}
46
47define i32 @sub_to_xor_extra_use_or(i32 %x, i32 %y) {
48; CHECK-LABEL: @sub_to_xor_extra_use_or(
49; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
50; CHECK-NEXT:    call void @use(i32 [[OR]])
51; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X]], [[Y]]
52; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[TMP1]]
53; CHECK-NEXT:    ret i32 [[SUB]]
54;
55  %or = or i32 %x, %y
56  call void @use(i32 %or)
57  %and = and i32 %x, %y
58  %sub = sub i32 %and, %or
59  ret i32 %sub
60}
61
62define i32 @sub_to_xor_or_commuted(i32 %x, i32 %y) {
63; CHECK-LABEL: @sub_to_xor_or_commuted(
64; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[X:%.*]], [[Y:%.*]]
65; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[TMP1]]
66; CHECK-NEXT:    ret i32 [[SUB]]
67;
68  %or = or i32 %y, %x
69  %and = and i32 %x, %y
70  %sub = sub i32 %and, %or
71  ret i32 %sub
72}
73
74define i32 @sub_to_xor_and_commuted(i32 %x, i32 %y) {
75; CHECK-LABEL: @sub_to_xor_and_commuted(
76; CHECK-NEXT:    [[TMP1:%.*]] = xor i32 [[Y:%.*]], [[X:%.*]]
77; CHECK-NEXT:    [[SUB:%.*]] = sub i32 0, [[TMP1]]
78; CHECK-NEXT:    ret i32 [[SUB]]
79;
80  %or = or i32 %x, %y
81  %and = and i32 %y, %x
82  %sub = sub i32 %and, %or
83  ret i32 %sub
84}
85
86define <2 x i32> @sub_to_xor_vec(<2 x i32> %x, <2 x i32> %y) {
87; CHECK-LABEL: @sub_to_xor_vec(
88; CHECK-NEXT:    [[TMP1:%.*]] = xor <2 x i32> [[Y:%.*]], [[X:%.*]]
89; CHECK-NEXT:    [[SUB:%.*]] = sub <2 x i32> zeroinitializer, [[TMP1]]
90; CHECK-NEXT:    ret <2 x i32> [[SUB]]
91;
92  %or = or <2 x i32> %x, %y
93  %and = and <2 x i32> %y, %x
94  %sub = sub <2 x i32> %and, %or
95  ret <2 x i32> %sub
96}
97
98; Negative tests
99
100define i32 @sub_to_xor_extra_use_and_or(i32 %x, i32 %y) {
101; CHECK-LABEL: @sub_to_xor_extra_use_and_or(
102; CHECK-NEXT:    [[OR:%.*]] = or i32 [[X:%.*]], [[Y:%.*]]
103; CHECK-NEXT:    call void @use(i32 [[OR]])
104; CHECK-NEXT:    [[AND:%.*]] = and i32 [[X]], [[Y]]
105; CHECK-NEXT:    call void @use(i32 [[AND]])
106; CHECK-NEXT:    [[SUB:%.*]] = sub i32 [[AND]], [[OR]]
107; CHECK-NEXT:    ret i32 [[SUB]]
108;
109  %or = or i32 %x, %y
110  call void @use(i32 %or)
111  %and = and i32 %x, %y
112  call void @use(i32 %and)
113  %sub = sub i32 %and, %or
114  ret i32 %sub
115}
116