mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 02:52:53 +02:00
[InstCombine] optimize unsigned icmp of increment
Allows LLVM to optimize sequences like the following: %add = add nuw i32 %x, 1 %cmp = icmp ugt i32 %add, %y Into: %cmp = icmp uge i32 %x, %y Previously, only signed comparisons were being handled. Decrements could also be handled, but 'sub nuw %x, 1' is currently canonicalized to 'add %x, -1' in InstCombineAddSub, losing the nuw flag. Removing that canonicalization seems like it might have far-reaching ramifications so I kept this simple for now. Patch by Matti Niemenmaa! Differential Revision: https://reviews.llvm.org/D24700 llvm-svn: 291975
This commit is contained in:
parent
ead291ba07
commit
c20cf10406
@ -2843,6 +2843,31 @@ Instruction *InstCombiner::foldICmpBinOp(ICmpInst &I) {
|
|||||||
if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_SLT && match(D, m_One()))
|
if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_SLT && match(D, m_One()))
|
||||||
return new ICmpInst(CmpInst::ICMP_SLE, Op0, C);
|
return new ICmpInst(CmpInst::ICMP_SLE, Op0, C);
|
||||||
|
|
||||||
|
// TODO: The subtraction-related identities shown below also hold, but
|
||||||
|
// canonicalization from (X -nuw 1) to (X + -1) means that the combinations
|
||||||
|
// wouldn't happen even if they were implemented.
|
||||||
|
//
|
||||||
|
// icmp ult (X - 1), Y -> icmp ule X, Y
|
||||||
|
// icmp uge (X - 1), Y -> icmp ugt X, Y
|
||||||
|
// icmp ugt X, (Y - 1) -> icmp uge X, Y
|
||||||
|
// icmp ule X, (Y - 1) -> icmp ult X, Y
|
||||||
|
|
||||||
|
// icmp ule (X + 1), Y -> icmp ult X, Y
|
||||||
|
if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_ULE && match(B, m_One()))
|
||||||
|
return new ICmpInst(CmpInst::ICMP_ULT, A, Op1);
|
||||||
|
|
||||||
|
// icmp ugt (X + 1), Y -> icmp uge X, Y
|
||||||
|
if (A && NoOp0WrapProblem && Pred == CmpInst::ICMP_UGT && match(B, m_One()))
|
||||||
|
return new ICmpInst(CmpInst::ICMP_UGE, A, Op1);
|
||||||
|
|
||||||
|
// icmp uge X, (Y + 1) -> icmp ugt X, Y
|
||||||
|
if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_UGE && match(D, m_One()))
|
||||||
|
return new ICmpInst(CmpInst::ICMP_UGT, Op0, C);
|
||||||
|
|
||||||
|
// icmp ult X, (Y + 1) -> icmp ule X, Y
|
||||||
|
if (C && NoOp1WrapProblem && Pred == CmpInst::ICMP_ULT && match(D, m_One()))
|
||||||
|
return new ICmpInst(CmpInst::ICMP_ULE, Op0, C);
|
||||||
|
|
||||||
// if C1 has greater magnitude than C2:
|
// if C1 has greater magnitude than C2:
|
||||||
// icmp (X + C1), (Y + C2) -> icmp (X + C3), Y
|
// icmp (X + C1), (Y + C2) -> icmp (X + C3), Y
|
||||||
// s.t. C3 = C1 - C2
|
// s.t. C3 = C1 - C2
|
||||||
|
@ -2425,6 +2425,10 @@ define i1 @f10(i16 %p) {
|
|||||||
ret i1 %cmp580
|
ret i1 %cmp580
|
||||||
}
|
}
|
||||||
|
|
||||||
|
; Note: fptosi is used in various tests below to ensure that operand complexity
|
||||||
|
; canonicalization does not kick in, which would make some of the tests
|
||||||
|
; equivalent to one another.
|
||||||
|
|
||||||
define i1 @cmp_sgt_rhs_dec(float %x, i32 %i) {
|
define i1 @cmp_sgt_rhs_dec(float %x, i32 %i) {
|
||||||
; CHECK-LABEL: @cmp_sgt_rhs_dec(
|
; CHECK-LABEL: @cmp_sgt_rhs_dec(
|
||||||
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
@ -2711,3 +2715,143 @@ define i1 @or_ptrtoint_mismatch(i8* %p, i32* %q) {
|
|||||||
%b = icmp eq i64 %o, 0
|
%b = icmp eq i64 %o, 0
|
||||||
ret i1 %b
|
ret i1 %b
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i1 @icmp_add1_ugt(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @icmp_add1_ugt(
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 %x, %y
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%add = add nuw i32 %x, 1
|
||||||
|
%cmp = icmp ugt i32 %add, %y
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @icmp_add1_ule(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @icmp_add1_ule(
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 %x, %y
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%add = add nuw i32 %x, 1
|
||||||
|
%cmp = icmp ule i32 %add, %y
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_uge_rhs_inc(float %x, i32 %i) {
|
||||||
|
; CHECK-LABEL: @cmp_uge_rhs_inc(
|
||||||
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[CONV]], %i
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%conv = fptosi float %x to i32
|
||||||
|
%inc = add nuw i32 %i, 1
|
||||||
|
%cmp = icmp uge i32 %conv, %inc
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_ult_rhs_inc(float %x, i32 %i) {
|
||||||
|
; CHECK-LABEL: @cmp_ult_rhs_inc(
|
||||||
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[CONV]], %i
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%conv = fptosi float %x to i32
|
||||||
|
%inc = add nuw i32 %i, 1
|
||||||
|
%cmp = icmp ult i32 %conv, %inc
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_sge_lhs_inc(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_sge_lhs_inc(
|
||||||
|
; CHECK-NEXT: [[INC:%.*]] = add
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[INC]], %y
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%inc = add nsw i32 %x, 1
|
||||||
|
%cmp = icmp sge i32 %inc, %y
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_uge_lhs_inc(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_uge_lhs_inc(
|
||||||
|
; CHECK-NEXT: [[INC:%.*]] = add
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[INC]], %y
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%inc = add nuw i32 %x, 1
|
||||||
|
%cmp = icmp uge i32 %inc, %y
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_sgt_lhs_dec(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_sgt_lhs_dec(
|
||||||
|
; CHECK-NEXT: [[DEC:%.*]] = {{add|sub}}
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sgt i32 [[DEC]], %y
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%dec = sub nsw i32 %x, 1
|
||||||
|
%cmp = icmp sgt i32 %dec, %y
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_ugt_lhs_dec(i32 %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_ugt_lhs_dec(
|
||||||
|
; CHECK-NEXT: [[DEC:%.*]] = {{add|sub}}
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ugt i32 [[DEC]], %y
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%dec = sub nuw i32 %x, 1
|
||||||
|
%cmp = icmp ugt i32 %dec, %y
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_sle_rhs_inc(float %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_sle_rhs_inc(
|
||||||
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
|
; CHECK-NEXT: [[INC:%.*]] = add
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[CONV]], [[INC]]
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%conv = fptosi float %x to i32
|
||||||
|
%inc = add nsw i32 %y, 1
|
||||||
|
%cmp = icmp sle i32 %conv, %inc
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_ule_rhs_inc(float %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_ule_rhs_inc(
|
||||||
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
|
; CHECK-NEXT: [[INC:%.*]] = add
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[CONV]], [[INC]]
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%conv = fptosi float %x to i32
|
||||||
|
%inc = add nuw i32 %y, 1
|
||||||
|
%cmp = icmp ule i32 %conv, %inc
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_slt_rhs_dec(float %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_slt_rhs_dec(
|
||||||
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
|
; CHECK-NEXT: [[DEC:%.*]] = {{add|sub}}
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp slt i32 [[CONV]], [[DEC]]
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%conv = fptosi float %x to i32
|
||||||
|
%dec = sub nsw i32 %y, 1
|
||||||
|
%cmp = icmp slt i32 %conv, %dec
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @cmp_ult_rhs_dec(float %x, i32 %y) {
|
||||||
|
; CHECK-LABEL: @cmp_ult_rhs_dec(
|
||||||
|
; CHECK-NEXT: [[CONV:%.*]] = fptosi float %x to i32
|
||||||
|
; CHECK-NEXT: [[DEC:%.*]] = {{add|sub}}
|
||||||
|
; CHECK-NEXT: [[CMP:%.*]] = icmp ult i32 [[CONV]], [[DEC]]
|
||||||
|
; CHECK-NEXT: ret i1 [[CMP]]
|
||||||
|
;
|
||||||
|
%conv = fptosi float %x to i32
|
||||||
|
%dec = sub nuw i32 %y, 1
|
||||||
|
%cmp = icmp ult i32 %conv, %dec
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user