Index: llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp =================================================================== --- llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp +++ llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp @@ -1067,28 +1067,31 @@ return new ZExtInst(NewLShr, Ty); } - if (match(Op0, m_SExt(m_Value(X))) && - (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) { - // Are we moving the sign bit to the low bit and widening with high zeros? + if (match(Op0, m_SExt(m_Value(X)))) { unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits(); - if (ShAmtC == BitWidth - 1) { - // lshr (sext i1 X to iN), N-1 --> zext X to iN - if (SrcTyBitWidth == 1) - return new ZExtInst(X, Ty); + // lshr (sext i1 X to iN), C --> select (X, -1 >> C, 0) + if (SrcTyBitWidth == 1) { + auto *NewC = ConstantInt::get( + Ty, APInt::getLowBitsSet(BitWidth, BitWidth - ShAmtC)); + return SelectInst::Create(X, NewC, ConstantInt::getNullValue(Ty)); + } - // lshr (sext iM X to iN), N-1 --> zext (lshr X, M-1) to iN - if (Op0->hasOneUse()) { + if ((!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType())) && + Op0->hasOneUse()) { + // Are we moving the sign bit to the low bit and widening with high + // zeros? lshr (sext iM X to iN), N-1 --> zext (lshr X, M-1) to iN + if (ShAmtC == BitWidth - 1) { Value *NewLShr = Builder.CreateLShr(X, SrcTyBitWidth - 1); return new ZExtInst(NewLShr, Ty); } - } - // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN - if (ShAmtC == BitWidth - SrcTyBitWidth && Op0->hasOneUse()) { - // The new shift amount can't be more than the narrow source type. - unsigned NewShAmt = std::min(ShAmtC, SrcTyBitWidth - 1); - Value *AShr = Builder.CreateAShr(X, NewShAmt); - return new ZExtInst(AShr, Ty); + // lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN + if (ShAmtC == BitWidth - SrcTyBitWidth) { + // The new shift amount can't be more than the narrow source type. + unsigned NewShAmt = std::min(ShAmtC, SrcTyBitWidth - 1); + Value *AShr = Builder.CreateAShr(X, NewShAmt); + return new ZExtInst(AShr, Ty); + } } } Index: llvm/test/Transforms/InstCombine/lshr.ll =================================================================== --- llvm/test/Transforms/InstCombine/lshr.ll +++ llvm/test/Transforms/InstCombine/lshr.ll @@ -607,8 +607,7 @@ define i16 @lshr_sext_i1_to_i16(i1 %a) { ; CHECK-LABEL: @lshr_sext_i1_to_i16( -; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i16 -; CHECK-NEXT: [[LSHR:%.*]] = lshr i16 [[SEXT]], 4 +; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i16 4095, i16 0 ; CHECK-NEXT: ret i16 [[LSHR]] ; %sext = sext i1 %a to i16 @@ -618,8 +617,7 @@ define i128 @lshr_sext_i1_to_i128(i1 %a) { ; CHECK-LABEL: @lshr_sext_i1_to_i128( -; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i128 -; CHECK-NEXT: [[LSHR:%.*]] = lshr i128 [[SEXT]], 42 +; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i128 77371252455336267181195263, i128 0 ; CHECK-NEXT: ret i128 [[LSHR]] ; %sext = sext i1 %a to i128 @@ -631,7 +629,7 @@ ; CHECK-LABEL: @lshr_sext_i1_to_i32_use( ; CHECK-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i32 ; CHECK-NEXT: call void @use(i32 [[SEXT]]) -; CHECK-NEXT: [[LSHR:%.*]] = lshr i32 [[SEXT]], 14 +; CHECK-NEXT: [[LSHR:%.*]] = select i1 [[A]], i32 262143, i32 0 ; CHECK-NEXT: ret i32 [[LSHR]] ; %sext = sext i1 %a to i32 @@ -644,7 +642,7 @@ ; CHECK-LABEL: @lshr_sext_i1_to_i14_splat_vec_use1( ; CHECK-NEXT: [[SEXT:%.*]] = sext <3 x i1> [[A:%.*]] to <3 x i14> ; CHECK-NEXT: call void @usevec(<3 x i14> [[SEXT]]) -; CHECK-NEXT: [[LSHR:%.*]] = lshr <3 x i14> [[SEXT]], +; CHECK-NEXT: [[LSHR:%.*]] = select <3 x i1> [[A]], <3 x i14> , <3 x i14> zeroinitializer ; CHECK-NEXT: ret <3 x i14> [[LSHR]] ; %sext = sext <3 x i1> %a to <3 x i14> Index: llvm/test/Transforms/PhaseOrdering/pr52078.ll =================================================================== --- llvm/test/Transforms/PhaseOrdering/pr52078.ll +++ llvm/test/Transforms/PhaseOrdering/pr52078.ll @@ -11,8 +11,7 @@ ; IC-NEXT: ret i16 [[TRUNC]] ; ; AIC_AND_IC-LABEL: @foo( -; AIC_AND_IC-NEXT: [[SEXT:%.*]] = sext i1 [[A:%.*]] to i16 -; AIC_AND_IC-NEXT: [[LSHR:%.*]] = lshr i16 [[SEXT]], 1 +; AIC_AND_IC-NEXT: [[LSHR:%.*]] = select i1 [[A:%.*]], i16 32767, i16 0 ; AIC_AND_IC-NEXT: ret i16 [[LSHR]] ; %sext = sext i1 %a to i16