diff --git a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp --- a/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp +++ b/llvm/lib/Transforms/InstCombine/InstCombineCalls.cpp @@ -1944,18 +1944,21 @@ "support vector types and may not work for vectors"); Value *InnerPtr, *InnerMask; - if (match(II->getArgOperand(0), - m_OneUse(m_Intrinsic(m_Value(InnerPtr), - m_Value(InnerMask))))) { - if (II->getArgOperand(1)->getType() == InnerMask->getType()) { - Value *NewMask = Builder.CreateAnd(II->getArgOperand(1), InnerMask); - return replaceInstUsesWith( - *II, - Builder.CreateIntrinsic(InnerPtr->getType(), Intrinsic::ptrmask, - {InnerPtr, NewMask})); + bool Changed = false; + // Combine: + // (ptrmask (ptrmask p, A), B) + // -> (ptrmask p, (and A, B)) + if (match(Op0, m_OneUse(m_Intrinsic( + m_Value(InnerPtr), m_Value(InnerMask))))) { + if (InnerMask->getType() == Op1->getType()) { + // TODO: If InnerMask == Op1, we could copy attributes from inner + // callsite -> outer callsite. + Value *NewMask = Builder.CreateAnd(Op1, InnerMask); + replaceOperand(CI, 0, InnerPtr); + replaceOperand(CI, 1, NewMask); + Changed = true; } } - bool Changed = false; // See if we can deduce non-null. if (!CI.hasRetAttr(Attribute::NonNull) && (Known.isNonZero() || 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 @@ -8,7 +8,7 @@ ; CHECK-LABEL: define ptr @ptrmask_combine_consecutive_preserve_attrs ; CHECK-SAME: (ptr [[P0:%.*]], i64 [[M1:%.*]]) { ; CHECK-NEXT: [[TMP1:%.*]] = and i64 [[M1]], 224 -; CHECK-NEXT: [[R:%.*]] = call align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[TMP1]]) +; CHECK-NEXT: [[R:%.*]] = call noalias align 32 ptr @llvm.ptrmask.p0.i64(ptr [[P0]], i64 [[TMP1]]) ; CHECK-NEXT: ret ptr [[R]] ; %pm0 = call ptr @llvm.ptrmask.p0.i64(ptr %p0, i64 224)