[InstSimplify] Simplify 'x u>= 1' to true when x is known non-zero (#145204)
This commit is contained in:
parent
fa0b84f23c
commit
f51d8730b3
@ -2981,7 +2981,7 @@ static Value *simplifyICmpWithZero(CmpPredicate Pred, Value *LHS, Value *RHS,
|
||||
}
|
||||
|
||||
static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS,
|
||||
Value *RHS, const InstrInfoQuery &IIQ) {
|
||||
Value *RHS, const SimplifyQuery &Q) {
|
||||
Type *ITy = getCompareTy(RHS); // The return type.
|
||||
|
||||
Value *X;
|
||||
@ -3007,7 +3007,7 @@ static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS,
|
||||
return ConstantInt::getTrue(ITy);
|
||||
|
||||
ConstantRange LHS_CR =
|
||||
computeConstantRange(LHS, CmpInst::isSigned(Pred), IIQ.UseInstrInfo);
|
||||
computeConstantRange(LHS, CmpInst::isSigned(Pred), Q.IIQ.UseInstrInfo);
|
||||
if (!LHS_CR.isFullSet()) {
|
||||
if (RHS_CR.contains(LHS_CR))
|
||||
return ConstantInt::getTrue(ITy);
|
||||
@ -3018,13 +3018,16 @@ static Value *simplifyICmpWithConstant(CmpPredicate Pred, Value *LHS,
|
||||
// (mul nuw/nsw X, MulC) != C --> true (if C is not a multiple of MulC)
|
||||
// (mul nuw/nsw X, MulC) == C --> false (if C is not a multiple of MulC)
|
||||
const APInt *MulC;
|
||||
if (IIQ.UseInstrInfo && ICmpInst::isEquality(Pred) &&
|
||||
if (Q.IIQ.UseInstrInfo && ICmpInst::isEquality(Pred) &&
|
||||
((match(LHS, m_NUWMul(m_Value(), m_APIntAllowPoison(MulC))) &&
|
||||
*MulC != 0 && C->urem(*MulC) != 0) ||
|
||||
(match(LHS, m_NSWMul(m_Value(), m_APIntAllowPoison(MulC))) &&
|
||||
*MulC != 0 && C->srem(*MulC) != 0)))
|
||||
return ConstantInt::get(ITy, Pred == ICmpInst::ICMP_NE);
|
||||
|
||||
if (Pred == ICmpInst::ICMP_UGE && C->isOne() && isKnownNonZero(LHS, Q))
|
||||
return ConstantInt::getTrue(ITy);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
@ -3776,7 +3779,7 @@ static Value *simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS,
|
||||
if (Value *V = simplifyICmpWithZero(Pred, LHS, RHS, Q))
|
||||
return V;
|
||||
|
||||
if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q.IIQ))
|
||||
if (Value *V = simplifyICmpWithConstant(Pred, LHS, RHS, Q))
|
||||
return V;
|
||||
|
||||
// If both operands have range metadata, use the metadata
|
||||
|
120
llvm/test/Transforms/InstSimplify/umax-1.ll
Normal file
120
llvm/test/Transforms/InstSimplify/umax-1.ll
Normal file
@ -0,0 +1,120 @@
|
||||
; NOTE: Assertions have been autogenerated by utils/update_test_checks.py UTC_ARGS: --version 5
|
||||
; RUN: opt < %s -passes=instsimplify -S | FileCheck %s
|
||||
|
||||
define i32 @known_non_zero_by_or(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: define i32 @known_non_zero_by_or(
|
||||
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
|
||||
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
|
||||
; CHECK: [[IF_THEN]]:
|
||||
; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]]
|
||||
; CHECK-NEXT: ret i32 [[VAL]]
|
||||
; CHECK: [[IF_ELSE]]:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%cond = icmp ne i32 %x, 0
|
||||
br i1 %cond, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%val = or i32 %x, %y
|
||||
%max = call i32 @llvm.umax.i32(i32 %val, i32 1)
|
||||
ret i32 %max
|
||||
|
||||
if.else:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @known_non_zero_by_mul(i32 %x) {
|
||||
; CHECK-LABEL: define i32 @known_non_zero_by_mul(
|
||||
; CHECK-SAME: i32 [[X:%.*]]) {
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
|
||||
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
|
||||
; CHECK: [[IF_THEN]]:
|
||||
; CHECK-NEXT: [[NONZERO1:%.*]] = mul nuw i32 [[X]], 3
|
||||
; CHECK-NEXT: ret i32 [[NONZERO1]]
|
||||
; CHECK: [[IF_ELSE]]:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%cond = icmp ne i32 %x, 0
|
||||
br i1 %cond, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%nonzero = mul nuw i32 %x, 3
|
||||
%max = call i32 @llvm.umax.i32(i32 %nonzero, i32 1)
|
||||
ret i32 %max
|
||||
|
||||
if.else:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @known_non_zero_commute(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: define i32 @known_non_zero_commute(
|
||||
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
|
||||
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
|
||||
; CHECK: [[IF_THEN]]:
|
||||
; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]]
|
||||
; CHECK-NEXT: ret i32 [[VAL]]
|
||||
; CHECK: [[IF_ELSE]]:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%cond = icmp ne i32 %x, 0
|
||||
br i1 %cond, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%val = or i32 %x, %y
|
||||
%max = call i32 @llvm.umax.i32(i32 1, i32 %val)
|
||||
ret i32 %max
|
||||
|
||||
if.else:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
; Negative
|
||||
define i32 @umax_ge_2(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: define i32 @umax_ge_2(
|
||||
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
|
||||
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
|
||||
; CHECK: [[IF_THEN]]:
|
||||
; CHECK-NEXT: [[VAL:%.*]] = or i32 [[X]], [[Y]]
|
||||
; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 2)
|
||||
; CHECK-NEXT: ret i32 [[MAX]]
|
||||
; CHECK: [[IF_ELSE]]:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%cond = icmp ne i32 %x, 0
|
||||
br i1 %cond, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%val = or i32 %x, %y
|
||||
%max = call i32 @llvm.umax.i32(i32 %val, i32 2)
|
||||
ret i32 %max
|
||||
|
||||
if.else:
|
||||
ret i32 0
|
||||
}
|
||||
|
||||
define i32 @unknown_by_and(i32 %x, i32 %y) {
|
||||
; CHECK-LABEL: define i32 @unknown_by_and(
|
||||
; CHECK-SAME: i32 [[X:%.*]], i32 [[Y:%.*]]) {
|
||||
; CHECK-NEXT: [[COND:%.*]] = icmp ne i32 [[X]], 0
|
||||
; CHECK-NEXT: br i1 [[COND]], label %[[IF_THEN:.*]], label %[[IF_ELSE:.*]]
|
||||
; CHECK: [[IF_THEN]]:
|
||||
; CHECK-NEXT: [[VAL:%.*]] = and i32 [[X]], [[Y]]
|
||||
; CHECK-NEXT: [[MAX:%.*]] = call i32 @llvm.umax.i32(i32 [[VAL]], i32 1)
|
||||
; CHECK-NEXT: ret i32 [[MAX]]
|
||||
; CHECK: [[IF_ELSE]]:
|
||||
; CHECK-NEXT: ret i32 0
|
||||
;
|
||||
%cond = icmp ne i32 %x, 0
|
||||
br i1 %cond, label %if.then, label %if.else
|
||||
|
||||
if.then:
|
||||
%val = and i32 %x, %y
|
||||
%max = call i32 @llvm.umax.i32(i32 %val, i32 1)
|
||||
ret i32 %max
|
||||
|
||||
if.else:
|
||||
ret i32 0
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user