================ @@ -2689,59 +2689,82 @@ SDValue DAGCombiner::visitPTRADD(SDNode *N) { if (PtrVT == IntVT && isNullConstant(N0)) return N1; - if (N0.getOpcode() != ISD::PTRADD || - reassociationCanBreakAddressingModePattern(ISD::PTRADD, DL, N, N0, N1)) - return SDValue(); - - SDValue X = N0.getOperand(0); - SDValue Y = N0.getOperand(1); - SDValue Z = N1; - bool N0OneUse = N0.hasOneUse(); - bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y); - bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z); - - // (ptradd (ptradd x, y), z) -> (ptradd x, (add y, z)) if: - // * y is a constant and (ptradd x, y) has one use; or - // * y and z are both constants. - if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) { - // If both additions in the original were NUW, the new ones are as well. - SDNodeFlags Flags = - (N->getFlags() & N0->getFlags()) & SDNodeFlags::NoUnsignedWrap; - SDValue Add = DAG.getNode(ISD::ADD, DL, IntVT, {Y, Z}, Flags); - AddToWorklist(Add.getNode()); - return DAG.getMemBasePlusOffset(X, Add, DL, Flags); + if (N0.getOpcode() == ISD::PTRADD && + !reassociationCanBreakAddressingModePattern(ISD::PTRADD, DL, N, N0, N1)) { + SDValue X = N0.getOperand(0); + SDValue Y = N0.getOperand(1); + SDValue Z = N1; + bool N0OneUse = N0.hasOneUse(); + bool YIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Y); + bool ZIsConstant = DAG.isConstantIntBuildVectorOrConstantInt(Z); + + // (ptradd (ptradd x, y), z) -> (ptradd x, (add y, z)) if: + // * y is a constant and (ptradd x, y) has one use; or + // * y and z are both constants. + if ((YIsConstant && N0OneUse) || (YIsConstant && ZIsConstant)) { + // If both additions in the original were NUW, the new ones are as well. + SDNodeFlags Flags = + (N->getFlags() & N0->getFlags()) & SDNodeFlags::NoUnsignedWrap; + SDValue Add = DAG.getNode(ISD::ADD, DL, IntVT, {Y, Z}, Flags); + AddToWorklist(Add.getNode()); + return DAG.getMemBasePlusOffset(X, Add, DL, Flags); + } + } + + // The following combines can turn in-bounds pointer arithmetic out of bounds. + // That is problematic for settings like AArch64's CPA, which checks that + // intermediate results of pointer arithmetic remain in bounds. The target + // therefore needs to opt-in to enable them. + if (!TLI.canTransformPtrArithOutOfBounds( + DAG.getMachineFunction().getFunction(), PtrVT)) + return SDValue(); + + if (N0.getOpcode() == ISD::PTRADD && N1.getOpcode() == ISD::Constant) { ---------------- ritter-x2a wrote:
I changed it to use `isa<ConstantSDNode>(N1)` for now and added a TODO to support vector splats. With the current state, I haven't found a way to get a splat constant as an offset for a global variable to test this situation: The SelectionDAGBuilder automatically translates `(gep scalarptr, splat(C))` into `(splat (ptradd scalarptr, C))` and we currently don't generate PTRADDs for a GEP with a vector of pointers (`SITargetLowering::shouldPreservePtrArith` checks `PtrVT == MVT::i64`). I don't think we should implement support for vector splats without a way of testing it. Also, `SelectionDAG::FoldSymbolOffset` needs to support vector splats so that it makes sense to support them here. https://github.com/llvm/llvm-project/pull/146074 _______________________________________________ llvm-branch-commits mailing list llvm-branch-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-branch-commits