Index: llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp =================================================================== --- llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -2625,6 +2625,21 @@ return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(0), VS); } + // fold a+truncate(vscale(c1))+truncate(vscale(c2)) + // to a+truncate(vscale(c1+c2)) + if (VT.isScalarInteger() && (N0.getOpcode() == ISD::ADD) && + (N0.getOperand(1).getOpcode() == ISD::TRUNCATE) && + (N0.getOperand(1).getOperand(0).getOpcode() == ISD::VSCALE) && + (N1.getOpcode() == ISD::TRUNCATE) && + (N1.getOperand(0).getOpcode() == ISD::VSCALE)) { + EVT VSVT = N1.getOperand(0).getValueType(); + const APInt &VS0 = + N0.getOperand(1).getOperand(0)->getConstantOperandAPInt(0); + const APInt &VS1 = N1.getOperand(0)->getConstantOperandAPInt(0); + SDValue VS = DAG.getZExtOrTrunc(DAG.getVScale(DL, VSVT, VS0 + VS1), DL, VT); + return DAG.getNode(ISD::ADD, DL, VT, N0.getOperand(0), VS); + } + // Fold (add step_vector(c1), step_vector(c2) to step_vector(c1+c2)) if (N0.getOpcode() == ISD::STEP_VECTOR && N1.getOpcode() == ISD::STEP_VECTOR) { Index: llvm/test/CodeGen/AArch64/sve-vscale-combine.ll =================================================================== --- llvm/test/CodeGen/AArch64/sve-vscale-combine.ll +++ llvm/test/CodeGen/AArch64/sve-vscale-combine.ll @@ -95,3 +95,17 @@ %shl = shl i32 %vscale, 4 ret i32 %shl } + +; Fold a+truncate(vscale(c1))+truncate(vscale(c2)) to a+truncate(vscale(c1+c2)) +define i32 @combine_add_vscale_C_i32(i32 %index) nounwind { +; CHECK-LABEL: combine_add_vscale_C_i32: +; CHECK-NEXT: cntd x8, all, mul #5 +; CHECK-NEXT: add w0, w0, w8 +; CHECK-NEXT: ret + %vscale = call i32 @llvm.vscale.i32() + %mul8 = mul i32 %vscale, 8 + %mul2 = mul i32 %vscale, 2 + %index.next = add nuw i32 %index, %mul8 + %add = add nuw i32 %index.next, %mul2 + ret i32 %add +}