Index: llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -1904,29 +1904,42 @@ return new ZExtInst(NewBO, Ty); } } + } + if (match(Op1, m_Power2())) { Constant *C1, *C2; - const APInt *C3 = C; + Constant *C3 = cast(Op1); Value *X; - if (C3->isPowerOf2() && - match(Op0, m_OneUse(m_LShr(m_Shl(m_ImmConstant(C1), m_Value(X)), + Constant *Log2C3 = ConstantExpr::getExactLogBase2(C3); + if (match(Op0, m_OneUse(m_LShr(m_Shl(m_ImmConstant(C1), m_Value(X)), m_ImmConstant(C2)))) && match(C1, m_Power2())) { Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1); - Constant *Log2C3 = ConstantInt::get(Ty, C3->countTrailingZeros()); Constant *LshrC = ConstantExpr::getAdd(C2, Log2C3); KnownBits KnownLShrc = computeKnownBits(LshrC, 0, nullptr); + unsigned Width = Ty->getScalarSizeInBits(); if (KnownLShrc.getMaxValue().ult(Width)) { // iff C1,C3 is pow2 and C2 + cttz(C3) < BitWidth: // ((C1 << X) >> C2) & C3 -> X == (cttz(C3)+C2-cttz(C1)) ? C3 : 0 Constant *CmpC = ConstantExpr::getSub(LshrC, Log2C1); Value *Cmp = Builder.CreateICmpEQ(X, CmpC); - return SelectInst::Create(Cmp, ConstantInt::get(Ty, *C3), - ConstantInt::getNullValue(Ty)); + return SelectInst::Create(Cmp, C3, ConstantInt::getNullValue(Ty)); + } + } + + if (match(Op0, m_OneUse(m_Shl(m_LShr(m_ImmConstant(C1), m_Value(X)), + m_ImmConstant(C2)))) && + match(C1, m_Power2())) { + Constant *Log2C1 = ConstantExpr::getExactLogBase2(C1); + Constant *Cmp = ConstantExpr::getCompare(ICmpInst::ICMP_ULT, Log2C3, C2); + if (Cmp->isZeroValue()) { + // iff C1,C3 is pow2 and Log2(C3) >= C2: + // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0 + Constant *ShlC = ConstantExpr::getAdd(C2, Log2C1); + Constant *CmpC = ConstantExpr::getSub(ShlC, Log2C3); + Value *Cmp = Builder.CreateICmpEQ(X, CmpC); + return SelectInst::Create(Cmp, C3, ConstantInt::getNullValue(Ty)); } - // TODO: Symmetrical case - // iff C1,C3 is pow2 and Log2(C3) >= C2: - // ((C1 >> X) << C2) & C3 -> X == (cttz(C1)+C2-cttz(C3)) ? C3 : 0 } } Index: llvm/test/Transforms/InstCombine/and.ll =================================================================== --- llvm/test/Transforms/InstCombine/and.ll +++ llvm/test/Transforms/InstCombine/and.ll @@ -1814,9 +1814,8 @@ define <3 x i16> @shl_lshr_pow2_const_case1_non_uniform_vec(<3 x i16> %x) { ; CHECK-LABEL: @shl_lshr_pow2_const_case1_non_uniform_vec( -; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> , [[X:%.*]] -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[LSHR]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> , <3 x i16> zeroinitializer ; CHECK-NEXT: ret <3 x i16> [[R]] ; %shl = shl <3 x i16> , %x @@ -1865,9 +1864,8 @@ define <3 x i16> @shl_lshr_pow2_const_case1_undef3_vec(<3 x i16> %x) { ; CHECK-LABEL: @shl_lshr_pow2_const_case1_undef3_vec( -; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> , [[X:%.*]] -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> [[SHL]], -; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[LSHR]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> , <3 x i16> zeroinitializer ; CHECK-NEXT: ret <3 x i16> [[R]] ; %shl = shl <3 x i16> , %x @@ -2066,9 +2064,8 @@ define i16 @lshr_shl_pow2_const_case2(i16 %x) { ; CHECK-LABEL: @lshr_shl_pow2_const_case2( -; CHECK-NEXT: [[LSHR1:%.*]] = lshr i16 8192, [[X:%.*]] -; CHECK-NEXT: [[SHL:%.*]] = shl i16 [[LSHR1]], 4 -; CHECK-NEXT: [[R:%.*]] = and i16 [[SHL]], 32 +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq i16 [[X:%.*]], 12 +; CHECK-NEXT: [[R:%.*]] = select i1 [[TMP1]], i16 32, i16 0 ; CHECK-NEXT: ret i16 [[R]] ; %lshr1 = lshr i16 8192, %x @@ -2106,9 +2103,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_uniform_vec(<3 x i16> %x) { ; CHECK-LABEL: @lshr_shl_pow2_const_case1_uniform_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> , [[X:%.*]] -; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> , <3 x i16> zeroinitializer ; CHECK-NEXT: ret <3 x i16> [[R]] ; %lshr = lshr <3 x i16> , %x @@ -2119,9 +2115,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_non_uniform_vec(<3 x i16> %x) { ; CHECK-LABEL: @lshr_shl_pow2_const_case1_non_uniform_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> , [[X:%.*]] -; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> , <3 x i16> zeroinitializer ; CHECK-NEXT: ret <3 x i16> [[R]] ; %lshr = lshr <3 x i16> , %x @@ -2145,9 +2140,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_undef1_vec(<3 x i16> %x) { ; CHECK-LABEL: @lshr_shl_pow2_const_case1_undef1_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> , [[X:%.*]] -; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> , <3 x i16> zeroinitializer ; CHECK-NEXT: ret <3 x i16> [[R]] ; %lshr = lshr <3 x i16> , %x @@ -2158,9 +2152,8 @@ define <3 x i16> @lshr_shl_pow2_const_case1_undef2_vec(<3 x i16> %x) { ; CHECK-LABEL: @lshr_shl_pow2_const_case1_undef2_vec( -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i16> , [[X:%.*]] -; CHECK-NEXT: [[SHL:%.*]] = shl <3 x i16> [[LSHR]], -; CHECK-NEXT: [[R:%.*]] = and <3 x i16> [[SHL]], +; CHECK-NEXT: [[TMP1:%.*]] = icmp eq <3 x i16> [[X:%.*]], +; CHECK-NEXT: [[R:%.*]] = select <3 x i1> [[TMP1]], <3 x i16> , <3 x i16> zeroinitializer ; CHECK-NEXT: ret <3 x i16> [[R]] ; %lshr = lshr <3 x i16> , %x