[llvm-commits] [llvm] r54751 - in /llvm/trunk: Makefile.rules include/llvm/CodeGen/FastISel.h lib/CodeGen/SelectionDAG/FastISel.cpp utils/TableGen/FastISelEmitter.cpp utils/TableGen/FastISelEmitter.h utils/TableGen/TableGen.cpp

Dan Gohman gohman at apple.com
Tue Aug 19 14:06:45 PDT 2008


On Aug 16, 2008, at 5:07 PM, Chris Lattner wrote:

> On Aug 13, 2008, at 1:19 PM, Dan Gohman wrote:
>> URL: http://llvm.org/viewvc/llvm-project?rev=54751&view=rev
>> Log:
>> Initial checkin of the new "fast" instruction selection support. See
>> the comments in FastISelEmitter.cpp for details on what this is.
>> This is currently experimental and unusable.
>
> Nice!
>
>> +++ llvm/trunk/utils/TableGen/FastISelEmitter.h Wed Aug 13 15:19:35
>> 2008
>> @@ -0,0 +1,38 @@
>> +#ifndef FASTISEL_EMITTER_H
>> +#define FASTISEL_EMITTER_H
>> +
>> +#include "TableGenBackend.h"
>> +#include "CodeGenDAGPatterns.h"
>> +#include <set>
>
> No need for <set>?

Nope.

>
>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =====================================================================
>> +++ llvm/trunk/utils/TableGen/FastISelEmitter.cpp Wed Aug 13
>> 15:19:35 2008
>> +// If compile time is so important, you might wonder why we don't
>> just
>> +// skip codegen all-together, emit LLVM bytecode files, and execute
>> them
>> +// with an interpreter. The answer is that it would complicate
>> linking and
>> +// debugging, and also because that isn't how a compiler is
>> expected to
>> +// work in some circles.
>
> That also doesn't really help necessarily, because lli has to do
> selection as well.  I guess it wins if you only execute a small
> percentage of the code being compiled though.

I specifically meant an interpreter, which wouldn't need a distinct
selection phase.

