diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -1445,10 +1445,11 @@ simplifyShift(Instruction::Shl, Op0, Op1, IsNSW, Q, MaxRecurse)) return V; + Type *Ty = Op0->getType(); // undef << X -> 0 // undef << X -> undef if (if it's NSW/NUW) if (Q.isUndefValue(Op0)) - return IsNSW || IsNUW ? Op0 : Constant::getNullValue(Op0->getType()); + return IsNSW || IsNUW ? Op0 : Constant::getNullValue(Ty); // (X >> A) << A -> X Value *X; @@ -1462,6 +1463,13 @@ // NOTE: could use computeKnownBits() / LazyValueInfo, // but the cost-benefit analysis suggests it isn't worth it. + // "nuw" guarantees that only zeros are shifted out, and "nsw" guarantees + // that the sign-bit does not change, so the only input that does not + // produce poison is 0, and "0 << (bitwidth-1) --> 0". + if (IsNSW && IsNUW && + match(Op1, m_SpecificInt(Ty->getScalarSizeInBits() - 1))) + return Constant::getNullValue(Ty); + return nullptr; } diff --git a/llvm/test/Transforms/InstSimplify/shift.ll b/llvm/test/Transforms/InstSimplify/shift.ll --- a/llvm/test/Transforms/InstSimplify/shift.ll +++ b/llvm/test/Transforms/InstSimplify/shift.ll @@ -354,8 +354,7 @@ ; shl nsw+nuw is 0 define i8 @shl_nsw_nuw_7_eq_0(i8 %x) { ; CHECK-LABEL: @shl_nsw_nuw_7_eq_0( -; CHECK-NEXT: [[Y:%.*]] = shl nuw nsw i8 [[X:%.*]], 7 -; CHECK-NEXT: ret i8 [[Y]] +; CHECK-NEXT: ret i8 0 ; %y = shl nsw nuw i8 %x, 7 ret i8 %y @@ -364,8 +363,7 @@ ; Make sure we match the element width define <2 x i8> @shl_vec_nsw_nuw_7_eq_0(<2 x i8> %x) { ; CHECK-LABEL: @shl_vec_nsw_nuw_7_eq_0( -; CHECK-NEXT: [[Y:%.*]] = shl nuw nsw <2 x i8> [[X:%.*]], -; CHECK-NEXT: ret <2 x i8> [[Y]] +; CHECK-NEXT: ret <2 x i8> zeroinitializer ; %y = shl nsw nuw <2 x i8> %x, ret <2 x i8> %y