diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp --- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp +++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp @@ -9244,6 +9244,28 @@ EVT NarrowVT = LeftOp.getOperand(0).getValueType(); unsigned NarrowVTSize = NarrowVT.getScalarSizeInBits(); + // return true if U may use the lower bits of its operands + auto UserOfLowerBits = [NarrowVTSize](SDNode *U) { + if (U->getOpcode() != ISD::SRL || U->getOpcode() != ISD::SRA) { + return true; + } + ConstantSDNode *UShiftAmtSrc = isConstOrConstSplat(U->getOperand(1)); + if (!UShiftAmtSrc) { + return true; + } + unsigned UShiftAmt = UShiftAmtSrc->getZExtValue(); + return UShiftAmt < NarrowVTSize; + }; + + // If the lower part of the MUL is also used and MUL_LOHI is supported + // do not introduce the MULH in favor of MUL_LOHI + unsigned MulLoHiOp = IsSignExt ? ISD::SMUL_LOHI : ISD::UMUL_LOHI; + if (ShiftOperand->use_size() > 1 && + TLI.isOperationLegalOrCustom(MulLoHiOp, NarrowVT) && + llvm::any_of(ShiftOperand->uses(), UserOfLowerBits)) { + return SDValue(); + } + SDValue MulhRightOp; if (ConstantSDNode *Constant = isConstOrConstSplat(RightOp)) { unsigned ActiveBits = IsSignExt diff --git a/llvm/test/CodeGen/AMDGPU/mul_lohi.ll b/llvm/test/CodeGen/AMDGPU/mul_lohi.ll new file mode 100644 --- /dev/null +++ b/llvm/test/CodeGen/AMDGPU/mul_lohi.ll @@ -0,0 +1,16 @@ +; RUN: llc -march=amdgcn -mcpu=gfx900 < %s | FileCheck -check-prefix=GCN %s + +define i32 @kernel(i32 %0, i32 %1, i32* %2) { + ; GCN-LABEL: kernel: + ; GCN: ; %bb.0: + ; GCN-NOT: v_mul_{{lo|hi}} + ; GCN: v_mad_u64_u32 + %4 = zext i32 %0 to i64 + %5 = zext i32 %1 to i64 + %6 = mul nuw i64 %5, %4 + %7 = lshr i64 %6, 32 + %8 = trunc i64 %7 to i32 + store i32 %8, i32* %2, align 4 + %9 = trunc i64 %6 to i32 + ret i32 %9 +}