[llvm] a35add4 - [MIPS] Correct the implementation of the msub optimization
Simon Dardis via llvm-commits
llvm-commits at lists.llvm.org
Thu May 12 14:33:32 PDT 2022
Author: Simon Dardis
Date: 2022-05-12T22:33:18+01:00
New Revision: a35add4c54be96a42fefc01ae1d74a23e3c16030
URL: https://github.com/llvm/llvm-project/commit/a35add4c54be96a42fefc01ae1d74a23e3c16030
DIFF: https://github.com/llvm/llvm-project/commit/a35add4c54be96a42fefc01ae1d74a23e3c16030.diff
LOG: [MIPS] Correct the implementation of the msub optimization
The MIPS backend attempts to combine integer multiply and addition or
subtraction into a madd or msub operation. This optimization is
heavily restricted due to its utility in many cases.
PR/51114 highlighted that the optimization was performed on an
associative basis which is correct in the `add` case but not in
the `sub` case.
Resolve this bug by performing an early exit in the case where the
multiply is the LHS operand of the subtraction.
This resolves PR/51114.
Thanks to digitalseraphim for reporting the issue!
Differential Revision: https://reviews.llvm.org/D124742
Added:
Modified:
llvm/lib/Target/Mips/MipsISelLowering.cpp
llvm/test/CodeGen/Mips/madd-msub.ll
Removed:
################################################################################
diff --git a/llvm/lib/Target/Mips/MipsISelLowering.cpp b/llvm/lib/Target/Mips/MipsISelLowering.cpp
index e5dbc50b3c263..10b2df072995a 100644
--- a/llvm/lib/Target/Mips/MipsISelLowering.cpp
+++ b/llvm/lib/Target/Mips/MipsISelLowering.cpp
@@ -950,6 +950,14 @@ static SDValue performMADD_MSUBCombine(SDNode *ROOTNode, SelectionDAG &CurDAG,
ROOTNode->getOperand(1).getOpcode() != ISD::MUL)
return SDValue();
+ // In the case where we have a multiplication as the left operand of
+ // of a subtraction, we can't combine into a MipsISD::MSub node as the
+ // the instruction definition of msub(u) places the multiplication on
+ // on the right.
+ if (ROOTNode->getOpcode() == ISD::SUB &&
+ ROOTNode->getOperand(0).getOpcode() == ISD::MUL)
+ return SDValue();
+
// We don't handle vector types here.
if (ROOTNode->getValueType(0).isVector())
return SDValue();
diff --git a/llvm/test/CodeGen/Mips/madd-msub.ll b/llvm/test/CodeGen/Mips/madd-msub.ll
index 8d261c1880e30..3a6fd68e9df2e 100644
--- a/llvm/test/CodeGen/Mips/madd-msub.ll
+++ b/llvm/test/CodeGen/Mips/madd-msub.ll
@@ -507,3 +507,79 @@ entry:
ret i32 %sub
}
+
+define i64 @msub5(i32 %a, i32 %b, i32 %c) {
+; 32-LABEL: msub5:
+; 32: # %bb.0: # %entry
+; 32-NEXT: mult $5, $4
+; 32-NEXT: mfhi $1
+; 32-NEXT: mflo $3
+; 32-NEXT: sltu $2, $3, $6
+; 32-NEXT: sra $4, $6, 31
+; 32-NEXT: subu $1, $1, $4
+; 32-NEXT: subu $2, $1, $2
+; 32-NEXT: jr $ra
+; 32-NEXT: subu $3, $3, $6
+;
+; 32R6-LABEL: msub5:
+; 32R6: # %bb.0: # %entry
+; 32R6-NEXT: mul $1, $5, $4
+; 32R6-NEXT: sltu $2, $1, $6
+; 32R6-NEXT: muh $3, $5, $4
+; 32R6-NEXT: sra $4, $6, 31
+; 32R6-NEXT: subu $3, $3, $4
+; 32R6-NEXT: subu $2, $3, $2
+; 32R6-NEXT: jr $ra
+; 32R6-NEXT: subu $3, $1, $6
+;
+; DSP-LABEL: msub5:
+; DSP: # %bb.0: # %entry
+; DSP-NEXT: mult $ac0, $5, $4
+; DSP-NEXT: mfhi $1, $ac0
+; DSP-NEXT: mflo $3, $ac0
+; DSP-NEXT: sltu $2, $3, $6
+; DSP-NEXT: sra $4, $6, 31
+; DSP-NEXT: subu $1, $1, $4
+; DSP-NEXT: subu $2, $1, $2
+; DSP-NEXT: jr $ra
+; DSP-NEXT: subu $3, $3, $6
+;
+; 64-LABEL: msub5:
+; 64: # %bb.0: # %entry
+; 64-NEXT: sll $1, $4, 0
+; 64-NEXT: sll $2, $5, 0
+; 64-NEXT: dmult $2, $1
+; 64-NEXT: mflo $1
+; 64-NEXT: sll $2, $6, 0
+; 64-NEXT: jr $ra
+; 64-NEXT: dsubu $2, $1, $2
+;
+; 64R6-LABEL: msub5:
+; 64R6: # %bb.0: # %entry
+; 64R6-NEXT: sll $1, $4, 0
+; 64R6-NEXT: sll $2, $5, 0
+; 64R6-NEXT: dmul $1, $2, $1
+; 64R6-NEXT: sll $2, $6, 0
+; 64R6-NEXT: jr $ra
+; 64R6-NEXT: dsubu $2, $1, $2
+;
+; 16-LABEL: msub5:
+; 16: # %bb.0: # %entry
+; 16-NEXT: mult $5, $4
+; 16-NEXT: mflo $2
+; 16-NEXT: mfhi $4
+; 16-NEXT: subu $3, $2, $6
+; 16-NEXT: sltu $2, $6
+; 16-NEXT: move $2, $24
+; 16-NEXT: sra $5, $6, 31
+; 16-NEXT: subu $4, $4, $5
+; 16-NEXT: subu $2, $4, $2
+; 16-NEXT: jrc $ra
+entry:
+ %conv = sext i32 %a to i64
+ %conv3 = sext i32 %b to i64
+ %conv4 = sext i32 %c to i64
+ %mul = mul nsw i64 %conv3, %conv
+ %sub = sub nsw i64 %mul, %conv4
+ ret i64 %sub
+}
More information about the llvm-commits
mailing list