diff --git a/llvm/include/llvm/IR/PatternMatch.h b/llvm/include/llvm/IR/PatternMatch.h index 2e31fe5bb431e..79342777aba4b 100644 --- a/llvm/include/llvm/IR/PatternMatch.h +++ b/llvm/include/llvm/IR/PatternMatch.h @@ -2184,6 +2184,18 @@ inline PtrToIntSameSize_match m_PtrToIntSameSize(const DataLayout &DL, return PtrToIntSameSize_match(DL, Op); } +/// Matches PtrToAddr. +template +inline CastOperator_match +m_PtrToAddr(const OpTy &Op) { + return CastOperator_match(Op); +} + +/// Matches PtrToInt or PtrToAddr. +template inline auto m_PtrToIntOrAddr(const OpTy &Op) { + return m_CombineOr(m_PtrToInt(Op), m_PtrToAddr(Op)); +} + /// Matches IntToPtr. template inline CastOperator_match diff --git a/llvm/lib/Analysis/InstructionSimplify.cpp b/llvm/lib/Analysis/InstructionSimplify.cpp index d1977f0b0daf9..71050a4117d5a 100644 --- a/llvm/lib/Analysis/InstructionSimplify.cpp +++ b/llvm/lib/Analysis/InstructionSimplify.cpp @@ -853,10 +853,12 @@ static Value *simplifySubInst(Value *Op0, Value *Op1, bool IsNSW, bool IsNUW, return W; // Variations on GEP(base, I, ...) - GEP(base, i, ...) -> GEP(null, I-i, ...). - if (match(Op0, m_PtrToInt(m_Value(X))) && match(Op1, m_PtrToInt(m_Value(Y)))) + if (match(Op0, m_PtrToIntOrAddr(m_Value(X))) && + match(Op1, m_PtrToIntOrAddr(m_Value(Y)))) { if (Constant *Result = computePointerDifference(Q.DL, X, Y)) return ConstantFoldIntegerCast(Result, Op0->getType(), /*IsSigned*/ true, Q.DL); + } // i1 sub -> xor. if (MaxRecurse && Op0->getType()->isIntOrIntVectorTy(1)) diff --git a/llvm/test/Transforms/InstCombine/ptrtoaddr.ll b/llvm/test/Transforms/InstCombine/ptrtoaddr.ll index 5211fbd8b897a..1de8ea7a662c2 100644 --- a/llvm/test/Transforms/InstCombine/ptrtoaddr.ll +++ b/llvm/test/Transforms/InstCombine/ptrtoaddr.ll @@ -130,3 +130,27 @@ define i32 @ptrtoaddr_sub_consts_offset_addrsize() { ; ret i32 sub (i32 ptrtoaddr (ptr addrspace(1) getelementptr (i8, ptr addrspace(1) @g.as1, i32 42) to i32), i32 ptrtoaddr (ptr addrspace(1) @g.as1 to i32)) } + +define i64 @ptrtoaddr_sub_known_offset(ptr %p) { +; CHECK-LABEL: define i64 @ptrtoaddr_sub_known_offset( +; CHECK-SAME: ptr [[P:%.*]]) { +; CHECK-NEXT: ret i64 42 +; + %p2 = getelementptr inbounds i8, ptr %p, i64 42 + %p.addr = ptrtoaddr ptr %p to i64 + %p2.addr = ptrtoaddr ptr %p2 to i64 + %sub = sub i64 %p2.addr, %p.addr + ret i64 %sub +} + +define i32 @ptrtoaddr_sub_known_offset_addrsize(ptr addrspace(1) %p) { +; CHECK-LABEL: define i32 @ptrtoaddr_sub_known_offset_addrsize( +; CHECK-SAME: ptr addrspace(1) [[P:%.*]]) { +; CHECK-NEXT: ret i32 42 +; + %p2 = getelementptr inbounds i8, ptr addrspace(1) %p, i32 42 + %p.addr = ptrtoaddr ptr addrspace(1) %p to i32 + %p2.addr = ptrtoaddr ptr addrspace(1) %p2 to i32 + %sub = sub i32 %p2.addr, %p.addr + ret i32 %sub +}