diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -2343,7 +2343,12 @@ // The bitcasts will either all exist or all not exist. The builder will // not create unnecessary casts if the types already match. Type *SelTy = A->getType(); - if (auto *VecTy = dyn_cast(Cond->getType())) { + auto *VecTy = dyn_cast(Cond->getType()); + // Check whether we have to cast. + if (VecTy && VecTy != C->getType()) { + // If we do have to cast, we must avoid scalable vectors here. + if (VecTy->getElementCount().isScalable()) + return nullptr; unsigned Elts = VecTy->getElementCount().getKnownMinValue(); Type *EltTy = Builder.getIntNTy(SelTy->getPrimitiveSizeInBits() / Elts); SelTy = VectorType::get(EltTy, VecTy->getElementCount()); diff --git a/llvm/test/Transforms/InstCombine/logical-select.ll b/llvm/test/Transforms/InstCombine/logical-select.ll --- a/llvm/test/Transforms/InstCombine/logical-select.ll +++ b/llvm/test/Transforms/InstCombine/logical-select.ll @@ -471,6 +471,18 @@ ret <4 x i1> %or } +define @vec_of_bools_scalable( %a, %c, %d) { +; CHECK-LABEL: @vec_of_bools_scalable( +; CHECK-NEXT: [[TMP1:%.*]] = select [[A:%.*]], [[C:%.*]], [[D:%.*]] +; CHECK-NEXT: ret [[TMP1]] +; + %b = xor %a, shufflevector ( insertelement ( poison, i1 true, i32 0), poison, zeroinitializer) + %t11 = and %a, %c + %t12 = and %b, %d + %r = or %t11, %t12 + ret %r +} + define i4 @vec_of_casted_bools(i4 %a, i4 %b, <4 x i1> %c) { ; CHECK-LABEL: @vec_of_casted_bools( ; CHECK-NEXT: [[TMP1:%.*]] = bitcast i4 [[B:%.*]] to <4 x i1> @@ -488,6 +500,31 @@ ret i4 %or } +; Negative test - we can't create the correct scalable vector casts + +define @vec_of_casted_bools_scalable( %a, %b, %cond) { +; CHECK-LABEL: @vec_of_casted_bools_scalable( +; CHECK-NEXT: [[SCOND:%.*]] = sext [[COND:%.*]] to +; CHECK-NEXT: [[NOTCOND:%.*]] = xor [[COND]], shufflevector ( insertelement ( poison, i1 true, i32 0), poison, zeroinitializer) +; CHECK-NEXT: [[SNOTCOND:%.*]] = sext [[NOTCOND]] to +; CHECK-NEXT: [[BC1:%.*]] = bitcast [[SCOND]] to +; CHECK-NEXT: [[BC2:%.*]] = bitcast [[SNOTCOND]] to +; CHECK-NEXT: [[AND1:%.*]] = and [[BC1]], [[A:%.*]] +; CHECK-NEXT: [[AND2:%.*]] = and [[BC2]], [[B:%.*]] +; CHECK-NEXT: [[OR:%.*]] = or [[AND1]], [[AND2]] +; CHECK-NEXT: ret [[OR]] +; + %scond = sext %cond to + %notcond = xor %cond, shufflevector ( insertelement ( poison, i1 true, i32 0), poison, zeroinitializer) + %snotcond = sext %notcond to + %bc1 = bitcast %scond to + %bc2 = bitcast %snotcond to + %and1 = and %a, %bc1 + %and2 = and %bc2, %b + %or = or %and1, %and2 + ret %or +} + ; Inverted 'and' constants mean this is a select which is canonicalized to a shuffle. define <4 x i32> @vec_sel_consts(<4 x i32> %a, <4 x i32> %b) {