1; NOTE: Assertions have been autogenerated by utils/update_test_checks.py 2; RUN: opt < %s -passes=instcombine -S | FileCheck %s 3 4; 5; (A & 2^C1) + A => A & (2^C1 - 1) iff bit C1 in A is a sign bit 6; 7 8define i32 @add_mask_sign_i32(i32 %x) { 9; CHECK-LABEL: @add_mask_sign_i32( 10; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0 11; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNEG]], i32 7, i32 0 12; CHECK-NEXT: ret i32 [[R]] 13; 14 %a = ashr i32 %x, 31 15 %m = and i32 %a, 8 16 %r = add i32 %m, %a 17 ret i32 %r 18} 19 20define i32 @add_mask_sign_commute_i32(i32 %x) { 21; CHECK-LABEL: @add_mask_sign_commute_i32( 22; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0 23; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNEG]], i32 7, i32 0 24; CHECK-NEXT: ret i32 [[R]] 25; 26 %a = ashr i32 %x, 31 27 %m = and i32 %a, 8 28 %r = add i32 %a, %m 29 ret i32 %r 30} 31 32define <2 x i32> @add_mask_sign_v2i32(<2 x i32> %x) { 33; CHECK-LABEL: @add_mask_sign_v2i32( 34; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer 35; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> splat (i32 7), <2 x i32> zeroinitializer 36; CHECK-NEXT: ret <2 x i32> [[R]] 37; 38 %a = ashr <2 x i32> %x, <i32 31, i32 31> 39 %m = and <2 x i32> %a, <i32 8, i32 8> 40 %r = add <2 x i32> %m, %a 41 ret <2 x i32> %r 42} 43 44define <2 x i32> @add_mask_sign_v2i32_nonuniform(<2 x i32> %x) { 45; CHECK-LABEL: @add_mask_sign_v2i32_nonuniform( 46; CHECK-NEXT: [[A:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 30, i32 31> 47; CHECK-NEXT: [[M:%.*]] = and <2 x i32> [[A]], <i32 8, i32 16> 48; CHECK-NEXT: [[R:%.*]] = add <2 x i32> [[M]], [[A]] 49; CHECK-NEXT: ret <2 x i32> [[R]] 50; 51 %a = ashr <2 x i32> %x, <i32 30, i32 31> 52 %m = and <2 x i32> %a, <i32 8, i32 16> 53 %r = add <2 x i32> %m, %a 54 ret <2 x i32> %r 55} 56 57define i32 @add_mask_ashr28_i32(i32 %x) { 58; CHECK-LABEL: @add_mask_ashr28_i32( 59; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 28 60; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], 7 61; CHECK-NEXT: ret i32 [[R]] 62; 63 %a = ashr i32 %x, 28 64 %m = and i32 %a, 8 65 %r = add i32 %m, %a 66 ret i32 %r 67} 68 69; negative case - mask isn't pow2 70define i32 @add_mask_ashr28_non_pow2_i32(i32 %x) { 71; CHECK-LABEL: @add_mask_ashr28_non_pow2_i32( 72; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 28 73; CHECK-NEXT: [[M:%.*]] = and i32 [[A]], 9 74; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[M]], [[A]] 75; CHECK-NEXT: ret i32 [[R]] 76; 77 %a = ashr i32 %x, 28 78 %m = and i32 %a, 9 79 %r = add i32 %m, %a 80 ret i32 %r 81} 82 83; negative case - insufficient sign bits 84define i32 @add_mask_ashr27_i32(i32 %x) { 85; CHECK-LABEL: @add_mask_ashr27_i32( 86; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 27 87; CHECK-NEXT: [[M:%.*]] = and i32 [[A]], 8 88; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[M]], [[A]] 89; CHECK-NEXT: ret i32 [[R]] 90; 91 %a = ashr i32 %x, 27 92 %m = and i32 %a, 8 93 %r = add i32 %m, %a 94 ret i32 %r 95} 96