Index: lib/Transforms/InstCombine/InstCombineSelect.cpp =================================================================== --- lib/Transforms/InstCombine/InstCombineSelect.cpp +++ lib/Transforms/InstCombine/InstCombineSelect.cpp @@ -956,32 +956,43 @@ return BinaryOperator::CreateOr(TrueVal, FalseVal); } - // Selecting between two integer constants? - if (ConstantInt *TrueValC = dyn_cast(TrueVal)) - if (ConstantInt *FalseValC = dyn_cast(FalseVal)) { - // select C, 1, 0 -> zext C to int - if (FalseValC->isZero() && TrueValC->getValue() == 1) - return new ZExtInst(CondVal, SI.getType()); - - // select C, -1, 0 -> sext C to int - if (FalseValC->isZero() && TrueValC->isAllOnesValue()) - return new SExtInst(CondVal, SI.getType()); - - // select C, 0, 1 -> zext !C to int - if (TrueValC->isZero() && FalseValC->getValue() == 1) { - Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName()); - return new ZExtInst(NotCond, SI.getType()); - } - - // select C, 0, -1 -> sext !C to int - if (TrueValC->isZero() && FalseValC->isAllOnesValue()) { - Value *NotCond = Builder->CreateNot(CondVal, "not."+CondVal->getName()); - return new SExtInst(NotCond, SI.getType()); - } + // Selecting between two integer or vector splat integer constants? + // + // Note that we don't handle a scalar select of vectors: + // select i1 %c, <2 x i8> <1, 1>, <2 x i8> <0, 0> + // because that may need 3 instructions to splat the condition value: + // extend, insertelement, shufflevector. + const APInt *TrueC, *FalseC; + if (match(TrueVal, m_APInt(TrueC)) && match(FalseVal, m_APInt(FalseC)) && + (CondVal->getType()->isVectorTy() == SI.getType()->isVectorTy())) { + assert(!SI.getType()->getScalarType()->isIntegerTy(1) && + "Bool operands should already be handled"); + + // select C, 1, 0 -> zext C to int + if (*FalseC == 0 && *TrueC == 1) + return new ZExtInst(CondVal, SI.getType()); + + // select C, -1, 0 -> sext C to int + if (*FalseC == 0 && TrueC->isAllOnesValue()) + return new SExtInst(CondVal, SI.getType()); + + // select C, 0, 1 -> zext !C to int + if (*TrueC == 0 && *FalseC == 1) { + Value *NotCond = Builder->CreateNot(CondVal, "not." + CondVal->getName()); + return new ZExtInst(NotCond, SI.getType()); + } + // select C, 0, -1 -> sext !C to int + if (*TrueC == 0 && FalseC->isAllOnesValue()) { + Value *NotCond = Builder->CreateNot(CondVal, "not." + CondVal->getName()); + return new SExtInst(NotCond, SI.getType()); + } + } + + if (ConstantInt *TrueValC = dyn_cast(TrueVal)) + if (ConstantInt *FalseValC = dyn_cast(FalseVal)) if (Value *V = foldSelectICmpAnd(SI, TrueValC, FalseValC, Builder)) return replaceInstUsesWith(SI, V); - } // See if we are selecting two values based on a comparison of the two values. if (FCmpInst *FCI = dyn_cast(CondVal)) { Index: test/Transforms/InstCombine/apint-select.ll =================================================================== --- test/Transforms/InstCombine/apint-select.ll +++ test/Transforms/InstCombine/apint-select.ll @@ -41,11 +41,11 @@ ret i999 %V } -; FIXME: Vector selects of vector splat constants match APInt too. +; Vector selects of vector splat constants match APInt too. define <2 x i41> @zext_vec(<2 x i1> %C) { ; CHECK-LABEL: @zext_vec( -; CHECK-NEXT: [[V:%.*]] = select <2 x i1> %C, <2 x i41> , <2 x i41> zeroinitializer +; CHECK-NEXT: [[V:%.*]] = zext <2 x i1> %C to <2 x i41> ; CHECK-NEXT: ret <2 x i41> [[V]] ; %V = select <2 x i1> %C, <2 x i41> , <2 x i41> @@ -54,7 +54,7 @@ define <2 x i32> @sext_vec(<2 x i1> %C) { ; CHECK-LABEL: @sext_vec( -; CHECK-NEXT: [[V:%.*]] = select <2 x i1> %C, <2 x i32> , <2 x i32> zeroinitializer +; CHECK-NEXT: [[V:%.*]] = sext <2 x i1> %C to <2 x i32> ; CHECK-NEXT: ret <2 x i32> [[V]] ; %V = select <2 x i1> %C, <2 x i32> , <2 x i32> @@ -63,7 +63,8 @@ define <2 x i999> @not_zext_vec(<2 x i1> %C) { ; CHECK-LABEL: @not_zext_vec( -; CHECK-NEXT: [[V:%.*]] = select <2 x i1> %C, <2 x i999> zeroinitializer, <2 x i999> +; CHECK-NEXT: [[TMP1:%.*]] = zext <2 x i1> %C to <2 x i999> +; CHECK-NEXT: [[V:%.*]] = xor <2 x i999> [[TMP1]], ; CHECK-NEXT: ret <2 x i999> [[V]] ; %V = select <2 x i1> %C, <2 x i999> , <2 x i999> @@ -72,13 +73,25 @@ define <2 x i64> @not_sext_vec(<2 x i1> %C) { ; CHECK-LABEL: @not_sext_vec( -; CHECK-NEXT: [[V:%.*]] = select <2 x i1> %C, <2 x i64> zeroinitializer, <2 x i64> +; CHECK-NEXT: [[NOT_C:%.*]] = xor <2 x i1> %C, +; CHECK-NEXT: [[V:%.*]] = sext <2 x i1> [[NOT_C]] to <2 x i64> ; CHECK-NEXT: ret <2 x i64> [[V]] ; %V = select <2 x i1> %C, <2 x i64> , <2 x i64> ret <2 x i64> %V } +; But don't touch this - we would need 3 instructions to extend and splat the scalar select condition. + +define <2 x i32> @scalar_select_of_vectors(i1 %c) { +; CHECK-LABEL: @scalar_select_of_vectors( +; CHECK-NEXT: [[V:%.*]] = select i1 %c, <2 x i32> , <2 x i32> zeroinitializer +; CHECK-NEXT: ret <2 x i32> [[V]] +; + %V = select i1 %c, <2 x i32> , <2 x i32> zeroinitializer + ret <2 x i32> %V +} + ;; (x ashr x, 31 define i41 @test3(i41 %X) {