Index: lib/Analysis/InstructionSimplify.cpp =================================================================== --- lib/Analysis/InstructionSimplify.cpp +++ lib/Analysis/InstructionSimplify.cpp @@ -1752,24 +1752,6 @@ if (match(Op1, m_c_Or(m_Specific(Op0), m_Value()))) return Op0; - // A mask that only clears known zeros of a shifted value is a no-op. - Value *X; - 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).isNullValue()) - 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).isNullValue()) - return Op0; - } - // A & (-A) = A if A is a power of two or zero. if (match(Op0, m_Neg(m_Specific(Op1))) || match(Op1, m_Neg(m_Specific(Op0)))) { @@ -1781,6 +1763,19 @@ return Op1; } + // Perform simplification based on known bits: + // If for each bit position, either LHS or RHS is known zero -> 0 + // If for each bit position, LHS is known zero or RHS is known one -> LHS + // If for each bit position, LHS is known one or RHS is known zero -> RHS + KnownBits LHSKnown = computeKnownBits(Op0, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); + KnownBits RHSKnown = computeKnownBits(Op1, Q.DL, 0, Q.AC, Q.CxtI, Q.DT); + if ((LHSKnown.Zero | RHSKnown.Zero).isAllOnesValue()) + return Constant::getNullValue(Op0->getType()); + if ((LHSKnown.Zero | RHSKnown.One).isAllOnesValue()) + return Op0; + if ((LHSKnown.One | RHSKnown.Zero).isAllOnesValue()) + return Op1; + if (Value *V = simplifyAndOrOfICmps(Op0, Op1, true)) return V; Index: test/Transforms/InstSimplify/AndOrXor.ll =================================================================== --- test/Transforms/InstSimplify/AndOrXor.ll +++ test/Transforms/InstSimplify/AndOrXor.ll @@ -873,3 +873,28 @@ %or = or i32 %a, %nega ret i32 %or } + +define i32 @zext_masked_hi(i8 %x, i32 %y) { +; CHECK-LABEL: @zext_masked_hi( +; CHECK-NEXT: [[HI:%.*]] = and i32 %y, -256 +; CHECK-NEXT: ret i32 [[HI]] +; + %lo = zext i8 %x to i32 + %hi = and i32 %y, -256 + %or = or i32 %lo, %hi + %mask = and i32 %or, -256 + ret i32 %mask +} + +define i32 @zext_masked_lo(i8 %x, i32 %y) { +; CHECK-LABEL: @zext_masked_lo( +; CHECK-NEXT: [[LO:%.*]] = zext i8 %x to i32 +; CHECK-NEXT: ret i32 [[LO]] +; + %lo = zext i8 %x to i32 + %hi = and i32 %y, -256 + %or = or i32 %lo, %hi + %mask = and i32 %or, 255 + ret i32 %mask +} +