diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCasts.cpp @@ -1955,6 +1955,15 @@ return CastInst::CreateIntegerCast(P, Ty, /*isSigned=*/false); } + // (ptrtoint (ptrmask P, M)) + // -> (and (ptrtoint P), M) + // This is generally beneficial as `and` is better supported than `ptrmask`. + Value *Ptr, *Mask; + if (match(SrcOp, m_OneUse(m_Intrinsic(m_Value(Ptr), + m_Value(Mask)))) && + Mask->getType() == Ty) + return BinaryOperator::CreateAnd(Builder.CreatePtrToInt(Ptr, Ty), Mask); + if (auto *GEP = dyn_cast(SrcOp)) { // Fold ptrtoint(gep null, x) to multiply + constant if the GEP has one use. // While this can increase the number of instructions it doesn't actually diff --git a/llvm/test/Transforms/InstCombine/ptrmask.ll b/llvm/test/Transforms/InstCombine/ptrmask.ll --- a/llvm/test/Transforms/InstCombine/ptrmask.ll +++ b/llvm/test/Transforms/InstCombine/ptrmask.ll @@ -118,8 +118,8 @@ define i64 @ptrtoint_of_ptrmask(ptr %p, i64 %m) { ; CHECK-LABEL: define i64 @ptrtoint_of_ptrmask ; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) { -; CHECK-NEXT: [[PM:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 [[M]]) -; CHECK-NEXT: [[R:%.*]] = ptrtoint ptr [[PM]] to i64 +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 +; CHECK-NEXT: [[R:%.*]] = and i64 [[TMP1]], [[M]] ; CHECK-NEXT: ret i64 [[R]] ; %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m) @@ -131,9 +131,9 @@ define i32 @ptrtoint_of_ptrmask2(ptr %p, i64 %m) { ; CHECK-LABEL: define i32 @ptrtoint_of_ptrmask2 ; CHECK-SAME: (ptr [[P:%.*]], i64 [[M:%.*]]) { -; CHECK-NEXT: [[PM:%.*]] = call ptr @llvm.ptrmask.p0.i64(ptr [[P]], i64 [[M]]) -; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[PM]] to i64 -; CHECK-NEXT: [[R:%.*]] = trunc i64 [[TMP1]] to i32 +; CHECK-NEXT: [[TMP1:%.*]] = ptrtoint ptr [[P]] to i64 +; CHECK-NEXT: [[TMP2:%.*]] = and i64 [[TMP1]], [[M]] +; CHECK-NEXT: [[R:%.*]] = trunc i64 [[TMP2]] to i32 ; CHECK-NEXT: ret i32 [[R]] ; %pm = call ptr @llvm.ptrmask.p0.i64(ptr %p, i64 %m)