aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/CodeGen
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/CodeGen')
-rw-r--r--llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp67
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp5
-rw-r--r--llvm/lib/CodeGen/SelectionDAG/FastISel.cpp3
3 files changed, 71 insertions, 4 deletions
diff --git a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
index 0ebee2c..fa0ccd6 100644
--- a/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
+++ b/llvm/lib/CodeGen/GlobalISel/CombinerHelper.cpp
@@ -6745,6 +6745,73 @@ bool CombinerHelper::matchCombineFMinMaxNaN(MachineInstr &MI,
return MatchNaN(1) || MatchNaN(2);
}
+// Combine multiple FDIVs with the same divisor into multiple FMULs by the
+// reciprocal.
+// E.g., (a / Y; b / Y;) -> (recip = 1.0 / Y; a * recip; b * recip)
+bool CombinerHelper::matchRepeatedFPDivisor(
+ MachineInstr &MI, SmallVector<MachineInstr *> &MatchInfo) const {
+ assert(MI.getOpcode() == TargetOpcode::G_FDIV);
+
+ Register X = MI.getOperand(1).getReg();
+ Register Y = MI.getOperand(2).getReg();
+
+ if (!MI.getFlag(MachineInstr::MIFlag::FmArcp))
+ return false;
+
+ // Skip if current node is a reciprocal/fneg-reciprocal.
+ auto N0CFP = isConstantOrConstantSplatVectorFP(*MRI.getVRegDef(X), MRI);
+ if (N0CFP && (N0CFP->isExactlyValue(1.0) || N0CFP->isExactlyValue(-1.0)))
+ return false;
+
+ // Exit early if the target does not want this transform or if there can't
+ // possibly be enough uses of the divisor to make the transform worthwhile.
+ unsigned MinUses = getTargetLowering().combineRepeatedFPDivisors();
+ if (!MinUses)
+ return false;
+
+ // Find all FDIV users of the same divisor. For the moment we limit all
+ // instructions to a single BB and use the first Instr in MatchInfo as the
+ // dominating position.
+ MatchInfo.push_back(&MI);
+ for (auto &U : MRI.use_nodbg_instructions(Y)) {
+ if (&U == &MI || U.getParent() != MI.getParent())
+ continue;
+ if (U.getOpcode() == TargetOpcode::G_FDIV &&
+ U.getOperand(2).getReg() == Y && U.getOperand(1).getReg() != Y) {
+ // This division is eligible for optimization only if global unsafe math
+ // is enabled or if this division allows reciprocal formation.
+ if (U.getFlag(MachineInstr::MIFlag::FmArcp)) {
+ MatchInfo.push_back(&U);
+ if (dominates(U, *MatchInfo[0]))
+ std::swap(MatchInfo[0], MatchInfo.back());
+ }
+ }
+ }
+
+ // Now that we have the actual number of divisor uses, make sure it meets
+ // the minimum threshold specified by the target.
+ return MatchInfo.size() >= MinUses;
+}
+
+void CombinerHelper::applyRepeatedFPDivisor(
+ SmallVector<MachineInstr *> &MatchInfo) const {
+ // Generate the new div at the position of the first instruction, that we have
+ // ensured will dominate all other instructions.
+ Builder.setInsertPt(*MatchInfo[0]->getParent(), MatchInfo[0]);
+ LLT Ty = MRI.getType(MatchInfo[0]->getOperand(0).getReg());
+ auto Div = Builder.buildFDiv(Ty, Builder.buildFConstant(Ty, 1.0),
+ MatchInfo[0]->getOperand(2).getReg(),
+ MatchInfo[0]->getFlags());
+
+ // Replace all found div's with fmul instructions.
+ for (MachineInstr *MI : MatchInfo) {
+ Builder.setInsertPt(*MI->getParent(), MI);
+ Builder.buildFMul(MI->getOperand(0).getReg(), MI->getOperand(1).getReg(),
+ Div->getOperand(0).getReg(), MI->getFlags());
+ MI->eraseFromParent();
+ }
+}
+
bool CombinerHelper::matchAddSubSameReg(MachineInstr &MI, Register &Src) const {
assert(MI.getOpcode() == TargetOpcode::G_ADD && "Expected a G_ADD");
Register LHS = MI.getOperand(1).getReg();
diff --git a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
index 309f1be..c5c3866 100644
--- a/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/DAGCombiner.cpp
@@ -19319,9 +19319,8 @@ SDValue DAGCombiner::visitFNEG(SDNode *N) {
// FIXME: This is duplicated in getNegatibleCost, but getNegatibleCost doesn't
// know it was called from a context with a nsz flag if the input fsub does
// not.
- if (N0.getOpcode() == ISD::FSUB &&
- (DAG.getTarget().Options.NoSignedZerosFPMath ||
- N->getFlags().hasNoSignedZeros()) && N0.hasOneUse()) {
+ if (N0.getOpcode() == ISD::FSUB && N->getFlags().hasNoSignedZeros() &&
+ N0.hasOneUse()) {
return DAG.getNode(ISD::FSUB, SDLoc(N), VT, N0.getOperand(1),
N0.getOperand(0));
}
diff --git a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
index 851d445..507b2d6 100644
--- a/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
+++ b/llvm/lib/CodeGen/SelectionDAG/FastISel.cpp
@@ -1843,7 +1843,8 @@ bool FastISel::selectOperator(const User *I, unsigned Opcode) {
return selectCast(I, ISD::SINT_TO_FP);
case Instruction::IntToPtr: // Deliberate fall-through.
- case Instruction::PtrToInt: {
+ case Instruction::PtrToInt:
+ case Instruction::PtrToAddr: {
EVT SrcVT = TLI.getValueType(DL, I->getOperand(0)->getType());
EVT DstVT = TLI.getValueType(DL, I->getType());
if (DstVT.bitsGT(SrcVT))