[llvm-commits] CVS: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
Evan Cheng
evan.cheng at apple.com
Mon Aug 28 13:10:31 PDT 2006
Changes in directory llvm/lib/Target/X86:
X86ISelDAGToDAG.cpp updated: 1.98 -> 1.99
---
Log message:
Add an optional pass to preprocess the DAG before x86 isel to allow selecting more load/mod/store instructions.
---
Diffs of the changes: (+130 -0)
X86ISelDAGToDAG.cpp | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++
1 files changed, 130 insertions(+)
Index: llvm/lib/Target/X86/X86ISelDAGToDAG.cpp
diff -u llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.98 llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.99
--- llvm/lib/Target/X86/X86ISelDAGToDAG.cpp:1.98 Sun Aug 27 07:54:01 2006
+++ llvm/lib/Target/X86/X86ISelDAGToDAG.cpp Mon Aug 28 15:10:17 2006
@@ -39,6 +39,10 @@
#include <set>
using namespace llvm;
+#include "llvm/Support/CommandLine.h"
+static cl::opt<bool> X86ISelPreproc("enable-x86-isel-preprocessing", cl::Hidden,
+ cl::desc("Enable isel preprocessing on X86"));
+
//===----------------------------------------------------------------------===//
// Pattern Matcher Implementation
//===----------------------------------------------------------------------===//
@@ -133,6 +137,7 @@
bool TryFoldLoad(SDOperand P, SDOperand N,
SDOperand &Base, SDOperand &Scale,
SDOperand &Index, SDOperand &Disp);
+ void InstructionSelectPreprocess(SelectionDAG &DAG);
/// SelectInlineAsmMemoryOperand - Implement addressing mode selection for
/// inline asm expressions.
@@ -232,12 +237,137 @@
return !isNonImmUse(U, N);
}
+/// MoveBelowTokenFactor - Replace TokenFactor operand with load's chain operand
+/// and move load below the TokenFactor. Replace store's chain operand with
+/// load's chain result.
+static void MoveBelowTokenFactor(SelectionDAG &DAG, SDOperand Load,
+ SDOperand Store, SDOperand TF) {
+ std::vector<SDOperand> Ops;
+ for (unsigned i = 0, e = TF.Val->getNumOperands(); i != e; ++i)
+ if (Load.Val == TF.Val->getOperand(i).Val)
+ Ops.push_back(Load.Val->getOperand(0));
+ else
+ Ops.push_back(TF.Val->getOperand(i));
+ DAG.UpdateNodeOperands(TF, &Ops[0], Ops.size());
+ DAG.UpdateNodeOperands(Load, TF, Load.getOperand(1), Load.getOperand(2));
+ DAG.UpdateNodeOperands(Store, Load.getValue(1), Store.getOperand(1),
+ Store.getOperand(2), Store.getOperand(3));
+}
+
+/// InstructionSelectPreprocess - Preprocess the DAG to allow the instruction
+/// selector to pick more load-modify-store instructions. This is a common
+/// case:
+///
+/// [Load chain]
+/// ^
+/// |
+/// [Load]
+/// ^ ^
+/// | |
+/// / \-
+/// / |
+/// [TokenFactor] [Op]
+/// ^ ^
+/// | |
+/// \ /
+/// \ /
+/// [Store]
+///
+/// The fact the store's chain operand != load's chain will prevent the
+/// (store (op (load))) instruction from being selected. We can transform it to:
+///
+/// [Load chain]
+/// ^
+/// |
+/// [TokenFactor]
+/// ^
+/// |
+/// [Load]
+/// ^ ^
+/// | |
+/// | \-
+/// | |
+/// | [Op]
+/// | ^
+/// | |
+/// \ /
+/// \ /
+/// [Store]
+void X86DAGToDAGISel::InstructionSelectPreprocess(SelectionDAG &DAG) {
+ for (SelectionDAG::allnodes_iterator I = DAG.allnodes_begin(),
+ E = DAG.allnodes_end(); I != E; ++I) {
+ if (I->getOpcode() != ISD::STORE)
+ continue;
+ SDOperand Chain = I->getOperand(0);
+ if (Chain.Val->getOpcode() != ISD::TokenFactor)
+ continue;
+
+ SDOperand N1 = I->getOperand(1);
+ SDOperand N2 = I->getOperand(2);
+ if (!N1.hasOneUse())
+ continue;
+
+ bool RModW = false;
+ SDOperand Load;
+ unsigned Opcode = N1.Val->getOpcode();
+ switch (Opcode) {
+ case ISD::ADD:
+ case ISD::MUL:
+ case ISD::FADD:
+ case ISD::FMUL:
+ case ISD::AND:
+ case ISD::OR:
+ case ISD::XOR:
+ case ISD::ADDC:
+ case ISD::ADDE: {
+ SDOperand N10 = N1.getOperand(0);
+ SDOperand N11 = N1.getOperand(1);
+ if (N10.Val->getOpcode() == ISD::LOAD)
+ RModW = true;
+ else if (N11.Val->getOpcode() == ISD::LOAD) {
+ RModW = true;
+ std::swap(N10, N11);
+ }
+ RModW = RModW && N10.Val->isOperand(Chain.Val) && N10.hasOneUse() &&
+ N10.getOperand(1) == N2;
+ if (RModW)
+ Load = N10;
+ break;
+ }
+ case ISD::SUB:
+ case ISD::SHL:
+ case ISD::SRA:
+ case ISD::SRL:
+ case ISD::ROTL:
+ case ISD::ROTR:
+ case ISD::SUBC:
+ case ISD::SUBE:
+ case X86ISD::SHLD:
+ case X86ISD::SHRD: {
+ SDOperand N10 = N1.getOperand(0);
+ if (N10.Val->getOpcode() == ISD::LOAD)
+ RModW = N10.Val->isOperand(Chain.Val) && N10.hasOneUse() &&
+ N10.getOperand(1) == N2;
+ if (RModW)
+ Load = N10;
+ break;
+ }
+ }
+
+ if (RModW)
+ MoveBelowTokenFactor(DAG, Load, SDOperand(I, 0), Chain);
+ }
+}
+
/// InstructionSelectBasicBlock - This callback is invoked by SelectionDAGISel
/// when it has created a SelectionDAG for us to codegen.
void X86DAGToDAGISel::InstructionSelectBasicBlock(SelectionDAG &DAG) {
DEBUG(BB->dump());
MachineFunction::iterator FirstMBB = BB;
+ if (X86ISelPreproc)
+ InstructionSelectPreprocess(DAG);
+
// Codegen the basic block.
#ifndef NDEBUG
DEBUG(std::cerr << "===== Instruction selection begins:\n");
More information about the llvm-commits
mailing list