diff --git a/llvm/lib/Analysis/ValueTracking.cpp b/llvm/lib/Analysis/ValueTracking.cpp --- a/llvm/lib/Analysis/ValueTracking.cpp +++ b/llvm/lib/Analysis/ValueTracking.cpp @@ -3321,10 +3321,18 @@ return Tmp; } - case Instruction::Trunc: - // FIXME: it's tricky to do anything useful for this, but it is an - // important case for targets like X86. + case Instruction::Trunc: { + // If the input contained enough sign bits that some remain after the + // truncation, then we can make use of that. Otherwise we don't know + // anything. + Tmp = ComputeNumSignBits(U->getOperand(0), Depth + 1, Q); + unsigned OperandTyBits = Q.DL.getTypeSizeInBits(U->getOperand(0)->getType()); + if (Tmp > (OperandTyBits - TyBits)) { + return Tmp - (OperandTyBits - TyBits); + } + break; + } case Instruction::ExtractElement: // Look through extract element. At the moment we keep this simple and diff --git a/llvm/test/Transforms/InstCombine/high-bit-signmask-with-trunc.ll b/llvm/test/Transforms/InstCombine/high-bit-signmask-with-trunc.ll --- a/llvm/test/Transforms/InstCombine/high-bit-signmask-with-trunc.ll +++ b/llvm/test/Transforms/InstCombine/high-bit-signmask-with-trunc.ll @@ -138,7 +138,7 @@ ; CHECK-LABEL: @n10( ; CHECK-NEXT: [[T0_NEG:%.*]] = ashr i64 [[X:%.*]], 63 ; CHECK-NEXT: [[T1_NEG:%.*]] = trunc i64 [[T0_NEG]] to i32 -; CHECK-NEXT: [[R:%.*]] = add i32 [[T1_NEG]], 1 +; CHECK-NEXT: [[R:%.*]] = add nsw i32 [[T1_NEG]], 1 ; CHECK-NEXT: ret i32 [[R]] ; %t0 = lshr i64 %x, 63 diff --git a/llvm/test/Transforms/InstCombine/negated-bitmask.ll b/llvm/test/Transforms/InstCombine/negated-bitmask.ll --- a/llvm/test/Transforms/InstCombine/negated-bitmask.ll +++ b/llvm/test/Transforms/InstCombine/negated-bitmask.ll @@ -71,7 +71,7 @@ ; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[A0:%.*]], 48 ; CHECK-NEXT: [[TMP2:%.*]] = ashr i64 [[TMP1]], 63 ; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i8 -; CHECK-NEXT: [[NEG:%.*]] = add i8 [[TMP3]], 10 +; CHECK-NEXT: [[NEG:%.*]] = add nsw i8 [[TMP3]], 10 ; CHECK-NEXT: ret i8 [[NEG]] ; %shift = lshr i64 %a0, 15 @@ -86,7 +86,7 @@ ; CHECK-NEXT: [[TMP1:%.*]] = shl i64 [[A0:%.*]], 48 ; CHECK-NEXT: [[TMP2:%.*]] = ashr i64 [[TMP1]], 63 ; CHECK-NEXT: [[TMP3:%.*]] = trunc i64 [[TMP2]] to i8 -; CHECK-NEXT: [[NARROW:%.*]] = add i8 [[TMP3]], 10 +; CHECK-NEXT: [[NARROW:%.*]] = add nsw i8 [[TMP3]], 10 ; CHECK-NEXT: [[NEG:%.*]] = zext i8 [[NARROW]] to i32 ; CHECK-NEXT: ret i32 [[NEG]] ;