mirror of
https://github.com/intel/llvm.git
synced 2026-01-12 18:27:07 +08:00
[InstSimplify] Support ptrtoaddr in simplifyICmpInst() (#171985)
This is basically the same change as #162653, but for InstSimplify instead of ConstantFolding. It folds `icmp (ptrtoaddr x, ptrtoaddr y)` to `icmp (x, y)` and `icmp (ptrtoaddr x, C)` to `icmp (x, inttoptr C)`. The fold is restricted to the case where the result type is the address type, as icmp only compares the icmp bits. As in the other PR, I think in practice all the folds are also going to work if the ptrtoint result type is larger than the address size, but it's unclear how to justify this in general.
This commit is contained in:
@@ -3847,17 +3847,19 @@ static Value *simplifyICmpInst(CmpPredicate Pred, Value *LHS, Value *RHS,
|
||||
Type *SrcTy = SrcOp->getType();
|
||||
Type *DstTy = LI->getType();
|
||||
|
||||
// Turn icmp (ptrtoint x), (ptrtoint/constant) into a compare of the input
|
||||
// if the integer type is the same size as the pointer type.
|
||||
if (MaxRecurse && isa<PtrToIntInst>(LI) &&
|
||||
Q.DL.getTypeSizeInBits(SrcTy) == DstTy->getPrimitiveSizeInBits()) {
|
||||
// Turn icmp (ptrtoint/ptrtoaddr x), (ptrtoint/ptrtoaddr/constant) into a
|
||||
// compare of the input if the integer type is the same size as the
|
||||
// pointer address type (icmp only compares the address of the pointer).
|
||||
if (MaxRecurse && (isa<PtrToIntInst, PtrToAddrInst>(LI)) &&
|
||||
Q.DL.getAddressType(SrcTy) == DstTy) {
|
||||
if (Constant *RHSC = dyn_cast<Constant>(RHS)) {
|
||||
// Transfer the cast to the constant.
|
||||
if (Value *V = simplifyICmpInst(Pred, SrcOp,
|
||||
ConstantExpr::getIntToPtr(RHSC, SrcTy),
|
||||
Q, MaxRecurse - 1))
|
||||
return V;
|
||||
} else if (PtrToIntInst *RI = dyn_cast<PtrToIntInst>(RHS)) {
|
||||
} else if (isa<PtrToIntInst, PtrToAddrInst>(RHS)) {
|
||||
auto *RI = cast<CastInst>(RHS);
|
||||
if (RI->getOperand(0)->getType() == SrcTy)
|
||||
// Compare without the cast.
|
||||
if (Value *V = simplifyICmpInst(Pred, SrcOp, RI->getOperand(0), Q,
|
||||
|
||||
@@ -398,3 +398,75 @@ define i1 @icmp_relational_ptrtoint_ptrtoint_addrsize() {
|
||||
%cmp = icmp ult i64 ptrtoint (ptr addrspace(1) @g.as1 to i64), ptrtoint (ptr addrspace(1) getelementptr inbounds (i8, ptr addrspace(1) @g.as1, i64 1) to i64)
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn(ptr %a) {
|
||||
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn(
|
||||
; CHECK-SAME: ptr [[A:%.*]]) {
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%gep = getelementptr i8, ptr %a, i64 1
|
||||
%a.addr = ptrtoaddr ptr %a to i64
|
||||
%gep.addr = ptrtoaddr ptr %gep to i64
|
||||
%cmp = icmp ne i64 %a.addr, %gep.addr
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn_addrsize(ptr addrspace(1) %a) {
|
||||
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_ptrtoaddr_dyn_addrsize(
|
||||
; CHECK-SAME: ptr addrspace(1) [[A:%.*]]) {
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%gep = getelementptr i8, ptr addrspace(1) %a, i32 1
|
||||
%a.addr = ptrtoaddr ptr addrspace(1) %a to i32
|
||||
%gep.addr = ptrtoaddr ptr addrspace(1) %gep to i32
|
||||
%cmp = icmp ne i32 %a.addr, %gep.addr
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
; This could still be folded, because the non-address bits being non-equal
|
||||
; implies that all bits taken together are also non-equal.
|
||||
define i1 @icmp_ptrtoint_ptrtoint_dyn_addrsize(ptr addrspace(1) %a) {
|
||||
; CHECK-LABEL: define i1 @icmp_ptrtoint_ptrtoint_dyn_addrsize(
|
||||
; CHECK-SAME: ptr addrspace(1) [[A:%.*]]) {
|
||||
; CHECK-NEXT: [[GEP:%.*]] = getelementptr i8, ptr addrspace(1) [[A]], i32 1
|
||||
; CHECK-NEXT: [[A_ADDR:%.*]] = ptrtoint ptr addrspace(1) [[A]] to i64
|
||||
; CHECK-NEXT: [[GEP_ADDR:%.*]] = ptrtoint ptr addrspace(1) [[GEP]] to i64
|
||||
; CHECK-NEXT: [[CMP:%.*]] = icmp ne i64 [[A_ADDR]], [[GEP_ADDR]]
|
||||
; CHECK-NEXT: ret i1 [[CMP]]
|
||||
;
|
||||
%gep = getelementptr i8, ptr addrspace(1) %a, i32 1
|
||||
%a.addr = ptrtoint ptr addrspace(1) %a to i64
|
||||
%gep.addr = ptrtoint ptr addrspace(1) %gep to i64
|
||||
%cmp = icmp ne i64 %a.addr, %gep.addr
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i1 @icmp_ptrtoaddr_null_dyn(ptr nonnull %a) {
|
||||
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_null_dyn(
|
||||
; CHECK-SAME: ptr nonnull [[A:%.*]]) {
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%a.addr = ptrtoaddr ptr %a to i64
|
||||
%cmp = icmp ne i64 %a.addr, 0
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i1 @icmp_ptrtoaddr_null_dyn_addrsize(ptr addrspace(1) nonnull %a) {
|
||||
; CHECK-LABEL: define i1 @icmp_ptrtoaddr_null_dyn_addrsize(
|
||||
; CHECK-SAME: ptr addrspace(1) nonnull [[A:%.*]]) {
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%a.addr = ptrtoaddr ptr addrspace(1) %a to i32
|
||||
%cmp = icmp ne i32 %a.addr, 0
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
define i1 @icmp_ptrtoint_null_dyn_addrsize(ptr addrspace(1) nonnull %a) {
|
||||
; CHECK-LABEL: define i1 @icmp_ptrtoint_null_dyn_addrsize(
|
||||
; CHECK-SAME: ptr addrspace(1) nonnull [[A:%.*]]) {
|
||||
; CHECK-NEXT: ret i1 true
|
||||
;
|
||||
%a.addr = ptrtoint ptr addrspace(1) %a to i64
|
||||
%cmp = icmp ne i64 %a.addr, 0
|
||||
ret i1 %cmp
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user