diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 11a658f335e82..fc223835e3db1 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -3949,6 +3949,15 @@ Instruction *InstCombinerImpl::foldNot(BinaryOperator &I) { return &I; } + // Move a 'not' ahead of casts of a bool to enable logic reduction: + // not (bitcast (sext i1 X)) --> bitcast (sext (not i1 X)) + if (match(NotOp, m_OneUse(m_BitCast(m_OneUse(m_SExt(m_Value(X)))))) && X->getType()->isIntOrIntVectorTy(1)) { + Type *SextTy = cast(NotOp)->getSrcTy(); + Value *NotX = Builder.CreateNot(X); + Value *Sext = Builder.CreateSExt(NotX, SextTy); + return CastInst::CreateBitOrPointerCast(Sext, Ty); + } + if (auto *NotOpI = dyn_cast(NotOp)) if (sinkNotIntoLogicalOp(*NotOpI)) return &I; diff --git a/llvm/test/Transforms/InstCombine/not.ll b/llvm/test/Transforms/InstCombine/not.ll index 009649e226ec8..4bcde2c703c21 100644 --- a/llvm/test/Transforms/InstCombine/not.ll +++ b/llvm/test/Transforms/InstCombine/not.ll @@ -635,11 +635,13 @@ define i1 @not_logicalOr_not_op0_use2(i1 %x, i1 %y) { ret i1 %notor } +; canonicalize 'not' ahead of casts of a bool value + define <2 x i64> @bitcast_to_wide_elts_sext_bool(<4 x i1> %b) { ; CHECK-LABEL: @bitcast_to_wide_elts_sext_bool( -; CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[B:%.*]] to <4 x i32> -; CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i32> [[SEXT]] to <2 x i64> -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i64> [[BC]], +; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i1> [[B:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32> +; CHECK-NEXT: [[NOT:%.*]] = bitcast <4 x i32> [[TMP2]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[NOT]] ; %sext = sext <4 x i1> %b to <4 x i32> @@ -650,9 +652,9 @@ define <2 x i64> @bitcast_to_wide_elts_sext_bool(<4 x i1> %b) { define <8 x i16> @bitcast_to_narrow_elts_sext_bool(<4 x i1> %b) { ; CHECK-LABEL: @bitcast_to_narrow_elts_sext_bool( -; CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[B:%.*]] to <4 x i32> -; CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i32> [[SEXT]] to <8 x i16> -; CHECK-NEXT: [[NOT:%.*]] = xor <8 x i16> [[BC]], +; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i1> [[B:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32> +; CHECK-NEXT: [[NOT:%.*]] = bitcast <4 x i32> [[TMP2]] to <8 x i16> ; CHECK-NEXT: ret <8 x i16> [[NOT]] ; %sext = sext <4 x i1> %b to <4 x i32> @@ -663,9 +665,9 @@ define <8 x i16> @bitcast_to_narrow_elts_sext_bool(<4 x i1> %b) { define <2 x i16> @bitcast_to_vec_sext_bool(i1 %b) { ; CHECK-LABEL: @bitcast_to_vec_sext_bool( -; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[B:%.*]] to i32 -; CHECK-NEXT: [[BC:%.*]] = bitcast i32 [[SEXT]] to <2 x i16> -; CHECK-NEXT: [[NOT:%.*]] = xor <2 x i16> [[BC]], +; CHECK-NEXT: [[TMP1:%.*]] = xor i1 [[B:%.*]], true +; CHECK-NEXT: [[TMP2:%.*]] = sext i1 [[TMP1]] to i32 +; CHECK-NEXT: [[NOT:%.*]] = bitcast i32 [[TMP2]] to <2 x i16> ; CHECK-NEXT: ret <2 x i16> [[NOT]] ; %sext = sext i1 %b to i32 @@ -676,9 +678,9 @@ define <2 x i16> @bitcast_to_vec_sext_bool(i1 %b) { define i128 @bitcast_to_scalar_sext_bool(<4 x i1> %b) { ; CHECK-LABEL: @bitcast_to_scalar_sext_bool( -; CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[B:%.*]] to <4 x i32> -; CHECK-NEXT: [[BC:%.*]] = bitcast <4 x i32> [[SEXT]] to i128 -; CHECK-NEXT: [[NOT:%.*]] = xor i128 [[BC]], -1 +; CHECK-NEXT: [[TMP1:%.*]] = xor <4 x i1> [[B:%.*]], +; CHECK-NEXT: [[TMP2:%.*]] = sext <4 x i1> [[TMP1]] to <4 x i32> +; CHECK-NEXT: [[NOT:%.*]] = bitcast <4 x i32> [[TMP2]] to i128 ; CHECK-NEXT: ret i128 [[NOT]] ; %sext = sext <4 x i1> %b to <4 x i32> @@ -687,6 +689,8 @@ define i128 @bitcast_to_scalar_sext_bool(<4 x i1> %b) { ret i128 %not } +; negative test + define <2 x i4> @bitcast_to_vec_sext_bool_use1(i1 %b) { ; CHECK-LABEL: @bitcast_to_vec_sext_bool_use1( ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[B:%.*]] to i8 @@ -702,6 +706,8 @@ define <2 x i4> @bitcast_to_vec_sext_bool_use1(i1 %b) { ret <2 x i4> %not } +; negative test + define i8 @bitcast_to_scalar_sext_bool_use2(<4 x i1> %b) { ; CHECK-LABEL: @bitcast_to_scalar_sext_bool_use2( ; CHECK-NEXT: [[SEXT:%.*]] = sext <4 x i1> [[B:%.*]] to <4 x i2>