diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -2043,21 +2043,18 @@ if (Value *V = simplifyLogicOfAddSub(Op0, Op1, Instruction::And)) return V; - // A mask that only clears known zeros of a shifted value is a no-op. + // If all of the demanded bits are known 1 on one side, return the other. + // These bits cannot contribute to the result of the 'and' in this + // context. + // TODO: Generalize this for Op1 KnownBits? const APInt *Mask; const APInt *ShAmt; if (match(Op1, m_APInt(Mask))) { - // If all bits in the inverted and shifted mask are clear: - // and (shl X, ShAmt), Mask --> shl X, ShAmt - if (match(Op0, m_Shl(m_Value(X), m_APInt(ShAmt))) && - (~(*Mask)).lshr(*ShAmt).isZero()) - return Op0; - - // If all bits in the inverted and shifted mask are clear: - // and (lshr X, ShAmt), Mask --> lshr X, ShAmt - if (match(Op0, m_LShr(m_Value(X), m_APInt(ShAmt))) && - (~(*Mask)).shl(*ShAmt).isZero()) + KnownBits Known0 = computeKnownBits(Op0, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); + if ((Known0.Zero | *Mask).isAllOnes()) return Op0; + if ((Known0.One | ~*Mask).isAllOnes()) + return Op1; } // If we have a multiplication overflow check that is being 'and'ed with a diff --git a/llvm/test/Transforms/InstSimplify/AndOrXor.ll b/llvm/test/Transforms/InstSimplify/AndOrXor.ll --- a/llvm/test/Transforms/InstSimplify/AndOrXor.ll +++ b/llvm/test/Transforms/InstSimplify/AndOrXor.ll @@ -1106,8 +1106,7 @@ ; CHECK-LABEL: @noop_and_t0( ; CHECK-NEXT: [[A:%.*]] = shl i8 [[X:%.*]], 3 ; CHECK-NEXT: [[B:%.*]] = lshr i8 [[A]], 2 -; CHECK-NEXT: [[R:%.*]] = and i8 [[B]], 62 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 [[B]] ; %a = shl i8 %x, 3 %b = lshr i8 %a, 2 @@ -1118,8 +1117,7 @@ ; CHECK-LABEL: @noop_and_t1( ; CHECK-NEXT: [[A:%.*]] = shl i8 [[X:%.*]], 3 ; CHECK-NEXT: [[B:%.*]] = lshr i8 [[A]], 2 -; CHECK-NEXT: [[R:%.*]] = and i8 [[B]], 126 -; CHECK-NEXT: ret i8 [[R]] +; CHECK-NEXT: ret i8 [[B]] ; %a = shl i8 %x, 3 %b = lshr i8 %a, 2 @@ -1130,10 +1128,7 @@ ; hidden simplifydemandedbits constant. define i8 @noop_and_t2(i8 %x) { ; CHECK-LABEL: @noop_and_t2( -; CHECK-NEXT: [[A:%.*]] = and i8 [[X:%.*]], 2 -; CHECK-NEXT: [[B:%.*]] = or i8 [[A]], 127 -; CHECK-NEXT: [[C:%.*]] = and i8 [[B]], 62 -; CHECK-NEXT: ret i8 [[C]] +; CHECK-NEXT: ret i8 62 ; %a = and i8 %x, 2 %b = or i8 %a, 127