>
>
>> +// If you need better generated code or more lowering than what this
>> +// instruction selector provides, use the SelectionDAG (DAGISel)
>> instruction
>> +// selector instead. If you're looking here because SelectionDAG
>> isn't fast
>> +// enough, consider looking into improving the SelectionDAG
>> infastructure
>> +// instead. At the time of this writing there remain several major
>> +// opportunities for improvement.
>
> I think a better and more permanent way of putting this is "only
> consider enhancing the fast isel if you want to make it produce code
> faster.  Changes to make the fast isel produce better code more slowly
> will be considered to be a step backward.
>
>>
>> +
>> +struct OperandsSignature {
>
> Please give a brief comment about what each of these classes is for.

Done.

>
>
>> +void FastISelEmitter::run(std::ostream &OS) {
> ...
>
>>
>> +  typedef std::map<MVT::SimpleValueType, InstructionMemo> TypeMap;
>> +  typedef std::map<std::string, TypeMap> OpcodeTypeMap;
>> +  typedef std::map<OperandsSignature, OpcodeTypeMap>
>> OperandsOpcodeTypeMap;
>> +  OperandsOpcodeTypeMap SimplePatterns;
>
> Maybe it would be cleaner to make fastiselemitter be a class with a
> bunch of methods?  That would give you a clean way to share these
> typedefs and still allow you to split up "run" into multiple different
> methods.  Splitting it up into methods gives the opportunity to pick
> useful names for each unit.  This works well for dagiselemitter at
> least.

Yep. OperandsSignature is an example of code that used to all be
done inline that I've refactored. I plan to keep doing this as I
proceed.

>
>
>> +  for (CodeGenDAGPatterns::ptm_iterator I = CGP.ptm_begin(),
>> +       E = CGP.ptm_end(); I != E; ++I) {
>> +    const PatternToMatch &Pattern = *I;
>> +
>> +    // For now, just look at Instructions, so that we don't have to
>> worry
>> +    // about emitting multiple instructions for a pattern.
>> +    TreePatternNode *Dst = Pattern.getDstPattern();
>> +    if (Dst->isLeaf()) continue;
>> +    Record *Op = Dst->getOperator();
>> +    if (!Op->isSubClassOf("Instruction"))
>> +      continue;
>> +    CodeGenInstruction &II = CGP.getTargetInfo().getInstruction(Op-
>>> getName());
>> +    if (II.OperandList.empty())
>> +      continue;
>> +    Record *Op0Rec = II.OperandList[0].Rec;
>> +    if (!Op0Rec->isSubClassOf("RegisterClass"))
>> +      continue;
>> +    const CodeGenRegisterClass *DstRC =
>> &Target.getRegisterClass(Op0Rec);
>> +    if (!DstRC)
>> +      continue;
>
> It would be useful to know why your rejecting each of these.  I think
> this will filter out the X86 shift patterns (which use CL), for
> example.  Is this a temporary or permanent approach?

It's temporary; I am assuming that a design that fundamentally
excludes shift instructions would evoke consternation.

>
>
>> +    // For now, filter out instructions which just set a register to
>> +    // an Operand, like MOV32ri.
>> +    if (InstPatOp->isSubClassOf("Operand"))
>> +      continue;
>
> This is a great description which makes it easier to follow the code.
>
>> +
>> +    // Check all the operands. For now only accept register  
>> operands.
>> +    OperandsSignature Operands;
>> +    for (unsigned i = 0, e = InstPatNode->getNumChildren(); i != e;
>> ++i) {
>> +      TreePatternNode *Op = InstPatNode->getChild(i);
>> +      if (!Op->isLeaf())
>> +        goto continue_label;
>> +      DefInit *OpDI = dynamic_cast<DefInit*>(Op->getLeafValue());
>> +      if (!OpDI)
>> +        goto continue_label;
>> +      Record *OpLeafRec = OpDI->getDef();
>> +      if (!OpLeafRec->isSubClassOf("RegisterClass"))
>> +        goto continue_label;
>> +      const CodeGenRegisterClass *RC =
>> &Target.getRegisterClass(OpLeafRec);
>> +      if (!RC)
>> +        goto continue_label;
>> +      if (Op->getTypeNum(0) != VT)
>> +        goto continue_label;
>> +      Operands.Operands.push_back("r");
>> +    }
>
> Please split this loop out into a helper function, this will let you
> get rid of the gotos, by using something like:
>
>       if (GetFooInfo(InstPatNode, Operands))
>         continue;

Ok.

>
>
>
>> +++ llvm/trunk/include/llvm/CodeGen/FastISel.h Wed Aug 13 15:19:35
>> 2008
>> @@ -0,0 +1,71 @@
>
>
>> +
>> +/// This file defines the FastISel class. This is a fast-path
>> instruction
>
> Plz update/remove the first sentence.

Done.

>
>
>> +/// selection class that generates poor code and doesn't support
>> illegal
>> +/// types or non-trivial lowering, but runs quickly.
>> +class FastISel {
>> +  MachineBasicBlock *MBB;
>> +  MachineFunction *MF;
>> +  const TargetInstrInfo *TII;
>> +
>> +public:
>> +  FastISel(MachineBasicBlock *mbb, MachineFunction *mf,
>> +           const TargetInstrInfo *tii)
>> +    : MBB(mbb), MF(mf), TII(tii) {}
>> +
>> +  /// SelectInstructions - Do "fast" instruction selection over the
>> +  /// LLVM IR instructions in the range [Begin, N) where N is either
>> +  /// End or the first unsupported instruction. Return N.
>> +  /// ValueMap is filled in with a mapping of LLVM IR Values to
>> +  /// register numbers.
>> +  BasicBlock::iterator
>> +  SelectInstructions(BasicBlock::iterator Begin,
>> BasicBlock::iterator End,
>> +                     DenseMap<const Value*, unsigned> &ValueMap);
>
> If you change this to take two Instruction*'s as an inclusive range to
> emit, you can avoid #including BasicBlock.h.  I agree this is somewhat
> ugly though and probably not worth it.

I'm leaving it as is for now.

>
>
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> =
>> = 
>> =====================================================================
>> --- llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp (added)
>> +++ llvm/trunk/lib/CodeGen/SelectionDAG/FastISel.cpp Wed Aug 13
>> 15:19:35 2008
>> @@ -0,0 +1,104 @@
>
>> +BasicBlock::iterator
>> +FastISel::SelectInstructions(BasicBlock::iterator Begin,
>> BasicBlock::iterator End,
>> +                             DenseMap<const Value*, unsigned>
>> &ValueMap) {
>
> I like this interface.  Is the idea that you only use selectiondag
> selection on the specific *instructions* that fastisel can't handle,
> instead of whole blocks?

Basically yes. The idea is that "fast" mode would start out
processing a block with fastisel and then switch over to
selectiondag if it hits something it can't handle.

>
>
>> +  BasicBlock::iterator I = Begin;
>> +
>> +  for (; I != End; ++I) {
>> +    switch (I->getOpcode()) {
>> +    case Instruction::Add: {
>> +      unsigned Op0 = ValueMap[I->getOperand(0)];
>> +      unsigned Op1 = ValueMap[I->getOperand(1)];
>> +      MVT VT = MVT::getMVT(I->getType(), /*HandleUnknown=*/true);
>> +      if (VT == MVT::Other || !VT.isSimple()) {
>> +        // Unhandled type. Halt "fast" selection and bail.
>> +        return I;
>> +      }
>>
>> +      unsigned ResultReg = FastEmit_rr(VT.getSimpleVT(), ISD::ADD,
>> Op0, Op1);
>
> I think this needs to 'return I' if ResultReg is 0.

Good catch. Fixed.

>
>
>>
>> +unsigned FastISel::FastEmitInst_(unsigned MachineInstOpcode,
>> +                                    const TargetRegisterClass* RC) {
>> +  MachineRegisterInfo &MRI = MF->getRegInfo();
>> +  const TargetInstrDesc &II = TII->get(MachineInstOpcode);
>> +  MachineInstr *MI = BuildMI(*MF, II);
>> +  unsigned ResultReg = MRI.createVirtualRegister(RC);
>> +
>> +  MI->addOperand(MachineOperand::CreateReg(ResultReg, true));
>> +  MBB->push_back(MI);
>
> Why not just "BuildMI(MBB, II, ResultReg);"

Ok.

>
>> +  return ResultReg;
>> +}
>> +
>> +unsigned FastISel::FastEmitInst_r(unsigned MachineInstOpcode,
>> +                                  const TargetRegisterClass *RC,
>> +                                  unsigned Op0) {
>> +  MachineRegisterInfo &MRI = MF->getRegInfo();
>> +  const TargetInstrDesc &II = TII->get(MachineInstOpcode);
>> +  MachineInstr *MI = BuildMI(*MF, II);
>> +  unsigned ResultReg = MRI.createVirtualRegister(RC);
>> +
>> +  MI->addOperand(MachineOperand::CreateReg(ResultReg, true));
>> +  MI->addOperand(MachineOperand::CreateReg(Op0, false));
>> +
>> +  MBB->push_back(MI);
>
> Why not just "BuildMI(MBB, II, ResultReg).addReg(Op0);"

Ok.

>
> Overall, very nice start.  Do you have hooks for SDISel to use this?
> If so, plz commit them as well under a flag.

Ok, I'll get there soon.

Dan




More information about the llvm-commits mailing list