mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-12-11 13:37:07 +00:00
[GuardWidening] Use getEquivalentICmp to fold constant compares
`ConstantRange::getEquivalentICmp` is more general, and better factored. llvm-svn: 270019
This commit is contained in:
parent
c63bcd9d33
commit
b590ade35e
@ -356,21 +356,31 @@ bool GuardWideningImpl::widenCondCommon(Value *Cond0, Value *Cond1,
|
|||||||
if (match(Cond0, m_ICmp(Pred0, m_Value(LHS), m_ConstantInt(RHS0))) &&
|
if (match(Cond0, m_ICmp(Pred0, m_Value(LHS), m_ConstantInt(RHS0))) &&
|
||||||
match(Cond1, m_ICmp(Pred1, m_Specific(LHS), m_ConstantInt(RHS1)))) {
|
match(Cond1, m_ICmp(Pred1, m_Specific(LHS), m_ConstantInt(RHS1)))) {
|
||||||
|
|
||||||
// TODO: This logic should be generalized and refactored into a new
|
ConstantRange CR0 =
|
||||||
// Constant::getEquivalentICmp helper.
|
ConstantRange::makeExactICmpRegion(Pred0, RHS0->getValue());
|
||||||
if (Pred0 == ICmpInst::ICMP_NE && RHS0->isZero())
|
ConstantRange CR1 =
|
||||||
Pred0 = ICmpInst::ICMP_UGT;
|
ConstantRange::makeExactICmpRegion(Pred1, RHS1->getValue());
|
||||||
if (Pred1 == ICmpInst::ICMP_NE && RHS1->isZero())
|
|
||||||
Pred1 = ICmpInst::ICMP_UGT;
|
|
||||||
|
|
||||||
if (Pred0 == ICmpInst::ICMP_UGT && Pred1 == ICmpInst::ICMP_UGT) {
|
// SubsetIntersect is a subset of the actual mathematical intersection of
|
||||||
|
// CR0 and CR1, while SupersetIntersect is a superset of the the actual
|
||||||
|
// mathematical intersection. If these two ConstantRanges are equal, then
|
||||||
|
// we know we were able to represent the actual mathematical intersection
|
||||||
|
// of CR0 and CR1, and can use the same to generate an icmp instruction.
|
||||||
|
//
|
||||||
|
// Given what we're doing here and the semantics of guards, it would
|
||||||
|
// actually be correct to just use SubsetIntersect, but that may be too
|
||||||
|
// aggressive in cases we care about.
|
||||||
|
auto SubsetIntersect = CR0.inverse().unionWith(CR1.inverse()).inverse();
|
||||||
|
auto SupersetIntersect = CR0.intersectWith(CR1);
|
||||||
|
|
||||||
|
APInt NewRHSAP;
|
||||||
|
CmpInst::Predicate Pred;
|
||||||
|
if (SubsetIntersect == SupersetIntersect &&
|
||||||
|
SubsetIntersect.getEquivalentICmp(Pred, NewRHSAP)) {
|
||||||
if (InsertPt) {
|
if (InsertPt) {
|
||||||
ConstantInt *NewRHS =
|
ConstantInt *NewRHS = ConstantInt::get(Cond0->getContext(), NewRHSAP);
|
||||||
RHS0->getValue().ugt(RHS1->getValue()) ? RHS0 : RHS1;
|
Result = new ICmpInst(InsertPt, Pred, LHS, NewRHS, "wide.chk");
|
||||||
Result = new ICmpInst(InsertPt, ICmpInst::ICMP_UGT, LHS, NewRHS,
|
|
||||||
"wide.chk");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -126,7 +126,7 @@ leave:
|
|||||||
define void @f_5(i32 %a) {
|
define void @f_5(i32 %a) {
|
||||||
; CHECK-LABEL: @f_5(
|
; CHECK-LABEL: @f_5(
|
||||||
entry:
|
entry:
|
||||||
; CHECK: %wide.chk = icmp ugt i32 %a, 10
|
; CHECK: %wide.chk = icmp uge i32 %a, 11
|
||||||
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
|
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
|
||||||
; CHECK: br i1 undef, label %left, label %right
|
; CHECK: br i1 undef, label %left, label %right
|
||||||
|
|
||||||
@ -335,3 +335,47 @@ entry:
|
|||||||
call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
|
call void(i1, ...) @llvm.experimental.guard(i1 %cond) [ "deopt"() ]
|
||||||
ret void
|
ret void
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define void @f_13(i32 %a) {
|
||||||
|
; CHECK-LABEL: @f_13(
|
||||||
|
entry:
|
||||||
|
; CHECK: %wide.chk = icmp ult i32 %a, 10
|
||||||
|
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %wide.chk) [ "deopt"() ]
|
||||||
|
; CHECK: br i1 undef, label %left, label %right
|
||||||
|
|
||||||
|
%cond_0 = icmp ult i32 %a, 14
|
||||||
|
call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
|
||||||
|
br i1 undef, label %left, label %right
|
||||||
|
|
||||||
|
left:
|
||||||
|
%cond_1 = icmp slt i32 %a, 10
|
||||||
|
call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
|
||||||
|
ret void
|
||||||
|
|
||||||
|
right:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
|
||||||
|
define void @f_14(i32 %a) {
|
||||||
|
; CHECK-LABEL: @f_14(
|
||||||
|
entry:
|
||||||
|
; CHECK: %cond_0 = icmp ult i32 %a, 14
|
||||||
|
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
|
||||||
|
; CHECK: br i1 undef, label %left, label %right
|
||||||
|
|
||||||
|
%cond_0 = icmp ult i32 %a, 14
|
||||||
|
call void(i1, ...) @llvm.experimental.guard(i1 %cond_0) [ "deopt"() ]
|
||||||
|
br i1 undef, label %left, label %right
|
||||||
|
|
||||||
|
left:
|
||||||
|
; CHECK: left:
|
||||||
|
; CHECK: %cond_1 = icmp sgt i32 %a, 10
|
||||||
|
; CHECK: call void (i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
|
||||||
|
|
||||||
|
%cond_1 = icmp sgt i32 %a, 10
|
||||||
|
call void(i1, ...) @llvm.experimental.guard(i1 %cond_1) [ "deopt"() ]
|
||||||
|
ret void
|
||||||
|
|
||||||
|
right:
|
||||||
|
ret void
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user