diff --git a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineNegator.cpp @@ -185,6 +185,17 @@ return Builder.CreateAdd(X, ConstantInt::get(X->getType(), 1), I->getName() + ".neg"); break; + case Instruction::And: + Constant *ShAmt; + std::array Ops = getSortedOperandsOfBinOp(I); + // sub(0,and(lshr(X,C),1)) --> ashr(shl(X,(BW-1)-C),BW-1) + if (match(Ops[1], m_One()) && + match(Ops[0], m_LShr(m_Value(X), m_Constant(ShAmt)))) { + Constant *Ofs = ConstantInt::get(X->getType(), BitWidth - 1); + Value *NewShAmt = Builder.CreateSub(Ofs, ShAmt); + return Builder.CreateAShr(Builder.CreateShl(X, NewShAmt), Ofs); + } + break; case Instruction::AShr: case Instruction::LShr: { // Right-shift sign bit smear is negatible. diff --git a/llvm/test/Transforms/InstCombine/negated-bitmask.ll b/llvm/test/Transforms/InstCombine/negated-bitmask.ll --- a/llvm/test/Transforms/InstCombine/negated-bitmask.ll +++ b/llvm/test/Transforms/InstCombine/negated-bitmask.ll @@ -5,10 +5,9 @@ define i8 @neg_mask1_lshr(i8 %a0) { ; CHECK-LABEL: @neg_mask1_lshr( -; CHECK-NEXT: [[SHIFT:%.*]] = lshr i8 [[A0:%.*]], 3 -; CHECK-NEXT: [[MASK:%.*]] = and i8 [[SHIFT]], 1 -; CHECK-NEXT: [[NEG:%.*]] = sub nsw i8 0, [[MASK]] -; CHECK-NEXT: ret i8 [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = shl i8 [[A0:%.*]], 4 +; CHECK-NEXT: [[TMP2:%.*]] = ashr i8 [[TMP1]], 7 +; CHECK-NEXT: ret i8 [[TMP2]] ; %shift = lshr i8 %a0, 3 %mask = and i8 %shift, 1 @@ -18,10 +17,9 @@ define <4 x i32> @neg_mask1_lshr_vector_uniform(<4 x i32> %a0) { ; CHECK-LABEL: @neg_mask1_lshr_vector_uniform( -; CHECK-NEXT: [[SHIFT:%.*]] = lshr <4 x i32> [[A0:%.*]], -; CHECK-NEXT: [[MASK:%.*]] = and <4 x i32> [[SHIFT]], -; CHECK-NEXT: [[NEG:%.*]] = sub nsw <4 x i32> zeroinitializer, [[MASK]] -; CHECK-NEXT: ret <4 x i32> [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = shl <4 x i32> [[A0:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[TMP2]] ; %shift = lshr <4 x i32> %a0, %mask = and <4 x i32> %shift, @@ -31,10 +29,9 @@ define <4 x i32> @neg_mask1_lshr_vector_nonuniform(<4 x i32> %a0) { ; CHECK-LABEL: @neg_mask1_lshr_vector_nonuniform( -; CHECK-NEXT: [[SHIFT:%.*]] = lshr <4 x i32> [[A0:%.*]], -; CHECK-NEXT: [[MASK:%.*]] = and <4 x i32> [[SHIFT]], -; CHECK-NEXT: [[NEG:%.*]] = sub nsw <4 x i32> zeroinitializer, [[MASK]] -; CHECK-NEXT: ret <4 x i32> [[NEG]] +; CHECK-NEXT: [[TMP1:%.*]] = shl <4 x i32> [[A0:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = ashr <4 x i32> [[TMP1]], +; CHECK-NEXT: ret <4 x i32> [[TMP2]] ; %shift = lshr <4 x i32> %a0, %mask = and <4 x i32> %shift,