forked from OSchip/llvm-project
[InstCombine] lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN
This is a follow-up to https://reviews.llvm.org/D33879 / https://reviews.llvm.org/rL304939 , and was discussed in https://reviews.llvm.org/D33338. We prefer this form because a narrower shift may be cheaper, and we can more easily fold a zext than a sext. http://rise4fun.com/Alive/slVe Name: shz %s = sext i8 %x to i12 %r = lshr i12 %s, 4 => %a = ashr i8 %x, 4 %r = zext i8 %a to i12 llvm-svn: 305190
This commit is contained in:
parent
c0112ae8da
commit
2e33bbaff0
|
@ -682,11 +682,11 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||||
return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
|
return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match(Op0, m_SExt(m_Value(X)))) {
|
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?
|
// Are we moving the sign bit to the low bit and widening with high zeros?
|
||||||
unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
|
unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
|
||||||
if (ShAmt == BitWidth - 1 &&
|
if (ShAmt == BitWidth - 1) {
|
||||||
(!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
|
|
||||||
// lshr (sext i1 X to iN), N-1 --> zext X to iN
|
// lshr (sext i1 X to iN), N-1 --> zext X to iN
|
||||||
if (SrcTyBitWidth == 1)
|
if (SrcTyBitWidth == 1)
|
||||||
return new ZExtInst(X, Ty);
|
return new ZExtInst(X, Ty);
|
||||||
|
@ -698,7 +698,13 @@ Instruction *InstCombiner::visitLShr(BinaryOperator &I) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Convert to ashr+zext if the shift equals the extension amount.
|
// lshr (sext iM X to iN), N-M --> zext (ashr X, min(N-M, M-1)) to iN
|
||||||
|
if (ShAmt == BitWidth - SrcTyBitWidth && Op0->hasOneUse()) {
|
||||||
|
// The new shift amount can't be more than the narrow source type.
|
||||||
|
unsigned NewShAmt = std::min(ShAmt, SrcTyBitWidth - 1);
|
||||||
|
Value *AShr = Builder->CreateAShr(X, NewShAmt);
|
||||||
|
return new ZExtInst(AShr, Ty);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (match(Op0, m_LShr(m_Value(X), m_APInt(ShOp1)))) {
|
if (match(Op0, m_LShr(m_Value(X), m_APInt(ShOp1)))) {
|
||||||
|
|
|
@ -122,10 +122,19 @@ define <2 x i8> @bool_zext_splat(<2 x i1> %x) {
|
||||||
ret <2 x i8> %hibit
|
ret <2 x i8> %hibit
|
||||||
}
|
}
|
||||||
|
|
||||||
; FIXME: The replicated sign bits are all that's left. This could be ashr+zext.
|
define i32 @smear_sign_and_widen(i8 %x) {
|
||||||
|
|
||||||
define i16 @smear_sign_and_widen(i4 %x) {
|
|
||||||
; CHECK-LABEL: @smear_sign_and_widen(
|
; CHECK-LABEL: @smear_sign_and_widen(
|
||||||
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr i8 %x, 7
|
||||||
|
; CHECK-NEXT: [[HIBIT:%.*]] = zext i8 [[TMP1]] to i32
|
||||||
|
; CHECK-NEXT: ret i32 [[HIBIT]]
|
||||||
|
;
|
||||||
|
%sext = sext i8 %x to i32
|
||||||
|
%hibit = lshr i32 %sext, 24
|
||||||
|
ret i32 %hibit
|
||||||
|
}
|
||||||
|
|
||||||
|
define i16 @smear_sign_and_widen_should_not_change_type(i4 %x) {
|
||||||
|
; CHECK-LABEL: @smear_sign_and_widen_should_not_change_type(
|
||||||
; CHECK-NEXT: [[SEXT:%.*]] = sext i4 %x to i16
|
; CHECK-NEXT: [[SEXT:%.*]] = sext i4 %x to i16
|
||||||
; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
|
; CHECK-NEXT: [[HIBIT:%.*]] = lshr i16 [[SEXT]], 12
|
||||||
; CHECK-NEXT: ret i16 [[HIBIT]]
|
; CHECK-NEXT: ret i16 [[HIBIT]]
|
||||||
|
@ -137,8 +146,8 @@ define i16 @smear_sign_and_widen(i4 %x) {
|
||||||
|
|
||||||
define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
|
define <2 x i8> @smear_sign_and_widen_splat(<2 x i6> %x) {
|
||||||
; CHECK-LABEL: @smear_sign_and_widen_splat(
|
; CHECK-LABEL: @smear_sign_and_widen_splat(
|
||||||
; CHECK-NEXT: [[SEXT:%.*]] = sext <2 x i6> %x to <2 x i8>
|
; CHECK-NEXT: [[TMP1:%.*]] = ashr <2 x i6> %x, <i6 2, i6 2>
|
||||||
; CHECK-NEXT: [[HIBIT:%.*]] = lshr <2 x i8> [[SEXT]], <i8 2, i8 2>
|
; CHECK-NEXT: [[HIBIT:%.*]] = zext <2 x i6> [[TMP1]] to <2 x i8>
|
||||||
; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
|
; CHECK-NEXT: ret <2 x i8> [[HIBIT]]
|
||||||
;
|
;
|
||||||
%sext = sext <2 x i6> %x to <2 x i8>
|
%sext = sext <2 x i6> %x to <2 x i8>
|
||||||
|
|
Loading…
Reference in New Issue