124 lines · plain
1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py2; RUN: opt < %s -S -passes=instcombine | FileCheck %s3 4;5; Canonicalize ((X & -X) - 1) --> ((X - 1) & ~X)6;7 8define i32 @dec_mask_neg_i32(i32 %X) {9; CHECK-LABEL: @dec_mask_neg_i32(10; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -111; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -112; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]]13; CHECK-NEXT: ret i32 [[DEC]]14;15 %neg = sub i32 0, %X16 %mask = and i32 %neg, %X17 %dec = add i32 %mask, -118 ret i32 %dec19}20 21define 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]], -125; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -126; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]]27; CHECK-NEXT: ret i32 [[DEC]]28;29 %X = sdiv i32 42, %A ; thwart complexity-based canonicalization30 %neg = sub i32 0, %X31 %mask = and i32 %X, %neg32 %dec = add i32 %mask, -133 ret i32 %dec34}35 36define i32 @dec_commute_mask_neg_i32(i32 %X) {37; CHECK-LABEL: @dec_commute_mask_neg_i32(38; CHECK-NEXT: [[TMP1:%.*]] = add i32 [[X:%.*]], -139; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -140; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]]41; CHECK-NEXT: ret i32 [[DEC]]42;43 %neg = sub i32 0, %X44 %mask = and i32 %neg, %X45 %dec = add i32 -1, %mask46 ret i32 %dec47}48 49define 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]], -154; CHECK-NEXT: call void @use(i32 [[NEG]])55; CHECK-NEXT: ret i32 [[DEC]]56;57 %neg = sub i32 0, %X58 %mask = and i32 %neg, %X59 %dec = add i32 %mask, -160 call void @use(i32 %neg)61 ret i32 %dec62}63 64define 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]], -169; CHECK-NEXT: call void @use(i32 [[MASK]])70; CHECK-NEXT: ret i32 [[DEC]]71;72 %neg = sub i32 0, %X73 %mask = and i32 %neg, %X74 %dec = add i32 %mask, -175 call void @use(i32 %mask)76 ret i32 %dec77}78 79define <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]]85;86 %neg = sub <2 x i32> zeroinitializer, %X87 %mask = and <2 x i32> %neg, %X88 %dec = add <2 x i32> %mask, <i32 -1, i32 -1>89 ret <2 x i32> %dec90}91 92define <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]]98;99 %neg = sub <2 x i32> zeroinitializer, %X100 %mask = and <2 x i32> %neg, %X101 %dec = add <2 x i32> %mask, <i32 -1, i32 poison>102 ret <2 x i32> %dec103}104 105define <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]]113;114 %neg = sub <2 x i32> zeroinitializer, %X115 %mask = and <2 x i32> %neg, %X116 %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)119 ret <2 x i32> %dec120}121 122declare void @use(i32)123declare void @usev(<2 x i32>)124