1 ; NOTE: Assertions have been autogenerated by utils/update_test_checks.py
2 ; RUN: opt < %s -S -passes=instcombine | FileCheck %s
5 ; Canonicalize ((X & -X) - 1) --> ((X - 1) & ~X)
8 define i32 @dec_mask_neg_i32(i32 %X) {
9 ; CHECK-LABEL: @dec_mask_neg_i32(
10 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -1
11 ; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -1
12 ; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]]
13 ; CHECK-NEXT: ret i32 [[DEC]]
16 %mask = and i32 %neg, %X
17 %dec = add i32 %mask, -1
21 define i32 @dec_mask_commute_neg_i32(i32 %A) {
22 ; CHECK-LABEL: @dec_mask_commute_neg_i32(
23 ; CHECK-NEXT: [[X:%.*]] = sdiv i32 42, [[A:%.*]]
24 ; CHECK-NEXT: [[TMP1:%.*]] = add nsw i32 [[X]], -1
25 ; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -1
26 ; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]]
27 ; CHECK-NEXT: ret i32 [[DEC]]
29 %X = sdiv i32 42, %A ; thwart complexity-based canonicalization
31 %mask = and i32 %X, %neg
32 %dec = add i32 %mask, -1
36 define i32 @dec_commute_mask_neg_i32(i32 %X) {
37 ; CHECK-LABEL: @dec_commute_mask_neg_i32(
38 ; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -1
39 ; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -1
40 ; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]]
41 ; CHECK-NEXT: ret i32 [[DEC]]
44 %mask = and i32 %neg, %X
45 %dec = add i32 -1, %mask
49 define i32 @dec_mask_neg_multiuse_i32(i32 %X) {
50 ; CHECK-LABEL: @dec_mask_neg_multiuse_i32(
51 ; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]
52 ; CHECK-NEXT: [[MASK:%.*]] = and i32 [[X]], [[NEG]]
53 ; CHECK-NEXT: [[DEC:%.*]] = add i32 [[MASK]], -1
54 ; CHECK-NEXT: call void @use(i32 [[NEG]])
55 ; CHECK-NEXT: ret i32 [[DEC]]
58 %mask = and i32 %neg, %X
59 %dec = add i32 %mask, -1
60 call void @use(i32 %neg)
64 define i32 @dec_mask_multiuse_neg_i32(i32 %X) {
65 ; CHECK-LABEL: @dec_mask_multiuse_neg_i32(
66 ; CHECK-NEXT: [[NEG:%.*]] = sub i32 0, [[X:%.*]]
67 ; CHECK-NEXT: [[MASK:%.*]] = and i32 [[X]], [[NEG]]
68 ; CHECK-NEXT: [[DEC:%.*]] = add i32 [[MASK]], -1
69 ; CHECK-NEXT: call void @use(i32 [[MASK]])
70 ; CHECK-NEXT: ret i32 [[DEC]]
73 %mask = and i32 %neg, %X
74 %dec = add i32 %mask, -1
75 call void @use(i32 %mask)
79 define <2 x i32> @dec_mask_neg_v2i32(<2 x i32> %X) {
80 ; CHECK-LABEL: @dec_mask_neg_v2i32(
81 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], splat (i32 -1)
82 ; CHECK-NEXT: [[TMP2:%.*]] = xor <2 x i32> [[X]], splat (i32 -1)
83 ; CHECK-NEXT: [[DEC:%.*]] = and <2 x i32> [[TMP1]], [[TMP2]]
84 ; CHECK-NEXT: ret <2 x i32> [[DEC]]
86 %neg = sub <2 x i32> zeroinitializer, %X
87 %mask = and <2 x i32> %neg, %X
88 %dec = add <2 x i32> %mask, <i32 -1, i32 -1>
92 define <2 x i32> @dec_mask_neg_v2i32_poison(<2 x i32> %X) {
93 ; CHECK-LABEL: @dec_mask_neg_v2i32_poison(
94 ; CHECK-NEXT: [[TMP1:%.*]] = add <2 x i32> [[X:%.*]], splat (i32 -1)
95 ; CHECK-NEXT: [[TMP2:%.*]] = xor <2 x i32> [[X]], splat (i32 -1)
96 ; CHECK-NEXT: [[DEC:%.*]] = and <2 x i32> [[TMP1]], [[TMP2]]
97 ; CHECK-NEXT: ret <2 x i32> [[DEC]]
99 %neg = sub <2 x i32> zeroinitializer, %X
100 %mask = and <2 x i32> %neg, %X
101 %dec = add <2 x i32> %mask, <i32 -1, i32 poison>
105 define <2 x i32> @dec_mask_multiuse_neg_multiuse_v2i32(<2 x i32> %X) {
106 ; CHECK-LABEL: @dec_mask_multiuse_neg_multiuse_v2i32(
107 ; CHECK-NEXT: [[NEG:%.*]] = sub <2 x i32> zeroinitializer, [[X:%.*]]
108 ; CHECK-NEXT: [[MASK:%.*]] = and <2 x i32> [[X]], [[NEG]]
109 ; CHECK-NEXT: [[DEC:%.*]] = add <2 x i32> [[MASK]], splat (i32 -1)
110 ; CHECK-NEXT: call void @usev(<2 x i32> [[NEG]])
111 ; CHECK-NEXT: call void @usev(<2 x i32> [[MASK]])
112 ; CHECK-NEXT: ret <2 x i32> [[DEC]]
114 %neg = sub <2 x i32> zeroinitializer, %X
115 %mask = and <2 x i32> %neg, %X
116 %dec = add <2 x i32> %mask, <i32 -1, i32 -1>
117 call void @usev(<2 x i32> %neg)
118 call void @usev(<2 x i32> %mask)
122 declare void @use(i32)
123 declare void @usev(<2 x i32>)