forked from OSchip/llvm-project
[CodeGen] Use MachineOperand::print in the MIRPrinter for MO_Register.
Work towards the unification of MIR and debug output by refactoring the interfaces. For MachineOperand::print, keep a simple version that can be easily called from `dump()`, and a more complex one which will be called from both the MIRPrinter and MachineInstr::print. Add extra checks inside MachineOperand for detached operands (operands with getParent() == nullptr). https://reviews.llvm.org/D40836 * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/kill: ([^ ]+) ([^ ]+)<def> ([^ ]+)/kill: \1 def \2 \3/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/kill: ([^ ]+) ([^ ]+) ([^ ]+)<def>/kill: \1 \2 def \3/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/kill: def ([^ ]+) ([^ ]+) ([^ ]+)<def>/kill: def \1 \2 def \3/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/<def>//g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<kill>/killed \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<imp-use,kill>/implicit killed \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<dead>/dead \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<def[ ]*,[ ]*dead>/dead \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<imp-def[ ]*,[ ]*dead>/implicit-def dead \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<imp-def>/implicit-def \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<imp-use>/implicit \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<internal>/internal \1/g' * find . \( -name "*.mir" -o -name "*.cpp" -o -name "*.h" -o -name "*.ll" -o -name "*.s" \) -type f -print0 | xargs -0 sed -i '' -E 's/([^ ]+)<undef>/undef \1/g' llvm-svn: 320022
This commit is contained in:
parent
62ef18562b
commit
a8a83d150f
|
@ -204,7 +204,7 @@ public:
|
|||
const MDNode *Variable,
|
||||
const MDNode *Expr);
|
||||
|
||||
/// Build and insert \p Res<def> = G_FRAME_INDEX \p Idx
|
||||
/// Build and insert \p Res = G_FRAME_INDEX \p Idx
|
||||
///
|
||||
/// G_FRAME_INDEX materializes the address of an alloca value or other
|
||||
/// stack-based object.
|
||||
|
@ -215,7 +215,7 @@ public:
|
|||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildFrameIndex(unsigned Res, int Idx);
|
||||
|
||||
/// Build and insert \p Res<def> = G_GLOBAL_VALUE \p GV
|
||||
/// Build and insert \p Res = G_GLOBAL_VALUE \p GV
|
||||
///
|
||||
/// G_GLOBAL_VALUE materializes the address of the specified global
|
||||
/// into \p Res.
|
||||
|
@ -227,7 +227,7 @@ public:
|
|||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildGlobalValue(unsigned Res, const GlobalValue *GV);
|
||||
|
||||
/// Build and insert \p Res<def> = G_ADD \p Op0, \p Op1
|
||||
/// Build and insert \p Res = G_ADD \p Op0, \p Op1
|
||||
///
|
||||
/// G_ADD sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
|
||||
/// truncated to their width.
|
||||
|
@ -245,7 +245,7 @@ public:
|
|||
return buildAdd(Res, (getRegFromArg(UseArgs))...);
|
||||
}
|
||||
|
||||
/// Build and insert \p Res<def> = G_SUB \p Op0, \p Op1
|
||||
/// Build and insert \p Res = G_SUB \p Op0, \p Op1
|
||||
///
|
||||
/// G_SUB sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
|
||||
/// truncated to their width.
|
||||
|
@ -258,7 +258,7 @@ public:
|
|||
MachineInstrBuilder buildSub(unsigned Res, unsigned Op0,
|
||||
unsigned Op1);
|
||||
|
||||
/// Build and insert \p Res<def> = G_MUL \p Op0, \p Op1
|
||||
/// Build and insert \p Res = G_MUL \p Op0, \p Op1
|
||||
///
|
||||
/// G_MUL sets \p Res to the sum of integer parameters \p Op0 and \p Op1,
|
||||
/// truncated to their width.
|
||||
|
@ -271,7 +271,7 @@ public:
|
|||
MachineInstrBuilder buildMul(unsigned Res, unsigned Op0,
|
||||
unsigned Op1);
|
||||
|
||||
/// Build and insert \p Res<def> = G_GEP \p Op0, \p Op1
|
||||
/// Build and insert \p Res = G_GEP \p Op0, \p Op1
|
||||
///
|
||||
/// G_GEP adds \p Op1 bytes to the pointer specified by \p Op0,
|
||||
/// storing the resulting pointer in \p Res.
|
||||
|
@ -285,7 +285,7 @@ public:
|
|||
MachineInstrBuilder buildGEP(unsigned Res, unsigned Op0,
|
||||
unsigned Op1);
|
||||
|
||||
/// Materialize and insert \p Res<def> = G_GEP \p Op0, (G_CONSTANT \p Value)
|
||||
/// Materialize and insert \p Res = G_GEP \p Op0, (G_CONSTANT \p Value)
|
||||
///
|
||||
/// G_GEP adds \p Value bytes to the pointer specified by \p Op0,
|
||||
/// storing the resulting pointer in \p Res. If \p Value is zero then no
|
||||
|
@ -305,7 +305,7 @@ public:
|
|||
const LLT &ValueTy,
|
||||
uint64_t Value);
|
||||
|
||||
/// Build and insert \p Res<def> = G_PTR_MASK \p Op0, \p NumBits
|
||||
/// Build and insert \p Res = G_PTR_MASK \p Op0, \p NumBits
|
||||
///
|
||||
/// G_PTR_MASK clears the low bits of a pointer operand without destroying its
|
||||
/// pointer properties. This has the effect of rounding the address *down* to
|
||||
|
@ -321,7 +321,7 @@ public:
|
|||
MachineInstrBuilder buildPtrMask(unsigned Res, unsigned Op0,
|
||||
uint32_t NumBits);
|
||||
|
||||
/// Build and insert \p Res<def>, \p CarryOut<def> = G_UADDE \p Op0,
|
||||
/// Build and insert \p Res, \p CarryOut = G_UADDE \p Op0,
|
||||
/// \p Op1, \p CarryIn
|
||||
///
|
||||
/// G_UADDE sets \p Res to \p Op0 + \p Op1 + \p CarryIn (truncated to the bit
|
||||
|
@ -338,7 +338,7 @@ public:
|
|||
MachineInstrBuilder buildUAdde(unsigned Res, unsigned CarryOut, unsigned Op0,
|
||||
unsigned Op1, unsigned CarryIn);
|
||||
|
||||
/// Build and insert \p Res<def> = G_AND \p Op0, \p Op1
|
||||
/// Build and insert \p Res = G_AND \p Op0, \p Op1
|
||||
///
|
||||
/// G_AND sets \p Res to the bitwise and of integer parameters \p Op0 and \p
|
||||
/// Op1.
|
||||
|
@ -355,7 +355,7 @@ public:
|
|||
MachineInstrBuilder buildAnd(unsigned Res, unsigned Op0,
|
||||
unsigned Op1);
|
||||
|
||||
/// Build and insert \p Res<def> = G_OR \p Op0, \p Op1
|
||||
/// Build and insert \p Res = G_OR \p Op0, \p Op1
|
||||
///
|
||||
/// G_OR sets \p Res to the bitwise or of integer parameters \p Op0 and \p
|
||||
/// Op1.
|
||||
|
@ -367,7 +367,7 @@ public:
|
|||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildOr(unsigned Res, unsigned Op0, unsigned Op1);
|
||||
|
||||
/// Build and insert \p Res<def> = G_ANYEXT \p Op0
|
||||
/// Build and insert \p Res = G_ANYEXT \p Op0
|
||||
///
|
||||
/// G_ANYEXT produces a register of the specified width, with bits 0 to
|
||||
/// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are unspecified
|
||||
|
@ -387,7 +387,7 @@ public:
|
|||
return buildAnyExt(getDestFromArg(Res), getRegFromArg(Arg));
|
||||
}
|
||||
|
||||
/// Build and insert \p Res<def> = G_SEXT \p Op
|
||||
/// Build and insert \p Res = G_SEXT \p Op
|
||||
///
|
||||
/// G_SEXT produces a register of the specified width, with bits 0 to
|
||||
/// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are duplicated from the
|
||||
|
@ -401,7 +401,7 @@ public:
|
|||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildSExt(unsigned Res, unsigned Op);
|
||||
|
||||
/// Build and insert \p Res<def> = G_ZEXT \p Op
|
||||
/// Build and insert \p Res = G_ZEXT \p Op
|
||||
///
|
||||
/// G_ZEXT produces a register of the specified width, with bits 0 to
|
||||
/// sizeof(\p Ty) * 8 set to \p Op. The remaining bits are 0. For a vector
|
||||
|
@ -415,7 +415,7 @@ public:
|
|||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildZExt(unsigned Res, unsigned Op);
|
||||
|
||||
/// Build and insert \p Res<def> = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or
|
||||
/// Build and insert \p Res = G_SEXT \p Op, \p Res = G_TRUNC \p Op, or
|
||||
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
|
||||
/// ///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
|
@ -425,7 +425,7 @@ public:
|
|||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildSExtOrTrunc(unsigned Res, unsigned Op);
|
||||
|
||||
/// Build and insert \p Res<def> = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
|
||||
/// Build and insert \p Res = G_ZEXT \p Op, \p Res = G_TRUNC \p Op, or
|
||||
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
|
||||
/// ///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
|
@ -435,7 +435,7 @@ public:
|
|||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildZExtOrTrunc(unsigned Res, unsigned Op);
|
||||
|
||||
// Build and insert \p Res<def> = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or
|
||||
// Build and insert \p Res = G_ANYEXT \p Op, \p Res = G_TRUNC \p Op, or
|
||||
/// \p Res = COPY \p Op depending on the differing sizes of \p Res and \p Op.
|
||||
/// ///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
|
@ -449,7 +449,7 @@ public:
|
|||
}
|
||||
MachineInstrBuilder buildAnyExtOrTrunc(unsigned Res, unsigned Op);
|
||||
|
||||
/// Build and insert \p Res<def> = \p ExtOpc, \p Res = G_TRUNC \p
|
||||
/// Build and insert \p Res = \p ExtOpc, \p Res = G_TRUNC \p
|
||||
/// Op, or \p Res = COPY \p Op depending on the differing sizes of \p Res and
|
||||
/// \p Op.
|
||||
/// ///
|
||||
|
@ -534,7 +534,7 @@ public:
|
|||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildFConstant(unsigned Res, const ConstantFP &Val);
|
||||
|
||||
/// Build and insert \p Res<def> = COPY Op
|
||||
/// Build and insert \p Res = COPY Op
|
||||
///
|
||||
/// Register-to-register COPY sets \p Res to \p Op.
|
||||
///
|
||||
|
@ -547,7 +547,7 @@ public:
|
|||
return buildCopy(getDestFromArg(Res), getRegFromArg(Src));
|
||||
}
|
||||
|
||||
/// Build and insert `Res<def> = G_LOAD Addr, MMO`.
|
||||
/// Build and insert `Res = G_LOAD Addr, MMO`.
|
||||
///
|
||||
/// Loads the value stored at \p Addr. Puts the result in \p Res.
|
||||
///
|
||||
|
@ -571,7 +571,7 @@ public:
|
|||
MachineInstrBuilder buildStore(unsigned Val, unsigned Addr,
|
||||
MachineMemOperand &MMO);
|
||||
|
||||
/// Build and insert `Res0<def>, ... = G_EXTRACT Src, Idx0`.
|
||||
/// Build and insert `Res0, ... = G_EXTRACT Src, Idx0`.
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre \p Res and \p Src must be generic virtual registers.
|
||||
|
@ -598,7 +598,7 @@ public:
|
|||
void buildSequence(unsigned Res, ArrayRef<unsigned> Ops,
|
||||
ArrayRef<uint64_t> Indices);
|
||||
|
||||
/// Build and insert \p Res<def> = G_MERGE_VALUES \p Op0, ...
|
||||
/// Build and insert \p Res = G_MERGE_VALUES \p Op0, ...
|
||||
///
|
||||
/// G_MERGE_VALUES combines the input elements contiguously into a larger
|
||||
/// register.
|
||||
|
@ -611,7 +611,7 @@ public:
|
|||
/// \return a MachineInstrBuilder for the newly created instruction.
|
||||
MachineInstrBuilder buildMerge(unsigned Res, ArrayRef<unsigned> Ops);
|
||||
|
||||
/// Build and insert \p Res0<def>, ... = G_UNMERGE_VALUES \p Op
|
||||
/// Build and insert \p Res0, ... = G_UNMERGE_VALUES \p Op
|
||||
///
|
||||
/// G_UNMERGE_VALUES splits contiguous bits of the input into multiple
|
||||
///
|
||||
|
@ -639,7 +639,7 @@ public:
|
|||
MachineInstrBuilder buildIntrinsic(Intrinsic::ID ID, unsigned Res,
|
||||
bool HasSideEffects);
|
||||
|
||||
/// Build and insert \p Res<def> = G_FPTRUNC \p Op
|
||||
/// Build and insert \p Res = G_FPTRUNC \p Op
|
||||
///
|
||||
/// G_FPTRUNC converts a floating-point value into one with a smaller type.
|
||||
///
|
||||
|
@ -651,7 +651,7 @@ public:
|
|||
/// \return The newly created instruction.
|
||||
MachineInstrBuilder buildFPTrunc(unsigned Res, unsigned Op);
|
||||
|
||||
/// Build and insert \p Res<def> = G_TRUNC \p Op
|
||||
/// Build and insert \p Res = G_TRUNC \p Op
|
||||
///
|
||||
/// G_TRUNC extracts the low bits of a type. For a vector type each element is
|
||||
/// truncated independently before being packed into the destination.
|
||||
|
@ -711,7 +711,7 @@ public:
|
|||
MachineInstrBuilder buildSelect(unsigned Res, unsigned Tst,
|
||||
unsigned Op0, unsigned Op1);
|
||||
|
||||
/// Build and insert \p Res<def> = G_INSERT_VECTOR_ELT \p Val,
|
||||
/// Build and insert \p Res = G_INSERT_VECTOR_ELT \p Val,
|
||||
/// \p Elt, \p Idx
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
|
@ -724,7 +724,7 @@ public:
|
|||
MachineInstrBuilder buildInsertVectorElement(unsigned Res, unsigned Val,
|
||||
unsigned Elt, unsigned Idx);
|
||||
|
||||
/// Build and insert \p Res<def> = G_EXTRACT_VECTOR_ELT \p Val, \p Idx
|
||||
/// Build and insert \p Res = G_EXTRACT_VECTOR_ELT \p Val, \p Idx
|
||||
///
|
||||
/// \pre setBasicBlock or setMI must have been called.
|
||||
/// \pre \p Res must be a generic virtual register with scalar type.
|
||||
|
@ -735,7 +735,7 @@ public:
|
|||
MachineInstrBuilder buildExtractVectorElement(unsigned Res, unsigned Val,
|
||||
unsigned Idx);
|
||||
|
||||
/// Build and insert `OldValRes<def> = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal,
|
||||
/// Build and insert `OldValRes = G_ATOMIC_CMPXCHG Addr, CmpVal, NewVal,
|
||||
/// MMO`.
|
||||
///
|
||||
/// Atomically replace the value at \p Addr with \p NewVal if it is currently
|
||||
|
|
|
@ -20,11 +20,11 @@
|
|||
/// register.
|
||||
///
|
||||
/// X86 Example:
|
||||
/// %ymm0<def> = ...
|
||||
/// %xmm0<def> = ... (Kills %xmm0, all %xmm0s sub-registers, and %ymm0)
|
||||
/// %ymm0 = ...
|
||||
/// %xmm0 = ... (Kills %xmm0, all %xmm0s sub-registers, and %ymm0)
|
||||
///
|
||||
/// %ymm0<def> = ...
|
||||
/// %xmm0<def> = ..., %ymm0<imp-use> (%ymm0 and all its sub-registers are alive)
|
||||
/// %ymm0 = ...
|
||||
/// %xmm0 = ..., implicit %ymm0 (%ymm0 and all its sub-registers are alive)
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLVM_CODEGEN_LIVEPHYSREGS_H
|
||||
|
|
|
@ -702,8 +702,8 @@ public:
|
|||
LQR_Unknown ///< Register liveness not decidable from local neighborhood.
|
||||
};
|
||||
|
||||
/// Return whether (physical) register \p Reg has been <def>ined and not
|
||||
/// <kill>ed as of just before \p Before.
|
||||
/// Return whether (physical) register \p Reg has been defined and not
|
||||
/// killed as of just before \p Before.
|
||||
///
|
||||
/// Search is localised to a neighborhood of \p Neighborhood instructions
|
||||
/// before (searching for defs or kills) and \p Neighborhood instructions
|
||||
|
|
|
@ -44,6 +44,7 @@ class MachineRegisterInfo;
|
|||
class ModuleSlotTracker;
|
||||
class raw_ostream;
|
||||
template <typename T> class SmallVectorImpl;
|
||||
class SmallBitVector;
|
||||
class StringRef;
|
||||
class TargetInstrInfo;
|
||||
class TargetRegisterClass;
|
||||
|
@ -1220,6 +1221,15 @@ public:
|
|||
|
||||
/// Debugging support
|
||||
/// @{
|
||||
/// Determine the generic type to be printed (if needed) on uses and defs.
|
||||
LLT getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes,
|
||||
const MachineRegisterInfo &MRI) const;
|
||||
|
||||
/// Return true when an instruction has tied register that can't be determined
|
||||
/// by the instruction's descriptor. This is useful for MIR printing, to
|
||||
/// determine whether we need to print the ties or not.
|
||||
bool hasComplexRegisterTies() const;
|
||||
|
||||
/// Print this MI to \p OS.
|
||||
/// Only print the defs and the opcode if \p SkipOpers is true.
|
||||
/// Otherwise, also print operands if \p SkipDebugLoc is true.
|
||||
|
|
|
@ -150,7 +150,7 @@ public:
|
|||
///
|
||||
struct VirtRegInfo {
|
||||
/// Reads - One of the operands read the virtual register. This does not
|
||||
/// include <undef> or <internal> use operands, see MO::readsReg().
|
||||
/// include undef or internal use operands, see MO::readsReg().
|
||||
bool Reads;
|
||||
|
||||
/// Writes - One of the operands writes the virtual register.
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "llvm/ADT/DenseMap.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/Support/LowLevelTypeImpl.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
|
@ -116,7 +117,7 @@ private:
|
|||
/// the same register. In that case, the instruction may depend on those
|
||||
/// operands reading the same dont-care value. For example:
|
||||
///
|
||||
/// %1<def> = XOR %2<undef>, %2<undef>
|
||||
/// %1 = XOR undef %2, undef %2
|
||||
///
|
||||
/// Any register can be used for %2, and its value doesn't matter, but
|
||||
/// the two operands must be the same register.
|
||||
|
@ -226,11 +227,33 @@ public:
|
|||
///
|
||||
void clearParent() { ParentMI = nullptr; }
|
||||
|
||||
/// Print the MachineOperand to \p os.
|
||||
/// Providing a valid \p TRI and \p IntrinsicInfo results in a more
|
||||
/// target-specific printing. If \p TRI and \p IntrinsicInfo are null, the
|
||||
/// function will try to pick it up from the parent.
|
||||
void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const;
|
||||
void print(raw_ostream &os, ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI = nullptr,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const;
|
||||
|
||||
/// More complex way of printing a MachineOperand.
|
||||
/// \param TypeToPrint specifies the generic type to be printed on uses and
|
||||
/// defs. It can be determined using MachineInstr::getTypeToPrint.
|
||||
/// \param PrintDef - whether we want to print `def` on an operand which
|
||||
/// isDef. Sometimes, if the operand is printed before '=', we don't print
|
||||
/// `def`.
|
||||
/// \param ShouldPrintRegisterTies - whether we want to print register ties.
|
||||
/// Sometimes they are easily determined by the instruction's descriptor
|
||||
/// (MachineInstr::hasComplexRegiterTies can determine if it's needed).
|
||||
/// \param TiedOperandIdx - if we need to print register ties this needs to
|
||||
/// provide the index of the tied register. If not, it will be ignored.
|
||||
/// \param TRI - provide more target-specific information to the printer.
|
||||
/// Unlike the previous function, this one will not try and get the
|
||||
/// information from it's parent.
|
||||
/// \param IntrinsicInfo - same as \p TRI.
|
||||
void print(raw_ostream &os, ModuleSlotTracker &MST, LLT TypeToPrint,
|
||||
bool PrintDef, bool ShouldPrintRegisterTies,
|
||||
unsigned TiedOperandIdx, const TargetRegisterInfo *TRI,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo) const;
|
||||
|
||||
void dump() const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
|
@ -831,7 +854,7 @@ template <> struct DenseMapInfo<MachineOperand> {
|
|||
};
|
||||
|
||||
inline raw_ostream &operator<<(raw_ostream &OS, const MachineOperand &MO) {
|
||||
MO.print(OS, nullptr);
|
||||
MO.print(OS);
|
||||
return OS;
|
||||
}
|
||||
|
||||
|
|
|
@ -547,7 +547,7 @@ public:
|
|||
/// Represents a predicate at the MachineFunction level. The control flow a
|
||||
/// MachineBranchPredicate represents is:
|
||||
///
|
||||
/// Reg <def>= LHS `Predicate` RHS == ConditionDef
|
||||
/// Reg = LHS `Predicate` RHS == ConditionDef
|
||||
/// if Reg then goto TrueDest else goto FalseDest
|
||||
///
|
||||
struct MachineBranchPredicate {
|
||||
|
@ -1432,7 +1432,7 @@ public:
|
|||
/// For example, AVX instructions may copy part of a register operand into
|
||||
/// the unused high bits of the destination register.
|
||||
///
|
||||
/// vcvtsi2sdq %rax, %xmm0<undef>, %xmm14
|
||||
/// vcvtsi2sdq %rax, undef %xmm0, %xmm14
|
||||
///
|
||||
/// In the code above, vcvtsi2sdq copies %xmm0[127:64] into %xmm14 creating a
|
||||
/// false dependence on any previous write to %xmm0.
|
||||
|
|
|
@ -1167,6 +1167,11 @@ Printable printRegUnit(unsigned Unit, const TargetRegisterInfo *TRI);
|
|||
/// registers on a \ref raw_ostream.
|
||||
Printable printVRegOrUnit(unsigned VRegOrUnit, const TargetRegisterInfo *TRI);
|
||||
|
||||
/// \brief Create Printable object to print register classes or register banks
|
||||
/// on a \ref raw_ostream.
|
||||
Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo,
|
||||
const TargetRegisterInfo *TRI);
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
#endif // LLVM_CODEGEN_TARGETREGISTERINFO_H
|
||||
|
|
|
@ -448,11 +448,11 @@ void AggressiveAntiDepBreaker::ScanInstruction(MachineInstr &MI,
|
|||
// FIXME: The issue with predicated instruction is more complex. We are being
|
||||
// conservatively here because the kill markers cannot be trusted after
|
||||
// if-conversion:
|
||||
// %r6<def> = LDR %sp, %reg0, 92, pred:14, pred:%reg0; mem:LD4[FixedStack14]
|
||||
// %r6 = LDR %sp, %reg0, 92, pred:14, pred:%reg0; mem:LD4[FixedStack14]
|
||||
// ...
|
||||
// STR %r0, %r6<kill>, %reg0, 0, pred:0, pred:%cpsr; mem:ST4[%395]
|
||||
// %r6<def> = LDR %sp, %reg0, 100, pred:0, pred:%cpsr; mem:LD4[FixedStack12]
|
||||
// STR %r0, %r6<kill>, %reg0, 0, pred:14, pred:%reg0; mem:ST4[%396](align=8)
|
||||
// STR %r0, killed %r6, %reg0, 0, pred:0, pred:%cpsr; mem:ST4[%395]
|
||||
// %r6 = LDR %sp, %reg0, 100, pred:0, pred:%cpsr; mem:LD4[FixedStack12]
|
||||
// STR %r0, killed %r6, %reg0, 0, pred:14, pred:%reg0; mem:ST4[%396](align=8)
|
||||
//
|
||||
// The first R6 kill is not really a kill since it's killed by a predicated
|
||||
// instruction which may not be executed. The second R6 def may or may not
|
||||
|
|
|
@ -815,10 +815,8 @@ static void emitKill(const MachineInstr *MI, AsmPrinter &AP) {
|
|||
for (unsigned i = 0, e = MI->getNumOperands(); i != e; ++i) {
|
||||
const MachineOperand &Op = MI->getOperand(i);
|
||||
assert(Op.isReg() && "KILL instruction must have only register operands");
|
||||
OS << ' '
|
||||
<< printReg(Op.getReg(),
|
||||
AP.MF->getSubtarget().getRegisterInfo())
|
||||
<< (Op.isDef() ? "<def>" : "<kill>");
|
||||
OS << ' ' << (Op.isDef() ? "def " : "killed ")
|
||||
<< printReg(Op.getReg(), AP.MF->getSubtarget().getRegisterInfo());
|
||||
}
|
||||
AP.OutStreamer->AddComment(OS.str());
|
||||
AP.OutStreamer->AddBlankLine();
|
||||
|
|
|
@ -1968,7 +1968,7 @@ bool BranchFolder::HoistCommonCodeInSuccs(MachineBasicBlock *MBB) {
|
|||
//
|
||||
// BB2:
|
||||
// r1 = op2, ...
|
||||
// = op3, r1<kill>
|
||||
// = op3, killed r1
|
||||
IsSafe = false;
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -170,11 +170,11 @@ void CriticalAntiDepBreaker::PrescanInstruction(MachineInstr &MI) {
|
|||
// FIXME: The issue with predicated instruction is more complex. We are being
|
||||
// conservative here because the kill markers cannot be trusted after
|
||||
// if-conversion:
|
||||
// %r6<def> = LDR %sp, %reg0, 92, pred:14, pred:%reg0; mem:LD4[FixedStack14]
|
||||
// %r6 = LDR %sp, %reg0, 92, pred:14, pred:%reg0; mem:LD4[FixedStack14]
|
||||
// ...
|
||||
// STR %r0, %r6<kill>, %reg0, 0, pred:0, pred:%cpsr; mem:ST4[%395]
|
||||
// %r6<def> = LDR %sp, %reg0, 100, pred:0, pred:%cpsr; mem:LD4[FixedStack12]
|
||||
// STR %r0, %r6<kill>, %reg0, 0, pred:14, pred:%reg0; mem:ST4[%396](align=8)
|
||||
// STR %r0, killed %r6, %reg0, 0, pred:0, pred:%cpsr; mem:ST4[%395]
|
||||
// %r6 = LDR %sp, %reg0, 100, pred:0, pred:%cpsr; mem:LD4[FixedStack12]
|
||||
// STR %r0, killed %r6, %reg0, 0, pred:14, pred:%reg0; mem:ST4[%396](align=8)
|
||||
//
|
||||
// The first R6 kill is not really a kill since it's killed by a predicated
|
||||
// instruction which may not be executed. The second R6 def may or may not
|
||||
|
|
|
@ -104,7 +104,7 @@ bool ExpandPostRA::LowerSubregToReg(MachineInstr *MI) {
|
|||
if (DstSubReg == InsReg) {
|
||||
// No need to insert an identity copy instruction.
|
||||
// Watch out for case like this:
|
||||
// %rax<def> = SUBREG_TO_REG 0, %eax<kill>, 3
|
||||
// %rax = SUBREG_TO_REG 0, killed %eax, 3
|
||||
// We must leave %rax live.
|
||||
if (DstReg != InsReg) {
|
||||
MI->setDesc(TII->get(TargetOpcode::KILL));
|
||||
|
|
|
@ -421,7 +421,7 @@ bool ImplicitNullChecks::canHoistInst(MachineInstr *FaultingMI,
|
|||
// test %rcx, %rcx
|
||||
// je _null_block
|
||||
// _non_null_block:
|
||||
// %rdx<def> = INST
|
||||
// %rdx = INST
|
||||
// ...
|
||||
//
|
||||
// This restriction does not apply to the faulting load inst because in
|
||||
|
|
|
@ -360,7 +360,7 @@ bool InlineSpiller::isSibling(unsigned Reg) {
|
|||
///
|
||||
/// x = def
|
||||
/// spill x
|
||||
/// y = use x<kill>
|
||||
/// y = use killed x
|
||||
///
|
||||
/// This hoist only helps when the copy kills its source.
|
||||
///
|
||||
|
|
|
@ -700,7 +700,7 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
|
|||
//
|
||||
// %eax = COPY %5
|
||||
// FOO %5 <--- MI, cancel kill because %eax is live.
|
||||
// BAR %eax<kill>
|
||||
// BAR killed %eax
|
||||
//
|
||||
// There should be no kill flag on FOO when %5 is rewritten as %eax.
|
||||
for (auto &RUP : RU) {
|
||||
|
@ -721,7 +721,7 @@ void LiveIntervals::addKillFlags(const VirtRegMap *VRM) {
|
|||
// Example:
|
||||
// %1 = ... ; R32: %1
|
||||
// %2:high16 = ... ; R64: %2
|
||||
// = read %2<kill> ; R64: %2
|
||||
// = read killed %2 ; R64: %2
|
||||
// = read %1 ; R32: %1
|
||||
// The <kill> flag is correct for %2, but the register allocator may
|
||||
// assign R0L to %1, and R0 to %2 because the low 32bits of R0
|
||||
|
|
|
@ -235,7 +235,7 @@ void LiveVariables::HandlePhysRegUse(unsigned Reg, MachineInstr &MI) {
|
|||
// Otherwise, the last sub-register def implicitly defines this register.
|
||||
// e.g.
|
||||
// AH =
|
||||
// AL = ... <imp-def EAX>, <imp-kill AH>
|
||||
// AL = ... implicit-def EAX, implicit killed AH
|
||||
// = AH
|
||||
// ...
|
||||
// = EAX
|
||||
|
@ -321,17 +321,17 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
|
|||
// AH =
|
||||
//
|
||||
// = AX
|
||||
// = AL, AX<imp-use, kill>
|
||||
// = AL, implicit killed AX
|
||||
// AX =
|
||||
//
|
||||
// Or whole register is defined, but not used at all.
|
||||
// AX<dead> =
|
||||
// dead AX =
|
||||
// ...
|
||||
// AX =
|
||||
//
|
||||
// Or whole register is defined, but only partly used.
|
||||
// AX<dead> = AL<imp-def>
|
||||
// = AL<kill>
|
||||
// dead AX = implicit-def AL
|
||||
// = killed AL
|
||||
// AX =
|
||||
MachineInstr *LastPartDef = nullptr;
|
||||
unsigned LastPartDefDist = 0;
|
||||
|
@ -364,7 +364,7 @@ bool LiveVariables::HandlePhysRegKill(unsigned Reg, MachineInstr *MI) {
|
|||
if (!PhysRegUse[Reg]) {
|
||||
// Partial uses. Mark register def dead and add implicit def of
|
||||
// sub-registers which are used.
|
||||
// EAX<dead> = op AL<imp-def>
|
||||
// dead EAX = op implicit-def AL
|
||||
// That is, EAX def is dead but AL def extends pass it.
|
||||
PhysRegDef[Reg]->addRegisterDead(Reg, TRI, true);
|
||||
for (MCSubRegIterator SubRegs(Reg, TRI); SubRegs.isValid(); ++SubRegs) {
|
||||
|
|
|
@ -164,7 +164,7 @@ public:
|
|||
void printTargetFlags(const MachineOperand &Op);
|
||||
void print(const MachineInstr &MI, unsigned OpIdx,
|
||||
const TargetRegisterInfo *TRI, bool ShouldPrintRegisterTies,
|
||||
LLT TypeToPrint, bool IsDef = false);
|
||||
LLT TypeToPrint, bool PrintDef = true);
|
||||
void print(const LLVMContext &Context, const TargetInstrInfo &TII,
|
||||
const MachineMemOperand &Op);
|
||||
void printSyncScope(const LLVMContext &Context, SyncScope::ID SSID);
|
||||
|
@ -257,25 +257,11 @@ static void printCustomRegMask(const uint32_t *RegMask, raw_ostream &OS,
|
|||
OS << ')';
|
||||
}
|
||||
|
||||
static void printRegClassOrBank(unsigned Reg, raw_ostream &OS,
|
||||
const MachineRegisterInfo &RegInfo,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
if (RegInfo.getRegClassOrNull(Reg))
|
||||
OS << StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
|
||||
else if (RegInfo.getRegBankOrNull(Reg))
|
||||
OS << StringRef(RegInfo.getRegBankOrNull(Reg)->getName()).lower();
|
||||
else {
|
||||
OS << "_";
|
||||
assert((RegInfo.def_empty(Reg) || RegInfo.getType(Reg).isValid()) &&
|
||||
"Generic registers must have a valid type");
|
||||
}
|
||||
}
|
||||
|
||||
static void printRegClassOrBank(unsigned Reg, yaml::StringValue &Dest,
|
||||
const MachineRegisterInfo &RegInfo,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
raw_string_ostream OS(Dest.Value);
|
||||
printRegClassOrBank(Reg, OS, RegInfo, TRI);
|
||||
OS << printRegClassOrBank(Reg, RegInfo, TRI);
|
||||
}
|
||||
|
||||
|
||||
|
@ -289,7 +275,7 @@ void MIRPrinter::convert(yaml::MachineFunction &MF,
|
|||
unsigned Reg = TargetRegisterInfo::index2VirtReg(I);
|
||||
yaml::VirtualRegisterDefinition VReg;
|
||||
VReg.ID = I;
|
||||
printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI);
|
||||
::printRegClassOrBank(Reg, VReg.Class, RegInfo, TRI);
|
||||
unsigned PreferredReg = RegInfo.getSimpleHint(Reg);
|
||||
if (PreferredReg)
|
||||
printRegMIR(PreferredReg, VReg.PreferredRegister, TRI);
|
||||
|
@ -661,44 +647,6 @@ void MIPrinter::print(const MachineBasicBlock &MBB) {
|
|||
OS.indent(2) << "}\n";
|
||||
}
|
||||
|
||||
/// Return true when an instruction has tied register that can't be determined
|
||||
/// by the instruction's descriptor.
|
||||
static bool hasComplexRegisterTies(const MachineInstr &MI) {
|
||||
const MCInstrDesc &MCID = MI.getDesc();
|
||||
for (unsigned I = 0, E = MI.getNumOperands(); I < E; ++I) {
|
||||
const auto &Operand = MI.getOperand(I);
|
||||
if (!Operand.isReg() || Operand.isDef())
|
||||
// Ignore the defined registers as MCID marks only the uses as tied.
|
||||
continue;
|
||||
int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO);
|
||||
int TiedIdx = Operand.isTied() ? int(MI.findTiedOperandIdx(I)) : -1;
|
||||
if (ExpectedTiedIdx != TiedIdx)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static LLT getTypeToPrint(const MachineInstr &MI, unsigned OpIdx,
|
||||
SmallBitVector &PrintedTypes,
|
||||
const MachineRegisterInfo &MRI) {
|
||||
const MachineOperand &Op = MI.getOperand(OpIdx);
|
||||
if (!Op.isReg())
|
||||
return LLT{};
|
||||
|
||||
if (MI.isVariadic() || OpIdx >= MI.getNumExplicitOperands())
|
||||
return MRI.getType(Op.getReg());
|
||||
|
||||
auto &OpInfo = MI.getDesc().OpInfo[OpIdx];
|
||||
if (!OpInfo.isGenericType())
|
||||
return MRI.getType(Op.getReg());
|
||||
|
||||
if (PrintedTypes[OpInfo.getGenericTypeIndex()])
|
||||
return LLT{};
|
||||
|
||||
PrintedTypes.set(OpInfo.getGenericTypeIndex());
|
||||
return MRI.getType(Op.getReg());
|
||||
}
|
||||
|
||||
void MIPrinter::print(const MachineInstr &MI) {
|
||||
const auto *MF = MI.getMF();
|
||||
const auto &MRI = MF->getRegInfo();
|
||||
|
@ -711,7 +659,7 @@ void MIPrinter::print(const MachineInstr &MI) {
|
|||
assert(MI.getNumOperands() == 1 && "Expected 1 operand in CFI instruction");
|
||||
|
||||
SmallBitVector PrintedTypes(8);
|
||||
bool ShouldPrintRegisterTies = hasComplexRegisterTies(MI);
|
||||
bool ShouldPrintRegisterTies = MI.hasComplexRegisterTies();
|
||||
unsigned I = 0, E = MI.getNumOperands();
|
||||
for (; I < E && MI.getOperand(I).isReg() && MI.getOperand(I).isDef() &&
|
||||
!MI.getOperand(I).isImplicit();
|
||||
|
@ -719,8 +667,8 @@ void MIPrinter::print(const MachineInstr &MI) {
|
|||
if (I)
|
||||
OS << ", ";
|
||||
print(MI, I, TRI, ShouldPrintRegisterTies,
|
||||
getTypeToPrint(MI, I, PrintedTypes, MRI),
|
||||
/*IsDef=*/true);
|
||||
MI.getTypeToPrint(I, PrintedTypes, MRI),
|
||||
/*PrintDef=*/false);
|
||||
}
|
||||
|
||||
if (I)
|
||||
|
@ -736,7 +684,7 @@ void MIPrinter::print(const MachineInstr &MI) {
|
|||
if (NeedComma)
|
||||
OS << ", ";
|
||||
print(MI, I, TRI, ShouldPrintRegisterTies,
|
||||
getTypeToPrint(MI, I, PrintedTypes, MRI));
|
||||
MI.getTypeToPrint(I, PrintedTypes, MRI));
|
||||
NeedComma = true;
|
||||
}
|
||||
|
||||
|
@ -902,44 +850,17 @@ static const char *getTargetIndexName(const MachineFunction &MF, int Index) {
|
|||
void MIPrinter::print(const MachineInstr &MI, unsigned OpIdx,
|
||||
const TargetRegisterInfo *TRI,
|
||||
bool ShouldPrintRegisterTies, LLT TypeToPrint,
|
||||
bool IsDef) {
|
||||
bool PrintDef) {
|
||||
const MachineOperand &Op = MI.getOperand(OpIdx);
|
||||
printTargetFlags(Op);
|
||||
switch (Op.getType()) {
|
||||
case MachineOperand::MO_Register: {
|
||||
unsigned Reg = Op.getReg();
|
||||
if (Op.isImplicit())
|
||||
OS << (Op.isDef() ? "implicit-def " : "implicit ");
|
||||
else if (!IsDef && Op.isDef())
|
||||
// Print the 'def' flag only when the operand is defined after '='.
|
||||
OS << "def ";
|
||||
if (Op.isInternalRead())
|
||||
OS << "internal ";
|
||||
if (Op.isDead())
|
||||
OS << "dead ";
|
||||
if (Op.isKill())
|
||||
OS << "killed ";
|
||||
if (Op.isUndef())
|
||||
OS << "undef ";
|
||||
if (Op.isEarlyClobber())
|
||||
OS << "early-clobber ";
|
||||
if (Op.isDebug())
|
||||
OS << "debug-use ";
|
||||
OS << printReg(Reg, TRI);
|
||||
// Print the sub register.
|
||||
if (Op.getSubReg() != 0)
|
||||
OS << '.' << TRI->getSubRegIndexName(Op.getSubReg());
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
const MachineRegisterInfo &MRI = Op.getParent()->getMF()->getRegInfo();
|
||||
if (IsDef || MRI.def_empty(Reg)) {
|
||||
OS << ':';
|
||||
printRegClassOrBank(Reg, OS, MRI, TRI);
|
||||
}
|
||||
}
|
||||
unsigned TiedOperandIdx = 0;
|
||||
if (ShouldPrintRegisterTies && Op.isTied() && !Op.isDef())
|
||||
OS << "(tied-def " << Op.getParent()->findTiedOperandIdx(OpIdx) << ")";
|
||||
if (TypeToPrint.isValid())
|
||||
OS << '(' << TypeToPrint << ')';
|
||||
TiedOperandIdx = Op.getParent()->findTiedOperandIdx(OpIdx);
|
||||
const TargetIntrinsicInfo *TII = MI.getMF()->getTarget().getIntrinsicInfo();
|
||||
Op.print(OS, MST, TypeToPrint, PrintDef, ShouldPrintRegisterTies,
|
||||
TiedOperandIdx, TRI, TII);
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_Immediate:
|
||||
|
|
|
@ -623,10 +623,10 @@ bool MachineCSE::ProcessBlock(MachineBasicBlock *MBB) {
|
|||
// Go through implicit defs of CSMI and MI, and clear the kill flags on
|
||||
// their uses in all the instructions between CSMI and MI.
|
||||
// We might have made some of the kill flags redundant, consider:
|
||||
// subs ... %nzcv<imp-def> <- CSMI
|
||||
// csinc ... %nzcv<imp-use,kill> <- this kill flag isn't valid anymore
|
||||
// subs ... %nzcv<imp-def> <- MI, to be eliminated
|
||||
// csinc ... %nzcv<imp-use,kill>
|
||||
// subs ... implicit-def %nzcv <- CSMI
|
||||
// csinc ... implicit killed %nzcv <- this kill flag isn't valid anymore
|
||||
// subs ... implicit-def %nzcv <- MI, to be eliminated
|
||||
// csinc ... implicit killed %nzcv
|
||||
// Since we eliminated MI, and reused a register imp-def'd by CSMI
|
||||
// (here %nzcv), that register, if it was killed before MI, should have
|
||||
// that kill flag removed, because it's lifetime was extended.
|
||||
|
|
|
@ -226,19 +226,19 @@ void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
|
|||
|
||||
// The two copies cancel out and the source of the first copy
|
||||
// hasn't been overridden, eliminate the second one. e.g.
|
||||
// %ecx<def> = COPY %eax
|
||||
// %ecx = COPY %eax
|
||||
// ... nothing clobbered eax.
|
||||
// %eax<def> = COPY %ecx
|
||||
// %eax = COPY %ecx
|
||||
// =>
|
||||
// %ecx<def> = COPY %eax
|
||||
// %ecx = COPY %eax
|
||||
//
|
||||
// or
|
||||
//
|
||||
// %ecx<def> = COPY %eax
|
||||
// %ecx = COPY %eax
|
||||
// ... nothing clobbered eax.
|
||||
// %ecx<def> = COPY %eax
|
||||
// %ecx = COPY %eax
|
||||
// =>
|
||||
// %ecx<def> = COPY %eax
|
||||
// %ecx = COPY %eax
|
||||
if (eraseIfRedundant(*MI, Def, Src) || eraseIfRedundant(*MI, Src, Def))
|
||||
continue;
|
||||
|
||||
|
@ -262,11 +262,11 @@ void MachineCopyPropagation::CopyPropagateBlock(MachineBasicBlock &MBB) {
|
|||
|
||||
// If 'Def' is previously source of another copy, then this earlier copy's
|
||||
// source is no longer available. e.g.
|
||||
// %xmm9<def> = copy %xmm2
|
||||
// %xmm9 = copy %xmm2
|
||||
// ...
|
||||
// %xmm2<def> = copy %xmm0
|
||||
// %xmm2 = copy %xmm0
|
||||
// ...
|
||||
// %xmm2<def> = copy %xmm9
|
||||
// %xmm2 = copy %xmm9
|
||||
ClobberRegister(Def);
|
||||
for (const MachineOperand &MO : MI->implicit_operands()) {
|
||||
if (!MO.isReg() || !MO.isDef())
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
#include "llvm/ADT/Hashing.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/ADT/STLExtras.h"
|
||||
#include "llvm/ADT/SmallBitVector.h"
|
||||
#include "llvm/ADT/SmallString.h"
|
||||
#include "llvm/ADT/SmallVector.h"
|
||||
#include "llvm/Analysis/AliasAnalysis.h"
|
||||
|
@ -742,7 +743,7 @@ MachineInstr::readsWritesVirtualRegister(unsigned Reg,
|
|||
if (MO.isUse())
|
||||
Use |= !MO.isUndef();
|
||||
else if (MO.getSubReg() && !MO.isUndef())
|
||||
// A partial <def,undef> doesn't count as reading the register.
|
||||
// A partial def undef doesn't count as reading the register.
|
||||
PartDef = true;
|
||||
else
|
||||
FullDef = true;
|
||||
|
@ -1163,6 +1164,41 @@ void MachineInstr::copyImplicitOps(MachineFunction &MF,
|
|||
}
|
||||
}
|
||||
|
||||
bool MachineInstr::hasComplexRegisterTies() const {
|
||||
const MCInstrDesc &MCID = getDesc();
|
||||
for (unsigned I = 0, E = getNumOperands(); I < E; ++I) {
|
||||
const auto &Operand = getOperand(I);
|
||||
if (!Operand.isReg() || Operand.isDef())
|
||||
// Ignore the defined registers as MCID marks only the uses as tied.
|
||||
continue;
|
||||
int ExpectedTiedIdx = MCID.getOperandConstraint(I, MCOI::TIED_TO);
|
||||
int TiedIdx = Operand.isTied() ? int(findTiedOperandIdx(I)) : -1;
|
||||
if (ExpectedTiedIdx != TiedIdx)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
LLT MachineInstr::getTypeToPrint(unsigned OpIdx, SmallBitVector &PrintedTypes,
|
||||
const MachineRegisterInfo &MRI) const {
|
||||
const MachineOperand &Op = getOperand(OpIdx);
|
||||
if (!Op.isReg())
|
||||
return LLT{};
|
||||
|
||||
if (isVariadic() || OpIdx >= getNumExplicitOperands())
|
||||
return MRI.getType(Op.getReg());
|
||||
|
||||
auto &OpInfo = getDesc().OpInfo[OpIdx];
|
||||
if (!OpInfo.isGenericType())
|
||||
return MRI.getType(Op.getReg());
|
||||
|
||||
if (PrintedTypes[OpInfo.getGenericTypeIndex()])
|
||||
return LLT{};
|
||||
|
||||
PrintedTypes.set(OpInfo.getGenericTypeIndex());
|
||||
return MRI.getType(Op.getReg());
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG) || defined(LLVM_ENABLE_DUMP)
|
||||
LLVM_DUMP_METHOD void MachineInstr::dump() const {
|
||||
dbgs() << " ";
|
||||
|
@ -1204,21 +1240,31 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
|||
// Save a list of virtual registers.
|
||||
SmallVector<unsigned, 8> VirtRegs;
|
||||
|
||||
SmallBitVector PrintedTypes(8);
|
||||
bool ShouldPrintRegisterTies = hasComplexRegisterTies();
|
||||
auto getTiedOperandIdx = [&](unsigned OpIdx) {
|
||||
if (!ShouldPrintRegisterTies)
|
||||
return 0U;
|
||||
const MachineOperand &MO = getOperand(OpIdx);
|
||||
if (MO.isReg() && MO.isTied() && !MO.isDef())
|
||||
return findTiedOperandIdx(OpIdx);
|
||||
return 0U;
|
||||
};
|
||||
// Print explicitly defined operands on the left of an assignment syntax.
|
||||
unsigned StartOp = 0, e = getNumOperands();
|
||||
for (; StartOp < e && getOperand(StartOp).isReg() &&
|
||||
getOperand(StartOp).isDef() &&
|
||||
!getOperand(StartOp).isImplicit();
|
||||
getOperand(StartOp).isDef() && !getOperand(StartOp).isImplicit();
|
||||
++StartOp) {
|
||||
if (StartOp != 0) OS << ", ";
|
||||
getOperand(StartOp).print(OS, MST, TRI, IntrinsicInfo);
|
||||
if (StartOp != 0)
|
||||
OS << ", ";
|
||||
LLT TypeToPrint = MRI ? getTypeToPrint(StartOp, PrintedTypes, *MRI) : LLT{};
|
||||
unsigned TiedOperandIdx = getTiedOperandIdx(StartOp);
|
||||
getOperand(StartOp).print(OS, MST, TypeToPrint, /*PrintDef=*/false,
|
||||
ShouldPrintRegisterTies, TiedOperandIdx, TRI,
|
||||
IntrinsicInfo);
|
||||
unsigned Reg = getOperand(StartOp).getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg))
|
||||
VirtRegs.push_back(Reg);
|
||||
LLT Ty = MRI ? MRI->getType(Reg) : LLT{};
|
||||
if (Ty.isValid())
|
||||
OS << '(' << Ty << ')';
|
||||
}
|
||||
}
|
||||
|
||||
if (StartOp != 0)
|
||||
|
@ -1241,7 +1287,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
|||
if (isInlineAsm() && e >= InlineAsm::MIOp_FirstOperand) {
|
||||
// Print asm string.
|
||||
OS << " ";
|
||||
getOperand(InlineAsm::MIOp_AsmString).print(OS, MST, TRI);
|
||||
const unsigned OpIdx = InlineAsm::MIOp_AsmString;
|
||||
LLT TypeToPrint = MRI ? getTypeToPrint(OpIdx, PrintedTypes, *MRI) : LLT{};
|
||||
unsigned TiedOperandIdx = getTiedOperandIdx(StartOp);
|
||||
getOperand(OpIdx).print(OS, MST, TypeToPrint, /*PrintDef=*/true,
|
||||
ShouldPrintRegisterTies, TiedOperandIdx, TRI,
|
||||
IntrinsicInfo);
|
||||
|
||||
// Print HasSideEffects, MayLoad, MayStore, IsAlignStack
|
||||
unsigned ExtraInfo = getOperand(InlineAsm::MIOp_ExtraInfo).getImm();
|
||||
|
@ -1284,8 +1335,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
|||
auto *DIV = dyn_cast<DILocalVariable>(MO.getMetadata());
|
||||
if (DIV && !DIV->getName().empty())
|
||||
OS << "!\"" << DIV->getName() << '\"';
|
||||
else
|
||||
MO.print(OS, MST, TRI);
|
||||
else {
|
||||
LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
|
||||
unsigned TiedOperandIdx = getTiedOperandIdx(StartOp);
|
||||
MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true,
|
||||
ShouldPrintRegisterTies, TiedOperandIdx, TRI, IntrinsicInfo);
|
||||
}
|
||||
} else if (TRI && (isInsertSubreg() || isRegSequence() ||
|
||||
(isSubregToReg() && i == 3)) && MO.isImm()) {
|
||||
OS << TRI->getSubRegIndexName(MO.getImm());
|
||||
|
@ -1347,8 +1402,12 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
|||
|
||||
// Compute the index of the next operand descriptor.
|
||||
AsmDescOp += 1 + InlineAsm::getNumOperandRegisters(Flag);
|
||||
} else
|
||||
MO.print(OS, MST, TRI);
|
||||
} else {
|
||||
LLT TypeToPrint = MRI ? getTypeToPrint(i, PrintedTypes, *MRI) : LLT{};
|
||||
unsigned TiedOperandIdx = getTiedOperandIdx(StartOp);
|
||||
MO.print(OS, MST, TypeToPrint, /*PrintDef=*/true, ShouldPrintRegisterTies,
|
||||
TiedOperandIdx, TRI, IntrinsicInfo);
|
||||
}
|
||||
}
|
||||
|
||||
bool HaveSemi = false;
|
||||
|
|
|
@ -15,10 +15,11 @@
|
|||
#include "llvm/Analysis/Loads.h"
|
||||
#include "llvm/CodeGen/MIRPrinter.h"
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||
#include "llvm/CodeGen/TargetRegisterInfo.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/ModuleSlotTracker.h"
|
||||
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
|
@ -333,75 +334,86 @@ hash_code llvm::hash_value(const MachineOperand &MO) {
|
|||
llvm_unreachable("Invalid machine operand type");
|
||||
}
|
||||
|
||||
// Try to crawl up to the machine function and get TRI and IntrinsicInfo from
|
||||
// it.
|
||||
static void tryToGetTargetInfo(const MachineOperand &MO,
|
||||
const TargetRegisterInfo *&TRI,
|
||||
const TargetIntrinsicInfo *&IntrinsicInfo) {
|
||||
if (const MachineInstr *MI = MO.getParent()) {
|
||||
if (const MachineBasicBlock *MBB = MI->getParent()) {
|
||||
if (const MachineFunction *MF = MBB->getParent()) {
|
||||
TRI = MF->getSubtarget().getRegisterInfo();
|
||||
IntrinsicInfo = MF->getTarget().getIntrinsicInfo();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo) const {
|
||||
tryToGetTargetInfo(*this, TRI, IntrinsicInfo);
|
||||
ModuleSlotTracker DummyMST(nullptr);
|
||||
print(OS, DummyMST, TRI, IntrinsicInfo);
|
||||
print(OS, DummyMST, LLT{}, /*PrintDef=*/false,
|
||||
/*ShouldPrintRegisterTies=*/true,
|
||||
/*TiedOperandIdx=*/0, TRI, IntrinsicInfo);
|
||||
}
|
||||
|
||||
void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
||||
LLT TypeToPrint, bool PrintDef,
|
||||
bool ShouldPrintRegisterTies,
|
||||
unsigned TiedOperandIdx,
|
||||
const TargetRegisterInfo *TRI,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo) const {
|
||||
switch (getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
OS << printReg(getReg(), TRI, getSubReg());
|
||||
|
||||
if (isDef() || isKill() || isDead() || isImplicit() || isUndef() ||
|
||||
isInternalRead() || isEarlyClobber() || isTied()) {
|
||||
OS << '<';
|
||||
bool NeedComma = false;
|
||||
if (isDef()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
if (isEarlyClobber())
|
||||
OS << "earlyclobber,";
|
||||
if (isImplicit())
|
||||
OS << "imp-";
|
||||
OS << "def";
|
||||
NeedComma = true;
|
||||
// <def,read-undef> only makes sense when getSubReg() is set.
|
||||
// Don't clutter the output otherwise.
|
||||
if (isUndef() && getSubReg())
|
||||
OS << ",read-undef";
|
||||
} else if (isImplicit()) {
|
||||
OS << "imp-use";
|
||||
NeedComma = true;
|
||||
}
|
||||
|
||||
if (isKill()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << "kill";
|
||||
NeedComma = true;
|
||||
}
|
||||
if (isDead()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << "dead";
|
||||
NeedComma = true;
|
||||
}
|
||||
if (isUndef() && isUse()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << "undef";
|
||||
NeedComma = true;
|
||||
}
|
||||
if (isInternalRead()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << "internal";
|
||||
NeedComma = true;
|
||||
}
|
||||
if (isTied()) {
|
||||
if (NeedComma)
|
||||
OS << ',';
|
||||
OS << "tied";
|
||||
if (TiedTo != 15)
|
||||
OS << unsigned(TiedTo - 1);
|
||||
}
|
||||
OS << '>';
|
||||
case MachineOperand::MO_Register: {
|
||||
unsigned Reg = getReg();
|
||||
if (isImplicit())
|
||||
OS << (isDef() ? "implicit-def " : "implicit ");
|
||||
else if (PrintDef && isDef())
|
||||
// Print the 'def' flag only when the operand is defined after '='.
|
||||
OS << "def ";
|
||||
if (isInternalRead())
|
||||
OS << "internal ";
|
||||
if (isDead())
|
||||
OS << "dead ";
|
||||
if (isKill())
|
||||
OS << "killed ";
|
||||
if (isUndef())
|
||||
OS << "undef ";
|
||||
if (isEarlyClobber())
|
||||
OS << "early-clobber ";
|
||||
if (isDebug())
|
||||
OS << "debug-use ";
|
||||
OS << printReg(Reg, TRI);
|
||||
// Print the sub register.
|
||||
if (unsigned SubReg = getSubReg()) {
|
||||
if (TRI)
|
||||
OS << '.' << TRI->getSubRegIndexName(SubReg);
|
||||
else
|
||||
OS << ".subreg" << SubReg;
|
||||
}
|
||||
// Print the register class / bank.
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
if (const MachineInstr *MI = getParent()) {
|
||||
if (const MachineBasicBlock *MBB = MI->getParent()) {
|
||||
if (const MachineFunction *MF = MBB->getParent()) {
|
||||
const MachineRegisterInfo &MRI = MF->getRegInfo();
|
||||
if (!PrintDef || MRI.def_empty(Reg)) {
|
||||
OS << ':';
|
||||
OS << printRegClassOrBank(Reg, MRI, TRI);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// Print ties.
|
||||
if (ShouldPrintRegisterTies && isTied() && !isDef())
|
||||
OS << "(tied-def " << TiedOperandIdx << ")";
|
||||
// Print types.
|
||||
if (TypeToPrint.isValid())
|
||||
OS << '(' << TypeToPrint << ')';
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_Immediate:
|
||||
OS << getImm();
|
||||
break;
|
||||
|
@ -475,23 +487,27 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
|||
OS << '>';
|
||||
break;
|
||||
case MachineOperand::MO_RegisterMask: {
|
||||
unsigned NumRegsInMask = 0;
|
||||
unsigned NumRegsEmitted = 0;
|
||||
OS << "<regmask";
|
||||
for (unsigned i = 0; i < TRI->getNumRegs(); ++i) {
|
||||
unsigned MaskWord = i / 32;
|
||||
unsigned MaskBit = i % 32;
|
||||
if (getRegMask()[MaskWord] & (1 << MaskBit)) {
|
||||
if (PrintRegMaskNumRegs < 0 ||
|
||||
NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) {
|
||||
OS << " " << printReg(i, TRI);
|
||||
NumRegsEmitted++;
|
||||
if (TRI) {
|
||||
unsigned NumRegsInMask = 0;
|
||||
unsigned NumRegsEmitted = 0;
|
||||
for (unsigned i = 0; i < TRI->getNumRegs(); ++i) {
|
||||
unsigned MaskWord = i / 32;
|
||||
unsigned MaskBit = i % 32;
|
||||
if (getRegMask()[MaskWord] & (1 << MaskBit)) {
|
||||
if (PrintRegMaskNumRegs < 0 ||
|
||||
NumRegsEmitted <= static_cast<unsigned>(PrintRegMaskNumRegs)) {
|
||||
OS << " " << printReg(i, TRI);
|
||||
NumRegsEmitted++;
|
||||
}
|
||||
NumRegsInMask++;
|
||||
}
|
||||
NumRegsInMask++;
|
||||
}
|
||||
if (NumRegsEmitted != NumRegsInMask)
|
||||
OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more...";
|
||||
} else {
|
||||
OS << " ...";
|
||||
}
|
||||
if (NumRegsEmitted != NumRegsInMask)
|
||||
OS << " and " << (NumRegsInMask - NumRegsEmitted) << " more...";
|
||||
OS << ">";
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -246,14 +246,14 @@ MachineSinking::AllUsesDominatedByBlock(unsigned Reg,
|
|||
// %bb.1: derived from LLVM BB %bb4.preheader
|
||||
// Predecessors according to CFG: %bb.0
|
||||
// ...
|
||||
// %reg16385<def> = DEC64_32r %reg16437, %eflags<imp-def,dead>
|
||||
// %reg16385 = DEC64_32r %reg16437, implicit-def dead %eflags
|
||||
// ...
|
||||
// JE_4 <%bb.37>, %eflags<imp-use>
|
||||
// JE_4 <%bb.37>, implicit %eflags
|
||||
// Successors according to CFG: %bb.37 %bb.2
|
||||
//
|
||||
// %bb.2: derived from LLVM BB %bb.nph
|
||||
// Predecessors according to CFG: %bb.0 %bb.1
|
||||
// %reg16386<def> = PHI %reg16434, %bb.0, %reg16385, %bb.1
|
||||
// %reg16386 = PHI %reg16434, %bb.0, %reg16385, %bb.1
|
||||
BreakPHIEdge = true;
|
||||
for (MachineOperand &MO : MRI->use_nodbg_operands(Reg)) {
|
||||
MachineInstr *UseInst = MO.getParent();
|
||||
|
|
|
@ -1961,7 +1961,7 @@ void MachineVerifier::verifyLiveRangeSegment(const LiveRange &LR,
|
|||
if (MOI->isDef()) {
|
||||
if (Sub != 0) {
|
||||
hasSubRegDef = true;
|
||||
// An operand %0:sub0<def> reads %0:sub1..n. Invert the lane
|
||||
// An operand %0:sub0 reads %0:sub1..n. Invert the lane
|
||||
// mask for subregister defs. Read-undef defs will be handled by
|
||||
// readsReg below.
|
||||
SLM = ~SLM;
|
||||
|
|
|
@ -272,7 +272,7 @@ void RegAllocFast::addKillFlag(const LiveReg &LR) {
|
|||
// subreg of this register and given we don't track which
|
||||
// lanes are actually dead, we cannot insert a kill flag here.
|
||||
// Otherwise we may end up in a situation like this:
|
||||
// ... = (MO) physreg:sub1, physreg <implicit-use, kill>
|
||||
// ... = (MO) physreg:sub1, implicit killed physreg
|
||||
// ... <== Here we would allow later pass to reuse physreg:sub1
|
||||
// which is potentially wrong.
|
||||
// LR:sub0 = ...
|
||||
|
@ -675,7 +675,7 @@ RegAllocFast::LiveRegMap::iterator RegAllocFast::reloadVirtReg(MachineInstr &MI,
|
|||
} else if (MO.isKill()) {
|
||||
// We must remove kill flags from uses of reloaded registers because the
|
||||
// register would be killed immediately, and there might be a second use:
|
||||
// %foo = OR %x<kill>, %x
|
||||
// %foo = OR killed %x, %x
|
||||
// This would cause a second reload of %x into a different register.
|
||||
DEBUG(dbgs() << "Clearing clean kill: " << MO << "\n");
|
||||
MO.setIsKill(false);
|
||||
|
|
|
@ -667,7 +667,7 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
|
|||
// its other operand is coalesced to the copy dest register, see if we can
|
||||
// transform the copy into a noop by commuting the definition. For example,
|
||||
//
|
||||
// A3 = op A2 B0<kill>
|
||||
// A3 = op A2 killed B0
|
||||
// ...
|
||||
// B1 = A3 <- this copy
|
||||
// ...
|
||||
|
@ -675,7 +675,7 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
|
|||
//
|
||||
// ==>
|
||||
//
|
||||
// B2 = op B0 A2<kill>
|
||||
// B2 = op B0 killed A2
|
||||
// ...
|
||||
// B1 = B2 <- now an identity copy
|
||||
// ...
|
||||
|
@ -768,7 +768,7 @@ bool RegisterCoalescer::removeCopyByCommutingDef(const CoalescerPair &CP,
|
|||
// ...
|
||||
// B = A
|
||||
// ...
|
||||
// C = A<kill>
|
||||
// C = killed A
|
||||
// ...
|
||||
// = B
|
||||
|
||||
|
@ -1254,7 +1254,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
|
|||
// Make sure that the subrange for resultant undef is removed
|
||||
// For example:
|
||||
// %1:sub1<def,read-undef> = LOAD CONSTANT 1
|
||||
// %2<def> = COPY %1
|
||||
// %2 = COPY %1
|
||||
// ==>
|
||||
// %2:sub1<def, read-undef> = LOAD CONSTANT 1
|
||||
// ; Correct but need to remove the subrange for %2:sub0
|
||||
|
@ -1297,7 +1297,7 @@ bool RegisterCoalescer::reMaterializeTrivialDef(const CoalescerPair &CP,
|
|||
// = somedef %1 ; %1 GR8
|
||||
// =>
|
||||
// %1 = somedef ; %1 GR8
|
||||
// ECX<def, dead> = remat ; CL<imp-def>
|
||||
// dead ECX = remat ; implicit-def CL
|
||||
// = somedef %1 ; %1 GR8
|
||||
// %1 will see the inteferences with CL but not with CH since
|
||||
// no live-ranges would have been created for ECX.
|
||||
|
@ -1352,7 +1352,7 @@ bool RegisterCoalescer::eliminateUndefCopy(MachineInstr *CopyMI) {
|
|||
// ProcessImpicitDefs may leave some copies of <undef> values, it only removes
|
||||
// local variables. When we have a copy like:
|
||||
//
|
||||
// %1 = COPY %2<undef>
|
||||
// %1 = COPY undef %2
|
||||
//
|
||||
// We delete the copy and remove the corresponding value number from %1.
|
||||
// Any uses of that value number are marked as <undef>.
|
||||
|
@ -1927,7 +1927,7 @@ bool RegisterCoalescer::joinReservedPhysReg(CoalescerPair &CP) {
|
|||
//
|
||||
// %dst:ssub0<def,read-undef> = FOO
|
||||
// %src = BAR
|
||||
// %dst:ssub1<def> = COPY %src
|
||||
// %dst:ssub1 = COPY %src
|
||||
//
|
||||
// The live range of %src overlaps the %dst value defined by FOO, but
|
||||
// merging %src into %dst:ssub1 is only going to clobber the ssub1 lane
|
||||
|
@ -1942,9 +1942,9 @@ bool RegisterCoalescer::joinReservedPhysReg(CoalescerPair &CP) {
|
|||
// is live, but never read. This can happen because we don't compute
|
||||
// individual live ranges per lane.
|
||||
//
|
||||
// %dst<def> = FOO
|
||||
// %dst = FOO
|
||||
// %src = BAR
|
||||
// %dst:ssub1<def> = COPY %src
|
||||
// %dst:ssub1 = COPY %src
|
||||
//
|
||||
// This kind of interference is only resolved locally. If the clobbered
|
||||
// lane value escapes the block, the join is aborted.
|
||||
|
@ -2287,7 +2287,7 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) {
|
|||
//
|
||||
// This adds ssub1 to the set of valid lanes in %src:
|
||||
//
|
||||
// %src:ssub1<def> = FOO
|
||||
// %src:ssub1 = FOO
|
||||
//
|
||||
// This leaves only ssub1 valid, making any other lanes undef:
|
||||
//
|
||||
|
@ -2425,9 +2425,9 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) {
|
|||
//
|
||||
// 1 %dst:ssub0 = FOO <-- OtherVNI
|
||||
// 2 %src = BAR <-- VNI
|
||||
// 3 %dst:ssub1 = COPY %src<kill> <-- Eliminate this copy.
|
||||
// 4 BAZ %dst<kill>
|
||||
// 5 QUUX %src<kill>
|
||||
// 3 %dst:ssub1 = COPY killed %src <-- Eliminate this copy.
|
||||
// 4 BAZ killed %dst
|
||||
// 5 QUUX killed %src
|
||||
//
|
||||
// Here OtherVNI will map to itself in [1;2), but to VNI in [2;5). CR_Replace
|
||||
// handles this complex value mapping.
|
||||
|
@ -2437,7 +2437,7 @@ JoinVals::analyzeValue(unsigned ValNo, JoinVals &Other) {
|
|||
// If the other live range is killed by DefMI and the live ranges are still
|
||||
// overlapping, it must be because we're looking at an early clobber def:
|
||||
//
|
||||
// %dst<def,early-clobber> = ASM %src<kill>
|
||||
// %dst<def,early-clobber> = ASM killed %src
|
||||
//
|
||||
// In this case, it is illegal to merge the two live ranges since the early
|
||||
// clobber def would clobber %src before it was read.
|
||||
|
@ -2682,7 +2682,7 @@ void JoinVals::pruneValues(JoinVals &Other,
|
|||
if (!Def.isBlock()) {
|
||||
if (changeInstrs) {
|
||||
// Remove <def,read-undef> flags. This def is now a partial redef.
|
||||
// Also remove <def,dead> flags since the joined live range will
|
||||
// Also remove dead flags since the joined live range will
|
||||
// continue past this instruction.
|
||||
for (MachineOperand &MO :
|
||||
Indexes->getInstructionFromIndex(Def)->operands()) {
|
||||
|
|
|
@ -213,7 +213,7 @@ void RegScavenger::forward() {
|
|||
continue;
|
||||
if (!isRegUsed(Reg)) {
|
||||
// Check if it's partial live: e.g.
|
||||
// D0 = insert_subreg D0<undef>, S0
|
||||
// D0 = insert_subreg undef D0, S0
|
||||
// ... D0
|
||||
// The problem is the insert_subreg could be eliminated. The use of
|
||||
// D0 is using a partially undef value. This is not *incorrect* since
|
||||
|
|
|
@ -1379,7 +1379,7 @@ void SplitEditor::rewriteAssigned(bool ExtendRanges) {
|
|||
// for a partially defined original register. For example:
|
||||
// %0:subreg_hireg<def,read-undef> = ...
|
||||
// ...
|
||||
// %1<def> = COPY %0
|
||||
// %1 = COPY %0
|
||||
if (S.empty())
|
||||
continue;
|
||||
SubLRC.reset(&VRM.getMachineFunction(), LIS.getSlotIndexes(), &MDT,
|
||||
|
|
|
@ -144,6 +144,21 @@ Printable printVRegOrUnit(unsigned Unit, const TargetRegisterInfo *TRI) {
|
|||
});
|
||||
}
|
||||
|
||||
Printable printRegClassOrBank(unsigned Reg, const MachineRegisterInfo &RegInfo,
|
||||
const TargetRegisterInfo *TRI) {
|
||||
return Printable([Reg, &RegInfo, TRI](raw_ostream &OS) {
|
||||
if (RegInfo.getRegClassOrNull(Reg))
|
||||
OS << StringRef(TRI->getRegClassName(RegInfo.getRegClass(Reg))).lower();
|
||||
else if (RegInfo.getRegBankOrNull(Reg))
|
||||
OS << StringRef(RegInfo.getRegBankOrNull(Reg)->getName()).lower();
|
||||
else {
|
||||
OS << "_";
|
||||
assert((RegInfo.def_empty(Reg) || RegInfo.getType(Reg).isValid()) &&
|
||||
"Generic registers must have a valid type");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
} // end namespace llvm
|
||||
|
||||
/// getAllocatableClass - Return the maximal subclass of the given register
|
||||
|
|
|
@ -458,8 +458,8 @@ static bool isPlainlyKilled(MachineInstr *MI, unsigned Reg,
|
|||
/// For example, in this code:
|
||||
///
|
||||
/// %reg1034 = copy %reg1024
|
||||
/// %reg1035 = copy %reg1025<kill>
|
||||
/// %reg1036 = add %reg1034<kill>, %reg1035<kill>
|
||||
/// %reg1035 = copy killed %reg1025
|
||||
/// %reg1036 = add killed %reg1034, killed %reg1035
|
||||
///
|
||||
/// %reg1034 is not considered to be killed, since it is copied from a
|
||||
/// register which is not killed. Treating it as not killed lets the
|
||||
|
@ -591,31 +591,31 @@ isProfitableToCommute(unsigned regA, unsigned regB, unsigned regC,
|
|||
// general, we want no uses between this instruction and the definition of
|
||||
// the two-address register.
|
||||
// e.g.
|
||||
// %reg1028<def> = EXTRACT_SUBREG %reg1027<kill>, 1
|
||||
// %reg1029<def> = MOV8rr %reg1028
|
||||
// %reg1029<def> = SHR8ri %reg1029, 7, %eflags<imp-def,dead>
|
||||
// insert => %reg1030<def> = MOV8rr %reg1028
|
||||
// %reg1030<def> = ADD8rr %reg1028<kill>, %reg1029<kill>, %eflags<imp-def,dead>
|
||||
// %reg1028 = EXTRACT_SUBREG killed %reg1027, 1
|
||||
// %reg1029 = MOV8rr %reg1028
|
||||
// %reg1029 = SHR8ri %reg1029, 7, implicit dead %eflags
|
||||
// insert => %reg1030 = MOV8rr %reg1028
|
||||
// %reg1030 = ADD8rr killed %reg1028, killed %reg1029, implicit dead %eflags
|
||||
// In this case, it might not be possible to coalesce the second MOV8rr
|
||||
// instruction if the first one is coalesced. So it would be profitable to
|
||||
// commute it:
|
||||
// %reg1028<def> = EXTRACT_SUBREG %reg1027<kill>, 1
|
||||
// %reg1029<def> = MOV8rr %reg1028
|
||||
// %reg1029<def> = SHR8ri %reg1029, 7, %eflags<imp-def,dead>
|
||||
// insert => %reg1030<def> = MOV8rr %reg1029
|
||||
// %reg1030<def> = ADD8rr %reg1029<kill>, %reg1028<kill>, %eflags<imp-def,dead>
|
||||
// %reg1028 = EXTRACT_SUBREG killed %reg1027, 1
|
||||
// %reg1029 = MOV8rr %reg1028
|
||||
// %reg1029 = SHR8ri %reg1029, 7, implicit dead %eflags
|
||||
// insert => %reg1030 = MOV8rr %reg1029
|
||||
// %reg1030 = ADD8rr killed %reg1029, killed %reg1028, implicit dead %eflags
|
||||
|
||||
if (!isPlainlyKilled(MI, regC, LIS))
|
||||
return false;
|
||||
|
||||
// Ok, we have something like:
|
||||
// %reg1030<def> = ADD8rr %reg1028<kill>, %reg1029<kill>, %eflags<imp-def,dead>
|
||||
// %reg1030 = ADD8rr killed %reg1028, killed %reg1029, implicit dead %eflags
|
||||
// let's see if it's worth commuting it.
|
||||
|
||||
// Look for situations like this:
|
||||
// %reg1024<def> = MOV r1
|
||||
// %reg1025<def> = MOV r0
|
||||
// %reg1026<def> = ADD %reg1024, %reg1025
|
||||
// %reg1024 = MOV r1
|
||||
// %reg1025 = MOV r0
|
||||
// %reg1026 = ADD %reg1024, %reg1025
|
||||
// r0 = MOV %reg1026
|
||||
// Commute the ADD to hopefully eliminate an otherwise unavoidable copy.
|
||||
unsigned ToRegA = getMappedReg(regA, DstRegMap);
|
||||
|
@ -713,9 +713,9 @@ bool TwoAddressInstructionPass::commuteInstruction(MachineInstr *MI,
|
|||
bool
|
||||
TwoAddressInstructionPass::isProfitableToConv3Addr(unsigned RegA,unsigned RegB){
|
||||
// Look for situations like this:
|
||||
// %reg1024<def> = MOV r1
|
||||
// %reg1025<def> = MOV r0
|
||||
// %reg1026<def> = ADD %reg1024, %reg1025
|
||||
// %reg1024 = MOV r1
|
||||
// %reg1025 = MOV r0
|
||||
// %reg1026 = ADD %reg1024, %reg1025
|
||||
// r2 = MOV %reg1026
|
||||
// Turn ADD into a 3-address instruction to avoid a copy.
|
||||
unsigned FromRegB = getMappedReg(RegB, SrcRegMap);
|
||||
|
@ -1466,7 +1466,7 @@ collectTiedOperands(MachineInstr *MI, TiedOperandMap &TiedOperands) {
|
|||
|
||||
assert(SrcReg && SrcMO.isUse() && "two address instruction invalid");
|
||||
|
||||
// Deal with <undef> uses immediately - simply rewrite the src operand.
|
||||
// Deal with undef uses immediately - simply rewrite the src operand.
|
||||
if (SrcMO.isUndef() && !DstMO.getSubReg()) {
|
||||
// Constrain the DstReg register class if required.
|
||||
if (TargetRegisterInfo::isVirtualRegister(DstReg))
|
||||
|
@ -1778,8 +1778,8 @@ bool TwoAddressInstructionPass::runOnMachineFunction(MachineFunction &Func) {
|
|||
///
|
||||
/// Becomes:
|
||||
///
|
||||
/// %dst:ssub0<def,undef> = COPY %v1
|
||||
/// %dst:ssub1<def> = COPY %v2
|
||||
/// undef %dst:ssub0 = COPY %v1
|
||||
/// %dst:ssub1 = COPY %v2
|
||||
void TwoAddressInstructionPass::
|
||||
eliminateRegSequence(MachineBasicBlock::iterator &MBBI) {
|
||||
MachineInstr &MI = *MBBI;
|
||||
|
@ -1803,7 +1803,7 @@ eliminateRegSequence(MachineBasicBlock::iterator &MBBI) {
|
|||
MachineOperand &UseMO = MI.getOperand(i);
|
||||
unsigned SrcReg = UseMO.getReg();
|
||||
unsigned SubIdx = MI.getOperand(i+1).getImm();
|
||||
// Nothing needs to be inserted for <undef> operands.
|
||||
// Nothing needs to be inserted for undef operands.
|
||||
if (UseMO.isUndef())
|
||||
continue;
|
||||
|
||||
|
@ -1825,7 +1825,7 @@ eliminateRegSequence(MachineBasicBlock::iterator &MBBI) {
|
|||
.addReg(DstReg, RegState::Define, SubIdx)
|
||||
.add(UseMO);
|
||||
|
||||
// The first def needs an <undef> flag because there is no live register
|
||||
// The first def needs an undef flag because there is no live register
|
||||
// before it.
|
||||
if (!DefEmitted) {
|
||||
CopyMI->getOperand(0).setIsUndef(true);
|
||||
|
|
|
@ -380,8 +380,8 @@ void VirtRegRewriter::handleIdentityCopy(MachineInstr &MI) const {
|
|||
++NumIdCopies;
|
||||
|
||||
// Copies like:
|
||||
// %r0 = COPY %r0<undef>
|
||||
// %al = COPY %al, %eax<imp-def>
|
||||
// %r0 = COPY undef %r0
|
||||
// %al = COPY %al, implicit-def %eax
|
||||
// give us additional liveness information: The target (super-)register
|
||||
// must not be valid before this point. Replace the COPY with a KILL
|
||||
// instruction to maintain this information.
|
||||
|
@ -488,7 +488,7 @@ void VirtRegRewriter::rewrite() {
|
|||
if (SubReg != 0) {
|
||||
if (NoSubRegLiveness) {
|
||||
// A virtual register kill refers to the whole register, so we may
|
||||
// have to add <imp-use,kill> operands for the super-register. A
|
||||
// have to add implicit killed operands for the super-register. A
|
||||
// partial redef always kills and redefines the super-register.
|
||||
if ((MO.readsReg() && (MO.isDef() || MO.isKill())) ||
|
||||
(MO.isDef() && subRegLiveThrough(*MI, PhysReg)))
|
||||
|
@ -513,9 +513,9 @@ void VirtRegRewriter::rewrite() {
|
|||
}
|
||||
}
|
||||
|
||||
// The <def,undef> and <def,internal> flags only make sense for
|
||||
// The def undef and def internal flags only make sense for
|
||||
// sub-register defs, and we are substituting a full physreg. An
|
||||
// <imp-use,kill> operand from the SuperKills list will represent the
|
||||
// implicit killed operand from the SuperKills list will represent the
|
||||
// partial read of the super-register.
|
||||
if (MO.isDef()) {
|
||||
MO.setIsUndef(false);
|
||||
|
|
|
@ -161,9 +161,9 @@ namespace {
|
|||
/// A Chain is a sequence of instructions that are linked together by
|
||||
/// an accumulation operand. For example:
|
||||
///
|
||||
/// fmul d0<def>, ?
|
||||
/// fmla d1<def>, ?, ?, d0<kill>
|
||||
/// fmla d2<def>, ?, ?, d1<kill>
|
||||
/// fmul def d0, ?
|
||||
/// fmla def d1, ?, ?, killed d0
|
||||
/// fmla def d2, ?, ?, killed d1
|
||||
///
|
||||
/// There may be other instructions interleaved in the sequence that
|
||||
/// do not belong to the chain. These other instructions must not use
|
||||
|
|
|
@ -2801,7 +2801,7 @@ MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl(
|
|||
LiveIntervals *LIS) const {
|
||||
// This is a bit of a hack. Consider this instruction:
|
||||
//
|
||||
// %0<def> = COPY %sp; GPR64all:%0
|
||||
// %0 = COPY %sp; GPR64all:%0
|
||||
//
|
||||
// We explicitly chose GPR64all for the virtual register so such a copy might
|
||||
// be eliminated by RegisterCoalescer. However, that may not be possible, and
|
||||
|
@ -2830,7 +2830,7 @@ MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl(
|
|||
// Handle the case where a copy is being spilled or filled but the source
|
||||
// and destination register class don't match. For example:
|
||||
//
|
||||
// %0<def> = COPY %xzr; GPR64common:%0
|
||||
// %0 = COPY %xzr; GPR64common:%0
|
||||
//
|
||||
// In this case we can still safely fold away the COPY and generate the
|
||||
// following spill code:
|
||||
|
@ -2840,7 +2840,7 @@ MachineInstr *AArch64InstrInfo::foldMemoryOperandImpl(
|
|||
// This also eliminates spilled cross register class COPYs (e.g. between x and
|
||||
// d regs) of the same size. For example:
|
||||
//
|
||||
// %0<def> = COPY %1; GPR64:%0, FPR64:%1
|
||||
// %0 = COPY %1; GPR64:%0, FPR64:%1
|
||||
//
|
||||
// will be filled as
|
||||
//
|
||||
|
|
|
@ -830,8 +830,8 @@ AArch64LoadStoreOpt::mergePairedInsns(MachineBasicBlock::iterator I,
|
|||
if (SExtIdx != -1) {
|
||||
// Generate the sign extension for the proper result of the ldp.
|
||||
// I.e., with X1, that would be:
|
||||
// %w1<def> = KILL %w1, %x1<imp-def>
|
||||
// %x1<def> = SBFMXri %x1<kill>, 0, 31
|
||||
// %w1 = KILL %w1, implicit-def %x1
|
||||
// %x1 = SBFMXri killed %x1, 0, 31
|
||||
MachineOperand &DstMO = MIB->getOperand(SExtIdx);
|
||||
// Right now, DstMO has the extended register, since it comes from an
|
||||
// extended opcode.
|
||||
|
|
|
@ -1450,8 +1450,7 @@ bool AMDGPUMachineCFGStructurizer::shrinkPHI(MachineInstr &PHI,
|
|||
unsigned *ReplaceReg) {
|
||||
DEBUG(dbgs() << "Shrink PHI: ");
|
||||
DEBUG(PHI.dump());
|
||||
DEBUG(dbgs() << " to " << printReg(getPHIDestReg(PHI), TRI)
|
||||
<< "<def> = PHI(");
|
||||
DEBUG(dbgs() << " to " << printReg(getPHIDestReg(PHI), TRI) << " = PHI(");
|
||||
|
||||
bool Replaced = false;
|
||||
unsigned NumInputs = getPHINumInputs(PHI);
|
||||
|
@ -1507,8 +1506,7 @@ void AMDGPUMachineCFGStructurizer::replacePHI(
|
|||
SmallVector<unsigned, 2> &PHIRegionIndices) {
|
||||
DEBUG(dbgs() << "Replace PHI: ");
|
||||
DEBUG(PHI.dump());
|
||||
DEBUG(dbgs() << " with " << printReg(getPHIDestReg(PHI), TRI)
|
||||
<< "<def> = PHI(");
|
||||
DEBUG(dbgs() << " with " << printReg(getPHIDestReg(PHI), TRI) << " = PHI(");
|
||||
|
||||
bool HasExternalEdge = false;
|
||||
unsigned NumInputs = getPHINumInputs(PHI);
|
||||
|
@ -1566,7 +1564,7 @@ void AMDGPUMachineCFGStructurizer::replaceEntryPHI(
|
|||
DEBUG(dbgs() << " register " << printReg(CombinedSourceReg, TRI) << "\n");
|
||||
PHI.eraseFromParent();
|
||||
} else {
|
||||
DEBUG(dbgs() << printReg(getPHIDestReg(PHI), TRI) << "<def> = PHI(");
|
||||
DEBUG(dbgs() << printReg(getPHIDestReg(PHI), TRI) << " = PHI(");
|
||||
MachineBasicBlock *MBB = PHI.getParent();
|
||||
MachineInstrBuilder MIB =
|
||||
BuildMI(*MBB, PHI, PHI.getDebugLoc(), TII->get(TargetOpcode::PHI),
|
||||
|
@ -1751,7 +1749,7 @@ void AMDGPUMachineCFGStructurizer::insertMergePHI(MachineBasicBlock *IfBB,
|
|||
return;
|
||||
}
|
||||
DEBUG(dbgs() << "Merge PHI (" << printMBBReference(*MergeBB)
|
||||
<< "): " << printReg(DestRegister, TRI) << "<def> = PHI("
|
||||
<< "): " << printReg(DestRegister, TRI) << " = PHI("
|
||||
<< printReg(IfSourceRegister, TRI) << ", "
|
||||
<< printMBBReference(*IfBB) << printReg(CodeSourceRegister, TRI)
|
||||
<< ", " << printMBBReference(*CodeBB) << ")\n");
|
||||
|
@ -2147,7 +2145,7 @@ void AMDGPUMachineCFGStructurizer::createEntryPHI(LinearizedRegion *CurrentRegio
|
|||
const DebugLoc &DL = Entry->findDebugLoc(Entry->begin());
|
||||
MachineInstrBuilder MIB = BuildMI(*Entry, Entry->instr_begin(), DL,
|
||||
TII->get(TargetOpcode::PHI), DestReg);
|
||||
DEBUG(dbgs() << "Entry PHI " << printReg(DestReg, TRI) << "<def> = PHI(");
|
||||
DEBUG(dbgs() << "Entry PHI " << printReg(DestReg, TRI) << " = PHI(");
|
||||
|
||||
unsigned CurrentBackedgeReg = 0;
|
||||
|
||||
|
@ -2172,7 +2170,7 @@ void AMDGPUMachineCFGStructurizer::createEntryPHI(LinearizedRegion *CurrentRegio
|
|||
BackedgePHI.addMBB((*SRI).second);
|
||||
CurrentBackedgeReg = NewBackedgeReg;
|
||||
DEBUG(dbgs() << "Inserting backedge PHI: "
|
||||
<< printReg(NewBackedgeReg, TRI) << "<def> = PHI("
|
||||
<< printReg(NewBackedgeReg, TRI) << " = PHI("
|
||||
<< printReg(CurrentBackedgeReg, TRI) << ", "
|
||||
<< printMBBReference(*getPHIPred(*PHIDefInstr, 0))
|
||||
<< ", "
|
||||
|
@ -2441,8 +2439,7 @@ void AMDGPUMachineCFGStructurizer::splitLoopPHI(MachineInstr &PHI,
|
|||
MachineInstrBuilder MIB =
|
||||
BuildMI(*EntrySucc, EntrySucc->instr_begin(), PHI.getDebugLoc(),
|
||||
TII->get(TargetOpcode::PHI), NewDestReg);
|
||||
DEBUG(dbgs() << "Split Entry PHI " << printReg(NewDestReg, TRI)
|
||||
<< "<def> = PHI(");
|
||||
DEBUG(dbgs() << "Split Entry PHI " << printReg(NewDestReg, TRI) << " = PHI(");
|
||||
MIB.addReg(PHISource);
|
||||
MIB.addMBB(Entry);
|
||||
DEBUG(dbgs() << printReg(PHISource, TRI) << ", "
|
||||
|
|
|
@ -144,8 +144,8 @@ def VTX_READ_32_cm
|
|||
// to be caused by ALU instructions in the next instruction group that wrote
|
||||
// to the $src_gpr registers of the VTX_READ.
|
||||
// e.g.
|
||||
// %t3_x<def> = VTX_READ_PARAM_32_eg %t2_x<kill>, 24
|
||||
// %t2_x<def> = MOV %zero
|
||||
// %t3_x = VTX_READ_PARAM_32_eg killed %t2_x, 24
|
||||
// %t2_x = MOV %zero
|
||||
//Adding this constraint prevents this from happening.
|
||||
let Constraints = "$src_gpr.ptr = $dst_gpr";
|
||||
}
|
||||
|
|
|
@ -212,8 +212,8 @@ def VTX_READ_32_eg
|
|||
// to be caused by ALU instructions in the next instruction group that wrote
|
||||
// to the $src_gpr registers of the VTX_READ.
|
||||
// e.g.
|
||||
// %t3_x<def> = VTX_READ_PARAM_32_eg %t2_x<kill>, 24
|
||||
// %t2_x<def> = MOV %zero
|
||||
// %t3_x = VTX_READ_PARAM_32_eg killed %t2_x, 24
|
||||
// %t2_x = MOV %zero
|
||||
//Adding this constraint prevents this from happening.
|
||||
let Constraints = "$src_gpr.ptr = $dst_gpr";
|
||||
}
|
||||
|
|
|
@ -12,15 +12,15 @@
|
|||
/// common data and/or have enough undef subreg using swizzle abilities.
|
||||
///
|
||||
/// For instance let's consider the following pseudo code :
|
||||
/// %5<def> = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3
|
||||
/// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3
|
||||
/// ...
|
||||
/// %7<def> = REG_SEQ %1, sub0, %3, sub1, undef, sub2, %4, sub3
|
||||
/// %7 = REG_SEQ %1, sub0, %3, sub1, undef, sub2, %4, sub3
|
||||
/// (swizzable Inst) %7, SwizzleMask : sub0, sub1, sub2, sub3
|
||||
///
|
||||
/// is turned into :
|
||||
/// %5<def> = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3
|
||||
/// %5 = REG_SEQ %1, sub0, %2, sub1, %3, sub2, undef, sub3
|
||||
/// ...
|
||||
/// %7<def> = INSERT_SUBREG %4, sub3
|
||||
/// %7 = INSERT_SUBREG %4, sub3
|
||||
/// (swizzable Inst) %7, SwizzleMask : sub0, sub2, sub1, sub3
|
||||
///
|
||||
/// This allow regalloc to reduce register pressure for vector registers and
|
||||
|
|
|
@ -17,8 +17,8 @@
|
|||
/// %vgpr0 = V_MOV_B32_e32 0.0
|
||||
/// if (...) {
|
||||
/// %vgpr1 = ...
|
||||
/// %vgpr2 = WWM %vgpr1<kill>
|
||||
/// ... = %vgpr2<kill>
|
||||
/// %vgpr2 = WWM killed %vgpr1
|
||||
/// ... = killed %vgpr2
|
||||
/// %vgpr0 = V_MOV_B32_e32 1.0
|
||||
/// }
|
||||
/// ... = %vgpr0
|
||||
|
|
|
@ -971,9 +971,9 @@ bool SIFoldOperands::runOnMachineFunction(MachineFunction &MF) {
|
|||
// Prevent folding operands backwards in the function. For example,
|
||||
// the COPY opcode must not be replaced by 1 in this example:
|
||||
//
|
||||
// %3<def> = COPY %vgpr0; VGPR_32:%3
|
||||
// %3 = COPY %vgpr0; VGPR_32:%3
|
||||
// ...
|
||||
// %vgpr0<def> = V_MOV_B32_e32 1, %exec<imp-use>
|
||||
// %vgpr0 = V_MOV_B32_e32 1, implicit %exec
|
||||
MachineOperand &Dst = MI.getOperand(0);
|
||||
if (Dst.isReg() &&
|
||||
!TargetRegisterInfo::isVirtualRegister(Dst.getReg()))
|
||||
|
|
|
@ -480,7 +480,7 @@ Optional<int64_t> SIPeepholeSDWA::foldToImm(const MachineOperand &Op) const {
|
|||
}
|
||||
|
||||
// If this is not immediate then it can be copy of immediate value, e.g.:
|
||||
// %1<def> = S_MOV_B32 255;
|
||||
// %1 = S_MOV_B32 255;
|
||||
if (Op.isReg()) {
|
||||
for (const MachineOperand &Def : MRI->def_operands(Op.getReg())) {
|
||||
if (!isSameReg(Op, Def))
|
||||
|
|
|
@ -1447,7 +1447,7 @@ bool ARMBaseInstrInfo::expandPostRAPseudo(MachineInstr &MI) const {
|
|||
DEBUG(dbgs() << "widening: " << MI);
|
||||
MachineInstrBuilder MIB(*MI.getParent()->getParent(), MI);
|
||||
|
||||
// Get rid of the old <imp-def> of DstRegD. Leave it if it defines a Q-reg
|
||||
// Get rid of the old implicit-def of DstRegD. Leave it if it defines a Q-reg
|
||||
// or some other super-register.
|
||||
int ImpDefIdx = MI.findRegisterDefOperandIdx(DstRegD);
|
||||
if (ImpDefIdx != -1)
|
||||
|
@ -1650,7 +1650,7 @@ bool ARMBaseInstrInfo::produceSameValue(const MachineInstr &MI0,
|
|||
}
|
||||
|
||||
for (unsigned i = 3, e = MI0.getNumOperands(); i != e; ++i) {
|
||||
// %12<def> = PICLDR %11, 0, pred:14, pred:%noreg
|
||||
// %12 = PICLDR %11, 0, pred:14, pred:%noreg
|
||||
const MachineOperand &MO0 = MI0.getOperand(i);
|
||||
const MachineOperand &MO1 = MI1.getOperand(i);
|
||||
if (!MO0.isIdenticalTo(MO1))
|
||||
|
@ -4668,7 +4668,7 @@ void ARMBaseInstrInfo::setExecutionDomain(MachineInstr &MI,
|
|||
NewMIB = BuildMI(*MI.getParent(), MI, MI.getDebugLoc(), get(ARM::VEXTd32),
|
||||
DDst);
|
||||
|
||||
// On the first instruction, both DSrc and DDst may be <undef> if present.
|
||||
// On the first instruction, both DSrc and DDst may be undef if present.
|
||||
// Specifically when the original instruction didn't have them as an
|
||||
// <imp-use>.
|
||||
unsigned CurReg = SrcLane == 1 && DstLane == 1 ? DSrc : DDst;
|
||||
|
@ -4688,7 +4688,7 @@ void ARMBaseInstrInfo::setExecutionDomain(MachineInstr &MI,
|
|||
MIB.addReg(DDst, RegState::Define);
|
||||
|
||||
// On the second instruction, DDst has definitely been defined above, so
|
||||
// it is not <undef>. DSrc, if present, can be <undef> as above.
|
||||
// it is not undef. DSrc, if present, can be undef as above.
|
||||
CurReg = SrcLane == 1 && DstLane == 0 ? DSrc : DDst;
|
||||
CurUndef = CurReg == DSrc && !MI.readsRegister(CurReg, TRI);
|
||||
MIB.addReg(CurReg, getUndefRegState(CurUndef));
|
||||
|
@ -4771,7 +4771,7 @@ unsigned ARMBaseInstrInfo::getPartialRegUpdateClearance(
|
|||
|
||||
// We must be able to clobber the whole D-reg.
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
// Virtual register must be a foo:ssub_0<def,undef> operand.
|
||||
// Virtual register must be a def undef foo:ssub_0 operand.
|
||||
if (!MO.getSubReg() || MI.readsVirtualRegister(Reg))
|
||||
return 0;
|
||||
} else if (ARM::SPRRegClass.contains(Reg)) {
|
||||
|
|
|
@ -922,7 +922,7 @@ bool ARMExpandPseudo::ExpandCMP_SWAP_64(MachineBasicBlock &MBB,
|
|||
// .Lloadcmp:
|
||||
// ldrexd rDestLo, rDestHi, [rAddr]
|
||||
// cmp rDestLo, rDesiredLo
|
||||
// sbcs rTempReg<dead>, rDestHi, rDesiredHi
|
||||
// sbcs dead rTempReg, rDestHi, rDesiredHi
|
||||
// bne .Ldone
|
||||
unsigned LDREXD = IsThumb ? ARM::t2LDREXD : ARM::LDREXD;
|
||||
MachineInstrBuilder MIB;
|
||||
|
|
|
@ -9168,7 +9168,7 @@ void ARMTargetLowering::AdjustInstrPostInstrSelection(MachineInstr &MI,
|
|||
// operand is still set to noreg. If needed, set the optional operand's
|
||||
// register to CPSR, and remove the redundant implicit def.
|
||||
//
|
||||
// e.g. ADCS (..., CPSR<imp-def>) -> ADC (... opt:CPSR<def>).
|
||||
// e.g. ADCS (..., implicit-def CPSR) -> ADC (... opt:def CPSR).
|
||||
|
||||
// Rename pseudo opcodes.
|
||||
unsigned NewOpc = convertAddSubFlagsOpcode(MI.getOpcode());
|
||||
|
|
|
@ -1697,7 +1697,7 @@ bool ARMLoadStoreOpt::FixInvalidRegPairOp(MachineBasicBlock &MBB,
|
|||
if (OddReg == EvenReg && EvenDeadKill) {
|
||||
// If the two source operands are the same, the kill marker is
|
||||
// probably on the first one. e.g.
|
||||
// t2STRDi8 %r5<kill>, %r5, %r9<kill>, 0, 14, %reg0
|
||||
// t2STRDi8 killed %r5, %r5, killed %r9, 0, 14, %reg0
|
||||
EvenDeadKill = false;
|
||||
OddDeadKill = true;
|
||||
}
|
||||
|
|
|
@ -573,7 +573,7 @@ void BPFDAGToDAGISel::PreprocessTrunc(SDNode *Node,
|
|||
return;
|
||||
} else {
|
||||
// The PHI node looks like:
|
||||
// %2<def> = PHI %0, <%bb.1>, %1, <%bb.3>
|
||||
// %2 = PHI %0, <%bb.1>, %1, <%bb.3>
|
||||
// Trace each incoming definition, e.g., (%0, %bb.1) and (%1, %bb.3)
|
||||
// The AND operation can be removed if both %0 in %bb.1 and %1 in
|
||||
// %bb.3 are defined with with a load matching the MaskN.
|
||||
|
|
|
@ -368,7 +368,7 @@ void HexagonBlockRanges::computeInitialLiveRanges(InstrIndexMap &IndexMap,
|
|||
}
|
||||
}
|
||||
// Defs and clobbers can overlap, e.g.
|
||||
// %d0<def,dead> = COPY %5, %r0<imp-def>, %r1<imp-def>
|
||||
// dead %d0 = COPY %5, implicit-def %r0, implicit-def %r1
|
||||
for (RegisterRef R : Defs)
|
||||
Clobbers.erase(R);
|
||||
|
||||
|
|
|
@ -187,7 +187,7 @@ namespace {
|
|||
|
||||
// Mapping: vreg -> cell
|
||||
// The keys are registers _without_ subregisters. This won't allow
|
||||
// definitions in the form of "vreg:subreg<def> = ...". Such definitions
|
||||
// definitions in the form of "vreg:subreg = ...". Such definitions
|
||||
// would be questionable from the point of view of SSA, since the "vreg"
|
||||
// could not be initialized in its entirety (specifically, an instruction
|
||||
// defining the "other part" of "vreg" would also count as a definition
|
||||
|
@ -1977,7 +1977,7 @@ bool HexagonConstEvaluator::evaluate(const MachineInstr &MI,
|
|||
{
|
||||
const MachineOperand &VO = MI.getOperand(1);
|
||||
// The operand of CONST32 can be a blockaddress, e.g.
|
||||
// %0<def> = CONST32 <blockaddress(@eat, %l)>
|
||||
// %0 = CONST32 <blockaddress(@eat, %l)>
|
||||
// Do this check for all instructions for safety.
|
||||
if (!VO.isImm())
|
||||
return false;
|
||||
|
@ -3147,7 +3147,7 @@ bool HexagonConstEvaluator::rewriteHexBranch(MachineInstr &BrI,
|
|||
BrI.setDesc(JD);
|
||||
while (BrI.getNumOperands() > 0)
|
||||
BrI.RemoveOperand(0);
|
||||
// This ensures that all implicit operands (e.g. %r31<imp-def>, etc)
|
||||
// This ensures that all implicit operands (e.g. implicit-def %r31, etc)
|
||||
// are present in the rewritten branch.
|
||||
for (auto &Op : NI->operands())
|
||||
BrI.addOperand(Op);
|
||||
|
|
|
@ -351,11 +351,11 @@ bool HexagonCopyToCombine::isSafeToMoveTogether(MachineInstr &I1,
|
|||
// kill flag for a register (a removeRegisterKilled() analogous to
|
||||
// addRegisterKilled) that handles aliased register correctly.
|
||||
// * or has a killed aliased register use of I1's use reg
|
||||
// %d4<def> = A2_tfrpi 16
|
||||
// %r6<def> = A2_tfr %r9
|
||||
// %r8<def> = KILL %r8, %d4<imp-use,kill>
|
||||
// %d4 = A2_tfrpi 16
|
||||
// %r6 = A2_tfr %r9
|
||||
// %r8 = KILL %r8, implicit killed %d4
|
||||
// If we want to move R6 = across the KILL instruction we would have
|
||||
// to remove the %d4<imp-use,kill> operand. For now, we are
|
||||
// to remove the implicit killed %d4 operand. For now, we are
|
||||
// conservative and disallow the move.
|
||||
// we can't move I1 across it.
|
||||
if (MI.isDebugValue()) {
|
||||
|
|
|
@ -25,38 +25,38 @@
|
|||
//
|
||||
// Example:
|
||||
//
|
||||
// %40<def> = L2_loadrub_io %39<kill>, 1
|
||||
// %41<def> = S2_tstbit_i %40<kill>, 0
|
||||
// J2_jumpt %41<kill>, <%bb.5>, %pc<imp-def,dead>
|
||||
// J2_jump <%bb.4>, %pc<imp-def,dead>
|
||||
// %40 = L2_loadrub_io killed %39, 1
|
||||
// %41 = S2_tstbit_i killed %40, 0
|
||||
// J2_jumpt killed %41, <%bb.5>, implicit dead %pc
|
||||
// J2_jump <%bb.4>, implicit dead %pc
|
||||
// Successors according to CFG: %bb.4(62) %bb.5(62)
|
||||
//
|
||||
// %bb.4: derived from LLVM BB %if.then
|
||||
// Predecessors according to CFG: %bb.3
|
||||
// %11<def> = A2_addp %6, %10
|
||||
// %11 = A2_addp %6, %10
|
||||
// S2_storerd_io %32, 16, %11
|
||||
// Successors according to CFG: %bb.5
|
||||
//
|
||||
// %bb.5: derived from LLVM BB %if.end
|
||||
// Predecessors according to CFG: %bb.3 %bb.4
|
||||
// %12<def> = PHI %6, <%bb.3>, %11, <%bb.4>
|
||||
// %13<def> = A2_addp %7, %12
|
||||
// %42<def> = C2_cmpeqi %9, 10
|
||||
// J2_jumpf %42<kill>, <%bb.3>, %pc<imp-def,dead>
|
||||
// J2_jump <%bb.6>, %pc<imp-def,dead>
|
||||
// %12 = PHI %6, <%bb.3>, %11, <%bb.4>
|
||||
// %13 = A2_addp %7, %12
|
||||
// %42 = C2_cmpeqi %9, 10
|
||||
// J2_jumpf killed %42, <%bb.3>, implicit dead %pc
|
||||
// J2_jump <%bb.6>, implicit dead %pc
|
||||
// Successors according to CFG: %bb.6(4) %bb.3(124)
|
||||
//
|
||||
// would become:
|
||||
//
|
||||
// %40<def> = L2_loadrub_io %39<kill>, 1
|
||||
// %41<def> = S2_tstbit_i %40<kill>, 0
|
||||
// spec-> %11<def> = A2_addp %6, %10
|
||||
// %40 = L2_loadrub_io killed %39, 1
|
||||
// %41 = S2_tstbit_i killed %40, 0
|
||||
// spec-> %11 = A2_addp %6, %10
|
||||
// pred-> S2_pstorerdf_io %41, %32, 16, %11
|
||||
// %46<def> = PS_pselect %41, %6, %11
|
||||
// %13<def> = A2_addp %7, %46
|
||||
// %42<def> = C2_cmpeqi %9, 10
|
||||
// J2_jumpf %42<kill>, <%bb.3>, %pc<imp-def,dead>
|
||||
// J2_jump <%bb.6>, %pc<imp-def,dead>
|
||||
// %46 = PS_pselect %41, %6, %11
|
||||
// %13 = A2_addp %7, %46
|
||||
// %42 = C2_cmpeqi %9, 10
|
||||
// J2_jumpf killed %42, <%bb.3>, implicit dead %pc
|
||||
// J2_jump <%bb.6>, implicit dead %pc
|
||||
// Successors according to CFG: %bb.6 %bb.3
|
||||
|
||||
#include "Hexagon.h"
|
||||
|
|
|
@ -28,14 +28,14 @@
|
|||
// definitions are predicable, then in the second step, the conditional
|
||||
// transfers will then be rewritten as predicated instructions. E.g.
|
||||
// %0 = A2_or %1, %2
|
||||
// %3 = A2_tfrt %99, %0<kill>
|
||||
// %3 = A2_tfrt %99, killed %0
|
||||
// will be rewritten as
|
||||
// %3 = A2_port %99, %1, %2
|
||||
//
|
||||
// This replacement has two variants: "up" and "down". Consider this case:
|
||||
// %0 = A2_or %1, %2
|
||||
// ... [intervening instructions] ...
|
||||
// %3 = A2_tfrt %99, %0<kill>
|
||||
// %3 = A2_tfrt %99, killed %0
|
||||
// variant "up":
|
||||
// %3 = A2_port %99, %1, %2
|
||||
// ... [intervening instructions, %0->vreg3] ...
|
||||
|
@ -65,15 +65,15 @@
|
|||
// will see both instructions as actual definitions, and will mark the
|
||||
// first one as dead. The definition is not actually dead, and this
|
||||
// situation will need to be fixed. For example:
|
||||
// %1<def,dead> = A2_tfrt ... ; marked as dead
|
||||
// %1<def> = A2_tfrf ...
|
||||
// dead %1 = A2_tfrt ... ; marked as dead
|
||||
// %1 = A2_tfrf ...
|
||||
//
|
||||
// Since any of the individual predicated transfers may end up getting
|
||||
// removed (in case it is an identity copy), some pre-existing def may
|
||||
// be marked as dead after live interval recomputation:
|
||||
// %1<def,dead> = ... ; marked as dead
|
||||
// dead %1 = ... ; marked as dead
|
||||
// ...
|
||||
// %1<def> = A2_tfrf ... ; if A2_tfrt is removed
|
||||
// %1 = A2_tfrf ... ; if A2_tfrt is removed
|
||||
// This case happens if %1 was used as a source in A2_tfrt, which means
|
||||
// that is it actually live at the A2_tfrf, and so the now dead definition
|
||||
// of %1 will need to be updated to non-dead at some point.
|
||||
|
|
|
@ -1720,7 +1720,7 @@ bool HexagonHardwareLoops::fixupInductionVariable(MachineLoop *L) {
|
|||
MachineOperand &MO = PredDef->getOperand(i);
|
||||
if (MO.isReg()) {
|
||||
// Skip all implicit references. In one case there was:
|
||||
// %140<def> = FCMPUGT32_rr %138, %139, %usr<imp-use>
|
||||
// %140 = FCMPUGT32_rr %138, %139, implicit %usr
|
||||
if (MO.isImplicit())
|
||||
continue;
|
||||
if (MO.isUse()) {
|
||||
|
|
|
@ -1615,8 +1615,8 @@ DFAPacketizer *HexagonInstrInfo::CreateTargetScheduleState(
|
|||
}
|
||||
|
||||
// Inspired by this pair:
|
||||
// %r13<def> = L2_loadri_io %r29, 136; mem:LD4[FixedStack0]
|
||||
// S2_storeri_io %r29, 132, %r1<kill>; flags: mem:ST4[FixedStack1]
|
||||
// %r13 = L2_loadri_io %r29, 136; mem:LD4[FixedStack0]
|
||||
// S2_storeri_io %r29, 132, killed %r1; flags: mem:ST4[FixedStack1]
|
||||
// Currently AA considers the addresses in these instructions to be aliasing.
|
||||
bool HexagonInstrInfo::areMemAccessesTriviallyDisjoint(
|
||||
MachineInstr &MIa, MachineInstr &MIb, AliasAnalysis *AA) const {
|
||||
|
@ -3515,7 +3515,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
|
|||
case Hexagon::EH_RETURN_JMPR:
|
||||
case Hexagon::PS_jmpret:
|
||||
// jumpr r31
|
||||
// Actual form JMPR %pc<imp-def>, %r31<imp-use>, %r0<imp-use,internal>.
|
||||
// Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0
|
||||
DstReg = MI.getOperand(0).getReg();
|
||||
if (Hexagon::IntRegsRegClass.contains(DstReg) && (Hexagon::R31 == DstReg))
|
||||
return HexagonII::HSIG_L2;
|
||||
|
@ -3705,7 +3705,7 @@ HexagonII::SubInstructionGroup HexagonInstrInfo::getDuplexCandidateGroup(
|
|||
case Hexagon::C2_cmovenewif:
|
||||
// if ([!]P0[.new]) Rd = #0
|
||||
// Actual form:
|
||||
// %r16<def> = C2_cmovenewit %p0<internal>, 0, %r16<imp-use,undef>;
|
||||
// %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
|
||||
DstReg = MI.getOperand(0).getReg();
|
||||
SrcReg = MI.getOperand(1).getReg();
|
||||
if (isIntRegForSubInst(DstReg) &&
|
||||
|
|
|
@ -129,9 +129,9 @@ static bool canBeFeederToNewValueJump(const HexagonInstrInfo *QII,
|
|||
// using -- if (QRI->isSubRegister(feederReg, cmpReg1) logic
|
||||
// before the callsite of this function
|
||||
// But we can not as it comes in the following fashion.
|
||||
// %d0<def> = Hexagon_S2_lsr_r_p %d0<kill>, %r2<kill>
|
||||
// %r0<def> = KILL %r0, %d0<imp-use,kill>
|
||||
// %p0<def> = CMPEQri %r0<kill>, 0
|
||||
// %d0 = Hexagon_S2_lsr_r_p killed %d0, killed %r2
|
||||
// %r0 = KILL %r0, implicit killed %d0
|
||||
// %p0 = CMPEQri killed %r0, 0
|
||||
// Hence, we need to check if it's a KILL instruction.
|
||||
if (II->getOpcode() == TargetOpcode::KILL)
|
||||
return false;
|
||||
|
@ -196,9 +196,9 @@ static bool commonChecksToProhibitNewValueJump(bool afterRA,
|
|||
// to new value jump. If they are in the path, bail out.
|
||||
// KILL sets kill flag on the opcode. It also sets up a
|
||||
// single register, out of pair.
|
||||
// %d0<def> = S2_lsr_r_p %d0<kill>, %r2<kill>
|
||||
// %r0<def> = KILL %r0, %d0<imp-use,kill>
|
||||
// %p0<def> = C2_cmpeqi %r0<kill>, 0
|
||||
// %d0 = S2_lsr_r_p killed %d0, killed %r2
|
||||
// %r0 = KILL %r0, implicit killed %d0
|
||||
// %p0 = C2_cmpeqi killed %r0, 0
|
||||
// PHI can be anything after RA.
|
||||
// COPY can remateriaze things in between feeder, compare and nvj.
|
||||
if (MII->getOpcode() == TargetOpcode::KILL ||
|
||||
|
|
|
@ -8,27 +8,27 @@
|
|||
// This peephole pass optimizes in the following cases.
|
||||
// 1. Optimizes redundant sign extends for the following case
|
||||
// Transform the following pattern
|
||||
// %170<def> = SXTW %166
|
||||
// %170 = SXTW %166
|
||||
// ...
|
||||
// %176<def> = COPY %170:isub_lo
|
||||
// %176 = COPY %170:isub_lo
|
||||
//
|
||||
// Into
|
||||
// %176<def> = COPY %166
|
||||
// %176 = COPY %166
|
||||
//
|
||||
// 2. Optimizes redundant negation of predicates.
|
||||
// %15<def> = CMPGTrr %6, %2
|
||||
// %15 = CMPGTrr %6, %2
|
||||
// ...
|
||||
// %16<def> = NOT_p %15<kill>
|
||||
// %16 = NOT_p killed %15
|
||||
// ...
|
||||
// JMP_c %16<kill>, <%bb.1>, %pc<imp-def,dead>
|
||||
// JMP_c killed %16, <%bb.1>, implicit dead %pc
|
||||
//
|
||||
// Into
|
||||
// %15<def> = CMPGTrr %6, %2;
|
||||
// %15 = CMPGTrr %6, %2;
|
||||
// ...
|
||||
// JMP_cNot %15<kill>, <%bb.1>, %pc<imp-def,dead>;
|
||||
// JMP_cNot killed %15, <%bb.1>, implicit dead %pc;
|
||||
//
|
||||
// Note: The peephole pass makes the instrucstions like
|
||||
// %170<def> = SXTW %166 or %16<def> = NOT_p %15<kill>
|
||||
// %170 = SXTW %166 or %16 = NOT_p killed %15
|
||||
// redundant and relies on some form of dead removal instructions, like
|
||||
// DCE or DIE to actually eliminate them.
|
||||
|
||||
|
@ -132,7 +132,7 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
|
|||
NextI = std::next(I);
|
||||
MachineInstr &MI = *I;
|
||||
// Look for sign extends:
|
||||
// %170<def> = SXTW %166
|
||||
// %170 = SXTW %166
|
||||
if (!DisableOptSZExt && MI.getOpcode() == Hexagon::A2_sxtw) {
|
||||
assert(MI.getNumOperands() == 2);
|
||||
MachineOperand &Dst = MI.getOperand(0);
|
||||
|
@ -143,13 +143,13 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
|
|||
if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
|
||||
TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
// Map the following:
|
||||
// %170<def> = SXTW %166
|
||||
// %170 = SXTW %166
|
||||
// PeepholeMap[170] = %166
|
||||
PeepholeMap[DstReg] = SrcReg;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for %170<def> = COMBINE_ir_V4 (0, %169)
|
||||
// Look for %170 = COMBINE_ir_V4 (0, %169)
|
||||
// %170:DoublRegs, %169:IntRegs
|
||||
if (!DisableOptExtTo64 && MI.getOpcode() == Hexagon::A4_combineir) {
|
||||
assert(MI.getNumOperands() == 3);
|
||||
|
@ -192,14 +192,14 @@ bool HexagonPeephole::runOnMachineFunction(MachineFunction &MF) {
|
|||
if (TargetRegisterInfo::isVirtualRegister(DstReg) &&
|
||||
TargetRegisterInfo::isVirtualRegister(SrcReg)) {
|
||||
// Map the following:
|
||||
// %170<def> = NOT_xx %166
|
||||
// %170 = NOT_xx %166
|
||||
// PeepholeMap[170] = %166
|
||||
PeepholeMap[DstReg] = SrcReg;
|
||||
}
|
||||
}
|
||||
|
||||
// Look for copy:
|
||||
// %176<def> = COPY %170:isub_lo
|
||||
// %176 = COPY %170:isub_lo
|
||||
if (!DisableOptSZExt && MI.isCopy()) {
|
||||
assert(MI.getNumOperands() == 2);
|
||||
MachineOperand &Dst = MI.getOperand(0);
|
||||
|
|
|
@ -772,8 +772,8 @@ bool HexagonPacketizerList::canPromoteToNewValueStore(const MachineInstr &MI,
|
|||
|
||||
// If data definition is because of implicit definition of the register,
|
||||
// do not newify the store. Eg.
|
||||
// %r9<def> = ZXTH %r12, %d6<imp-use>, %r12<imp-def>
|
||||
// S2_storerh_io %r8, 2, %r12<kill>; mem:ST2[%scevgep343]
|
||||
// %r9 = ZXTH %r12, implicit %d6, implicit-def %r12
|
||||
// S2_storerh_io %r8, 2, killed %r12; mem:ST2[%scevgep343]
|
||||
for (auto &MO : PacketMI.operands()) {
|
||||
if (MO.isRegMask() && MO.clobbersPhysReg(DepReg))
|
||||
return false;
|
||||
|
@ -787,8 +787,8 @@ bool HexagonPacketizerList::canPromoteToNewValueStore(const MachineInstr &MI,
|
|||
// Handle imp-use of super reg case. There is a target independent side
|
||||
// change that should prevent this situation but I am handling it for
|
||||
// just-in-case. For example, we cannot newify R2 in the following case:
|
||||
// %r3<def> = A2_tfrsi 0;
|
||||
// S2_storeri_io %r0<kill>, 0, %r2<kill>, %d1<imp-use,kill>;
|
||||
// %r3 = A2_tfrsi 0;
|
||||
// S2_storeri_io killed %r0, 0, killed %r2, implicit killed %d1;
|
||||
for (auto &MO : MI.operands()) {
|
||||
if (MO.isReg() && MO.isUse() && MO.isImplicit() && MO.getReg() == DepReg)
|
||||
return false;
|
||||
|
@ -892,12 +892,12 @@ bool HexagonPacketizerList::canPromoteToDotNew(const MachineInstr &MI,
|
|||
// Go through the packet instructions and search for an anti dependency between
|
||||
// them and DepReg from MI. Consider this case:
|
||||
// Trying to add
|
||||
// a) %r1<def> = TFRI_cdNotPt %p3, 2
|
||||
// a) %r1 = TFRI_cdNotPt %p3, 2
|
||||
// to this packet:
|
||||
// {
|
||||
// b) %p0<def> = C2_or %p3<kill>, %p0<kill>
|
||||
// c) %p3<def> = C2_tfrrp %r23
|
||||
// d) %r1<def> = C2_cmovenewit %p3, 4
|
||||
// b) %p0 = C2_or killed %p3, killed %p0
|
||||
// c) %p3 = C2_tfrrp %r23
|
||||
// d) %r1 = C2_cmovenewit %p3, 4
|
||||
// }
|
||||
// The P3 from a) and d) will be complements after
|
||||
// a)'s P3 is converted to .new form
|
||||
|
@ -962,11 +962,11 @@ bool HexagonPacketizerList::arePredicatesComplements(MachineInstr &MI1,
|
|||
|
||||
// One corner case deals with the following scenario:
|
||||
// Trying to add
|
||||
// a) %r24<def> = A2_tfrt %p0, %r25
|
||||
// a) %r24 = A2_tfrt %p0, %r25
|
||||
// to this packet:
|
||||
// {
|
||||
// b) %r25<def> = A2_tfrf %p0, %r24
|
||||
// c) %p0<def> = C2_cmpeqi %r26, 1
|
||||
// b) %r25 = A2_tfrf %p0, %r24
|
||||
// c) %p0 = C2_cmpeqi %r26, 1
|
||||
// }
|
||||
//
|
||||
// On general check a) and b) are complements, but presence of c) will
|
||||
|
@ -1543,7 +1543,7 @@ bool HexagonPacketizerList::isLegalToPacketizeTogether(SUnit *SUI, SUnit *SUJ) {
|
|||
|
||||
// There are certain anti-dependencies that cannot be ignored.
|
||||
// Specifically:
|
||||
// J2_call ... %r0<imp-def> ; SUJ
|
||||
// J2_call ... implicit-def %r0 ; SUJ
|
||||
// R0 = ... ; SUI
|
||||
// Those cannot be packetized together, since the call will observe
|
||||
// the effect of the assignment to R0.
|
||||
|
|
|
@ -272,7 +272,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
|
|||
case Hexagon::J2_jumpr:
|
||||
case Hexagon::PS_jmpret:
|
||||
// jumpr r31
|
||||
// Actual form JMPR %pc<imp-def>, %r31<imp-use>, %r0<imp-use,internal>.
|
||||
// Actual form JMPR implicit-def %pc, implicit %r31, implicit internal %r0.
|
||||
DstReg = MCI.getOperand(0).getReg();
|
||||
if (Hexagon::R31 == DstReg)
|
||||
return HexagonII::HSIG_L2;
|
||||
|
@ -471,7 +471,7 @@ unsigned HexagonMCInstrInfo::getDuplexCandidateGroup(MCInst const &MCI) {
|
|||
case Hexagon::C2_cmovenewif:
|
||||
// if ([!]P0[.new]) Rd = #0
|
||||
// Actual form:
|
||||
// %r16<def> = C2_cmovenewit %p0<internal>, 0, %r16<imp-use,undef>;
|
||||
// %r16 = C2_cmovenewit internal %p0, 0, implicit undef %r16;
|
||||
DstReg = MCI.getOperand(0).getReg(); // Rd
|
||||
PredReg = MCI.getOperand(1).getReg(); // P0
|
||||
if (HexagonMCInstrInfo::isIntRegForSubInst(DstReg) &&
|
||||
|
|
|
@ -113,9 +113,10 @@ bool llvm::HexagonMCShuffle(MCContext &Context, bool Fatal,
|
|||
|
||||
if (!HexagonMCInstrInfo::bundleSize(MCB)) {
|
||||
// There once was a bundle:
|
||||
// BUNDLE %d2<imp-def>, %r4<imp-def>, %r5<imp-def>, %d7<imp-def>, ...
|
||||
// * %d2<def> = IMPLICIT_DEF; flags:
|
||||
// * %d7<def> = IMPLICIT_DEF; flags:
|
||||
// BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
|
||||
// implicit-def %d7, ...
|
||||
// * %d2 = IMPLICIT_DEF; flags:
|
||||
// * %d7 = IMPLICIT_DEF; flags:
|
||||
// After the IMPLICIT_DEFs were removed by the asm printer, the bundle
|
||||
// became empty.
|
||||
DEBUG(dbgs() << "Skipping empty bundle");
|
||||
|
@ -137,9 +138,10 @@ llvm::HexagonMCShuffle(MCContext &Context, MCInstrInfo const &MCII,
|
|||
|
||||
if (!HexagonMCInstrInfo::bundleSize(MCB)) {
|
||||
// There once was a bundle:
|
||||
// BUNDLE %d2<imp-def>, %r4<imp-def>, %r5<imp-def>, %d7<imp-def>, ...
|
||||
// * %d2<def> = IMPLICIT_DEF; flags:
|
||||
// * %d7<def> = IMPLICIT_DEF; flags:
|
||||
// BUNDLE implicit-def %d2, implicit-def %r4, implicit-def %r5,
|
||||
// implicit-def %d7, ...
|
||||
// * %d2 = IMPLICIT_DEF; flags:
|
||||
// * %d7 = IMPLICIT_DEF; flags:
|
||||
// After the IMPLICIT_DEFs were removed by the asm printer, the bundle
|
||||
// became empty.
|
||||
DEBUG(dbgs() << "Skipping empty bundle");
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
// This is typically used to prevent keeping registers artificially live
|
||||
// in cases when they are defined via predicated instructions. For example:
|
||||
// r0 = add-if-true cond, r10, r11 (1)
|
||||
// r0 = add-if-false cond, r12, r13, r0<imp-use> (2)
|
||||
// r0 = add-if-false cond, r12, r13, implicit r0 (2)
|
||||
// ... = r0 (3)
|
||||
// Before (1), r0 is not intended to be live, and the use of r0 in (3) is
|
||||
// not meant to be reached by any def preceding (1). However, since the
|
||||
|
|
|
@ -480,7 +480,7 @@ MipsInstrInfo::genInstrWithNewOpc(unsigned NewOpc,
|
|||
MIB = BuildMI(*I->getParent(), I, I->getDebugLoc(), get(NewOpc));
|
||||
|
||||
// For MIPSR6 JI*C requires an immediate 0 as an operand, JIALC(64) an
|
||||
// immediate 0 as an operand and requires the removal of it's %ra<imp-def>
|
||||
// immediate 0 as an operand and requires the removal of it's implicit-def %ra
|
||||
// implicit operand as copying the implicit operations of the instructio we're
|
||||
// looking at will give us the correct flags.
|
||||
if (NewOpc == Mips::JIC || NewOpc == Mips::JIALC || NewOpc == Mips::JIC64 ||
|
||||
|
|
|
@ -22,11 +22,11 @@
|
|||
// This peephole pass optimizes these cases, for example
|
||||
//
|
||||
// It will transform the following pattern
|
||||
// %0<def> = LEA_ADDRi64 %VRFrame, 4
|
||||
// %1<def> = cvta_to_local_yes_64 %0
|
||||
// %0 = LEA_ADDRi64 %VRFrame, 4
|
||||
// %1 = cvta_to_local_yes_64 %0
|
||||
//
|
||||
// into
|
||||
// %1<def> = LEA_ADDRi64 %VRFrameLocal, 4
|
||||
// %1 = LEA_ADDRi64 %VRFrameLocal, 4
|
||||
//
|
||||
// %VRFrameLocal is the virtual register name of %SPL
|
||||
//
|
||||
|
|
|
@ -62,9 +62,9 @@ namespace llvm {
|
|||
/// %bb.0: derived from LLVM BB %entry
|
||||
/// Live Ins: %f1 %f3 %x6
|
||||
/// <SNIP1>
|
||||
/// %0<def> = COPY %f1; F8RC:%0
|
||||
/// %5<def> = CMPLWI %4<kill>, 0; CRRC:%5 GPRC:%4
|
||||
/// %8<def> = LXSDX %zero8, %7<kill>, %rm<imp-use>;
|
||||
/// %0 = COPY %f1; F8RC:%0
|
||||
/// %5 = CMPLWI killed %4, 0; CRRC:%5 GPRC:%4
|
||||
/// %8 = LXSDX %zero8, killed %7, implicit %rm;
|
||||
/// mem:LD8[ConstantPool] F8RC:%8 G8RC:%7
|
||||
/// BCC 76, %5, <%bb.2>; CRRC:%5
|
||||
/// Successors according to CFG: %bb.1(?%) %bb.2(?%)
|
||||
|
@ -75,7 +75,7 @@ namespace llvm {
|
|||
///
|
||||
/// %bb.2: derived from LLVM BB %entry
|
||||
/// Predecessors according to CFG: %bb.0 %bb.1
|
||||
/// %9<def> = PHI %8, <%bb.1>, %0, <%bb.0>;
|
||||
/// %9 = PHI %8, <%bb.1>, %0, <%bb.0>;
|
||||
/// F8RC:%9,%8,%0
|
||||
/// <SNIP2>
|
||||
/// BCC 76, %5, <%bb.4>; CRRC:%5
|
||||
|
@ -87,10 +87,10 @@ namespace llvm {
|
|||
///
|
||||
/// %bb.4: derived from LLVM BB %entry
|
||||
/// Predecessors according to CFG: %bb.2 %bb.3
|
||||
/// %13<def> = PHI %12, <%bb.3>, %2, <%bb.2>;
|
||||
/// %13 = PHI %12, <%bb.3>, %2, <%bb.2>;
|
||||
/// F8RC:%13,%12,%2
|
||||
/// <SNIP3>
|
||||
/// BLR8 %lr8<imp-use>, %rm<imp-use>, %f1<imp-use>
|
||||
/// BLR8 implicit %lr8, implicit %rm, implicit %f1
|
||||
///
|
||||
/// When this pattern is detected, branch coalescing will try to collapse
|
||||
/// it by moving code in %bb.2 to %bb.0 and/or %bb.4 and removing %bb.3.
|
||||
|
@ -100,9 +100,9 @@ namespace llvm {
|
|||
/// %bb.0: derived from LLVM BB %entry
|
||||
/// Live Ins: %f1 %f3 %x6
|
||||
/// <SNIP1>
|
||||
/// %0<def> = COPY %f1; F8RC:%0
|
||||
/// %5<def> = CMPLWI %4<kill>, 0; CRRC:%5 GPRC:%4
|
||||
/// %8<def> = LXSDX %zero8, %7<kill>, %rm<imp-use>;
|
||||
/// %0 = COPY %f1; F8RC:%0
|
||||
/// %5 = CMPLWI killed %4, 0; CRRC:%5 GPRC:%4
|
||||
/// %8 = LXSDX %zero8, killed %7, implicit %rm;
|
||||
/// mem:LD8[ConstantPool] F8RC:%8 G8RC:%7
|
||||
/// <SNIP2>
|
||||
/// BCC 76, %5, <%bb.4>; CRRC:%5
|
||||
|
@ -115,12 +115,12 @@ namespace llvm {
|
|||
///
|
||||
/// %bb.4: derived from LLVM BB %entry
|
||||
/// Predecessors according to CFG: %bb.0 %bb.1
|
||||
/// %9<def> = PHI %8, <%bb.1>, %0, <%bb.0>;
|
||||
/// %9 = PHI %8, <%bb.1>, %0, <%bb.0>;
|
||||
/// F8RC:%9,%8,%0
|
||||
/// %13<def> = PHI %12, <%bb.1>, %2, <%bb.0>;
|
||||
/// %13 = PHI %12, <%bb.1>, %2, <%bb.0>;
|
||||
/// F8RC:%13,%12,%2
|
||||
/// <SNIP3>
|
||||
/// BLR8 %lr8<imp-use>, %rm<imp-use>, %f1<imp-use>
|
||||
/// BLR8 implicit %lr8, implicit %rm, implicit %f1
|
||||
///
|
||||
/// Branch Coalescing does not split blocks, it moves everything in the same
|
||||
/// direction ensuring it does not break use/definition semantics.
|
||||
|
|
|
@ -2315,10 +2315,10 @@ PPCInstrInfo::isSignOrZeroExtended(const MachineInstr &MI, bool SignExt,
|
|||
|
||||
// For a method return value, we check the ZExt/SExt flags in attribute.
|
||||
// We assume the following code sequence for method call.
|
||||
// ADJCALLSTACKDOWN 32, %r1<imp-def,dead>, %r1<imp-use>
|
||||
// ADJCALLSTACKDOWN 32, implicit dead %r1, implicit %r1
|
||||
// BL8_NOP <ga:@func>,...
|
||||
// ADJCALLSTACKUP 32, 0, %r1<imp-def,dead>, %r1<imp-use>
|
||||
// %5<def> = COPY %x3; G8RC:%5
|
||||
// ADJCALLSTACKUP 32, 0, implicit dead %r1, implicit %r1
|
||||
// %5 = COPY %x3; G8RC:%5
|
||||
if (SrcReg == PPC::X3) {
|
||||
const MachineBasicBlock *MBB = MI.getParent();
|
||||
MachineBasicBlock::const_instr_iterator II =
|
||||
|
|
|
@ -585,8 +585,8 @@ bool PPCMIPeephole::simplifyCode(void) {
|
|||
// We can eliminate RLDICL (e.g. for zero-extension)
|
||||
// if all bits to clear are already zero in the input.
|
||||
// This code assume following code sequence for zero-extension.
|
||||
// %6<def> = COPY %5:sub_32; (optional)
|
||||
// %8<def> = IMPLICIT_DEF;
|
||||
// %6 = COPY %5:sub_32; (optional)
|
||||
// %8 = IMPLICIT_DEF;
|
||||
// %7<def,tied1> = INSERT_SUBREG %8<tied0>, %6, sub_32;
|
||||
if (!EnableZExtElimination) break;
|
||||
|
||||
|
@ -685,7 +685,7 @@ bool PPCMIPeephole::simplifyCode(void) {
|
|||
DEBUG(dbgs() << "Optimizing LI to ADDI: ");
|
||||
DEBUG(LiMI->dump());
|
||||
|
||||
// There could be repeated registers in the PHI, e.g: %1<def> =
|
||||
// There could be repeated registers in the PHI, e.g: %1 =
|
||||
// PHI %6, <%bb.2>, %8, <%bb.3>, %8, <%bb.6>; So if we've
|
||||
// already replaced the def instruction, skip.
|
||||
if (LiMI->getOpcode() == PPC::ADDI || LiMI->getOpcode() == PPC::ADDI8)
|
||||
|
|
|
@ -79,8 +79,8 @@ bool PPCQPXLoadSplat::runOnMachineFunction(MachineFunction &MF) {
|
|||
}
|
||||
|
||||
// We're looking for a sequence like this:
|
||||
// %f0<def> = LFD 0, %x3<kill>, %qf0<imp-def>; mem:LD8[%a](tbaa=!2)
|
||||
// %qf1<def> = QVESPLATI %qf0<kill>, 0, %rm<imp-use>
|
||||
// %f0 = LFD 0, killed %x3, implicit-def %qf0; mem:LD8[%a](tbaa=!2)
|
||||
// %qf1 = QVESPLATI killed %qf0, 0, implicit %rm
|
||||
|
||||
for (auto SI = Splats.begin(); SI != Splats.end();) {
|
||||
MachineInstr *SMI = *SI;
|
||||
|
|
|
@ -90,21 +90,21 @@ protected:
|
|||
// This pass is run after register coalescing, and so we're looking for
|
||||
// a situation like this:
|
||||
// ...
|
||||
// %5<def> = COPY %9; VSLRC:%5,%9
|
||||
// %5 = COPY %9; VSLRC:%5,%9
|
||||
// %5<def,tied1> = XSMADDADP %5<tied0>, %17, %16,
|
||||
// %rm<imp-use>; VSLRC:%5,%17,%16
|
||||
// implicit %rm; VSLRC:%5,%17,%16
|
||||
// ...
|
||||
// %9<def,tied1> = XSMADDADP %9<tied0>, %17, %19,
|
||||
// %rm<imp-use>; VSLRC:%9,%17,%19
|
||||
// implicit %rm; VSLRC:%9,%17,%19
|
||||
// ...
|
||||
// Where we can eliminate the copy by changing from the A-type to the
|
||||
// M-type instruction. Specifically, for this example, this means:
|
||||
// %5<def,tied1> = XSMADDADP %5<tied0>, %17, %16,
|
||||
// %rm<imp-use>; VSLRC:%5,%17,%16
|
||||
// implicit %rm; VSLRC:%5,%17,%16
|
||||
// is replaced by:
|
||||
// %16<def,tied1> = XSMADDMDP %16<tied0>, %18, %9,
|
||||
// %rm<imp-use>; VSLRC:%16,%18,%9
|
||||
// and we remove: %5<def> = COPY %9; VSLRC:%5,%9
|
||||
// implicit %rm; VSLRC:%16,%18,%9
|
||||
// and we remove: %5 = COPY %9; VSLRC:%5,%9
|
||||
|
||||
SlotIndex FMAIdx = LIS->getInstructionIndex(MI);
|
||||
|
||||
|
@ -150,10 +150,10 @@ protected:
|
|||
// walking the MIs we may as well test liveness here.
|
||||
//
|
||||
// FIXME: There is a case that occurs in practice, like this:
|
||||
// %9<def> = COPY %f1; VSSRC:%9
|
||||
// %9 = COPY %f1; VSSRC:%9
|
||||
// ...
|
||||
// %6<def> = COPY %9; VSSRC:%6,%9
|
||||
// %7<def> = COPY %9; VSSRC:%7,%9
|
||||
// %6 = COPY %9; VSSRC:%6,%9
|
||||
// %7 = COPY %9; VSSRC:%7,%9
|
||||
// %9<def,tied1> = XSMADDASP %9<tied0>, %1, %4; VSSRC:
|
||||
// %6<def,tied1> = XSMADDASP %6<tied0>, %1, %2; VSSRC:
|
||||
// %7<def,tied1> = XSMADDASP %7<tied0>, %1, %3; VSSRC:
|
||||
|
|
|
@ -436,8 +436,8 @@ bool SystemZElimCompare::optimizeCompareZero(
|
|||
// Also do a forward search to handle cases where an instruction after the
|
||||
// compare can be converted like
|
||||
//
|
||||
// LTEBRCompare %f0s, %f0s, %cc<imp-def> LTEBRCompare %f0s, %f0s, %cc<imp-def>
|
||||
// %f2s<def> = LER %f0s
|
||||
// LTEBRCompare %f0s, %f0s, implicit-def %cc LTEBRCompare %f0s, %f0s,
|
||||
// implicit-def %cc %f2s = LER %f0s
|
||||
//
|
||||
MBBI = Compare, MBBE = MBB.end();
|
||||
while (++MBBI != MBBE) {
|
||||
|
|
|
@ -103,20 +103,20 @@ LBB1_3: ## bb
|
|||
|
||||
Before regalloc, we have:
|
||||
|
||||
%reg1025<def> = IMUL32rri8 %reg1024, 45, %eflags<imp-def>
|
||||
%reg1025 = IMUL32rri8 %reg1024, 45, implicit-def %eflags
|
||||
JMP mbb<bb2,0x203afb0>
|
||||
Successors according to CFG: 0x203afb0 (#3)
|
||||
|
||||
bb1: 0x203af60, LLVM BB @0x1e02310, ID#2:
|
||||
Predecessors according to CFG: 0x203aec0 (#0)
|
||||
%reg1026<def> = IMUL32rri8 %reg1024, 78, %eflags<imp-def>
|
||||
%reg1026 = IMUL32rri8 %reg1024, 78, implicit-def %eflags
|
||||
Successors according to CFG: 0x203afb0 (#3)
|
||||
|
||||
bb2: 0x203afb0, LLVM BB @0x1e02340, ID#3:
|
||||
Predecessors according to CFG: 0x203af10 (#1) 0x203af60 (#2)
|
||||
%reg1027<def> = PHI %reg1025, mbb<bb,0x203af10>,
|
||||
%reg1027 = PHI %reg1025, mbb<bb,0x203af10>,
|
||||
%reg1026, mbb<bb1,0x203af60>
|
||||
%reg1029<def> = MOVZX64rr32 %reg1027
|
||||
%reg1029 = MOVZX64rr32 %reg1027
|
||||
|
||||
so we'd have to know that IMUL32rri8 leaves the high word zero extended and to
|
||||
be able to recognize the zero extend. This could also presumably be implemented
|
||||
|
|
|
@ -191,15 +191,15 @@ bool FixupBWInstPass::runOnMachineFunction(MachineFunction &MF) {
|
|||
/// %bb.2: derived from LLVM BB %if.then
|
||||
/// Live Ins: %rdi
|
||||
/// Predecessors according to CFG: %bb.0
|
||||
/// %ax<def> = MOV16rm %rdi<kill>, 1, %noreg, 0, %noreg, %eax<imp-def>;
|
||||
/// %ax = MOV16rm killed %rdi, 1, %noreg, 0, %noreg, implicit-def %eax;
|
||||
/// mem:LD2[%p]
|
||||
/// No %eax<imp-use>
|
||||
/// No implicit %eax
|
||||
/// Successors according to CFG: %bb.3(?%)
|
||||
///
|
||||
/// %bb.3: derived from LLVM BB %if.end
|
||||
/// Live Ins: %eax Only %ax is actually live
|
||||
/// Predecessors according to CFG: %bb.2 %bb.1
|
||||
/// %ax<def> = KILL %ax, %eax<imp-use,kill>
|
||||
/// %ax = KILL %ax, implicit killed %eax
|
||||
/// RET 0, %ax
|
||||
static bool isLive(const MachineInstr &MI,
|
||||
const LivePhysRegs &LiveRegs,
|
||||
|
|
|
@ -4469,7 +4469,7 @@ MachineInstr *X86InstrInfo::convertToThreeAddressWithLEA(
|
|||
unsigned leaInReg2 = 0;
|
||||
MachineInstr *InsMI2 = nullptr;
|
||||
if (Src == Src2) {
|
||||
// ADD16rr %reg1028<kill>, %reg1028
|
||||
// ADD16rr killed %reg1028, %reg1028
|
||||
// just a single insert_subreg.
|
||||
addRegReg(MIB, leaInReg, true, leaInReg, false);
|
||||
} else {
|
||||
|
@ -7633,7 +7633,7 @@ MachineInstr *X86InstrInfo::optimizeLoadInstr(MachineInstr &MI,
|
|||
/// This is used for mapping:
|
||||
/// %xmm4 = V_SET0
|
||||
/// to:
|
||||
/// %xmm4 = PXORrr %xmm4<undef>, %xmm4<undef>
|
||||
/// %xmm4 = PXORrr undef %xmm4, undef %xmm4
|
||||
///
|
||||
static bool Expand2AddrUndef(MachineInstrBuilder &MIB,
|
||||
const MCInstrDesc &Desc) {
|
||||
|
@ -8197,12 +8197,12 @@ static bool hasUndefRegUpdate(unsigned Opcode) {
|
|||
///
|
||||
/// This catches the VCVTSI2SD family of instructions:
|
||||
///
|
||||
/// vcvtsi2sdq %rax, %xmm0<undef>, %xmm14
|
||||
/// vcvtsi2sdq %rax, undef %xmm0, %xmm14
|
||||
///
|
||||
/// We should to be careful *not* to catch VXOR idioms which are presumably
|
||||
/// handled specially in the pipeline:
|
||||
///
|
||||
/// vxorps %xmm1<undef>, %xmm1<undef>, %xmm1
|
||||
/// vxorps undef %xmm1, undef %xmm1, %xmm1
|
||||
///
|
||||
/// Like getPartialRegUpdateClearance, this makes a strong assumption that the
|
||||
/// high bits that are passed-through are not live.
|
||||
|
@ -10895,7 +10895,7 @@ X86InstrInfo::getOutliningType(MachineInstr &MI) const {
|
|||
// FIXME: There are instructions which are being manually built without
|
||||
// explicit uses/defs so we also have to check the MCInstrDesc. We should be
|
||||
// able to remove the extra checks once those are fixed up. For example,
|
||||
// sometimes we might get something like %rax<def> = POP64r 1. This won't be
|
||||
// sometimes we might get something like %rax = POP64r 1. This won't be
|
||||
// caught by modifiesRegister or readsRegister even though the instruction
|
||||
// really ought to be formed so that modifiesRegister/readsRegister would
|
||||
// catch it.
|
||||
|
|
|
@ -235,7 +235,7 @@ void VZeroUpperInserter::processBasicBlock(MachineBasicBlock &MBB) {
|
|||
// If the call has no RegMask, skip it as well. It usually happens on
|
||||
// helper function calls (such as '_chkstk', '_ftol2') where standard
|
||||
// calling convention is not used (RegMask is not used to mark register
|
||||
// clobbered and register usage (def/imp-def/use) is well-defined and
|
||||
// clobbered and register usage (def/implicit-def/use) is well-defined and
|
||||
// explicitly specified.
|
||||
if (IsCall && !callHasRegMask(MI))
|
||||
continue;
|
||||
|
|
|
@ -43,7 +43,7 @@ define [1 x double] @constant() {
|
|||
; The key problem here is that we may fail to create an MBB referenced by a
|
||||
; PHI. If so, we cannot complete the G_PHI and mustn't try or bad things
|
||||
; happen.
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: G_STORE %6, %2; mem:ST4[%addr] GPR:%6,%2 (in function: pending_phis)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: G_STORE %6(s32), %2(p0); mem:ST4[%addr] GPR:%6,%2 (in function: pending_phis)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for pending_phis
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: pending_phis:
|
||||
define i32 @pending_phis(i1 %tst, i32 %val, i32* %addr) {
|
||||
|
@ -63,7 +63,7 @@ false:
|
|||
}
|
||||
|
||||
; General legalizer inability to handle types whose size wasn't a power of 2.
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1, %0; mem:ST6[%addr](align=8) (in function: odd_type)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1(s42), %0(p0); mem:ST6[%addr](align=8) (in function: odd_type)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for odd_type
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: odd_type:
|
||||
define void @odd_type(i42* %addr) {
|
||||
|
@ -72,7 +72,7 @@ define void @odd_type(i42* %addr) {
|
|||
ret void
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1, %0; mem:ST28[%addr](align=32) (in function: odd_vector)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1(<7 x s32>), %0(p0); mem:ST28[%addr](align=32) (in function: odd_vector)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for odd_vector
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: odd_vector:
|
||||
define void @odd_vector(<7 x i32>* %addr) {
|
||||
|
@ -91,7 +91,7 @@ define i128 @sequence_sizes([8 x i8] %in) {
|
|||
}
|
||||
|
||||
; Just to make sure we don't accidentally emit a normal load/store.
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: %2<def>(s64) = G_LOAD %0; mem:LD8[%addr] GPR:%2,%0 (in function: atomic_ops)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: cannot select: %2:gpr(s64) = G_LOAD %0(p0); mem:LD8[%addr] GPR:%2,%0 (in function: atomic_ops)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for atomic_ops
|
||||
; FALLBACK-WITH-REPORT-LABEL: atomic_ops:
|
||||
define i64 @atomic_ops(i64* %addr) {
|
||||
|
@ -132,14 +132,14 @@ continue:
|
|||
}
|
||||
|
||||
; Check that we fallback on invoke translation failures.
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %0<def>(s128) = G_FCONSTANT quad 2
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %0:_(s128) = G_FCONSTANT quad 2
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for test_quad_dump
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: test_quad_dump:
|
||||
define fp128 @test_quad_dump() {
|
||||
ret fp128 0xL00000000000000004000000000000000
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %0<def>(p0) = G_EXTRACT_VECTOR_ELT %1, %2; (in function: vector_of_pointers_extractelement)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %0:_(p0) = G_EXTRACT_VECTOR_ELT %1(<2 x p0>), %2(s32); (in function: vector_of_pointers_extractelement)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for vector_of_pointers_extractelement
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: vector_of_pointers_extractelement:
|
||||
@var = global <2 x i16*> zeroinitializer
|
||||
|
@ -156,7 +156,7 @@ end:
|
|||
br label %block
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %0, %4; mem:ST16[undef] (in function: vector_of_pointers_insertelement)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %0(<2 x p0>), %4(p0); mem:ST16[undef] (in function: vector_of_pointers_insertelement)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for vector_of_pointers_insertelement
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: vector_of_pointers_insertelement:
|
||||
define void @vector_of_pointers_insertelement() {
|
||||
|
@ -172,7 +172,7 @@ end:
|
|||
br label %block
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1, %3; mem:ST12[undef](align=4) (in function: nonpow2_insertvalue_narrowing)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %1(s96), %3(p0); mem:ST12[undef](align=4) (in function: nonpow2_insertvalue_narrowing)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_insertvalue_narrowing
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_insertvalue_narrowing:
|
||||
%struct96 = type { float, float, float }
|
||||
|
@ -213,7 +213,7 @@ define void @nonpow2_load_narrowing() {
|
|||
ret void
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %3, %0; mem:ST12[%c](align=16) (in function: nonpow2_store_narrowing
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %3(s96), %0(p0); mem:ST12[%c](align=16) (in function: nonpow2_store_narrowing
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_store_narrowing
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_store_narrowing:
|
||||
define void @nonpow2_store_narrowing(i96* %c) {
|
||||
|
@ -223,7 +223,7 @@ define void @nonpow2_store_narrowing(i96* %c) {
|
|||
ret void
|
||||
}
|
||||
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %0, %1; mem:ST12[undef](align=16) (in function: nonpow2_constant_narrowing)
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: G_STORE %0(s96), %1(p0); mem:ST12[undef](align=16) (in function: nonpow2_constant_narrowing)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_constant_narrowing
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_constant_narrowing:
|
||||
define void @nonpow2_constant_narrowing() {
|
||||
|
@ -233,8 +233,8 @@ define void @nonpow2_constant_narrowing() {
|
|||
|
||||
; Currently can't handle vector lengths that aren't an exact multiple of
|
||||
; natively supported vector lengths. Test that the fall-back works for those.
|
||||
; FALLBACK-WITH-REPORT-ERR-G_IMPLICIT_DEF-LEGALIZABLE: (FIXME: this is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF) remark: <unknown>:0:0: unable to legalize instruction: %1<def>(<7 x s64>) = G_ADD %0, %0; (in function: nonpow2_vector_add_fewerelements
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %2<def>(s64) = G_EXTRACT_VECTOR_ELT %1, %3; (in function: nonpow2_vector_add_fewerelements)
|
||||
; FALLBACK-WITH-REPORT-ERR-G_IMPLICIT_DEF-LEGALIZABLE: (FIXME: this is what is expected once we can legalize non-pow-of-2 G_IMPLICIT_DEF) remark: <unknown>:0:0: unable to legalize instruction: %1(<7 x s64>) = G_ADD %0, %0; (in function: nonpow2_vector_add_fewerelements
|
||||
; FALLBACK-WITH-REPORT-ERR: remark: <unknown>:0:0: unable to legalize instruction: %2:_(s64) = G_EXTRACT_VECTOR_ELT %1(<7 x s64>), %3(s64); (in function: nonpow2_vector_add_fewerelements)
|
||||
; FALLBACK-WITH-REPORT-ERR: warning: Instruction selection used fallback path for nonpow2_vector_add_fewerelements
|
||||
; FALLBACK-WITH-REPORT-OUT-LABEL: nonpow2_vector_add_fewerelements:
|
||||
define void @nonpow2_vector_add_fewerelements() {
|
||||
|
|
|
@ -9,8 +9,8 @@
|
|||
...
|
||||
---
|
||||
# CHECK: *** Bad machine code: Generic virtual register must have a bank in a RegBankSelected function ***
|
||||
# CHECK: instruction: %0<def>(s64) = COPY
|
||||
# CHECK: operand 0: %0<def>
|
||||
# CHECK: instruction: %0:_(s64) = COPY
|
||||
# CHECK: operand 0: %0
|
||||
name: test
|
||||
regBankSelected: true
|
||||
registers:
|
||||
|
|
|
@ -22,11 +22,11 @@ body: |
|
|||
%0 = COPY %x0
|
||||
|
||||
; CHECK: *** Bad machine code: Unexpected generic instruction in a Selected function ***
|
||||
; CHECK: instruction: %1<def> = G_ADD
|
||||
; CHECK: instruction: %1:gpr64 = G_ADD
|
||||
%1 = G_ADD %0, %0
|
||||
|
||||
; CHECK: *** Bad machine code: Generic virtual register invalid in a Selected function ***
|
||||
; CHECK: instruction: %2<def>(s64) = COPY
|
||||
; CHECK: operand 0: %2<def>
|
||||
; CHECK: instruction: %2:gpr(s64) = COPY
|
||||
; CHECK: operand 0: %2
|
||||
%2(s64) = COPY %x0
|
||||
...
|
||||
|
|
|
@ -296,7 +296,7 @@ declare double @hh(double) #1
|
|||
|
||||
; Check that we correctly deal with repeated operands.
|
||||
; The following testcase creates:
|
||||
; %d1<def> = FADDDrr %d0<kill>, %d0
|
||||
; %d1 = FADDDrr killed %d0, %d0
|
||||
; We'll get a crash if we naively look at the first operand, remove it
|
||||
; from the substitution list then look at the second operand.
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
; RUN: llc < %s -mtriple=arm64-apple-ios -verify-machineinstrs | FileCheck %s
|
||||
|
||||
; LdStOpt bug created illegal instruction:
|
||||
; %d1<def>, %d2<def> = LDPSi %x0, 1
|
||||
; %d1, %d2 = LDPSi %x0, 1
|
||||
; rdar://11512047
|
||||
|
||||
%0 = type opaque
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
; CHECK: Before post-MI-sched:
|
||||
; CHECK-LABEL: # Machine code for function test1:
|
||||
; CHECK: SU(2): STRWui %wzr
|
||||
; CHECK: SU(3): %x21<def>, %x20<def> = LDPXi %sp
|
||||
; CHECK: SU(3): %x21, %x20 = LDPXi %sp
|
||||
; CHECK: Predecessors:
|
||||
; CHECK-NEXT: SU(0): Out
|
||||
; CHECK-NEXT: SU(0): Out
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
; Check that the dead register definition pass is considering implicit defs.
|
||||
; When rematerializing through truncates, the coalescer may produce instructions
|
||||
; with dead defs, but live implicit-defs of subregs:
|
||||
; E.g. %x1<def, dead> = MOVi64imm 2, %w1<imp-def>; %x1:GPR64, %w1:GPR32
|
||||
; E.g. dead %x1 = MOVi64imm 2, implicit-def %w1; %x1:GPR64, %w1:GPR32
|
||||
; These instructions are live, and their definitions should not be rewritten.
|
||||
;
|
||||
; <rdar://problem/16492408>
|
||||
|
|
|
@ -4,9 +4,9 @@
|
|||
|
||||
; CHECK-SSA-LABEL: Machine code for function t1
|
||||
|
||||
; CHECK-SSA: [[QUOTREG:%[0-9]+]]<def> = SDIVWr
|
||||
; CHECK-SSA-NOT: [[QUOTREG]]<def> =
|
||||
; CHECK-SSA: {{%[0-9]+}}<def> = MSUBWrrr [[QUOTREG]]
|
||||
; CHECK-SSA: [[QUOTREG:%[0-9]+]]:gpr32 = SDIVWr
|
||||
; CHECK-SSA-NOT: [[QUOTREG]] =
|
||||
; CHECK-SSA: {{%[0-9]+}}:gpr32 = MSUBWrrr killed [[QUOTREG]]
|
||||
|
||||
; CHECK-SSA-LABEL: Machine code for function t2
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldr_int:%bb.0
|
||||
; CHECK: Cluster ld/st SU(1) - SU(2)
|
||||
; CHECK: SU(1): %{{[0-9]+}}<def> = LDRWui
|
||||
; CHECK: SU(2): %{{[0-9]+}}<def> = LDRWui
|
||||
; CHECK: SU(1): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
; CHECK: SU(2): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldr_int:%bb.0
|
||||
; EXYNOS: Cluster ld/st SU(1) - SU(2)
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}<def> = LDRWui
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}<def> = LDRWui
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
define i32 @ldr_int(i32* %a) nounwind {
|
||||
%p1 = getelementptr inbounds i32, i32* %a, i32 1
|
||||
%tmp1 = load i32, i32* %p1, align 2
|
||||
|
@ -26,13 +26,13 @@ define i32 @ldr_int(i32* %a) nounwind {
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldp_sext_int:%bb.0
|
||||
; CHECK: Cluster ld/st SU(1) - SU(2)
|
||||
; CHECK: SU(1): %{{[0-9]+}}<def> = LDRSWui
|
||||
; CHECK: SU(2): %{{[0-9]+}}<def> = LDRSWui
|
||||
; CHECK: SU(1): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
; CHECK: SU(2): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldp_sext_int:%bb.0
|
||||
; EXYNOS: Cluster ld/st SU(1) - SU(2)
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}<def> = LDRSWui
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}<def> = LDRSWui
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
define i64 @ldp_sext_int(i32* %p) nounwind {
|
||||
%tmp = load i32, i32* %p, align 4
|
||||
%add.ptr = getelementptr inbounds i32, i32* %p, i64 1
|
||||
|
@ -47,13 +47,13 @@ define i64 @ldp_sext_int(i32* %p) nounwind {
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldur_int:%bb.0
|
||||
; CHECK: Cluster ld/st SU(2) - SU(1)
|
||||
; CHECK: SU(1): %{{[0-9]+}}<def> = LDURWi
|
||||
; CHECK: SU(2): %{{[0-9]+}}<def> = LDURWi
|
||||
; CHECK: SU(1): %{{[0-9]+}}:gpr32 = LDURWi
|
||||
; CHECK: SU(2): %{{[0-9]+}}:gpr32 = LDURWi
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldur_int:%bb.0
|
||||
; EXYNOS: Cluster ld/st SU(2) - SU(1)
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}<def> = LDURWi
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}<def> = LDURWi
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}:gpr32 = LDURWi
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}:gpr32 = LDURWi
|
||||
define i32 @ldur_int(i32* %a) nounwind {
|
||||
%p1 = getelementptr inbounds i32, i32* %a, i32 -1
|
||||
%tmp1 = load i32, i32* %p1, align 2
|
||||
|
@ -67,13 +67,13 @@ define i32 @ldur_int(i32* %a) nounwind {
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldp_half_sext_zext_int:%bb.0
|
||||
; CHECK: Cluster ld/st SU(3) - SU(4)
|
||||
; CHECK: SU(3): %{{[0-9]+}}<def> = LDRSWui
|
||||
; CHECK: SU(4): %{{[0-9]+}}:sub_32<def,read-undef> = LDRWui
|
||||
; CHECK: SU(3): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
; CHECK: SU(4): undef %{{[0-9]+}}.sub_32:gpr64 = LDRWui
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldp_half_sext_zext_int:%bb.0
|
||||
; EXYNOS: Cluster ld/st SU(3) - SU(4)
|
||||
; EXYNOS: SU(3): %{{[0-9]+}}<def> = LDRSWui
|
||||
; EXYNOS: SU(4): %{{[0-9]+}}:sub_32<def,read-undef> = LDRWui
|
||||
; EXYNOS: SU(3): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
; EXYNOS: SU(4): undef %{{[0-9]+}}.sub_32:gpr64 = LDRWui
|
||||
define i64 @ldp_half_sext_zext_int(i64* %q, i32* %p) nounwind {
|
||||
%tmp0 = load i64, i64* %q, align 4
|
||||
%tmp = load i32, i32* %p, align 4
|
||||
|
@ -90,13 +90,13 @@ define i64 @ldp_half_sext_zext_int(i64* %q, i32* %p) nounwind {
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldp_half_zext_sext_int:%bb.0
|
||||
; CHECK: Cluster ld/st SU(3) - SU(4)
|
||||
; CHECK: SU(3): %{{[0-9]+}}:sub_32<def,read-undef> = LDRWui
|
||||
; CHECK: SU(4): %{{[0-9]+}}<def> = LDRSWui
|
||||
; CHECK: SU(3): undef %{{[0-9]+}}.sub_32:gpr64 = LDRWui
|
||||
; CHECK: SU(4): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldp_half_zext_sext_int:%bb.0
|
||||
; EXYNOS: Cluster ld/st SU(3) - SU(4)
|
||||
; EXYNOS: SU(3): %{{[0-9]+}}:sub_32<def,read-undef> = LDRWui
|
||||
; EXYNOS: SU(4): %{{[0-9]+}}<def> = LDRSWui
|
||||
; EXYNOS: SU(3): undef %{{[0-9]+}}.sub_32:gpr64 = LDRWui
|
||||
; EXYNOS: SU(4): %{{[0-9]+}}:gpr64 = LDRSWui
|
||||
define i64 @ldp_half_zext_sext_int(i64* %q, i32* %p) nounwind {
|
||||
%tmp0 = load i64, i64* %q, align 4
|
||||
%tmp = load i32, i32* %p, align 4
|
||||
|
@ -113,13 +113,13 @@ define i64 @ldp_half_zext_sext_int(i64* %q, i32* %p) nounwind {
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldr_int_volatile:%bb.0
|
||||
; CHECK-NOT: Cluster ld/st
|
||||
; CHECK: SU(1): %{{[0-9]+}}<def> = LDRWui
|
||||
; CHECK: SU(2): %{{[0-9]+}}<def> = LDRWui
|
||||
; CHECK: SU(1): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
; CHECK: SU(2): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldr_int_volatile:%bb.0
|
||||
; EXYNOS-NOT: Cluster ld/st
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}<def> = LDRWui
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}<def> = LDRWui
|
||||
; EXYNOS: SU(1): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
; EXYNOS: SU(2): %{{[0-9]+}}:gpr32 = LDRWui
|
||||
define i32 @ldr_int_volatile(i32* %a) nounwind {
|
||||
%p1 = getelementptr inbounds i32, i32* %a, i32 1
|
||||
%tmp1 = load volatile i32, i32* %p1, align 2
|
||||
|
@ -133,8 +133,8 @@ define i32 @ldr_int_volatile(i32* %a) nounwind {
|
|||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK-LABEL: ldq_cluster:%bb.0
|
||||
; CHECK: Cluster ld/st SU(1) - SU(3)
|
||||
; CHECK: SU(1): %{{[0-9]+}}<def> = LDRQui
|
||||
; CHECK: SU(3): %{{[0-9]+}}<def> = LDRQui
|
||||
; CHECK: SU(1): %{{[0-9]+}}:fpr128 = LDRQui
|
||||
; CHECK: SU(3): %{{[0-9]+}}:fpr128 = LDRQui
|
||||
; EXYNOS: ********** MI Scheduling **********
|
||||
; EXYNOS-LABEL: ldq_cluster:%bb.0
|
||||
; EXYNOS-NOT: Cluster ld/st
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
;
|
||||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK: shiftable
|
||||
; CHECK: SU(2): %2<def> = SUBXri %1, 20, 0
|
||||
; CHECK: SU(2): %2:gpr64common = SUBXri %1, 20, 0
|
||||
; CHECK: Successors:
|
||||
; CHECK-NEXT: SU(4): Data Latency=1 Reg=%2
|
||||
; CHECK-NEXT: SU(3): Data Latency=2 Reg=%2
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
;
|
||||
; CHECK: ********** MI Scheduling **********
|
||||
; CHECK: misched_bug:%bb.0 entry
|
||||
; CHECK: SU(2): %2<def> = LDRWui %0, 1; mem:LD4[%ptr1_plus1] GPR32:%2 GPR64common:%0
|
||||
; CHECK: SU(2): %2:gpr32 = LDRWui %0, 1; mem:LD4[%ptr1_plus1] GPR32:%2 GPR64common:%0
|
||||
; CHECK: Successors:
|
||||
; CHECK-NEXT: SU(5): Data Latency=4 Reg=%2
|
||||
; CHECK-NEXT: SU(4): Ord Latency=0
|
||||
|
@ -13,7 +13,7 @@
|
|||
; CHECK: Successors:
|
||||
; CHECK: SU(4): Ord Latency=0
|
||||
; CHECK: SU(4): STRWui %wzr, %1, 0; mem:ST4[%ptr2] GPR64common:%1
|
||||
; CHECK: SU(5): %w0<def> = COPY %2; GPR32:%2
|
||||
; CHECK: SU(5): %w0 = COPY %2; GPR32:%2
|
||||
; CHECK: ** ScheduleDAGMI::schedule picking next node
|
||||
define i32 @misched_bug(i32* %ptr1, i32* %ptr2) {
|
||||
entry:
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
; Check that no scheduling dependencies are created between the paired loads and the store during post-RA MI scheduling.
|
||||
;
|
||||
; CHECK-LABEL: # Machine code for function foo:
|
||||
; CHECK: SU(2): %w{{[0-9]+}}<def>, %w{{[0-9]+}}<def> = LDPWi
|
||||
; CHECK: SU(2): %w{{[0-9]+}}, %w{{[0-9]+}} = LDPWi
|
||||
; CHECK: Successors:
|
||||
; CHECK-NOT: ch SU(4)
|
||||
; CHECK: SU(3)
|
||||
|
|
|
@ -22,14 +22,14 @@ tracksRegLiveness: true
|
|||
body: |
|
||||
bb.0:
|
||||
; CHECK: Adding MCLOH_AdrpAdrp:
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g4>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g4>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAdrp:
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAdrp:
|
||||
; CHECK-NEXT: %x0<def> = ADRP <ga:@g0>
|
||||
; CHECK-NEXT: %x0<def> = ADRP <ga:@g1>
|
||||
; CHECK-NEXT: %x0 = ADRP <ga:@g0>
|
||||
; CHECK-NEXT: %x0 = ADRP <ga:@g1>
|
||||
%x0 = ADRP target-flags(aarch64-page) @g0
|
||||
%x0 = ADRP target-flags(aarch64-page) @g1
|
||||
%x1 = ADRP target-flags(aarch64-page) @g2
|
||||
|
@ -38,11 +38,11 @@ body: |
|
|||
|
||||
bb.1:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAdd:
|
||||
; CHECK-NEXT: %x20<def> = ADRP <ga:@g0>
|
||||
; CHECK-NEXT: %x3<def> = ADDXri %x20, <ga:@g0>
|
||||
; CHECK-NEXT: %x20 = ADRP <ga:@g0>
|
||||
; CHECK-NEXT: %x3 = ADDXri %x20, <ga:@g0>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAdd:
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g0>
|
||||
; CHECK-NEXT: %x1<def> = ADDXri %x1, <ga:@g0>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g0>
|
||||
; CHECK-NEXT: %x1 = ADDXri %x1, <ga:@g0>
|
||||
%x1 = ADRP target-flags(aarch64-page) @g0
|
||||
%x9 = SUBXri undef %x11, 5, 0 ; should not affect MCLOH formation
|
||||
%x1 = ADDXri %x1, target-flags(aarch64-pageoff) @g0, 0
|
||||
|
@ -73,11 +73,11 @@ body: |
|
|||
|
||||
bb.5:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdr:
|
||||
; CHECK-NEXT: %x5<def> = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %s6<def> = LDRSui %x5, <ga:@g2>
|
||||
; CHECK-NEXT: %x5 = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %s6 = LDRSui %x5, <ga:@g2>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdr:
|
||||
; CHECK-NEXT: %x4<def> = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x4<def> = LDRXui %x4, <ga:@g2>
|
||||
; CHECK-NEXT: %x4 = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x4 = LDRXui %x4, <ga:@g2>
|
||||
%x4 = ADRP target-flags(aarch64-page) @g2
|
||||
%x4 = LDRXui %x4, target-flags(aarch64-pageoff) @g2
|
||||
%x5 = ADRP target-flags(aarch64-page) @g2
|
||||
|
@ -85,11 +85,11 @@ body: |
|
|||
|
||||
bb.6:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdrGot:
|
||||
; CHECK-NEXT: %x5<def> = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x6<def> = LDRXui %x5, <ga:@g2>
|
||||
; CHECK-NEXT: %x5 = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x6 = LDRXui %x5, <ga:@g2>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdrGot:
|
||||
; CHECK-NEXT: %x4<def> = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x4<def> = LDRXui %x4, <ga:@g2>
|
||||
; CHECK-NEXT: %x4 = ADRP <ga:@g2>
|
||||
; CHECK-NEXT: %x4 = LDRXui %x4, <ga:@g2>
|
||||
%x4 = ADRP target-flags(aarch64-page, aarch64-got) @g2
|
||||
%x4 = LDRXui %x4, target-flags(aarch64-pageoff, aarch64-got) @g2
|
||||
%x5 = ADRP target-flags(aarch64-page, aarch64-got) @g2
|
||||
|
@ -104,23 +104,23 @@ body: |
|
|||
|
||||
bb.8:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAddLdr:
|
||||
; CHECK-NEXT: %x7<def> = ADRP <ga:@g3>[TF=1]
|
||||
; CHECK-NEXT: %x8<def> = ADDXri %x7, <ga:@g3>
|
||||
; CHECK-NEXT: %d1<def> = LDRDui %x8, 8
|
||||
; CHECK-NEXT: %x7 = ADRP <ga:@g3>[TF=1]
|
||||
; CHECK-NEXT: %x8 = ADDXri %x7, <ga:@g3>
|
||||
; CHECK-NEXT: %d1 = LDRDui %x8, 8
|
||||
%x7 = ADRP target-flags(aarch64-page) @g3
|
||||
%x8 = ADDXri %x7, target-flags(aarch64-pageoff) @g3, 0
|
||||
%d1 = LDRDui %x8, 8
|
||||
|
||||
bb.9:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAdd:
|
||||
; CHECK-NEXT: %x3<def> = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x3<def> = ADDXri %x3, <ga:@g3>
|
||||
; CHECK-NEXT: %x3 = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x3 = ADDXri %x3, <ga:@g3>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAdd:
|
||||
; CHECK-NEXT: %x5<def> = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x2<def> = ADDXri %x5, <ga:@g3>
|
||||
; CHECK-NEXT: %x5 = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x2 = ADDXri %x5, <ga:@g3>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpAddStr:
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x1<def> = ADDXri %x1, <ga:@g3>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x1 = ADDXri %x1, <ga:@g3>
|
||||
; CHECK-NEXT: STRXui %xzr, %x1, 16
|
||||
%x1 = ADRP target-flags(aarch64-page) @g3
|
||||
%x1 = ADDXri %x1, target-flags(aarch64-pageoff) @g3, 0
|
||||
|
@ -138,12 +138,12 @@ body: |
|
|||
|
||||
bb.10:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdr:
|
||||
; CHECK-NEXT: %x2<def> = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x2<def> = LDRXui %x2, <ga:@g3>
|
||||
; CHECK-NEXT: %x2 = ADRP <ga:@g3>
|
||||
; CHECK-NEXT: %x2 = LDRXui %x2, <ga:@g3>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdrGotLdr:
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g4>
|
||||
; CHECK-NEXT: %x1<def> = LDRXui %x1, <ga:@g4>
|
||||
; CHECK-NEXT: %x1<def> = LDRXui %x1, 24
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g4>
|
||||
; CHECK-NEXT: %x1 = LDRXui %x1, <ga:@g4>
|
||||
; CHECK-NEXT: %x1 = LDRXui %x1, 24
|
||||
%x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4
|
||||
%x1 = LDRXui %x1, target-flags(aarch64-pageoff, aarch64-got) @g4
|
||||
%x1 = LDRXui %x1, 24
|
||||
|
@ -154,11 +154,11 @@ body: |
|
|||
|
||||
bb.11:
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdr
|
||||
; CHECK-NEXT: %x5<def> = ADRP <ga:@g1>
|
||||
; CHECK-NEXT: %x5<def> = LDRXui %x5, <ga:@g1>
|
||||
; CHECK-NEXT: %x5 = ADRP <ga:@g1>
|
||||
; CHECK-NEXT: %x5 = LDRXui %x5, <ga:@g1>
|
||||
; CHECK-NEXT: Adding MCLOH_AdrpLdrGotStr:
|
||||
; CHECK-NEXT: %x1<def> = ADRP <ga:@g4>
|
||||
; CHECK-NEXT: %x1<def> = LDRXui %x1, <ga:@g4>
|
||||
; CHECK-NEXT: %x1 = ADRP <ga:@g4>
|
||||
; CHECK-NEXT: %x1 = LDRXui %x1, <ga:@g4>
|
||||
; CHECK-NEXT: STRXui %xzr, %x1, 32
|
||||
%x1 = ADRP target-flags(aarch64-page, aarch64-got) @g4
|
||||
%x1 = LDRXui %x1, target-flags(aarch64-pageoff, aarch64-got) @g4
|
||||
|
@ -171,9 +171,9 @@ body: |
|
|||
bb.12:
|
||||
; CHECK-NOT: MCLOH_AdrpAdrp
|
||||
; CHECK: Adding MCLOH_AdrpAddLdr
|
||||
; %x9<def> = ADRP <ga:@g4>
|
||||
; %x9<def> = ADDXri %x9, <ga:@g4>
|
||||
; %x5<def> = LDRXui %x9, 0
|
||||
; %x9 = ADRP <ga:@g4>
|
||||
; %x9 = ADDXri %x9, <ga:@g4>
|
||||
; %x5 = LDRXui %x9, 0
|
||||
%x9 = ADRP target-flags(aarch64-page, aarch64-got) @g4
|
||||
%x9 = ADDXri %x9, target-flags(aarch64-pageoff, aarch64-got) @g4, 0
|
||||
%x5 = LDRXui %x9, 0
|
||||
|
|
|
@ -2,18 +2,18 @@
|
|||
|
||||
; This file check a bug in MachineCopyPropagation pass. The last COPY will be
|
||||
; incorrectly removed if the machine instructions are as follows:
|
||||
; %q5_q6<def> = COPY %q2_q3
|
||||
; %d5<def> =
|
||||
; %d3<def> =
|
||||
; %d3<def> = COPY %d6
|
||||
; %q5_q6 = COPY %q2_q3
|
||||
; %d5 =
|
||||
; %d3 =
|
||||
; %d3 = COPY %d6
|
||||
; This is caused by a bug in function SourceNoLongerAvailable(), which fails to
|
||||
; remove the relationship of D6 and "%q5_q6<def> = COPY %q2_q3".
|
||||
; remove the relationship of D6 and "%q5_q6 = COPY %q2_q3".
|
||||
|
||||
@failed = internal unnamed_addr global i1 false
|
||||
|
||||
; CHECK-LABEL: foo:
|
||||
; CHECK: ld2
|
||||
; CHECK-NOT: // kill: D{{[0-9]+}}<def> D{{[0-9]+}}<kill>
|
||||
; CHECK-NOT: // kill: def D{{[0-9]+}} killed D{{[0-9]+}}
|
||||
define void @foo(<2 x i32> %shuffle251, <8 x i8> %vtbl1.i, i8* %t2, <2 x i32> %vrsubhn_v2.i1364) {
|
||||
entry:
|
||||
%val0 = alloca [2 x i64], align 8
|
||||
|
|
|
@ -7,16 +7,16 @@
|
|||
# Check that the instructions are not dependent on each other, even though
|
||||
# they all read/write to the zero register.
|
||||
# CHECK-LABEL: MI Scheduling
|
||||
# CHECK: SU(0): %wzr<def,dead> = SUBSWri %w1, 0, 0, %nzcv<imp-def,dead>
|
||||
# CHECK: SU(0): dead %wzr = SUBSWri %w1, 0, 0, implicit-def dead %nzcv
|
||||
# CHECK: # succs left : 0
|
||||
# CHECK-NOT: Successors:
|
||||
# CHECK: SU(1): %w2<def> = COPY %wzr
|
||||
# CHECK: SU(1): %w2 = COPY %wzr
|
||||
# CHECK: # succs left : 0
|
||||
# CHECK-NOT: Successors:
|
||||
# CHECK: SU(2): %wzr<def,dead> = SUBSWri %w3, 0, 0, %nzcv<imp-def,dead>
|
||||
# CHECK: SU(2): dead %wzr = SUBSWri %w3, 0, 0, implicit-def dead %nzcv
|
||||
# CHECK: # succs left : 0
|
||||
# CHECK-NOT: Successors:
|
||||
# CHECK: SU(3): %w4<def> = COPY %wzr
|
||||
# CHECK: SU(3): %w4 = COPY %wzr
|
||||
# CHECK: # succs left : 0
|
||||
# CHECK-NOT: Successors:
|
||||
name: func
|
||||
|
|
|
@ -26,15 +26,15 @@ declare void @callee2(i8*, i8*, i8*, i8*, i8*,
|
|||
; CHECK: fi#-2: {{.*}} fixed, at location [SP+8]
|
||||
; CHECK: fi#-1: {{.*}} fixed, at location [SP]
|
||||
|
||||
; CHECK: [[VRA:%.*]]<def> = LDRXui <fi#-1>
|
||||
; CHECK: [[VRB:%.*]]<def> = LDRXui <fi#-2>
|
||||
; CHECK: [[VRA:%.*]]:gpr64 = LDRXui <fi#-1>
|
||||
; CHECK: [[VRB:%.*]]:gpr64 = LDRXui <fi#-2>
|
||||
; CHECK: STRXui %{{.*}}, <fi#-4>
|
||||
; CHECK: STRXui [[VRB]], <fi#-3>
|
||||
|
||||
; Make sure that there is an dependence edge between fi#-2 and fi#-4.
|
||||
; Without this edge the scheduler would be free to move the store accross the load.
|
||||
|
||||
; CHECK: SU({{.*}}): [[VRB]]<def> = LDRXui <fi#-2>
|
||||
; CHECK: SU({{.*}}): [[VRB]]:gpr64 = LDRXui <fi#-2>
|
||||
; CHECK-NOT: SU
|
||||
; CHECK: Successors:
|
||||
; CHECK: SU([[DEPSTOREB:.*]]): Ord Latency=0
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
; NOOPT: s_load_dwordx2 s[4:5]
|
||||
|
||||
; FIXME: Why is the SGPR4_SGPR5 reference being removed from DBG_VALUE?
|
||||
; NOOPT: ; kill: %sgpr8_sgpr9<def> %sgpr4_sgpr5<kill>
|
||||
; NOOPT: ; kill: def %sgpr8_sgpr9 killed %sgpr4_sgpr5
|
||||
; NOOPT-NEXT: ;DEBUG_VALUE: test_debug_value:globalptr_arg <- undef
|
||||
|
||||
; GCN: flat_store_dword
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
# Check there is no SReg_32 pressure created by DS_* instructions because of M0 use
|
||||
|
||||
# CHECK: ScheduleDAGMILive::schedule starting
|
||||
# CHECK: SU({{.*}} = DS_READ_B32 {{.*}} %m0<imp-use>, %exec<imp-use>
|
||||
# CHECK: SU({{.*}} = DS_READ_B32 {{.*}} implicit %m0, implicit %exec
|
||||
# CHECK: Pressure Diff : {{$}}
|
||||
# CHECK: SU({{.*}} DS_WRITE_B32
|
||||
|
||||
|
|
|
@ -4,8 +4,8 @@ target triple = "thumbv7-apple-darwin10"
|
|||
|
||||
; This tests the fast register allocator's handling of partial redefines:
|
||||
;
|
||||
; %reg1028:dsub_0<def>, %reg1028:dsub_1<def> = VLD1q64 %reg1025...
|
||||
; %reg1030:dsub_1<def> = COPY %reg1028:dsub_0<kill>
|
||||
; %reg1028:dsub_0, %reg1028:dsub_1 = VLD1q64 %reg1025...
|
||||
; %reg1030:dsub_1 = COPY killed %reg1028:dsub_0
|
||||
;
|
||||
; %reg1028 gets allocated %Q0, and if %reg1030 is reloaded for the partial
|
||||
; redef, it cannot also get %Q0.
|
||||
|
|
|
@ -9,7 +9,7 @@ target triple = "thumbv7-apple-ios"
|
|||
;
|
||||
; The early-clobber instruction is an str:
|
||||
;
|
||||
; %12<earlyclobber,def> = t2STR_PRE %6, %12, 32, pred:14, pred:%noreg
|
||||
; early-clobber %12 = t2STR_PRE %6, %12, 32, pred:14, pred:%noreg
|
||||
;
|
||||
; This tests that shrinkToUses handles the EC redef correctly.
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
define void @vst(i8* %m, [4 x i64] %v) {
|
||||
entry:
|
||||
; CHECK: vst:
|
||||
; CHECK: VST1d64Q %r{{[0-9]+}}<kill>, 8, %d{{[0-9]+}}, pred:14, pred:%noreg, %q{{[0-9]+}}_q{{[0-9]+}}<imp-use,kill>
|
||||
; CHECK: VST1d64Q killed %r{{[0-9]+}}, 8, %d{{[0-9]+}}, pred:14, pred:%noreg, implicit killed %q{{[0-9]+}}_q{{[0-9]+}}
|
||||
|
||||
%v0 = extractvalue [4 x i64] %v, 0
|
||||
%v1 = extractvalue [4 x i64] %v, 1
|
||||
|
@ -37,7 +37,7 @@ entry:
|
|||
%struct.__neon_int8x8x4_t = type { <8 x i8>, <8 x i8>, <8 x i8>, <8 x i8> }
|
||||
define <8 x i8> @vtbx4(<8 x i8>* %A, %struct.__neon_int8x8x4_t* %B, <8 x i8>* %C) nounwind {
|
||||
; CHECK: vtbx4:
|
||||
; CHECK: VTBX4 {{.*}}, pred:14, pred:%noreg, %q{{[0-9]+}}_q{{[0-9]+}}<imp-use>
|
||||
; CHECK: VTBX4 {{.*}}, pred:14, pred:%noreg, implicit %q{{[0-9]+}}_q{{[0-9]+}}
|
||||
%tmp1 = load <8 x i8>, <8 x i8>* %A
|
||||
%tmp2 = load %struct.__neon_int8x8x4_t, %struct.__neon_int8x8x4_t* %B
|
||||
%tmp3 = extractvalue %struct.__neon_int8x8x4_t %tmp2, 0
|
||||
|
|
|
@ -9,5 +9,5 @@ entry:
|
|||
ret void
|
||||
}
|
||||
|
||||
; CHECK: tBL pred:14, pred:%noreg, <es:__chkstk>, %lr<imp-def>, %sp<imp-use>, %r4<imp-use,kill>, %r4<imp-def>, %r12<imp-def,dead>, %cpsr<imp-def,dead>
|
||||
; CHECK: tBL pred:14, pred:%noreg, <es:__chkstk>, implicit-def %lr, implicit %sp, implicit killed %r4, implicit-def %r4, implicit-def dead %r12, implicit-def dead %cpsr
|
||||
|
||||
|
|
|
@ -61,7 +61,7 @@ for.end: ; preds = %cond.end
|
|||
|
||||
; CHECK: insert_elem
|
||||
; This test has a sub-register copy with a kill flag:
|
||||
; %6:ssub_3<def> = COPY %6:ssub_2<kill>; QPR_VFP2:%6
|
||||
; %6:ssub_3 = COPY killed %6:ssub_2; QPR_VFP2:%6
|
||||
; The rewriter must do something sensible with that, or the scavenger crashes.
|
||||
define void @insert_elem() nounwind {
|
||||
entry:
|
||||
|
|
|
@ -8,7 +8,7 @@ target triple = "thumbv7-unknown-unknown"
|
|||
%struct.gs_color_s = type { i16, i16, i16, i16, i8, i8 }
|
||||
|
||||
; In this case, the if converter was cloning the return instruction so that we had
|
||||
; r2<def> = ...
|
||||
; r2 = ...
|
||||
; return [pred] r2<dead,def>
|
||||
; ldr <r2, kill>
|
||||
; return
|
||||
|
|
|
@ -33,9 +33,9 @@ for.end: ; preds = %for.body, %entry
|
|||
; This case was a crasher in constrainLocalCopy.
|
||||
; The problem was the t2LDR_PRE defining both the global and local lrg.
|
||||
; CHECK-LABEL: *** Final schedule for %bb.5 ***
|
||||
; CHECK: %[[R4:[0-9]+]]<def>, %[[R1:[0-9]+]]<def,tied2> = t2LDR_PRE %[[R1]]<tied1>
|
||||
; CHECK: %{{[0-9]+}}<def> = COPY %[[R1]]
|
||||
; CHECK: %{{[0-9]+}}<def> = COPY %[[R4]]
|
||||
; CHECK: %[[R4:[0-9]+]]:gpr, %[[R1:[0-9]+]]:gpr = t2LDR_PRE %[[R1]]
|
||||
; CHECK: %{{[0-9]+}}:gpr = COPY %[[R1]]
|
||||
; CHECK: %{{[0-9]+}}:gpr = COPY %[[R4]]
|
||||
; CHECK-LABEL: MACHINEINSTRS
|
||||
%struct.rtx_def = type { [4 x i8], [1 x %union.rtunion_def] }
|
||||
%union.rtunion_def = type { i64 }
|
||||
|
|
|
@ -37,22 +37,22 @@
|
|||
}
|
||||
#
|
||||
# CHECK: ********** MI Scheduling **********
|
||||
# CHECK: SU(2): %2<def> = t2MOVi32imm <ga:@g1>; rGPR:%2
|
||||
# CHECK: SU(2): %2:rgpr = t2MOVi32imm <ga:@g1>; rGPR:%2
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 2
|
||||
# CHECK_R52: Latency : 2
|
||||
#
|
||||
# CHECK: SU(3): %3<def> = t2LDRi12 %2, 0, pred:14, pred:%noreg; mem:LD4[@g1](dereferenceable) rGPR:%3,%2
|
||||
# CHECK: SU(3): %3:rgpr = t2LDRi12 %2, 0, pred:14, pred:%noreg; mem:LD4[@g1](dereferenceable) rGPR:%3,%2
|
||||
# CHECK_A9: Latency : 1
|
||||
# CHECK_SWIFT: Latency : 3
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK : SU(6): %6<def> = t2ADDrr %3, %3, pred:14, pred:%noreg, opt:%noreg; rGPR:%6,%3,%3
|
||||
# CHECK : SU(6): %6 = t2ADDrr %3, %3, pred:14, pred:%noreg, opt:%noreg; rGPR:%6,%3,%3
|
||||
# CHECK_A9: Latency : 1
|
||||
# CHECK_SWIFT: Latency : 1
|
||||
# CHECK_R52: Latency : 3
|
||||
|
||||
# CHECK: SU(7): %7<def> = t2SDIV %6, %5, pred:14, pred:%noreg; rGPR:%7,%6,%5
|
||||
# CHECK: SU(7): %7:rgpr = t2SDIV %6, %5, pred:14, pred:%noreg; rGPR:%7,%6,%5
|
||||
# CHECK_A9: Latency : 0
|
||||
# CHECK_SWIFT: Latency : 14
|
||||
# CHECK_R52: Latency : 8
|
||||
|
@ -62,37 +62,37 @@
|
|||
# CHECK_SWIFT: Latency : 0
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(9): %8<def> = t2SMULBB %1, %1, pred:14, pred:%noreg; rGPR:%8,%1,%1
|
||||
# CHECK: SU(9): %8:rgpr = t2SMULBB %1, %1, pred:14, pred:%noreg; rGPR:%8,%1,%1
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(10): %9<def> = t2SMLABB %0, %0, %8, pred:14, pred:%noreg; rGPR:%9,%0,%0,%8
|
||||
# CHECK: SU(10): %9:rgpr = t2SMLABB %0, %0, %8, pred:14, pred:%noreg; rGPR:%9,%0,%0,%8
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(11): %10<def> = t2UXTH %9, 0, pred:14, pred:%noreg; rGPR:%10,%9
|
||||
# CHECK: SU(11): %10:rgpr = t2UXTH %9, 0, pred:14, pred:%noreg; rGPR:%10,%9
|
||||
# CHECK_A9: Latency : 1
|
||||
# CHECK_SWIFT: Latency : 1
|
||||
# CHECK_R52: Latency : 3
|
||||
#
|
||||
# CHECK: SU(12): %11<def> = t2MUL %10, %7, pred:14, pred:%noreg; rGPR:%11,%10,%7
|
||||
# CHECK: SU(12): %11:rgpr = t2MUL %10, %7, pred:14, pred:%noreg; rGPR:%11,%10,%7
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(13): %12<def> = t2MLA %11, %11, %11, pred:14, pred:%noreg; rGPR:%12,%11,%11,%11
|
||||
# CHECK: SU(13): %12:rgpr = t2MLA %11, %11, %11, pred:14, pred:%noreg; rGPR:%12,%11,%11,%11
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(14): %13<def>, %14<def> = t2UMULL %12, %12, pred:14, pred:%noreg; rGPR:%13,%14,%12,%12
|
||||
# CHECK: SU(14): %13:rgpr, %14:rgpr = t2UMULL %12, %12, pred:14, pred:%noreg; rGPR:%13,%14,%12,%12
|
||||
# CHECK_A9: Latency : 3
|
||||
# CHECK_SWIFT: Latency : 5
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(18): %19<def,tied4>, %20<def,tied5> = t2UMLAL %12, %12, %19<tied0>, %20<tied1>, pred:14, pred:%noreg; rGPR:%19,%20,%12,%12,%20
|
||||
# CHECK: SU(18): %19:rgpr, %20:rgpr = t2UMLAL %12, %12, %19, %20, pred:14, pred:%noreg; rGPR:%19,%20,%12,%12,%20
|
||||
# CHECK_A9: Latency : 3
|
||||
# CHECK_SWIFT: Latency : 7
|
||||
# CHECK_R52: Latency : 4
|
||||
|
|
|
@ -28,37 +28,37 @@
|
|||
}
|
||||
|
||||
# CHECK: ********** MI Scheduling **********
|
||||
# CHECK: SU(2): %2<def> = SMULBB %1, %1, pred:14, pred:%noreg; GPR:%2,%1,%1
|
||||
# CHECK: SU(2): %2:gpr = SMULBB %1, %1, pred:14, pred:%noreg; GPR:%2,%1,%1
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(3): %3<def> = SMLABB %0, %0, %2, pred:14, pred:%noreg; GPRnopc:%3,%0,%0 GPR:%2
|
||||
# CHECK: SU(3): %3:gprnopc = SMLABB %0, %0, %2, pred:14, pred:%noreg; GPRnopc:%3,%0,%0 GPR:%2
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(4): %4<def> = UXTH %3, 0, pred:14, pred:%noreg; GPRnopc:%4,%3
|
||||
# CHECK: SU(4): %4:gprnopc = UXTH %3, 0, pred:14, pred:%noreg; GPRnopc:%4,%3
|
||||
# CHECK_A9: Latency : 1
|
||||
# CHECK_SWIFT: Latency : 1
|
||||
# CHECK_R52: Latency : 3
|
||||
#
|
||||
# CHECK: SU(5): %5<def> = MUL %4, %4, pred:14, pred:%noreg, opt:%noreg; GPRnopc:%5,%4,%4
|
||||
# CHECK: SU(5): %5:gprnopc = MUL %4, %4, pred:14, pred:%noreg, opt:%noreg; GPRnopc:%5,%4,%4
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(6): %6<def> = MLA %5, %5, %5, pred:14, pred:%noreg, opt:%noreg; GPRnopc:%6,%5,%5,%5
|
||||
# CHECK: SU(6): %6:gprnopc = MLA %5, %5, %5, pred:14, pred:%noreg, opt:%noreg; GPRnopc:%6,%5,%5,%5
|
||||
# CHECK_A9: Latency : 2
|
||||
# CHECK_SWIFT: Latency : 4
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(7): %7<def>, %8<def> = UMULL %6, %6, pred:14, pred:%noreg, opt:%noreg; GPRnopc:%7,%8,%6,%6
|
||||
# CHECK: SU(7): %7:gprnopc, %8:gprnopc = UMULL %6, %6, pred:14, pred:%noreg, opt:%noreg; GPRnopc:%7,%8,%6,%6
|
||||
# CHECK_A9: Latency : 3
|
||||
# CHECK_SWIFT: Latency : 5
|
||||
# CHECK_R52: Latency : 4
|
||||
#
|
||||
# CHECK: SU(11): %13<def,tied4>, %14<def,tied5> = UMLAL %6, %6, %13<tied0>, %14<tied1>, pred:14, pred:%noreg, opt:%noreg; GPR:%13 GPRnopc:%14,%6,%6
|
||||
# CHECK: SU(11): %13:gpr, %14:gprnopc = UMLAL %6, %6, %13, %14, pred:14, pred:%noreg, opt:%noreg; GPR:%13 GPRnopc:%14,%6,%6
|
||||
# CHECK_SWIFT: Latency : 7
|
||||
# CHECK_A9: Latency : 3
|
||||
# CHECK_R52: Latency : 4
|
||||
|
|
|
@ -32,9 +32,9 @@
|
|||
; debug value as KILL'ed, resulting in a DEBUG_VALUE node changing codegen! (or
|
||||
; hopefully, triggering an assert).
|
||||
|
||||
; CHECK: BUNDLE %itstate<imp-def,dead>
|
||||
; CHECK: * DBG_VALUE %r1, %noreg, !"u"
|
||||
; CHECK-NOT: * DBG_VALUE %r1<kill>, %noreg, !"u"
|
||||
; CHECK: BUNDLE implicit-def dead %itstate
|
||||
; CHECK: * DBG_VALUE debug-use %r1, debug-use %noreg, !"u"
|
||||
; CHECK-NOT: * DBG_VALUE killed %r1, %noreg, !"u"
|
||||
|
||||
declare arm_aapcscc void @g(%struct.s*, i8*, i32) #1
|
||||
|
||||
|
|
|
@ -20,22 +20,22 @@
|
|||
|
||||
# CHECK: ********** MI Scheduling **********
|
||||
# CHECK: ScheduleDAGMILive::schedule starting
|
||||
# CHECK: SU(1): %1<def> = VLD4d8Pseudo %0, 8, pred:14, pred:%noreg; mem:LD32[%A](align=8) QQPR:%1 GPR:%0
|
||||
# CHECK: SU(1): %1:qqpr = VLD4d8Pseudo %0, 8, pred:14, pred:%noreg; mem:LD32[%A](align=8) QQPR:%1 GPR:%0
|
||||
# CHECK: Latency : 8
|
||||
# CHECK: Single Issue : true;
|
||||
# CHECK: SU(2): %4<def> = VADDv8i8 %1:dsub_0, %1:dsub_1, pred:14, pred:%noreg; DPR:%4 QQPR:%1
|
||||
# CHECK: SU(2): %4:dpr = VADDv8i8 %1.dsub_0, %1.dsub_1, pred:14, pred:%noreg; DPR:%4 QQPR:%1
|
||||
# CHECK: Latency : 5
|
||||
# CHECK: Single Issue : false;
|
||||
# CHECK: SU(3): %5<def>, %6<def> = VMOVRRD %4, pred:14, pred:%noreg; GPR:%5,%6 DPR:%4
|
||||
# CHECK: SU(3): %5:gpr, %6:gpr = VMOVRRD %4, pred:14, pred:%noreg; GPR:%5,%6 DPR:%4
|
||||
# CHECK: Latency : 4
|
||||
# CHECK: Single Issue : false;
|
||||
|
||||
# TOPDOWN: Scheduling SU(1) %1<def> = VLD4d8Pseudo
|
||||
# TOPDOWN: Scheduling SU(1) %1:qqpr = VLD4d8Pseudo
|
||||
# TOPDOWN: Bump cycle to end group
|
||||
# TOPDOWN: Scheduling SU(2) %4<def> = VADDv8i8
|
||||
# TOPDOWN: Scheduling SU(2) %4:dpr = VADDv8i8
|
||||
|
||||
# BOTTOMUP: Scheduling SU(2) %4<def> = VADDv8i8
|
||||
# BOTTOMUP: Scheduling SU(1) %1<def> = VLD4d8Pseudo
|
||||
# BOTTOMUP: Scheduling SU(2) %4:dpr = VADDv8i8
|
||||
# BOTTOMUP: Scheduling SU(1) %1:qqpr = VLD4d8Pseudo
|
||||
# BOTTOMUP: Bump cycle to begin group
|
||||
|
||||
...
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue