mirror of
https://github.com/c64scene-ar/llvm-6502.git
synced 2025-06-15 21:24:00 +00:00
Teach instsimplify how to simplify comparisons of pointers which are
constant-offsets of a common base using the generic GEP-walking logic I added for computing pointer differences in the same situation. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@153419 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
@ -1591,6 +1591,45 @@ static Value *ExtractEquivalentCondition(Value *V, CmpInst::Predicate Pred,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Constant *computePointerICmp(const TargetData &TD,
|
||||||
|
CmpInst::Predicate Pred,
|
||||||
|
Value *LHS, Value *RHS) {
|
||||||
|
// We can only fold certain predicates on pointer comparisons.
|
||||||
|
switch (Pred) {
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// Equality comaprisons are easy to fold.
|
||||||
|
case CmpInst::ICMP_EQ:
|
||||||
|
case CmpInst::ICMP_NE:
|
||||||
|
break;
|
||||||
|
|
||||||
|
// We can only handle unsigned relational comparisons because 'inbounds' on
|
||||||
|
// a GEP only protects against unsigned wrapping.
|
||||||
|
case CmpInst::ICMP_UGT:
|
||||||
|
case CmpInst::ICMP_UGE:
|
||||||
|
case CmpInst::ICMP_ULT:
|
||||||
|
case CmpInst::ICMP_ULE:
|
||||||
|
// However, we have to switch them to their signed variants to handle
|
||||||
|
// negative indices from the base pointer.
|
||||||
|
Pred = ICmpInst::getSignedPredicate(Pred);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
Constant *LHSOffset = stripAndComputeConstantOffsets(TD, LHS);
|
||||||
|
if (!LHSOffset)
|
||||||
|
return 0;
|
||||||
|
Constant *RHSOffset = stripAndComputeConstantOffsets(TD, RHS);
|
||||||
|
if (!RHSOffset)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
// If LHS and RHS are not related via constant offsets to the same base
|
||||||
|
// value, there is nothing we can do here.
|
||||||
|
if (LHS != RHS)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
return ConstantExpr::getICmp(Pred, LHSOffset, RHSOffset);
|
||||||
|
}
|
||||||
|
|
||||||
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
/// SimplifyICmpInst - Given operands for an ICmpInst, see if we can
|
||||||
/// fold the result. If not, this returns null.
|
/// fold the result. If not, this returns null.
|
||||||
@ -2311,7 +2350,12 @@ static Value *SimplifyICmpInst(unsigned Predicate, Value *LHS, Value *RHS,
|
|||||||
return getFalse(ITy);
|
return getFalse(ITy);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Simplify comparisons of GEPs.
|
// Simplify comparisons of related pointers using a powerful, recursive
|
||||||
|
// GEP-walk when we have target data available..
|
||||||
|
if (Q.TD && LHS->getType()->isPointerTy() && RHS->getType()->isPointerTy())
|
||||||
|
if (Constant *C = computePointerICmp(*Q.TD, Pred, LHS, RHS))
|
||||||
|
return C;
|
||||||
|
|
||||||
if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) {
|
if (GetElementPtrInst *GLHS = dyn_cast<GetElementPtrInst>(LHS)) {
|
||||||
if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) {
|
if (GEPOperator *GRHS = dyn_cast<GEPOperator>(RHS)) {
|
||||||
if (GLHS->getPointerOperand() == GRHS->getPointerOperand() &&
|
if (GLHS->getPointerOperand() == GRHS->getPointerOperand() &&
|
||||||
|
@ -103,6 +103,68 @@ define i1 @gep8(%gept* %x) {
|
|||||||
; CHECK: ret i1 %equal
|
; CHECK: ret i1 %equal
|
||||||
}
|
}
|
||||||
|
|
||||||
|
define i1 @gep9(i8* %ptr) {
|
||||||
|
; CHECK: @gep9
|
||||||
|
; CHECK-NOT: ret
|
||||||
|
; CHECK: ret i1 true
|
||||||
|
|
||||||
|
entry:
|
||||||
|
%first1 = getelementptr inbounds i8* %ptr, i32 0
|
||||||
|
%first2 = getelementptr inbounds i8* %first1, i32 1
|
||||||
|
%first3 = getelementptr inbounds i8* %first2, i32 2
|
||||||
|
%first4 = getelementptr inbounds i8* %first3, i32 4
|
||||||
|
%last1 = getelementptr inbounds i8* %first2, i32 48
|
||||||
|
%last2 = getelementptr inbounds i8* %last1, i32 8
|
||||||
|
%last3 = getelementptr inbounds i8* %last2, i32 -4
|
||||||
|
%last4 = getelementptr inbounds i8* %last3, i32 -4
|
||||||
|
%first.int = ptrtoint i8* %first4 to i32
|
||||||
|
%last.int = ptrtoint i8* %last4 to i32
|
||||||
|
%cmp = icmp ne i32 %last.int, %first.int
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @gep10(i8* %ptr) {
|
||||||
|
; CHECK: @gep10
|
||||||
|
; CHECK-NOT: ret
|
||||||
|
; CHECK: ret i1 true
|
||||||
|
|
||||||
|
entry:
|
||||||
|
%first1 = getelementptr inbounds i8* %ptr, i32 -2
|
||||||
|
%first2 = getelementptr inbounds i8* %first1, i32 44
|
||||||
|
%last1 = getelementptr inbounds i8* %ptr, i32 48
|
||||||
|
%last2 = getelementptr inbounds i8* %last1, i32 -6
|
||||||
|
%first.int = ptrtoint i8* %first2 to i32
|
||||||
|
%last.int = ptrtoint i8* %last2 to i32
|
||||||
|
%cmp = icmp eq i32 %last.int, %first.int
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @gep11(i8* %ptr) {
|
||||||
|
; CHECK: @gep11
|
||||||
|
; CHECK-NOT: ret
|
||||||
|
; CHECK: ret i1 true
|
||||||
|
|
||||||
|
entry:
|
||||||
|
%first1 = getelementptr inbounds i8* %ptr, i32 -2
|
||||||
|
%last1 = getelementptr inbounds i8* %ptr, i32 48
|
||||||
|
%last2 = getelementptr inbounds i8* %last1, i32 -6
|
||||||
|
%cmp = icmp ult i8* %first1, %last2
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
|
define i1 @gep12(i8* %ptr) {
|
||||||
|
; CHECK: @gep12
|
||||||
|
; CHECK-NOT: ret
|
||||||
|
; CHECK: ret i1 %cmp
|
||||||
|
|
||||||
|
entry:
|
||||||
|
%first1 = getelementptr inbounds i8* %ptr, i32 -2
|
||||||
|
%last1 = getelementptr inbounds i8* %ptr, i32 48
|
||||||
|
%last2 = getelementptr inbounds i8* %last1, i32 -6
|
||||||
|
%cmp = icmp slt i8* %first1, %last2
|
||||||
|
ret i1 %cmp
|
||||||
|
}
|
||||||
|
|
||||||
define i1 @zext(i32 %x) {
|
define i1 @zext(i32 %x) {
|
||||||
; CHECK: @zext
|
; CHECK: @zext
|
||||||
%e1 = zext i32 %x to i64
|
%e1 = zext i32 %x to i64
|
||||||
|
Reference in New Issue
Block a user