Index: llvm/trunk/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp =================================================================== --- llvm/trunk/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp +++ llvm/trunk/lib/Transforms/InstCombine/InstCombineSimplifyDemanded.cpp @@ -1260,17 +1260,35 @@ break; } case Instruction::Select: { + // If this is a vector select, try to transform the select condition based + // on the current demanded elements. SelectInst *Sel = cast(I); - Value *Cond = Sel->getCondition(); + if (Sel->getCondition()->getType()->isVectorTy()) { + // TODO: We are not doing anything with UndefElts based on this call. + // It is overwritten below based on the other select operands. If an + // element of the select condition is known undef, then we are free to + // choose the output value from either arm of the select. If we know that + // one of those values is undef, then the output can be undef. + if (Value *V = SimplifyDemandedVectorElts(Sel->getCondition(), + DemandedElts, UndefElts, + Depth + 1)) { + Sel->setCondition(V); + MadeChange = true; + } + } + // Next, see if we can transform the arms of the select. APInt DemandedLHS(DemandedElts), DemandedRHS(DemandedElts); - if (auto *CV = dyn_cast(Cond)) { + if (auto *CV = dyn_cast(Sel->getCondition())) { for (unsigned i = 0; i < VWidth; i++) { // isNullValue() always returns false when called on a ConstantExpr. // Skip constant expressions to avoid propagating incorrect information. Constant *CElt = CV->getAggregateElement(i); if (isa(CElt)) continue; + // TODO: If a select condition element is undef, we can demand from + // either side. If one side is known undef, choosing that side would + // propagate undef. if (CElt->isNullValue()) DemandedLHS.clearBit(i); else @@ -1291,6 +1309,7 @@ } // Output elements are undefined if the element from each arm is undefined. + // TODO: This can be improved. See comment in select condition handling. UndefElts = UndefElts2 & UndefElts3; break; } Index: llvm/trunk/test/Transforms/InstCombine/shuffle-select-narrow.ll =================================================================== --- llvm/trunk/test/Transforms/InstCombine/shuffle-select-narrow.ll +++ llvm/trunk/test/Transforms/InstCombine/shuffle-select-narrow.ll @@ -16,13 +16,13 @@ ret <2 x i8> %r } -; TODO: The 1st shuffle is not extending with undefs, but demanded elements should correct that. +; The 1st shuffle is not extending with undefs, but demanded elements corrects that. define <2 x i8> @narrow_shuffle_of_select_overspecified_extend(<2 x i1> %cmp, <4 x i8> %x, <4 x i8> %y) { ; CHECK-LABEL: @narrow_shuffle_of_select_overspecified_extend( -; CHECK-NEXT: [[WIDECMP:%.*]] = shufflevector <2 x i1> [[CMP:%.*]], <2 x i1> undef, <4 x i32> -; CHECK-NEXT: [[WIDESEL:%.*]] = select <4 x i1> [[WIDECMP]], <4 x i8> [[X:%.*]], <4 x i8> [[Y:%.*]] -; CHECK-NEXT: [[R:%.*]] = shufflevector <4 x i8> [[WIDESEL]], <4 x i8> undef, <2 x i32> +; CHECK-NEXT: [[TMP1:%.*]] = shufflevector <4 x i8> [[X:%.*]], <4 x i8> undef, <2 x i32> +; CHECK-NEXT: [[TMP2:%.*]] = shufflevector <4 x i8> [[Y:%.*]], <4 x i8> undef, <2 x i32> +; CHECK-NEXT: [[R:%.*]] = select <2 x i1> [[CMP:%.*]], <2 x i8> [[TMP1]], <2 x i8> [[TMP2]] ; CHECK-NEXT: ret <2 x i8> [[R]] ; %widecmp = shufflevector <2 x i1> %cmp, <2 x i1> undef, <4 x i32> @@ -102,7 +102,7 @@ define <3 x i8> @narrow_shuffle_of_select_mismatch_types2(<4 x i1> %cmp, <6 x i8> %x, <6 x i8> %y) { ; CHECK-LABEL: @narrow_shuffle_of_select_mismatch_types2( -; CHECK-NEXT: [[WIDECMP:%.*]] = shufflevector <4 x i1> [[CMP:%.*]], <4 x i1> undef, <6 x i32> +; CHECK-NEXT: [[WIDECMP:%.*]] = shufflevector <4 x i1> [[CMP:%.*]], <4 x i1> undef, <6 x i32> ; CHECK-NEXT: [[WIDESEL:%.*]] = select <6 x i1> [[WIDECMP]], <6 x i8> [[X:%.*]], <6 x i8> [[Y:%.*]] ; CHECK-NEXT: [[R:%.*]] = shufflevector <6 x i8> [[WIDESEL]], <6 x i8> undef, <3 x i32> ; CHECK-NEXT: ret <3 x i8> [[R]]