Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1885,6 +1885,42 @@ return new ZExtInst(And, Ty); } } + + const APInt *C1; + const APInt *C2; + Value *X; + if (C->isPowerOf2()) { + if (match(Op0, m_OneUse(m_LShr(m_Shl(m_APInt(C1), m_Value(X)), + m_APInt(C2)))) && + C1->isPowerOf2()) { + unsigned Log2C1 = C1->countTrailingZeros(); + unsigned Log2C = C->countTrailingZeros(); + unsigned LShrEqBits = Log2C + C2->getZExtValue(); + if (LShrEqBits >= Log2C1 && LShrEqBits < Width) { + // iff C,C1 is pow2 and Log2(C1) < Log2(C)+C2 < BitWidth: + // ((C1 << X) >> C2) & C -> X == (Log2(C)+C2-Log2(C1)) ? C : 0 + unsigned CmpC = LShrEqBits - Log2C1; + Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, CmpC)); + return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C), + ConstantInt::getNullValue(Ty)); + } + } + if (match(Op0, m_OneUse(m_LShr(m_LShr(m_APInt(C1), m_Value(X)), + m_APInt(C2)))) && + C1->isPowerOf2()) { + unsigned Log2C1 = C1->countTrailingZeros(); + unsigned Log2C = C->countTrailingZeros(); + unsigned LShrEqBits = Log2C + C2->getZExtValue(); + if (LShrEqBits < Log2C1) { + // iff C,C1 is pow2 and Log2(C)+C2 < Log2(C1): + // ((C1 >> X) >> C2) & C -> X == (Log2(C1)-Log2(C)-C2) ? C : 0 + unsigned CmpC = Log2C1 - LShrEqBits; + Value *Cmp = Builder.CreateICmpEQ(X, ConstantInt::get(Ty, CmpC)); + return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C), + ConstantInt::getNullValue(Ty)); + } + } + } } if (match(&I, m_And(m_OneUse(m_Shl(m_ZExt(m_Value(X)), m_Value(Y))), Index: llvm/test/Transforms/InstCombine/and.ll =================================================================== --- llvm/test/Transforms/InstCombine/and.ll +++ llvm/test/Transforms/InstCombine/and.ll @@ -1624,9 +1624,8 @@ define i16 @shl_lshr_pow2_const(i16 %x) { ; CHECK-LABEL: @shl_lshr_pow2_const( -; CHECK-NEXT: [[SHL:%.*]] = shl i16 4, [[X:%.*]] -; CHECK-NEXT: [[LSHR:%.*]] = lshr i16 [[SHL]], 6 -; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR]], 8 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 7 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i16 8, i16 0 ; CHECK-NEXT: ret i16 [[R]] ; %shl = shl i16 4, %x @@ -1699,9 +1698,8 @@ define i16 @lshr_lshr_pow2_const(i16 %x) { ; CHECK-LABEL: @lshr_lshr_pow2_const( -; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 2048, [[X:%.*]] -; CHECK-NEXT: [[LSHR2:%.*]] = lshr i16 [[LSHR1]], 6 -; CHECK-NEXT: [[R:%.*]] = and i16 [[LSHR2]], 4 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 3 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i16 4, i16 0 ; CHECK-NEXT: ret i16 [[R]] ; %lshr1 = lshr i16 2048, %x