xref: /llvm-project/llvm/test/Transforms/InstCombine/xor-ashr.ll (revision 97298853b4de70dbce9c0a140ac38e3ac179e02e)
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2; RUN: opt < %s -passes=instcombine -S | FileCheck %s
3; RUN: opt < %s -passes=instcombine -use-constant-int-for-fixed-length-splat -S | FileCheck %s
4
5target datalayout = "e-p:64:64:64-i1:8:8-i8:8:8-i16:16:16-i32:32:32-i64:64:64-f32:32:32-f64:64:64-v64:64:64-v128:128:128-a0:0:64-s0:64:64-f80:128:128-n8:16:32:64"
6
7declare void @use16(i16)
8declare void @use32(i32)
9
10define i8 @testi8i8(i8 %add) {
11; CHECK-LABEL: @testi8i8(
12; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i8 [[ADD:%.*]], -1
13; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i8 127, i8 -128
14; CHECK-NEXT:    ret i8 [[X]]
15;
16  %sh = ashr i8 %add, 7
17  %x = xor i8 %sh, 127
18  ret i8 %x
19}
20
21define i8 @testi16i8(i16 %add) {
22; CHECK-LABEL: @testi16i8(
23; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i16 [[ADD:%.*]], -1
24; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i8 27, i8 -28
25; CHECK-NEXT:    ret i8 [[X]]
26;
27  %sh = ashr i16 %add, 15
28  %t = trunc i16 %sh to i8
29  %x = xor i8 %t, 27
30  ret i8 %x
31}
32
33define i32 @testi64i32(i64 %add) {
34; CHECK-LABEL: @testi64i32(
35; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i64 [[ADD:%.*]], -1
36; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i32 127, i32 -128
37; CHECK-NEXT:    ret i32 [[X]]
38;
39  %sh = ashr i64 %add, 63
40  %t = trunc i64 %sh to i32
41  %x = xor i32 %t, 127
42  ret i32 %x
43}
44
45define i128 @testi128i128(i128 %add) {
46; CHECK-LABEL: @testi128i128(
47; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i128 [[ADD:%.*]], -1
48; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i128 27, i128 -28
49; CHECK-NEXT:    ret i128 [[X]]
50;
51  %sh = ashr i128 %add, 127
52  %x = xor i128 %sh, 27
53  ret i128 %x
54}
55
56define <4 x i8> @testv4i16i8(<4 x i16> %add) {
57; CHECK-LABEL: @testv4i16i8(
58; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD:%.*]], splat (i16 -1)
59; CHECK-NEXT:    [[X:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> splat (i8 27), <4 x i8> splat (i8 -28)
60; CHECK-NEXT:    ret <4 x i8> [[X]]
61;
62  %sh = ashr <4 x i16> %add, <i16 15, i16 15, i16 15, i16 15>
63  %t = trunc <4 x i16> %sh to <4 x i8>
64  %x = xor <4 x i8> %t, <i8 27, i8 27, i8 27, i8 27>
65  ret <4 x i8> %x
66}
67
68define <4 x i8> @testv4i16i8_poison(<4 x i16> %add) {
69; CHECK-LABEL: @testv4i16i8_poison(
70; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt <4 x i16> [[ADD:%.*]], splat (i16 -1)
71; CHECK-NEXT:    [[X:%.*]] = select <4 x i1> [[TMP1]], <4 x i8> <i8 27, i8 27, i8 poison, i8 27>, <4 x i8> <i8 -28, i8 -28, i8 poison, i8 -28>
72; CHECK-NEXT:    ret <4 x i8> [[X]]
73;
74  %sh = ashr <4 x i16> %add, <i16 15, i16 poison, i16 15, i16 15>
75  %t = trunc <4 x i16> %sh to <4 x i8>
76  %x = xor <4 x i8> %t, <i8 27, i8 27, i8 poison, i8 27>
77  ret <4 x i8> %x
78}
79
80; Negative tests
81
82define i8 @wrongimm(i16 %add) {
83; CHECK-LABEL: @wrongimm(
84; CHECK-NEXT:    [[SH:%.*]] = ashr i16 [[ADD:%.*]], 14
85; CHECK-NEXT:    [[T:%.*]] = trunc nsw i16 [[SH]] to i8
86; CHECK-NEXT:    [[X:%.*]] = xor i8 [[T]], 27
87; CHECK-NEXT:    ret i8 [[X]]
88;
89  %sh = ashr i16 %add, 14
90  %t = trunc i16 %sh to i8
91  %x = xor i8 %t, 27
92  ret i8 %x
93}
94
95; PR52397 Some of the lanes of the xor/ashr are unused, becoming poison.
96define <4 x i32> @vectorpoison(<6 x i32> %0) {
97; CHECK-LABEL: @vectorpoison(
98; CHECK-NEXT:  entry:
99; CHECK-NEXT:    [[ISNOTNEG:%.*]] = icmp sgt <6 x i32> [[TMP0:%.*]], splat (i32 -1)
100; CHECK-NEXT:    [[SHR:%.*]] = sext <6 x i1> [[ISNOTNEG]] to <6 x i32>
101; CHECK-NEXT:    [[TMP1:%.*]] = shufflevector <6 x i32> [[SHR]], <6 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 2>
102; CHECK-NEXT:    ret <4 x i32> [[TMP1]]
103;
104entry:
105  %neg = xor <6 x i32> %0, <i32 -1, i32 -1, i32 -1, i32 -1, i32 -1, i32 -1>
106  %shr = ashr <6 x i32> %neg, <i32 31, i32 31, i32 31, i32 31, i32 31, i32 31>
107  %1 = shufflevector <6 x i32> %shr, <6 x i32> poison, <4 x i32> <i32 0, i32 1, i32 0, i32 2>
108  ret <4 x i32> %1
109}
110
111
112; One use
113
114define i16 @extrause(i16 %add) {
115; CHECK-LABEL: @extrause(
116; CHECK-NEXT:    [[SH:%.*]] = ashr i16 [[ADD:%.*]], 15
117; CHECK-NEXT:    [[X:%.*]] = xor i16 [[SH]], 27
118; CHECK-NEXT:    call void @use16(i16 [[SH]])
119; CHECK-NEXT:    ret i16 [[X]]
120;
121  %sh = ashr i16 %add, 15
122  %x = xor i16 %sh, 27
123  call void @use16(i16 %sh)
124  ret i16 %x
125}
126
127define i16 @extrause_trunc1(i32 %add) {
128; CHECK-LABEL: @extrause_trunc1(
129; CHECK-NEXT:    [[SH:%.*]] = ashr i32 [[ADD:%.*]], 31
130; CHECK-NEXT:    call void @use32(i32 [[SH]])
131; CHECK-NEXT:    [[TMP1:%.*]] = icmp sgt i32 [[ADD]], -1
132; CHECK-NEXT:    [[X:%.*]] = select i1 [[TMP1]], i16 127, i16 -128
133; CHECK-NEXT:    ret i16 [[X]]
134;
135  %sh = ashr i32 %add, 31
136  %t = trunc i32 %sh to i16
137  call void @use32(i32 %sh)
138  %x = xor i16 %t, 127
139  ret i16 %x
140}
141
142define i16 @extrause_trunc2(i32 %add) {
143; CHECK-LABEL: @extrause_trunc2(
144; CHECK-NEXT:    [[SH:%.*]] = ashr i32 [[ADD:%.*]], 31
145; CHECK-NEXT:    [[T:%.*]] = trunc nsw i32 [[SH]] to i16
146; CHECK-NEXT:    call void @use16(i16 [[T]])
147; CHECK-NEXT:    [[X:%.*]] = xor i16 [[T]], 127
148; CHECK-NEXT:    ret i16 [[X]]
149;
150  %sh = ashr i32 %add, 31
151  %t = trunc i32 %sh to i16
152  call void @use16(i16 %t)
153  %x = xor i16 %t, 127
154  ret i16 %x
155}
156