mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-10-19 11:02:59 +02:00
[InstSimplify] Teach decomposeBitTestICmp to handle non-canonical compares
This adds support non-canonical compare predicates. InstSimplify can't rely on canonicalization to have occurred. Differential Revision: https://reviews.llvm.org/D36646 llvm-svn: 310893
This commit is contained in:
parent
4947e7accc
commit
182026cffe
@ -81,6 +81,13 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
|
||||
Mask = APInt::getSignMask(C->getBitWidth());
|
||||
Pred = ICmpInst::ICMP_NE;
|
||||
break;
|
||||
case ICmpInst::ICMP_SLE:
|
||||
// X <= -1 is equivalent to (X & SignMask) != 0.
|
||||
if (!C->isAllOnesValue())
|
||||
return false;
|
||||
Mask = APInt::getSignMask(C->getBitWidth());
|
||||
Pred = ICmpInst::ICMP_NE;
|
||||
break;
|
||||
case ICmpInst::ICMP_SGT:
|
||||
// X > -1 is equivalent to (X & SignMask) == 0.
|
||||
if (!C->isAllOnesValue())
|
||||
@ -88,6 +95,13 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
|
||||
Mask = APInt::getSignMask(C->getBitWidth());
|
||||
Pred = ICmpInst::ICMP_EQ;
|
||||
break;
|
||||
case ICmpInst::ICMP_SGE:
|
||||
// X >= 0 is equivalent to (X & SignMask) == 0.
|
||||
if (!C->isNullValue())
|
||||
return false;
|
||||
Mask = APInt::getSignMask(C->getBitWidth());
|
||||
Pred = ICmpInst::ICMP_EQ;
|
||||
break;
|
||||
case ICmpInst::ICMP_ULT:
|
||||
// X <u 2^n is equivalent to (X & ~(2^n-1)) == 0.
|
||||
if (!C->isPowerOf2())
|
||||
@ -95,6 +109,13 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
|
||||
Mask = -*C;
|
||||
Pred = ICmpInst::ICMP_EQ;
|
||||
break;
|
||||
case ICmpInst::ICMP_ULE:
|
||||
// X <=u 2^n-1 is equivalent to (X & ~(2^n-1)) == 0.
|
||||
if (!(*C + 1).isPowerOf2())
|
||||
return false;
|
||||
Mask = ~*C;
|
||||
Pred = ICmpInst::ICMP_EQ;
|
||||
break;
|
||||
case ICmpInst::ICMP_UGT:
|
||||
// X >u 2^n-1 is equivalent to (X & ~(2^n-1)) != 0.
|
||||
if (!(*C + 1).isPowerOf2())
|
||||
@ -102,6 +123,13 @@ bool llvm::decomposeBitTestICmp(Value *LHS, Value *RHS,
|
||||
Mask = ~*C;
|
||||
Pred = ICmpInst::ICMP_NE;
|
||||
break;
|
||||
case ICmpInst::ICMP_UGE:
|
||||
// X >=u 2^n is equivalent to (X & ~(2^n-1)) != 0.
|
||||
if (!C->isPowerOf2())
|
||||
return false;
|
||||
Mask = -*C;
|
||||
Pred = ICmpInst::ICMP_NE;
|
||||
break;
|
||||
}
|
||||
|
||||
X = LHS;
|
||||
|
@ -47,13 +47,10 @@ define i32 @test4(i32 %X) {
|
||||
}
|
||||
|
||||
; Same as above, but the compare isn't canonical
|
||||
; TODO: we should be able to simplify this
|
||||
define i32 @test4noncanon(i32 %X) {
|
||||
; CHECK-LABEL: @test4noncanon(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sle i32 [[X:%.*]], -1
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], -2147483648
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[OR]]
|
||||
; CHECK-NEXT: ret i32 [[COND]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
|
||||
; CHECK-NEXT: ret i32 [[OR]]
|
||||
;
|
||||
%cmp = icmp sle i32 %X, -1
|
||||
%or = or i32 %X, -2147483648
|
||||
@ -114,13 +111,10 @@ define i32 @test9(i32 %X) {
|
||||
}
|
||||
|
||||
; Same as above, but the compare isn't canonical
|
||||
; TODO: we should be able to simplify this
|
||||
define i32 @test9noncanon(i32 %X) {
|
||||
; CHECK-LABEL: @test9noncanon(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp sge i32 [[X:%.*]], 0
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X]], -2147483648
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[OR]], i32 [[X]]
|
||||
; CHECK-NEXT: ret i32 [[COND]]
|
||||
; CHECK-NEXT: [[OR:%.*]] = or i32 [[X:%.*]], -2147483648
|
||||
; CHECK-NEXT: ret i32 [[OR]]
|
||||
;
|
||||
%cmp = icmp sge i32 %X, 0
|
||||
%or = or i32 %X, -2147483648
|
||||
@ -172,13 +166,10 @@ define i32 @test12(i32 %X) {
|
||||
}
|
||||
|
||||
; Same as above, but the compare isn't canonical
|
||||
; TODO: we should be able to simplify this
|
||||
define i32 @test12noncanon(i32 %X) {
|
||||
; CHECK-LABEL: @test12noncanon(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ule i32 [[X:%.*]], 3
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 3
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[X]], i32 [[AND]]
|
||||
; CHECK-NEXT: ret i32 [[COND]]
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
|
||||
; CHECK-NEXT: ret i32 [[AND]]
|
||||
;
|
||||
%cmp = icmp ule i32 %X, 3
|
||||
%and = and i32 %X, 3
|
||||
@ -198,13 +189,10 @@ define i32 @test13(i32 %X) {
|
||||
}
|
||||
|
||||
; Same as above, but the compare isn't canonical
|
||||
; TODO: we should be able to simplify this
|
||||
define i32 @test13noncanon(i32 %X) {
|
||||
; CHECK-LABEL: @test13noncanon(
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp uge i32 [[X:%.*]], 4
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X]], 3
|
||||
; CHECK-NEXT: [[COND:%.*]] = select i1 [[CMP]], i32 [[AND]], i32 [[X]]
|
||||
; CHECK-NEXT: ret i32 [[COND]]
|
||||
; CHECK-NEXT: [[AND:%.*]] = and i32 [[X:%.*]], 3
|
||||
; CHECK-NEXT: ret i32 [[AND]]
|
||||
;
|
||||
%cmp = icmp uge i32 %X, 4
|
||||
%and = and i32 %X, 3
|
||||
|
Loading…
Reference in New Issue
Block a user