[FastISel] Some long overdue spring cleaning of FastISel.

Things got a little bit messy over the years and it is time for a little bit
spring cleaning.

This first commit is focused on the FastISel base class itself. It doxyfies all
comments, C++11fies the code where it makes sense, renames internal methods to
adhere to the coding standard, and clang-formats the files.

Reviewed by Eric

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@217060 91177308-0d34-0410-b5e6-96231b3b80d8
This commit is contained in:
Juergen Ributzka 2014-09-03 18:46:45 +00:00
parent 75899aab35
commit 39af4e655a
3 changed files with 554 additions and 650 deletions

View File

@ -24,51 +24,31 @@
namespace llvm { namespace llvm {
class AllocaInst; /// \brief This is a fast-path instruction selection class that generates poor
class Constant; /// code and doesn't support illegal types or non-trivial lowering, but runs
class ConstantFP; /// quickly.
class CallInst;
class DataLayout;
class FunctionLoweringInfo;
class Instruction;
class LoadInst;
class MVT;
class MachineConstantPool;
class MachineFrameInfo;
class MachineFunction;
class MachineInstr;
class MachineRegisterInfo;
class TargetInstrInfo;
class TargetLibraryInfo;
class TargetLowering;
class TargetMachine;
class TargetRegisterClass;
class TargetRegisterInfo;
class User;
class Value;
/// This is a fast-path instruction selection class that generates poor code and
/// doesn't support illegal types or non-trivial lowering, but runs quickly.
class FastISel { class FastISel {
public: public:
struct ArgListEntry { struct ArgListEntry {
Value *Val; Value *Val;
Type *Ty; Type *Ty;
bool isSExt : 1; bool IsSExt : 1;
bool isZExt : 1; bool IsZExt : 1;
bool isInReg : 1; bool IsInReg : 1;
bool isSRet : 1; bool IsSRet : 1;
bool isNest : 1; bool IsNest : 1;
bool isByVal : 1; bool IsByVal : 1;
bool isInAlloca : 1; bool IsInAlloca : 1;
bool isReturned : 1; bool IsReturned : 1;
uint16_t Alignment; uint16_t Alignment;
ArgListEntry() ArgListEntry()
: Val(nullptr), Ty(nullptr), isSExt(false), isZExt(false), isInReg(false), : Val(nullptr), Ty(nullptr), IsSExt(false), IsZExt(false),
isSRet(false), isNest(false), isByVal(false), isInAlloca(false), IsInReg(false), IsSRet(false), IsNest(false), IsByVal(false),
isReturned(false), Alignment(0) { } IsInAlloca(false), IsReturned(false), Alignment(0) {}
/// \brief Set CallLoweringInfo attribute flags based on a call instruction
/// and called function attributes.
void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx); void setAttributes(ImmutableCallSite *CS, unsigned AttrIdx);
}; };
typedef std::vector<ArgListEntry> ArgListTy; typedef std::vector<ArgListEntry> ArgListTy;
@ -82,8 +62,8 @@ class FastISel {
bool DoesNotReturn : 1; bool DoesNotReturn : 1;
bool IsReturnValueUsed : 1; bool IsReturnValueUsed : 1;
// IsTailCall should be modified by implementations of // \brief IsTailCall Should be modified by implementations of FastLowerCall
// FastLowerCall that perform tail call conversions. // that perform tail call conversions.
bool IsTailCall; bool IsTailCall;
unsigned NumFixedArgs; unsigned NumFixedArgs;
@ -107,8 +87,7 @@ class FastISel {
IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true), IsInReg(false), DoesNotReturn(false), IsReturnValueUsed(true),
IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C), IsTailCall(false), NumFixedArgs(-1), CallConv(CallingConv::C),
Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr), Callee(nullptr), SymName(nullptr), CS(nullptr), Call(nullptr),
ResultReg(0), NumResultRegs(0) ResultReg(0), NumResultRegs(0) {}
{}
CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy, CallLoweringInfo &setCallee(Type *ResultTy, FunctionType *FuncTy,
const Value *Target, ArgListTy &&ArgsList, const Value *Target, ArgListTy &&ArgsList,
@ -172,9 +151,7 @@ class FastISel {
return *this; return *this;
} }
ArgListTy &getArgs() { ArgListTy &getArgs() { return Args; }
return Args;
}
void clearOuts() { void clearOuts() {
OutVals.clear(); OutVals.clear();
@ -204,60 +181,62 @@ protected:
const TargetLibraryInfo *LibInfo; const TargetLibraryInfo *LibInfo;
bool SkipTargetIndependentISel; bool SkipTargetIndependentISel;
/// The position of the last instruction for materializing constants for use /// \brief The position of the last instruction for materializing constants
/// in the current block. It resets to EmitStartPt when it makes sense (for /// for use in the current block. It resets to EmitStartPt when it makes sense
/// example, it's usually profitable to avoid function calls between the /// (for example, it's usually profitable to avoid function calls between the
/// definition and the use) /// definition and the use)
MachineInstr *LastLocalValue; MachineInstr *LastLocalValue;
/// The top most instruction in the current block that is allowed for emitting /// \brief The top most instruction in the current block that is allowed for
/// local variables. LastLocalValue resets to EmitStartPt when it makes sense /// emitting local variables. LastLocalValue resets to EmitStartPt when it
/// (for example, on function calls) /// makes sense (for example, on function calls)
MachineInstr *EmitStartPt; MachineInstr *EmitStartPt;
public: public:
/// Return the position of the last instruction emitted for materializing /// \brief Return the position of the last instruction emitted for
/// constants for use in the current block. /// materializing constants for use in the current block.
MachineInstr *getLastLocalValue() { return LastLocalValue; } MachineInstr *getLastLocalValue() { return LastLocalValue; }
/// Update the position of the last instruction emitted for materializing /// \brief Update the position of the last instruction emitted for
/// constants for use in the current block. /// materializing constants for use in the current block.
void setLastLocalValue(MachineInstr *I) { void setLastLocalValue(MachineInstr *I) {
EmitStartPt = I; EmitStartPt = I;
LastLocalValue = I; LastLocalValue = I;
} }
/// Set the current block to which generated machine instructions will be /// \brief Set the current block to which generated machine instructions will
/// appended, and clear the local CSE map. /// be appended, and clear the local CSE map.
void startNewBlock(); void startNewBlock();
/// Return current debug location information. /// \brief Return current debug location information.
DebugLoc getCurDebugLoc() const { return DbgLoc; } DebugLoc getCurDebugLoc() const { return DbgLoc; }
/// Do "fast" instruction selection for function arguments and append machine /// \brief Do "fast" instruction selection for function arguments and append
/// instructions to the current block. Return true if it is successful. /// the machine instructions to the current block. Returns true when
/// successful.
bool LowerArguments(); bool LowerArguments();
/// Do "fast" instruction selection for the given LLVM IR instruction, and /// \brief Do "fast" instruction selection for the given LLVM IR instruction
/// append generated machine instructions to the current block. Return true if /// and append the generated machine instructions to the current block.
/// selection was successful. /// Returns true if selection was successful.
bool SelectInstruction(const Instruction *I); bool SelectInstruction(const Instruction *I);
/// Do "fast" instruction selection for the given LLVM IR operator /// \brief Do "fast" instruction selection for the given LLVM IR operator
/// (Instruction or ConstantExpr), and append generated machine instructions /// (Instruction or ConstantExpr), and append generated machine instructions
/// to the current block. Return true if selection was successful. /// to the current block. Return true if selection was successful.
bool SelectOperator(const User *I, unsigned Opcode); bool selectOperator(const User *I, unsigned Opcode);
/// Create a virtual register and arrange for it to be assigned the value for /// \brief Create a virtual register and arrange for it to be assigned the
/// the given LLVM value. /// value for the given LLVM value.
unsigned getRegForValue(const Value *V); unsigned getRegForValue(const Value *V);
/// Look up the value to see if its value is already cached in a register. It /// \brief Look up the value to see if its value is already cached in a
/// may be defined by instructions across blocks or defined locally. /// register. It may be defined by instructions across blocks or defined
/// locally.
unsigned lookUpRegForValue(const Value *V); unsigned lookUpRegForValue(const Value *V);
/// This is a wrapper around getRegForValue that also takes care of truncating /// \brief This is a wrapper around getRegForValue that also takes care of
/// or sign-extending the given getelementptr index value. /// truncating or sign-extending the given getelementptr index value.
std::pair<unsigned, bool> getRegForGEPIndex(const Value *V); std::pair<unsigned, bool> getRegForGEPIndex(const Value *V);
/// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note /// \brief We're checking to see if we can fold \p LI into \p FoldInst. Note
@ -285,11 +264,11 @@ public:
return false; return false;
} }
/// Reset InsertPt to prepare for inserting instructions into the current /// \brief Reset InsertPt to prepare for inserting instructions into the
/// block. /// current block.
void recomputeInsertPt(); void recomputeInsertPt();
/// Remove all dead instructions between the I and E. /// \brief Remove all dead instructions between the I and E.
void removeDeadCode(MachineBasicBlock::iterator I, void removeDeadCode(MachineBasicBlock::iterator I,
MachineBasicBlock::iterator E); MachineBasicBlock::iterator E);
@ -298,11 +277,11 @@ public:
DebugLoc DL; DebugLoc DL;
}; };
/// Prepare InsertPt to begin inserting instructions into the local value area /// \brief Prepare InsertPt to begin inserting instructions into the local
/// and return the old insert position. /// value area and return the old insert position.
SavePoint enterLocalValueArea(); SavePoint enterLocalValueArea();
/// Reset InsertPt to the given old insert position. /// \brief Reset InsertPt to the given old insert position.
void leaveLocalValueArea(SavePoint Old); void leaveLocalValueArea(SavePoint Old);
virtual ~FastISel(); virtual ~FastISel();
@ -312,207 +291,180 @@ protected:
const TargetLibraryInfo *LibInfo, const TargetLibraryInfo *LibInfo,
bool SkipTargetIndependentISel = false); bool SkipTargetIndependentISel = false);
/// This method is called by target-independent code when the normal FastISel /// \brief This method is called by target-independent code when the normal
/// process fails to select an instruction. This gives targets a chance to /// FastISel process fails to select an instruction. This gives targets a
/// emit code for anything that doesn't fit into FastISel's framework. It /// chance to emit code for anything that doesn't fit into FastISel's
/// returns true if it was successful. /// framework. It returns true if it was successful.
virtual bool TargetSelectInstruction(const Instruction *I) = 0; virtual bool TargetSelectInstruction(const Instruction *I) = 0;
/// This method is called by target-independent code to do target specific /// \brief This method is called by target-independent code to do target-
/// argument lowering. It returns true if it was successful. /// specific argument lowering. It returns true if it was successful.
virtual bool FastLowerArguments(); virtual bool FastLowerArguments();
/// \brief This method is called by target-independent code to do target /// \brief This method is called by target-independent code to do target-
/// specific call lowering. It returns true if it was successful. /// specific call lowering. It returns true if it was successful.
virtual bool FastLowerCall(CallLoweringInfo &CLI); virtual bool FastLowerCall(CallLoweringInfo &CLI);
/// \brief This method is called by target-independent code to do target /// \brief This method is called by target-independent code to do target-
/// specific intrinsic lowering. It returns true if it was successful. /// specific intrinsic lowering. It returns true if it was successful.
virtual bool FastLowerIntrinsicCall(const IntrinsicInst *II); virtual bool FastLowerIntrinsicCall(const IntrinsicInst *II);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type and opcode be emitted. /// instruction with the given type and opcode be emitted.
virtual unsigned FastEmit_(MVT VT, virtual unsigned FastEmit_(MVT VT, MVT RetVT, unsigned Opcode);
MVT RetVT,
unsigned Opcode);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register operand be emitted. /// instruction with the given type, opcode, and register operand be emitted.
virtual unsigned FastEmit_r(MVT VT, virtual unsigned FastEmit_r(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
MVT RetVT, bool Op0IsKill);
unsigned Opcode,
unsigned Op0, bool Op0IsKill);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register operands be emitted. /// instruction with the given type, opcode, and register operands be emitted.
virtual unsigned FastEmit_rr(MVT VT, virtual unsigned FastEmit_rr(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
MVT RetVT, bool Op0IsKill, unsigned Op1, bool Op1IsKill);
unsigned Opcode,
unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register and immediate /// instruction with the given type, opcode, and register and immediate
/// operands be emitted. // operands be emitted.
virtual unsigned FastEmit_ri(MVT VT, virtual unsigned FastEmit_ri(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
MVT RetVT, bool Op0IsKill, uint64_t Imm);
unsigned Opcode,
unsigned Op0, bool Op0IsKill,
uint64_t Imm);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register and floating-point /// instruction with the given type, opcode, and register and floating-point
/// immediate operands be emitted. /// immediate operands be emitted.
virtual unsigned FastEmit_rf(MVT VT, virtual unsigned FastEmit_rf(MVT VT, MVT RetVT, unsigned Opcode, unsigned Op0,
MVT RetVT, bool Op0IsKill, const ConstantFP *FPImm);
unsigned Opcode,
unsigned Op0, bool Op0IsKill,
const ConstantFP *FPImm);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and register and immediate /// instruction with the given type, opcode, and register and immediate
/// operands be emitted. /// operands be emitted.
virtual unsigned FastEmit_rri(MVT VT, virtual unsigned FastEmit_rri(MVT VT, MVT RetVT, unsigned Opcode,
MVT RetVT, unsigned Op0, bool Op0IsKill, unsigned Op1,
unsigned Opcode, bool Op1IsKill, uint64_t Imm);
unsigned Op0, bool Op0IsKill,
unsigned Op1, bool Op1IsKill,
uint64_t Imm);
/// \brief This method is a wrapper of FastEmit_ri. /// \brief This method is a wrapper of FastEmit_ri.
/// ///
/// It first tries to emit an instruction with an immediate operand using /// It first tries to emit an instruction with an immediate operand using
/// FastEmit_ri. If that fails, it materializes the immediate into a register /// FastEmit_ri. If that fails, it materializes the immediate into a register
/// and try FastEmit_rr instead. /// and try FastEmit_rr instead.
unsigned FastEmit_ri_(MVT VT, unsigned FastEmit_ri_(MVT VT, unsigned Opcode, unsigned Op0, bool Op0IsKill,
unsigned Opcode,
unsigned Op0, bool Op0IsKill,
uint64_t Imm, MVT ImmType); uint64_t Imm, MVT ImmType);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and immediate operand be emitted. /// instruction with the given type, opcode, and immediate operand be emitted.
virtual unsigned FastEmit_i(MVT VT, virtual unsigned FastEmit_i(MVT VT, MVT RetVT, unsigned Opcode, uint64_t Imm);
MVT RetVT,
unsigned Opcode,
uint64_t Imm);
/// This method is called by target-independent code to request that an /// \brief This method is called by target-independent code to request that an
/// instruction with the given type, opcode, and floating-point immediate /// instruction with the given type, opcode, and floating-point immediate
/// operand be emitted. /// operand be emitted.
virtual unsigned FastEmit_f(MVT VT, virtual unsigned FastEmit_f(MVT VT, MVT RetVT, unsigned Opcode,
MVT RetVT,
unsigned Opcode,
const ConstantFP *FPImm); const ConstantFP *FPImm);
/// Emit a MachineInstr with no operands and a result register in the given /// \brief Emit a MachineInstr with no operands and a result register in the
/// register class. /// given register class.
unsigned FastEmitInst_(unsigned MachineInstOpcode, unsigned FastEmitInst_(unsigned MachineInstOpcode,
const TargetRegisterClass *RC); const TargetRegisterClass *RC);
/// Emit a MachineInstr with one register operand and a result register in the /// \brief Emit a MachineInstr with one register operand and a result register
/// given register class. /// in the given register class.
unsigned FastEmitInst_r(unsigned MachineInstOpcode, unsigned FastEmitInst_r(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill); bool Op0IsKill);
/// Emit a MachineInstr with two register operands and a result register in /// \brief Emit a MachineInstr with two register operands and a result
/// the given register class. /// register in the given register class.
unsigned FastEmitInst_rr(unsigned MachineInstOpcode, unsigned FastEmitInst_rr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill, bool Op0IsKill, unsigned Op1, bool Op1IsKill);
unsigned Op1, bool Op1IsKill);
/// Emit a MachineInstr with three register operands and a result register in /// \brief Emit a MachineInstr with three register operands and a result
/// the given register class. /// register in the given register class.
unsigned FastEmitInst_rrr(unsigned MachineInstOpcode, unsigned FastEmitInst_rrr(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill, bool Op0IsKill, unsigned Op1, bool Op1IsKill,
unsigned Op1, bool Op1IsKill,
unsigned Op2, bool Op2IsKill); unsigned Op2, bool Op2IsKill);
/// Emit a MachineInstr with a register operand, an immediate, and a result /// \brief Emit a MachineInstr with a register operand, an immediate, and a
/// register in the given register class. /// result register in the given register class.
unsigned FastEmitInst_ri(unsigned MachineInstOpcode, unsigned FastEmitInst_ri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill, bool Op0IsKill, uint64_t Imm);
uint64_t Imm);
/// Emit a MachineInstr with one register operand and two immediate operands. /// \brief Emit a MachineInstr with one register operand and two immediate
/// operands.
unsigned FastEmitInst_rii(unsigned MachineInstOpcode, unsigned FastEmitInst_rii(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill, bool Op0IsKill, uint64_t Imm1, uint64_t Imm2);
uint64_t Imm1, uint64_t Imm2);
/// Emit a MachineInstr with two register operands and a result register in /// \brief Emit a MachineInstr with two register operands and a result
/// the given register class.
unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC,
unsigned Op0, bool Op0IsKill,
const ConstantFP *FPImm);
/// Emit a MachineInstr with two register operands, an immediate, and a result
/// register in the given register class. /// register in the given register class.
unsigned FastEmitInst_rf(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, unsigned Op0,
bool Op0IsKill, const ConstantFP *FPImm);
/// \brief Emit a MachineInstr with two register operands, an immediate, and a
/// result register in the given register class.
unsigned FastEmitInst_rri(unsigned MachineInstOpcode, unsigned FastEmitInst_rri(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill, bool Op0IsKill, unsigned Op1, bool Op1IsKill,
unsigned Op1, bool Op1IsKill,
uint64_t Imm); uint64_t Imm);
/// Emit a MachineInstr with two register operands, two immediates operands, /// \brief Emit a MachineInstr with two register operands, two immediates
/// and a result register in the given register class. /// operands, and a result register in the given register class.
unsigned FastEmitInst_rrii(unsigned MachineInstOpcode, unsigned FastEmitInst_rrii(unsigned MachineInstOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, unsigned Op0,
unsigned Op0, bool Op0IsKill, bool Op0IsKill, unsigned Op1, bool Op1IsKill,
unsigned Op1, bool Op1IsKill,
uint64_t Imm1, uint64_t Imm2); uint64_t Imm1, uint64_t Imm2);
/// Emit a MachineInstr with a single immediate operand, and a result register /// \brief Emit a MachineInstr with a single immediate operand, and a result
/// in the given register class. /// register in the given register class.
unsigned FastEmitInst_i(unsigned MachineInstrOpcode, unsigned FastEmitInst_i(unsigned MachineInstrOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, uint64_t Imm);
uint64_t Imm);
/// Emit a MachineInstr with a two immediate operands. /// \brief Emit a MachineInstr with a two immediate operands.
unsigned FastEmitInst_ii(unsigned MachineInstrOpcode, unsigned FastEmitInst_ii(unsigned MachineInstrOpcode,
const TargetRegisterClass *RC, const TargetRegisterClass *RC, uint64_t Imm1,
uint64_t Imm1, uint64_t Imm2); uint64_t Imm2);
/// Emit a MachineInstr for an extract_subreg from a specified index of a /// \brief Emit a MachineInstr for an extract_subreg from a specified index of
/// superregister to a specified type. /// a superregister to a specified type.
unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned FastEmitInst_extractsubreg(MVT RetVT, unsigned Op0, bool Op0IsKill,
unsigned Op0, bool Op0IsKill,
uint32_t Idx); uint32_t Idx);
/// Emit MachineInstrs to compute the value of Op with all but the least /// \brief Emit MachineInstrs to compute the value of Op with all but the
/// significant bit set to zero. /// least significant bit set to zero.
unsigned FastEmitZExtFromI1(MVT VT, unsigned FastEmitZExtFromI1(MVT VT, unsigned Op0, bool Op0IsKill);
unsigned Op0, bool Op0IsKill);
/// Emit an unconditional branch to the given block, unless it is the /// \brief Emit an unconditional branch to the given block, unless it is the
/// immediate (fall-through) successor, and update the CFG. /// immediate (fall-through) successor, and update the CFG.
void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL); void FastEmitBranch(MachineBasicBlock *MBB, DebugLoc DL);
/// \brief Update the value map to include the new mapping for this
/// instruction, or insert an extra copy to get the result in a previous
/// determined register.
///
/// NOTE: This is only necessary because we might select a block that uses a
/// value before we select the block that defines the value. It might be
/// possible to fix this by selecting blocks in reverse postorder.
void UpdateValueMap(const Value *I, unsigned Reg, unsigned NumRegs = 1); void UpdateValueMap(const Value *I, unsigned Reg, unsigned NumRegs = 1);
unsigned createResultReg(const TargetRegisterClass *RC); unsigned createResultReg(const TargetRegisterClass *RC);
/// Try to constrain Op so that it is usable by argument OpNum of the provided /// \brief Try to constrain Op so that it is usable by argument OpNum of the
/// MCInstrDesc. If this fails, create a new virtual register in the correct /// provided MCInstrDesc. If this fails, create a new virtual register in the
/// class and COPY the value there. /// correct class and COPY the value there.
unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op, unsigned constrainOperandRegClass(const MCInstrDesc &II, unsigned Op,
unsigned OpNum); unsigned OpNum);
/// Emit a constant in a register using target-specific logic, such as /// \brief Emit a constant in a register using target-specific logic, such as
/// constant pool loads. /// constant pool loads.
virtual unsigned TargetMaterializeConstant(const Constant* C) { virtual unsigned TargetMaterializeConstant(const Constant *C) { return 0; }
return 0;
}
/// Emit an alloca address in a register using target-specific logic. /// \brief Emit an alloca address in a register using target-specific logic.
virtual unsigned TargetMaterializeAlloca(const AllocaInst* C) { virtual unsigned TargetMaterializeAlloca(const AllocaInst *C) { return 0; }
return 0;
}
/// \brief Emit the floating-point constant +0.0 in a register using target-
/// specific logic.
virtual unsigned TargetMaterializeFloatZero(const ConstantFP *CF) { virtual unsigned TargetMaterializeFloatZero(const ConstantFP *CF) {
return 0; return 0;
} }
@ -526,14 +478,14 @@ protected:
/// - \c Add has a constant operand. /// - \c Add has a constant operand.
bool canFoldAddIntoGEP(const User *GEP, const Value *Add); bool canFoldAddIntoGEP(const User *GEP, const Value *Add);
/// Test whether the given value has exactly one use. /// \brief Test whether the given value has exactly one use.
bool hasTrivialKill(const Value *V); bool hasTrivialKill(const Value *V);
/// \brief Create a machine mem operand from the given instruction. /// \brief Create a machine mem operand from the given instruction.
MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const; MachineMemOperand *createMachineMemOperandFor(const Instruction *I) const;
bool LowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs); bool LowerCallTo(const CallInst *CI, const char *SymName, unsigned NumArgs);
bool LowerCallTo(CallLoweringInfo &CLI); bool lowerCallTo(CallLoweringInfo &CLI);
bool isCommutativeIntrinsic(IntrinsicInst const *II) { bool isCommutativeIntrinsic(IntrinsicInst const *II) {
switch (II->getIntrinsicID()) { switch (II->getIntrinsicID()) {
@ -547,25 +499,20 @@ protected:
} }
} }
bool SelectBinaryOp(const User *I, unsigned ISDOpcode); /// \brief Select and emit code for a binary operator instruction, which has
/// an opcode which directly corresponds to the given ISD opcode.
bool SelectFNeg(const User *I); bool selectBinaryOp(const User *I, unsigned ISDOpcode);
bool selectFNeg(const User *I);
bool SelectGetElementPtr(const User *I); bool selectGetElementPtr(const User *I);
bool selectStackmap(const CallInst *I);
bool SelectStackmap(const CallInst *I); bool selectPatchpoint(const CallInst *I);
bool SelectPatchpoint(const CallInst *I); bool lowerCall(const CallInst *I);
bool LowerCall(const CallInst *I); bool selectCall(const User *Call);
bool SelectCall(const User *Call); bool selectIntrinsicCall(const IntrinsicInst *II);
bool SelectIntrinsicCall(const IntrinsicInst *II); bool selectBitCast(const User *I);
bool selectCast(const User *I, unsigned Opcode);
bool SelectBitCast(const User *I); bool selectExtractValue(const User *I);
bool selectInsertValue(const User *I);
bool SelectCast(const User *I, unsigned Opcode);
bool SelectExtractValue(const User *I);
bool SelectInsertValue(const User *I);
private: private:
/// \brief Handle PHI nodes in successor blocks. /// \brief Handle PHI nodes in successor blocks.
@ -575,22 +522,24 @@ private:
/// nodes as input. We cannot just directly add them, because expansion might /// nodes as input. We cannot just directly add them, because expansion might
/// result in multiple MBB's for one BB. As such, the start of the BB might /// result in multiple MBB's for one BB. As such, the start of the BB might
/// correspond to a different MBB than the end. /// correspond to a different MBB than the end.
bool HandlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB); bool handlePHINodesInSuccessorBlocks(const BasicBlock *LLVMBB);
/// \brief Helper for materializeRegForValue to materialize a constant in a /// \brief Helper for materializeRegForValue to materialize a constant in a
/// target-independent way. /// target-independent way.
unsigned MaterializeConstant(const Value *V, MVT VT); unsigned materializeConstant(const Value *V, MVT VT);
/// Helper for getRegForVale. This function is called when the value isn't /// \brief Helper for getRegForVale. This function is called when the value
/// already available in a register and must be materialized with new /// isn't already available in a register and must be materialized with new
/// instructions. /// instructions.
unsigned materializeRegForValue(const Value *V, MVT VT); unsigned materializeRegForValue(const Value *V, MVT VT);
/// Clears LocalValueMap and moves the area for the new local variables to the /// \brief Clears LocalValueMap and moves the area for the new local variables
/// beginning of the block. It helps to avoid spilling cached variables across /// to the beginning of the block. It helps to avoid spilling cached variables
/// heavy instructions like calls. /// across heavy instructions like calls.
void flushLocalValueMap(); void flushLocalValueMap();
/// \brief Add a stackmap or patchpoint intrinsic call's live variable
/// operands to a stackmap or patchpoint machine instruction.
bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops, bool addStackMapLiveVars(SmallVectorImpl<MachineOperand> &Ops,
const CallInst *CI, unsigned StartIdx); const CallInst *CI, unsigned StartIdx);
bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs, bool lowerCallOperands(const CallInst *CI, unsigned ArgIdx, unsigned NumArgs,
@ -598,6 +547,6 @@ private:
CallLoweringInfo &CLI); CallLoweringInfo &CLI);
}; };
} } // end namespace llvm
#endif #endif

