Index: lib/Transforms/InstCombine/InstCombineCasts.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCasts.cpp +++ lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -706,8 +706,9 @@ if (SimplifyDemandedInstructionBits(CI)) return &CI; - // Canonicalize trunc x to i1 -> (icmp ne (and x, 1), 0), likewise for vector. - if (DestTy->getScalarSizeInBits() == 1) { + // Canonicalize trunc x to i1 -> icmp ne (and x, 1), 0 (scalar only). + // TODO: Why is using an icmp preferable to the minimal form? + if (DestTy->getPrimitiveSizeInBits() == 1) { Constant *One = ConstantInt::get(SrcTy, 1); Src = Builder.CreateAnd(Src, One); Value *Zero = Constant::getNullValue(Src->getType()); Index: lib/Transforms/InstCombine/InstCombineCompares.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineCompares.cpp +++ lib/Transforms/InstCombine/InstCombineCompares.cpp @@ -1708,6 +1708,12 @@ if (!Cmp.isEquality()) return nullptr; + // For vectors: icmp ne (and X, 1), 0 --> trunc X to N x i1 + // TODO: We canonicalize to the longer form for scalars. Why? + if (Cmp.getPredicate() == CmpInst::ICMP_NE && Cmp.getType()->isVectorTy() && + match(Cmp.getOperand(1), m_Zero()) && match(And->getOperand(1), m_One())) + return CastInst::CreateTruncOrBitCast(And->getOperand(0), Cmp.getType()); + // X & -C == -C -> X > u ~C // X & -C != -C -> X <= u ~C // iff C is a power of 2 Index: test/Transforms/InstCombine/apint-shl-trunc.ll =================================================================== --- test/Transforms/InstCombine/apint-shl-trunc.ll +++ test/Transforms/InstCombine/apint-shl-trunc.ll @@ -27,9 +27,8 @@ define <2 x i1> @test0vec(<2 x i39> %X, <2 x i39> %A) { ; CHECK-LABEL: @test0vec( -; CHECK-NEXT: [[TMP1:%.*]] = shl <2 x i39> , [[A:%.*]] -; CHECK-NEXT: [[TMP2:%.*]] = and <2 x i39> [[TMP1]], [[X:%.*]] -; CHECK-NEXT: [[D:%.*]] = icmp ne <2 x i39> [[TMP2]], zeroinitializer +; CHECK-NEXT: [[B:%.*]] = lshr <2 x i39> [[X:%.*]], [[A:%.*]] +; CHECK-NEXT: [[D:%.*]] = trunc <2 x i39> [[B]] to <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[D]] ; %B = lshr <2 x i39> %X, %A Index: test/Transforms/InstCombine/vector-casts.ll =================================================================== --- test/Transforms/InstCombine/vector-casts.ll +++ test/Transforms/InstCombine/vector-casts.ll @@ -5,8 +5,7 @@ define <2 x i1> @trunc(<2 x i64> %a) { ; CHECK-LABEL: @trunc( -; CHECK-NEXT: [[TMP1:%.*]] = and <2 x i64> [[A:%.*]], -; CHECK-NEXT: [[T:%.*]] = icmp ne <2 x i64> [[TMP1]], zeroinitializer +; CHECK-NEXT: [[T:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[T]] ; %t = trunc <2 x i64> %a to <2 x i1> @@ -15,8 +14,7 @@ define <2 x i1> @and_cmp_is_trunc(<2 x i64> %a) { ; CHECK-LABEL: @and_cmp_is_trunc( -; CHECK-NEXT: [[T:%.*]] = and <2 x i64> [[A:%.*]], -; CHECK-NEXT: [[R:%.*]] = icmp ne <2 x i64> [[T]], zeroinitializer +; CHECK-NEXT: [[R:%.*]] = trunc <2 x i64> [[A:%.*]] to <2 x i1> ; CHECK-NEXT: ret <2 x i1> [[R]] ; %t = and <2 x i64> %a,