mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-23 19:23:23 +01:00
InstCombine: If we have a bit test and a sign test anded/ored together, merge the sign bit into the bit test.
This is common in bit field code, e.g. checking if the first or the last bit of a bit field is set. llvm-svn: 147749
This commit is contained in:
parent
5d24f5f51a
commit
e94856c8c4
@ -743,6 +743,22 @@ Value *InstCombiner::FoldAndOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// (X & C) == 0 & X > -1 -> (X & (C | SignBit)) == 0
|
||||
if (LHS->hasOneUse() && RHS->hasOneUse() &&
|
||||
((LHSCC == ICmpInst::ICMP_EQ && LHSCst->isZero() &&
|
||||
RHSCC == ICmpInst::ICMP_SGT && RHSCst->isAllOnesValue()) ||
|
||||
(RHSCC == ICmpInst::ICMP_EQ && RHSCst->isZero() &&
|
||||
LHSCC == ICmpInst::ICMP_SGT && LHSCst->isAllOnesValue()))) {
|
||||
BinaryOperator *BO =
|
||||
dyn_cast<BinaryOperator>(LHSCC == ICmpInst::ICMP_EQ ? Val : Val2);
|
||||
ConstantInt *AndCst;
|
||||
if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) {
|
||||
APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth());
|
||||
BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New));
|
||||
return BO == Val ? LHS : RHS;
|
||||
}
|
||||
}
|
||||
|
||||
// From here on, we only handle:
|
||||
// (icmp1 A, C1) & (icmp2 A, C2) --> something simpler.
|
||||
@ -1442,6 +1458,22 @@ Value *InstCombiner::FoldOrOfICmps(ICmpInst *LHS, ICmpInst *RHS) {
|
||||
}
|
||||
}
|
||||
|
||||
// (X & C) != 0 & X < 0 -> (X & (C | SignBit)) != 0
|
||||
if (LHS->hasOneUse() && RHS->hasOneUse() &&
|
||||
((LHSCC == ICmpInst::ICMP_NE && LHSCst->isZero() &&
|
||||
RHSCC == ICmpInst::ICMP_SLT && RHSCst->isZero()) ||
|
||||
(RHSCC == ICmpInst::ICMP_NE && RHSCst->isZero() &&
|
||||
LHSCC == ICmpInst::ICMP_SLT && LHSCst->isZero()))) {
|
||||
BinaryOperator *BO =
|
||||
dyn_cast<BinaryOperator>(LHSCC == ICmpInst::ICMP_NE ? Val : Val2);
|
||||
ConstantInt *AndCst;
|
||||
if (BO && match(BO, m_OneUse(m_And(m_Value(), m_ConstantInt(AndCst))))) {
|
||||
APInt New = AndCst->getValue() | APInt::getSignBit(AndCst->getBitWidth());
|
||||
BO->setOperand(1, ConstantInt::get(AndCst->getContext(), New));
|
||||
return BO == Val ? LHS : RHS;
|
||||
}
|
||||
}
|
||||
|
||||
// (icmp ult (X + CA), C1) | (icmp eq X, C2) -> (icmp ule (X + CA), C1)
|
||||
// iff C2 + CA == C1.
|
||||
if (LHSCC == ICmpInst::ICMP_ULT && RHSCC == ICmpInst::ICMP_EQ) {
|
||||
|
@ -77,3 +77,83 @@ if.then:
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test5(i32 %a) nounwind {
|
||||
%and = and i32 %a, 134217728
|
||||
%1 = icmp eq i32 %and, 0
|
||||
%2 = icmp sgt i32 %a, -1
|
||||
%or.cond = and i1 %1, %2
|
||||
br i1 %or.cond, label %if.then, label %if.end
|
||||
|
||||
; CHECK: @test5
|
||||
; CHECK-NEXT: %and = and i32 %a, -2013265920
|
||||
; CHECK-NEXT: %1 = icmp eq i32 %and, 0
|
||||
; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
tail call void @foo() nounwind
|
||||
ret void
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test6(i32 %a) nounwind {
|
||||
%1 = icmp sgt i32 %a, -1
|
||||
%and = and i32 %a, 134217728
|
||||
%2 = icmp eq i32 %and, 0
|
||||
%or.cond = and i1 %1, %2
|
||||
br i1 %or.cond, label %if.then, label %if.end
|
||||
|
||||
; CHECK: @test6
|
||||
; CHECK-NEXT: %and = and i32 %a, -2013265920
|
||||
; CHECK-NEXT: %1 = icmp eq i32 %and, 0
|
||||
; CHECK-NEXT: br i1 %1, label %if.then, label %if.end
|
||||
|
||||
if.then:
|
||||
tail call void @foo() nounwind
|
||||
ret void
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test7(i32 %a) nounwind {
|
||||
%and = and i32 %a, 134217728
|
||||
%1 = icmp ne i32 %and, 0
|
||||
%2 = icmp slt i32 %a, 0
|
||||
%or.cond = or i1 %1, %2
|
||||
br i1 %or.cond, label %if.then, label %if.end
|
||||
|
||||
; CHECK: @test7
|
||||
; CHECK-NEXT: %and = and i32 %a, -2013265920
|
||||
; CHECK-NEXT: %1 = icmp eq i32 %and, 0
|
||||
; CHECK-NEXT: br i1 %1, label %if.end, label %if.the
|
||||
|
||||
if.then:
|
||||
tail call void @foo() nounwind
|
||||
ret void
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
||||
define void @test8(i32 %a) nounwind {
|
||||
%1 = icmp slt i32 %a, 0
|
||||
%and = and i32 %a, 134217728
|
||||
%2 = icmp ne i32 %and, 0
|
||||
%or.cond = or i1 %1, %2
|
||||
br i1 %or.cond, label %if.then, label %if.end
|
||||
|
||||
; CHECK: @test8
|
||||
; CHECK-NEXT: %and = and i32 %a, -2013265920
|
||||
; CHECK-NEXT: %1 = icmp eq i32 %and, 0
|
||||
; CHECK-NEXT: br i1 %1, label %if.end, label %if.the
|
||||
|
||||
if.then:
|
||||
tail call void @foo() nounwind
|
||||
ret void
|
||||
|
||||
if.end:
|
||||
ret void
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user