forked from OSchip/llvm-project
[ValueTracking] recognize sub X, (X % Y) as not overflowing
I fixed some poison-safety violations on related patterns in InstCombine and noticed that we missed adding nsw/nuw on them, so this adds clauses to the underlying analysis for that. We need the undef input restriction to make this safe according to Alive2: https://alive2.llvm.org/ce/z/48g9K8 Differential Revision: https://reviews.llvm.org/D125500
This commit is contained in:
parent
0fefb56da7
commit
ee6754c277
|
@ -4841,6 +4841,15 @@ OverflowResult llvm::computeOverflowForUnsignedSub(const Value *LHS,
|
|||
AssumptionCache *AC,
|
||||
const Instruction *CxtI,
|
||||
const DominatorTree *DT) {
|
||||
// X - (X % ?)
|
||||
// The remainder of a value can't have greater magnitude than itself,
|
||||
// so the subtraction can't overflow.
|
||||
// TODO: There are other patterns like this.
|
||||
// See simplifyICmpWithBinOpOnLHS() for candidates.
|
||||
if (match(RHS, m_URem(m_Specific(LHS), m_Value())) &&
|
||||
isGuaranteedNotToBeUndefOrPoison(LHS, AC, CxtI, DT))
|
||||
return OverflowResult::NeverOverflows;
|
||||
|
||||
// Checking for conditions implied by dominating conditions may be expensive.
|
||||
// Limit it to usub_with_overflow calls for now.
|
||||
if (match(CxtI,
|
||||
|
@ -4864,6 +4873,13 @@ OverflowResult llvm::computeOverflowForSignedSub(const Value *LHS,
|
|||
AssumptionCache *AC,
|
||||
const Instruction *CxtI,
|
||||
const DominatorTree *DT) {
|
||||
// X - (X % ?)
|
||||
// The remainder of a value can't have greater magnitude than itself,
|
||||
// so the subtraction can't overflow.
|
||||
if (match(RHS, m_SRem(m_Specific(LHS), m_Value())) &&
|
||||
isGuaranteedNotToBeUndefOrPoison(LHS, AC, CxtI, DT))
|
||||
return OverflowResult::NeverOverflows;
|
||||
|
||||
// If LHS and RHS each have at least two sign bits, the subtraction
|
||||
// cannot overflow.
|
||||
if (ComputeNumSignBits(LHS, DL, 0, AC, CxtI, DT) > 1 &&
|
||||
|
|
|
@ -116,7 +116,7 @@ define i32 @not_match_overflow(i32 %x) {
|
|||
; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]]
|
||||
; CHECK-NEXT: [[T:%.*]] = urem i32 [[X_FR]], 299
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = urem i32 [[X_FR]], 299
|
||||
; CHECK-NEXT: [[T3:%.*]] = sub i32 [[X_FR]], [[TMP1]]
|
||||
; CHECK-NEXT: [[T3:%.*]] = sub nuw i32 [[X_FR]], [[TMP1]]
|
||||
; CHECK-NEXT: [[T4:%.*]] = add i32 [[T]], [[T3]]
|
||||
; CHECK-NEXT: ret i32 [[T4]]
|
||||
;
|
||||
|
|
|
@ -32,7 +32,7 @@ define i32 @sdiv3(i32 %x) {
|
|||
; CHECK-LABEL: @sdiv3(
|
||||
; CHECK-NEXT: [[X_FR:%.*]] = freeze i32 [[X:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = srem i32 [[X_FR]], 3
|
||||
; CHECK-NEXT: [[Z:%.*]] = sub i32 [[X_FR]], [[TMP1]]
|
||||
; CHECK-NEXT: [[Z:%.*]] = sub nsw i32 [[X_FR]], [[TMP1]]
|
||||
; CHECK-NEXT: ret i32 [[Z]]
|
||||
;
|
||||
%y = sdiv i32 %x, 3
|
||||
|
|
|
@ -139,7 +139,7 @@ define i8 @urem3(i8 %x) {
|
|||
; CHECK-LABEL: @urem3(
|
||||
; CHECK-NEXT: [[X_FR:%.*]] = freeze i8 [[X:%.*]]
|
||||
; CHECK-NEXT: [[TMP1:%.*]] = urem i8 [[X_FR]], 3
|
||||
; CHECK-NEXT: [[B_NEG:%.*]] = sub i8 [[X_FR]], [[TMP1]]
|
||||
; CHECK-NEXT: [[B_NEG:%.*]] = sub nuw i8 [[X_FR]], [[TMP1]]
|
||||
; CHECK-NEXT: [[C:%.*]] = add i8 [[B_NEG]], [[X_FR]]
|
||||
; CHECK-NEXT: ret i8 [[C]]
|
||||
;
|
||||
|
|
|
@ -1705,7 +1705,7 @@ define i32 @pr51584(i32 %a, i32 %b) {
|
|||
define i8 @sub_srem(i8 noundef %x, i8 %y) {
|
||||
; CHECK-LABEL: @sub_srem(
|
||||
; CHECK-NEXT: [[REM:%.*]] = srem i8 [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[SUB:%.*]] = sub i8 [[X]], [[REM]]
|
||||
; CHECK-NEXT: [[SUB:%.*]] = sub nsw i8 [[X]], [[REM]]
|
||||
; CHECK-NEXT: ret i8 [[SUB]]
|
||||
;
|
||||
%rem = srem i8 %x, %y
|
||||
|
@ -1716,7 +1716,7 @@ define i8 @sub_srem(i8 noundef %x, i8 %y) {
|
|||
define <2 x i5> @sub_urem(<2 x i5> noundef %x, <2 x i5> %y) {
|
||||
; CHECK-LABEL: @sub_urem(
|
||||
; CHECK-NEXT: [[REM:%.*]] = urem <2 x i5> [[X:%.*]], [[Y:%.*]]
|
||||
; CHECK-NEXT: [[SUB:%.*]] = sub <2 x i5> [[X]], [[REM]]
|
||||
; CHECK-NEXT: [[SUB:%.*]] = sub nuw <2 x i5> [[X]], [[REM]]
|
||||
; CHECK-NEXT: ret <2 x i5> [[SUB]]
|
||||
;
|
||||
%rem = urem <2 x i5> %x, %y
|
||||
|
|
Loading…
Reference in New Issue