forked from OSchip/llvm-project
[InstCombine] Fold (A & 2^C1) + A => A & (2^C1 - 1) iff bit C1 in A is a sign bit (PR21929)
Alive2: https://alive2.llvm.org/ce/z/Ygq26C This is the final missing fold to handle the modulo2 simplification: https://github.com/llvm/llvm-project/issues/22303 Fixes #22303 Differential Revision: https://reviews.llvm.org/D123374
This commit is contained in:
parent
2efccf5166
commit
ffe13960b5
|
@ -1369,6 +1369,13 @@ Instruction *InstCombinerImpl::visitAdd(BinaryOperator &I) {
|
|||
}
|
||||
}
|
||||
|
||||
// (A & 2^C1) + A => A & (2^C1 - 1) iff bit C1 in A is a sign bit
|
||||
if (match(&I, m_c_Add(m_And(m_Value(A), m_APInt(C1)), m_Deferred(A))) &&
|
||||
C1->isPowerOf2() && (ComputeNumSignBits(A) > C1->countLeadingZeros())) {
|
||||
Constant *NewMask = ConstantInt::get(RHS->getType(), *C1 - 1);
|
||||
return BinaryOperator::CreateAnd(A, NewMask);
|
||||
}
|
||||
|
||||
// A+B --> A|B iff A and B have no bits set in common.
|
||||
if (haveNoCommonBitsSet(LHS, RHS, DL, &AC, &I, &DT))
|
||||
return BinaryOperator::CreateOr(LHS, RHS);
|
||||
|
|
|
@ -7,9 +7,8 @@
|
|||
|
||||
define i32 @add_mask_sign_i32(i32 %x) {
|
||||
; CHECK-LABEL: @add_mask_sign_i32(
|
||||
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 31
|
||||
; CHECK-NEXT: [[M:%.*]] = and i32 [[A]], 8
|
||||
; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[M]], [[A]]
|
||||
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNEG]], i32 7, i32 0
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = ashr i32 %x, 31
|
||||
|
@ -20,9 +19,8 @@ define i32 @add_mask_sign_i32(i32 %x) {
|
|||
|
||||
define i32 @add_mask_sign_commute_i32(i32 %x) {
|
||||
; CHECK-LABEL: @add_mask_sign_commute_i32(
|
||||
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 31
|
||||
; CHECK-NEXT: [[M:%.*]] = and i32 [[A]], 8
|
||||
; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[A]], [[M]]
|
||||
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[R:%.*]] = select i1 [[ISNEG]], i32 7, i32 0
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = ashr i32 %x, 31
|
||||
|
@ -33,9 +31,8 @@ define i32 @add_mask_sign_commute_i32(i32 %x) {
|
|||
|
||||
define <2 x i32> @add_mask_sign_v2i32(<2 x i32> %x) {
|
||||
; CHECK-LABEL: @add_mask_sign_v2i32(
|
||||
; CHECK-NEXT: [[A:%.*]] = ashr <2 x i32> [[X:%.*]], <i32 31, i32 31>
|
||||
; CHECK-NEXT: [[M:%.*]] = and <2 x i32> [[A]], <i32 8, i32 8>
|
||||
; CHECK-NEXT: [[R:%.*]] = add nsw <2 x i32> [[M]], [[A]]
|
||||
; CHECK-NEXT: [[ISNEG:%.*]] = icmp slt <2 x i32> [[X:%.*]], zeroinitializer
|
||||
; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[ISNEG]], <2 x i32> <i32 7, i32 7>, <2 x i32> zeroinitializer
|
||||
; CHECK-NEXT: ret <2 x i32> [[R]]
|
||||
;
|
||||
%a = ashr <2 x i32> %x, <i32 31, i32 31>
|
||||
|
@ -59,9 +56,8 @@ define <2 x i32> @add_mask_sign_v2i32_nonuniform(<2 x i32> %x) {
|
|||
|
||||
define i32 @add_mask_ashr28_i32(i32 %x) {
|
||||
; CHECK-LABEL: @add_mask_ashr28_i32(
|
||||
; CHECK-NEXT: [[A:%.*]] = ashr i32 [[X:%.*]], 28
|
||||
; CHECK-NEXT: [[M:%.*]] = and i32 [[A]], 8
|
||||
; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[M]], [[A]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = lshr i32 [[X:%.*]], 28
|
||||
; CHECK-NEXT: [[R:%.*]] = and i32 [[TMP1]], 7
|
||||
; CHECK-NEXT: ret i32 [[R]]
|
||||
;
|
||||
%a = ashr i32 %x, 28
|
||||
|
|
|
@ -4,9 +4,7 @@
|
|||
; PR21929
|
||||
define i32 @modulo2(i32 %x) {
|
||||
; CHECK-LABEL: @modulo2(
|
||||
; CHECK-NEXT: [[REM_I:%.*]] = srem i32 [[X:%.*]], 2
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[REM_I]], 2
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = add nsw i32 [[TMP1]], [[REM_I]]
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = and i32 [[X:%.*]], 1
|
||||
; CHECK-NEXT: ret i32 [[RET_I]]
|
||||
;
|
||||
%rem.i = srem i32 %x, 2
|
||||
|
@ -18,9 +16,7 @@ define i32 @modulo2(i32 %x) {
|
|||
|
||||
define <2 x i32> @modulo2_vec(<2 x i32> %x) {
|
||||
; CHECK-LABEL: @modulo2_vec(
|
||||
; CHECK-NEXT: [[REM_I:%.*]] = srem <2 x i32> [[X:%.*]], <i32 2, i32 2>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[REM_I]], <i32 2, i32 2>
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = add nsw <2 x i32> [[TMP1]], [[REM_I]]
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = and <2 x i32> [[X:%.*]], <i32 1, i32 1>
|
||||
; CHECK-NEXT: ret <2 x i32> [[RET_I]]
|
||||
;
|
||||
%rem.i = srem <2 x i32> %x, <i32 2, i32 2>
|
||||
|
@ -62,9 +58,7 @@ define <2 x i32> @modulo3_vec(<2 x i32> %x) {
|
|||
|
||||
define i32 @modulo4(i32 %x) {
|
||||
; CHECK-LABEL: @modulo4(
|
||||
; CHECK-NEXT: [[REM_I:%.*]] = srem i32 [[X:%.*]], 4
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[REM_I]], 4
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = add nsw i32 [[TMP1]], [[REM_I]]
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = and i32 [[X:%.*]], 3
|
||||
; CHECK-NEXT: ret i32 [[RET_I]]
|
||||
;
|
||||
%rem.i = srem i32 %x, 4
|
||||
|
@ -76,9 +70,7 @@ define i32 @modulo4(i32 %x) {
|
|||
|
||||
define <2 x i32> @modulo4_vec(<2 x i32> %x) {
|
||||
; CHECK-LABEL: @modulo4_vec(
|
||||
; CHECK-NEXT: [[REM_I:%.*]] = srem <2 x i32> [[X:%.*]], <i32 4, i32 4>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[REM_I]], <i32 4, i32 4>
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = add nsw <2 x i32> [[TMP1]], [[REM_I]]
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = and <2 x i32> [[X:%.*]], <i32 3, i32 3>
|
||||
; CHECK-NEXT: ret <2 x i32> [[RET_I]]
|
||||
;
|
||||
%rem.i = srem <2 x i32> %x, <i32 4, i32 4>
|
||||
|
@ -120,9 +112,7 @@ define <2 x i32> @modulo7_vec(<2 x i32> %x) {
|
|||
|
||||
define i32 @modulo32(i32 %x) {
|
||||
; CHECK-LABEL: @modulo32(
|
||||
; CHECK-NEXT: [[REM_I:%.*]] = srem i32 [[X:%.*]], 32
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and i32 [[REM_I]], 32
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = add nsw i32 [[TMP1]], [[REM_I]]
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = and i32 [[X:%.*]], 31
|
||||
; CHECK-NEXT: ret i32 [[RET_I]]
|
||||
;
|
||||
%rem.i = srem i32 %x, 32
|
||||
|
@ -134,9 +124,7 @@ define i32 @modulo32(i32 %x) {
|
|||
|
||||
define <2 x i32> @modulo32_vec(<2 x i32> %x) {
|
||||
; CHECK-LABEL: @modulo32_vec(
|
||||
; CHECK-NEXT: [[REM_I:%.*]] = srem <2 x i32> [[X:%.*]], <i32 32, i32 32>
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i32> [[REM_I]], <i32 32, i32 32>
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = add nsw <2 x i32> [[TMP1]], [[REM_I]]
|
||||
; CHECK-NEXT: [[RET_I:%.*]] = and <2 x i32> [[X:%.*]], <i32 31, i32 31>
|
||||
; CHECK-NEXT: ret <2 x i32> [[RET_I]]
|
||||
;
|
||||
%rem.i = srem <2 x i32> %x, <i32 32, i32 32>
|
||||
|
|
Loading…
Reference in New Issue