diff --git a/llvm/lib/Transforms/Scalar/Reassociate.cpp b/llvm/lib/Transforms/Scalar/Reassociate.cpp --- a/llvm/lib/Transforms/Scalar/Reassociate.cpp +++ b/llvm/lib/Transforms/Scalar/Reassociate.cpp @@ -976,7 +976,8 @@ /// this into a multiply by a constant to assist with further reassociation. static BinaryOperator *ConvertShiftToMul(Instruction *Shl) { Constant *MulCst = ConstantInt::get(Shl->getType(), 1); - MulCst = ConstantExpr::getShl(MulCst, cast(Shl->getOperand(1))); + auto *SA = cast(Shl->getOperand(1)); + MulCst = ConstantExpr::getShl(MulCst, SA); BinaryOperator *Mul = BinaryOperator::CreateMul(Shl->getOperand(0), MulCst, "", Shl); @@ -989,10 +990,12 @@ // We can safely preserve the nuw flag in all cases. It's also safe to turn a // nuw nsw shl into a nuw nsw mul. However, nsw in isolation requires special - // handling. + // handling. It can be preserved as long as we're not left shifting by + // bitwidth - 1. bool NSW = cast(Shl)->hasNoSignedWrap(); bool NUW = cast(Shl)->hasNoUnsignedWrap(); - if (NSW && NUW) + unsigned BitWidth = Shl->getType()->getIntegerBitWidth(); + if (NSW && (NUW || SA->getValue().ult(BitWidth - 1))) Mul->setHasNoSignedWrap(true); Mul->setHasNoUnsignedWrap(NUW); return Mul; diff --git a/llvm/test/Transforms/Reassociate/wrap-flags.ll b/llvm/test/Transforms/Reassociate/wrap-flags.ll --- a/llvm/test/Transforms/Reassociate/wrap-flags.ll +++ b/llvm/test/Transforms/Reassociate/wrap-flags.ll @@ -18,6 +18,20 @@ ret i32 %mul2 } +define i32 @shl_to_mul_nsw_2(i32 %i) { +; +; CHECK-LABEL: @shl_to_mul_nsw_2( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL:%.*]] = mul nsw i32 [[I:%.*]], 1073741824 +; CHECK-NEXT: [[MUL2:%.*]] = add i32 [[MUL]], 1 +; CHECK-NEXT: ret i32 [[MUL2]] +; +entry: + %mul = shl nsw i32 %i, 30 + %mul2 = add i32 %mul, 1 + ret i32 %mul2 +} + define i32 @shl_to_mul_nuw(i32 %i) { ; ; CHECK-LABEL: @shl_to_mul_nuw( @@ -46,6 +60,20 @@ ret i32 %mul2 } +define i32 @shl_to_mul_nuw_nsw_bitwidth_m1(i32 %i) { +; +; CHECK-LABEL: @shl_to_mul_nuw_nsw_bitwidth_m1( +; CHECK-NEXT: entry: +; CHECK-NEXT: [[MUL:%.*]] = mul nuw nsw i32 [[I:%.*]], -2147483648 +; CHECK-NEXT: [[MUL2:%.*]] = add i32 [[MUL]], 1 +; CHECK-NEXT: ret i32 [[MUL2]] +; +entry: + %mul = shl nuw nsw i32 %i, 31 + %mul2 = add i32 %mul, 1 + ret i32 %mul2 +} + define i2 @pr23926(i2 %X1, i2 %X2) { ; ; CHECK-LABEL: @pr23926(