[InstCombine] fold lshr (sext X), C1 --> zext (lshr X, C2)
This was discussed in D33338. We have larger pattern-matching ending in a truncate that
we can reduce or remove by handling these smaller patterns first. Further motivation is
that narrower shift ops are easier for value tracking and zext is better than sext.
http://rise4fun.com/Alive/rhh
Name: boolshift
%sext = sext i1 %x to i8
%r = lshr i8 %sext, 7
=>
%r = zext i1 %x to i8
Name: noboolshift
%sext = sext i3 %x to i8
%r = lshr i8 %sext, 7
=>
%sh = lshr i3 %x, 2
%r = zext i3 %sh to i8
Differential Revision: https://reviews.llvm.org/D33879
llvm-svn: 304939
diff --git a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
index b40d067..dc0032b 100644
--- a/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
+++ b/llvm/lib/Transforms/InstCombine/InstCombineShifts.cpp
@@ -680,6 +680,25 @@
return BinaryOperator::CreateAnd(X, ConstantInt::get(Ty, Mask));
}
+ if (match(Op0, m_SExt(m_Value(X)))) {
+ // Are we moving the sign bit to the low bit and widening with high zeros?
+ unsigned SrcTyBitWidth = X->getType()->getScalarSizeInBits();
+ if (ShAmt == BitWidth - 1 &&
+ (!Ty->isIntegerTy() || shouldChangeType(Ty, X->getType()))) {
+ // lshr (sext i1 X to iN), N-1 --> zext X to iN
+ if (SrcTyBitWidth == 1)
+ return new ZExtInst(X, Ty);
+
+ // lshr (sext iM X to iN), N-1 --> zext (lshr X, M-1) to iN
+ if (Op0->hasOneUse()) {
+ Value *NewLShr = Builder->CreateLShr(X, SrcTyBitWidth - 1);
+ return new ZExtInst(NewLShr, Ty);
+ }
+ }
+
+ // TODO: Convert to ashr+zext if the shift equals the extension amount.
+ }
+
if (match(Op0, m_LShr(m_Value(X), m_APInt(ShOp1)))) {
unsigned AmtSum = ShAmt + ShOp1->getZExtValue();
// Oversized shifts are simplified to zero in InstSimplify.