From c2a990bc00faf4a7017590d24a8a3d08b0a2640b Mon Sep 17 00:00:00 2001 From: David Majnemer Date: Fri, 5 Jul 2013 00:31:17 +0000 Subject: [PATCH] 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 --- .../InstCombine/InstCombineAndOrXor.cpp | 29 ++++++++++++++++++- llvm/test/Transforms/InstCombine/icmp.ll | 11 +++++++ 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp index 496fce65e0bb..b631b2856526 100644 --- a/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineAndOrXor.cpp @@ -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(LHS->getOperand(1)); ConstantInt *RHSCst = dyn_cast(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) { diff --git a/llvm/test/Transforms/InstCombine/icmp.ll b/llvm/test/Transforms/InstCombine/icmp.ll index 0026b20696cc..195dc572adfe 100644 --- a/llvm/test/Transforms/InstCombine/icmp.ll +++ b/llvm/test/Transforms/InstCombine/icmp.ll @@ -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 +}