File diff suppressed because it is too large Load Diff

View File

@ -3422,61 +3422,61 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
return false; return false;
case Instruction::Add: case Instruction::Add:
if (!selectAddSub(I)) if (!selectAddSub(I))
return SelectBinaryOp(I, ISD::ADD); return selectBinaryOp(I, ISD::ADD);
return true; return true;
case Instruction::Sub: case Instruction::Sub:
if (!selectAddSub(I)) if (!selectAddSub(I))
return SelectBinaryOp(I, ISD::SUB); return selectBinaryOp(I, ISD::SUB);
return true; return true;
case Instruction::FAdd: case Instruction::FAdd:
return SelectBinaryOp(I, ISD::FADD); return selectBinaryOp(I, ISD::FADD);
case Instruction::FSub: case Instruction::FSub:
// FNeg is currently represented in LLVM IR as a special case of FSub. // FNeg is currently represented in LLVM IR as a special case of FSub.
if (BinaryOperator::isFNeg(I)) if (BinaryOperator::isFNeg(I))
return SelectFNeg(I); return selectFNeg(I);
return SelectBinaryOp(I, ISD::FSUB); return selectBinaryOp(I, ISD::FSUB);
case Instruction::Mul: case Instruction::Mul:
if (!SelectBinaryOp(I, ISD::MUL)) if (!selectBinaryOp(I, ISD::MUL))
return SelectMul(I); return SelectMul(I);
return true; return true;
case Instruction::FMul: case Instruction::FMul:
return SelectBinaryOp(I, ISD::FMUL); return selectBinaryOp(I, ISD::FMUL);
case Instruction::SDiv: case Instruction::SDiv:
return SelectBinaryOp(I, ISD::SDIV); return selectBinaryOp(I, ISD::SDIV);
case Instruction::UDiv: case Instruction::UDiv:
return SelectBinaryOp(I, ISD::UDIV); return selectBinaryOp(I, ISD::UDIV);
case Instruction::FDiv: case Instruction::FDiv:
return SelectBinaryOp(I, ISD::FDIV); return selectBinaryOp(I, ISD::FDIV);
case Instruction::SRem: case Instruction::SRem:
if (!SelectBinaryOp(I, ISD::SREM)) if (!selectBinaryOp(I, ISD::SREM))
return SelectRem(I, ISD::SREM); return SelectRem(I, ISD::SREM);
return true; return true;
case Instruction::URem: case Instruction::URem:
if (!SelectBinaryOp(I, ISD::UREM)) if (!selectBinaryOp(I, ISD::UREM))
return SelectRem(I, ISD::UREM); return SelectRem(I, ISD::UREM);
return true; return true;
case Instruction::FRem: case Instruction::FRem:
return SelectBinaryOp(I, ISD::FREM); return selectBinaryOp(I, ISD::FREM);
case Instruction::Shl: case Instruction::Shl:
if (!SelectShift(I)) if (!SelectShift(I))
return SelectBinaryOp(I, ISD::SHL); return selectBinaryOp(I, ISD::SHL);
return true; return true;
case Instruction::LShr: case Instruction::LShr:
if (!SelectShift(I)) if (!SelectShift(I))
return SelectBinaryOp(I, ISD::SRL); return selectBinaryOp(I, ISD::SRL);
return true; return true;
case Instruction::AShr: case Instruction::AShr:
if (!SelectShift(I)) if (!SelectShift(I))
return SelectBinaryOp(I, ISD::SRA); return selectBinaryOp(I, ISD::SRA);
return true; return true;
case Instruction::And: case Instruction::And:
return SelectBinaryOp(I, ISD::AND); return selectBinaryOp(I, ISD::AND);
case Instruction::Or: case Instruction::Or:
return SelectBinaryOp(I, ISD::OR); return selectBinaryOp(I, ISD::OR);
case Instruction::Xor: case Instruction::Xor:
return SelectBinaryOp(I, ISD::XOR); return selectBinaryOp(I, ISD::XOR);
case Instruction::GetElementPtr: case Instruction::GetElementPtr:
return SelectGetElementPtr(I); return selectGetElementPtr(I);
case Instruction::Br: case Instruction::Br:
return SelectBranch(I); return SelectBranch(I);
case Instruction::IndirectBr: case Instruction::IndirectBr:
@ -3493,27 +3493,27 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
// Dynamic-sized alloca is not handled yet. // Dynamic-sized alloca is not handled yet.
return false; return false;
case Instruction::Call: case Instruction::Call:
return SelectCall(I); return selectCall(I);
case Instruction::BitCast: case Instruction::BitCast:
if (!FastISel::SelectBitCast(I)) if (!FastISel::selectBitCast(I))
return SelectBitCast(I); return SelectBitCast(I);
return true; return true;
case Instruction::FPToSI: case Instruction::FPToSI:
if (!SelectCast(I, ISD::FP_TO_SINT)) if (!selectCast(I, ISD::FP_TO_SINT))
return SelectFPToInt(I, /*Signed=*/true); return SelectFPToInt(I, /*Signed=*/true);
return true; return true;
case Instruction::FPToUI: case Instruction::FPToUI:
return SelectFPToInt(I, /*Signed=*/false); return SelectFPToInt(I, /*Signed=*/false);
case Instruction::ZExt: case Instruction::ZExt:
if (!SelectCast(I, ISD::ZERO_EXTEND)) if (!selectCast(I, ISD::ZERO_EXTEND))
return SelectIntExt(I); return SelectIntExt(I);
return true; return true;
case Instruction::SExt: case Instruction::SExt:
if (!SelectCast(I, ISD::SIGN_EXTEND)) if (!selectCast(I, ISD::SIGN_EXTEND))
return SelectIntExt(I); return SelectIntExt(I);
return true; return true;
case Instruction::Trunc: case Instruction::Trunc:
if (!SelectCast(I, ISD::TRUNCATE)) if (!selectCast(I, ISD::TRUNCATE))
return SelectTrunc(I); return SelectTrunc(I);
return true; return true;
case Instruction::FPExt: case Instruction::FPExt:
@ -3521,7 +3521,7 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
case Instruction::FPTrunc: case Instruction::FPTrunc:
return SelectFPTrunc(I); return SelectFPTrunc(I);
case Instruction::SIToFP: case Instruction::SIToFP:
if (!SelectCast(I, ISD::SINT_TO_FP)) if (!selectCast(I, ISD::SINT_TO_FP))
return SelectIntToFP(I, /*Signed=*/true); return SelectIntToFP(I, /*Signed=*/true);
return true; return true;
case Instruction::UIToFP: case Instruction::UIToFP:
@ -3531,9 +3531,9 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType()); EVT SrcVT = TLI.getValueType(I->getOperand(0)->getType());
EVT DstVT = TLI.getValueType(I->getType()); EVT DstVT = TLI.getValueType(I->getType());
if (DstVT.bitsGT(SrcVT)) if (DstVT.bitsGT(SrcVT))
return SelectCast(I, ISD::ZERO_EXTEND); return selectCast(I, ISD::ZERO_EXTEND);
if (DstVT.bitsLT(SrcVT)) if (DstVT.bitsLT(SrcVT))
return SelectCast(I, ISD::TRUNCATE); return selectCast(I, ISD::TRUNCATE);
unsigned Reg = getRegForValue(I->getOperand(0)); unsigned Reg = getRegForValue(I->getOperand(0));
if (!Reg) if (!Reg)
return false; return false;
@ -3541,7 +3541,7 @@ bool AArch64FastISel::TargetSelectInstruction(const Instruction *I) {
return true; return true;
} }
case Instruction::ExtractValue: case Instruction::ExtractValue:
return SelectExtractValue(I); return selectExtractValue(I);
case Instruction::PHI: case Instruction::PHI:
llvm_unreachable("FastISel shouldn't visit PHI nodes!"); llvm_unreachable("FastISel shouldn't visit PHI nodes!");
case Instruction::Load: case Instruction::Load: