1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -S -passes=instcombine | FileCheck %s 3 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:%.*]], -1 11; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -1 12; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]] 13; CHECK-NEXT: ret i32 [[DEC]] 14; 15 %neg = sub i32 0, %X 16 %mask = and i32 %neg, %X 17 %dec = add i32 %mask, -1 18 ret i32 %dec 19} 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]], -1 25; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -1 26; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]] 27; CHECK-NEXT: ret i32 [[DEC]] 28; 29 %X = sdiv i32 42, %A ; thwart complexity-based canonicalization 30 %neg = sub i32 0, %X 31 %mask = and i32 %X, %neg 32 %dec = add i32 %mask, -1 33 ret i32 %dec 34} 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:%.*]], -1 39; CHECK-NEXT: [[TMP2:%.*]] = xor i32 [[X]], -1 40; CHECK-NEXT: [[DEC:%.*]] = and i32 [[TMP1]], [[TMP2]] 41; CHECK-NEXT: ret i32 [[DEC]] 42; 43 %neg = sub i32 0, %X 44 %mask = and i32 %neg, %X 45 %dec = add i32 -1, %mask 46 ret i32 %dec 47} 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]], -1 54; CHECK-NEXT: call void @use(i32 [[NEG]]) 55; CHECK-NEXT: ret i32 [[DEC]] 56; 57 %neg = sub i32 0, %X 58 %mask = and i32 %neg, %X 59 %dec = add i32 %mask, -1 60 call void @use(i32 %neg) 61 ret i32 %dec 62} 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]], -1 69; CHECK-NEXT: call void @use(i32 [[MASK]]) 70; CHECK-NEXT: ret i32 [[DEC]] 71; 72 %neg = sub i32 0, %X 73 %mask = and i32 %neg, %X 74 %dec = add i32 %mask, -1 75 call void @use(i32 %mask) 76 ret i32 %dec 77} 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, %X 87 %mask = and <2 x i32> %neg, %X 88 %dec = add <2 x i32> %mask, <i32 -1, i32 -1> 89 ret <2 x i32> %dec 90} 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, %X 100 %mask = and <2 x i32> %neg, %X 101 %dec = add <2 x i32> %mask, <i32 -1, i32 poison> 102 ret <2 x i32> %dec 103} 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, %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) 119 ret <2 x i32> %dec 120} 121 122declare void @use(i32) 123declare void @usev(<2 x i32>) 124