forked from OSchip/llvm-project
InstCombine: (icmp eq B, 0) | (icmp ult A, B) -> (icmp ule A, B-1)
This transform allows us to turn IR that looks like: %1 = icmp eq i64 %b, 0 %2 = icmp ult i64 %a, %b %3 = or i1 %1, %2 ret i1 %3 into: %0 = add i64 %b, -1 %1 = icmp uge i64 %0, %a ret i1 %1 which means we go from lowering: cmpq %rsi, %rdi setb %cl testq %rsi, %rsi sete %al orb %cl, %al ret to lowering: decq %rsi cmpq %rdi, %rsi setae %al ret llvm-svn: 185677
This commit is contained in:
parent
156a2deafe
commit
c2a990bc00
|
@ -1477,10 +1477,37 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
|||
if (Value *V = foldLogOpOfMaskedICmps(LHS, RHS, ICmpInst::ICMP_NE, Builder))
|
||||
return V;
|
||||
|
||||
// This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
|
||||
Value *Val = LHS->getOperand(0), *Val2 = RHS->getOperand(0);
|
||||
ConstantInt *LHSCst = dyn_cast<ConstantInt>(LHS->getOperand(1));
|
||||
ConstantInt *RHSCst = dyn_cast<ConstantInt>(RHS->getOperand(1));
|
||||
|
||||
if (LHS->hasOneUse() || RHS->hasOneUse()) {
|
||||
// (icmp eq B, 0) | (icmp ult A, B) -> (icmp ule A, B-1)
|
||||
// (icmp eq B, 0) | (icmp ugt B, A) -> (icmp ule A, B-1)
|
||||
Value *A = 0, *B = 0;
|
||||
if (LHSCC == ICmpInst::ICMP_EQ && LHSCst && LHSCst->isZero()) {
|
||||
B = Val;
|
||||
if (RHSCC == ICmpInst::ICMP_ULT && Val == RHS->getOperand(1))
|
||||
A = Val2;
|
||||
else if (RHSCC == ICmpInst::ICMP_UGT && Val == Val2)
|
||||
A = RHS->getOperand(1);
|
||||
}
|
||||
// (icmp ult A, B) | (icmp eq B, 0) -> (icmp ule A, B-1)
|
||||
// (icmp ugt B, A) | (icmp eq B, 0) -> (icmp ule A, B-1)
|
||||
else if (RHSCC == ICmpInst::ICMP_EQ && RHSCst && RHSCst->isZero()) {
|
||||
B = Val2;
|
||||
if (LHSCC == ICmpInst::ICMP_ULT && Val2 == LHS->getOperand(1))
|
||||
A = Val;
|
||||
else if (LHSCC == ICmpInst::ICMP_UGT && Val2 == Val)
|
||||
A = LHS->getOperand(1);
|
||||
}
|
||||
if (A && B)
|
||||
return Builder->CreateICmp(
|
||||
ICmpInst::ICMP_UGE,
|
||||
Builder->CreateAdd(B, ConstantInt::getSigned(B->getType(), -1)), A);
|
||||
}
|
||||
|
||||
// This only handles icmp of constants: (icmp1 A, C1) | (icmp2 B, C2).
|
||||
if (LHSCst == 0 || RHSCst == 0) return 0;
|
||||
|
||||
if (LHSCst == RHSCst && LHSCC == RHSCC) {
|
||||
|
|
|
@ -1102,3 +1102,14 @@ define i1 @icmp_shl_1_V_ult_2147483648(i32 %V) {
|
|||
%cmp = icmp ult i32 %shl, 2147483648
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; CEHCK: @or_icmp_eq_B_0_icmp_ult_A_B
|
||||
; CHECK: [[SUB:%[a-z0-9]+]] = add i64 %b, -1
|
||||
; CHECK-NEXT: [[CMP:%[a-z0-9]+]] = icmp uge i64 [[SUB]], %a
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
define i1 @or_icmp_eq_B_0_icmp_ult_A_B(i64 %a, i64 %b) {
|
||||
%1 = icmp eq i64 %b, 0
|
||||
%2 = icmp ult i64 %a, %b
|
||||
%3 = or i1 %1, %2
|
||||
ret i1 %3
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue