mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2025-01-31 12:41:49 +01:00
CodeGen: add new "intrinsic" MachineOperand kind.
This will be used during GlobalISel, where we need a more robust and readable way to write tests than a simple immediate ID. llvm-svn: 277209
This commit is contained in:
parent
d5e10c8e46
commit
dda86274a2
@ -205,6 +205,11 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
const MachineInstrBuilder &addIntrinsicID(Intrinsic::ID ID) const {
|
||||
MI->addOperand(*MF, MachineOperand::CreateIntrinsicID(ID));
|
||||
return *this;
|
||||
}
|
||||
|
||||
const MachineInstrBuilder &addSym(MCSymbol *Sym,
|
||||
unsigned char TargetFlags = 0) const {
|
||||
MI->addOperand(*MF, MachineOperand::CreateMCSymbol(Sym, TargetFlags));
|
||||
|
@ -15,6 +15,7 @@
|
||||
#define LLVM_CODEGEN_MACHINEOPERAND_H
|
||||
|
||||
#include "llvm/Support/DataTypes.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include <cassert>
|
||||
|
||||
namespace llvm {
|
||||
@ -29,6 +30,7 @@ class MachineRegisterInfo;
|
||||
class MDNode;
|
||||
class ModuleSlotTracker;
|
||||
class TargetMachine;
|
||||
class TargetIntrinsicInfo;
|
||||
class TargetRegisterInfo;
|
||||
class hash_code;
|
||||
class raw_ostream;
|
||||
@ -60,7 +62,8 @@ public:
|
||||
MO_RegisterLiveOut, ///< Mask of live-out registers.
|
||||
MO_Metadata, ///< Metadata reference (for debug info)
|
||||
MO_MCSymbol, ///< MCSymbol reference (for debug/eh info)
|
||||
MO_CFIIndex ///< MCCFIInstruction index.
|
||||
MO_CFIIndex, ///< MCCFIInstruction index.
|
||||
MO_IntrinsicID, ///< Intrinsic ID
|
||||
};
|
||||
|
||||
private:
|
||||
@ -160,6 +163,7 @@ private:
|
||||
const MDNode *MD; // For MO_Metadata.
|
||||
MCSymbol *Sym; // For MO_MCSymbol.
|
||||
unsigned CFIIndex; // For MO_CFI.
|
||||
Intrinsic::ID IntrinsicID; // For MO_IntrinsicID.
|
||||
|
||||
struct { // For MO_Register.
|
||||
// Register number is in SmallContents.RegNo.
|
||||
@ -218,9 +222,11 @@ public:
|
||||
///
|
||||
void clearParent() { ParentMI = nullptr; }
|
||||
|
||||
void print(raw_ostream &os, const TargetRegisterInfo *TRI = nullptr) const;
|
||||
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;
|
||||
const TargetRegisterInfo *TRI = nullptr,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo = nullptr) const;
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Accessors that tell you what kind of MachineOperand you're looking at.
|
||||
@ -258,7 +264,7 @@ public:
|
||||
bool isMetadata() const { return OpKind == MO_Metadata; }
|
||||
bool isMCSymbol() const { return OpKind == MO_MCSymbol; }
|
||||
bool isCFIIndex() const { return OpKind == MO_CFIIndex; }
|
||||
|
||||
bool isIntrinsicID() const { return OpKind == MO_IntrinsicID; }
|
||||
//===--------------------------------------------------------------------===//
|
||||
// Accessors for Register Operands
|
||||
//===--------------------------------------------------------------------===//
|
||||
@ -453,6 +459,11 @@ public:
|
||||
return Contents.CFIIndex;
|
||||
}
|
||||
|
||||
Intrinsic::ID getIntrinsicID() const {
|
||||
assert(isIntrinsicID() && "Wrong MachineOperand accessor");
|
||||
return Contents.IntrinsicID;
|
||||
}
|
||||
|
||||
/// Return the offset from the symbol in this operand. This always returns 0
|
||||
/// for ExternalSymbol operands.
|
||||
int64_t getOffset() const {
|
||||
@ -732,6 +743,12 @@ public:
|
||||
return Op;
|
||||
}
|
||||
|
||||
static MachineOperand CreateIntrinsicID(Intrinsic::ID ID) {
|
||||
MachineOperand Op(MachineOperand::MO_IntrinsicID);
|
||||
Op.Contents.IntrinsicID = ID;
|
||||
return Op;
|
||||
}
|
||||
|
||||
friend class MachineInstr;
|
||||
friend class MachineRegisterInfo;
|
||||
private:
|
||||
|
@ -139,6 +139,8 @@ public:
|
||||
Intrinsic::ID getIntrinsicID() const LLVM_READONLY { return IntID; }
|
||||
bool isIntrinsic() const { return getName().startswith("llvm."); }
|
||||
|
||||
static Intrinsic::ID lookupIntrinsicID(StringRef Name);
|
||||
|
||||
/// \brief Recalculate the ID for this function if it is an Intrinsic defined
|
||||
/// in llvm/Intrinsics.h. Sets the intrinsic ID to Intrinsic::not_intrinsic
|
||||
/// if the name of this function does not match an intrinsic in that header.
|
||||
|
@ -14,6 +14,7 @@
|
||||
#ifndef LLVM_TARGET_TARGETINTRINSICINFO_H
|
||||
#define LLVM_TARGET_TARGETINTRINSICINFO_H
|
||||
|
||||
#include "llvm/ADT/StringRef.h"
|
||||
#include "llvm/Support/Compiler.h"
|
||||
#include <string>
|
||||
|
||||
@ -47,6 +48,10 @@ public:
|
||||
/// names.
|
||||
virtual unsigned lookupName(const char *Name, unsigned Len) const =0;
|
||||
|
||||
unsigned lookupName(StringRef Name) const {
|
||||
return lookupName(Name.data(), Name.size());
|
||||
}
|
||||
|
||||
/// Return the target intrinsic ID of a function, or 0.
|
||||
virtual unsigned getIntrinsicID(Function *F) const;
|
||||
|
||||
|
@ -211,6 +211,7 @@ static MIToken::TokenKind getIdentifierKind(StringRef Identifier) {
|
||||
.Case("def_cfa_offset", MIToken::kw_cfi_def_cfa_offset)
|
||||
.Case("def_cfa", MIToken::kw_cfi_def_cfa)
|
||||
.Case("blockaddress", MIToken::kw_blockaddress)
|
||||
.Case("intrinsic", MIToken::kw_intrinsic)
|
||||
.Case("target-index", MIToken::kw_target_index)
|
||||
.Case("half", MIToken::kw_half)
|
||||
.Case("float", MIToken::kw_float)
|
||||
|
@ -68,6 +68,7 @@ struct MIToken {
|
||||
kw_cfi_def_cfa_offset,
|
||||
kw_cfi_def_cfa,
|
||||
kw_blockaddress,
|
||||
kw_intrinsic,
|
||||
kw_target_index,
|
||||
kw_half,
|
||||
kw_float,
|
||||
|
@ -26,12 +26,14 @@
|
||||
#include "llvm/CodeGen/MachineRegisterInfo.h"
|
||||
#include "llvm/IR/Constants.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/ModuleSlotTracker.h"
|
||||
#include "llvm/IR/ValueSymbolTable.h"
|
||||
#include "llvm/Support/SourceMgr.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -152,6 +154,7 @@ public:
|
||||
bool parseCFIOperand(MachineOperand &Dest);
|
||||
bool parseIRBlock(BasicBlock *&BB, const Function &F);
|
||||
bool parseBlockAddressOperand(MachineOperand &Dest);
|
||||
bool parseIntrinsicOperand(MachineOperand &Dest);
|
||||
bool parseTargetIndexOperand(MachineOperand &Dest);
|
||||
bool parseLiveoutRegisterMaskOperand(MachineOperand &Dest);
|
||||
bool parseMachineOperand(MachineOperand &Dest,
|
||||
@ -1437,6 +1440,35 @@ bool MIParser::parseBlockAddressOperand(MachineOperand &Dest) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseIntrinsicOperand(MachineOperand &Dest) {
|
||||
assert(Token.is(MIToken::kw_intrinsic));
|
||||
lex();
|
||||
if (expectAndConsume(MIToken::lparen))
|
||||
return error("expected syntax intrinsic(@llvm.whatever)");
|
||||
|
||||
if (Token.isNot(MIToken::NamedGlobalValue))
|
||||
return error("expected syntax intrinsic(@llvm.whatever)");
|
||||
|
||||
std::string Name = Token.stringValue();
|
||||
lex();
|
||||
|
||||
if (expectAndConsume(MIToken::rparen))
|
||||
return error("expected ')' to terminate intrinsic name");
|
||||
|
||||
// Find out what intrinsic we're dealing with, first try the global namespace
|
||||
// and then the target's private intrinsics if that fails.
|
||||
const TargetIntrinsicInfo *TII = MF.getTarget().getIntrinsicInfo();
|
||||
Intrinsic::ID ID = Function::lookupIntrinsicID(Name);
|
||||
if (ID == Intrinsic::not_intrinsic && TII)
|
||||
ID = static_cast<Intrinsic::ID>(TII->lookupName(Name));
|
||||
|
||||
if (ID == Intrinsic::not_intrinsic)
|
||||
return error("unknown intrinsic name");
|
||||
Dest = MachineOperand::CreateIntrinsicID(ID);
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MIParser::parseTargetIndexOperand(MachineOperand &Dest) {
|
||||
assert(Token.is(MIToken::kw_target_index));
|
||||
lex();
|
||||
@ -1537,6 +1569,8 @@ bool MIParser::parseMachineOperand(MachineOperand &Dest,
|
||||
return parseCFIOperand(Dest);
|
||||
case MIToken::kw_blockaddress:
|
||||
return parseBlockAddressOperand(Dest);
|
||||
case MIToken::kw_intrinsic:
|
||||
return parseIntrinsicOperand(Dest);
|
||||
case MIToken::kw_target_index:
|
||||
return parseTargetIndexOperand(Dest);
|
||||
case MIToken::kw_liveout:
|
||||
|
@ -27,6 +27,7 @@
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/IRPrintingPasses.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/IR/ModuleSlotTracker.h"
|
||||
#include "llvm/MC/MCSymbol.h"
|
||||
@ -34,6 +35,7 @@
|
||||
#include "llvm/Support/YAMLTraits.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
|
||||
using namespace llvm;
|
||||
@ -871,6 +873,17 @@ void MIPrinter::print(const MachineOperand &Op, const TargetRegisterInfo *TRI,
|
||||
print(MMI.getFrameInstructions()[Op.getCFIIndex()], TRI);
|
||||
break;
|
||||
}
|
||||
case MachineOperand::MO_IntrinsicID: {
|
||||
Intrinsic::ID ID = Op.getIntrinsicID();
|
||||
if (ID < Intrinsic::num_intrinsics)
|
||||
OS << "intrinsic(@" << Intrinsic::getName(ID) << ')';
|
||||
else {
|
||||
const MachineFunction &MF = *Op.getParent()->getParent()->getParent();
|
||||
const TargetIntrinsicInfo *TII = MF.getTarget().getIntrinsicInfo();
|
||||
OS << "intrinsic(@" << TII->getName(ID) << ')';
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/InlineAsm.h"
|
||||
#include "llvm/IR/Intrinsics.h"
|
||||
#include "llvm/IR/LLVMContext.h"
|
||||
#include "llvm/IR/Metadata.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
@ -40,6 +41,7 @@
|
||||
#include "llvm/Support/MathExtras.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Target/TargetInstrInfo.h"
|
||||
#include "llvm/Target/TargetIntrinsicInfo.h"
|
||||
#include "llvm/Target/TargetMachine.h"
|
||||
#include "llvm/Target/TargetRegisterInfo.h"
|
||||
#include "llvm/Target/TargetSubtargetInfo.h"
|
||||
@ -256,6 +258,8 @@ bool MachineOperand::isIdenticalTo(const MachineOperand &Other) const {
|
||||
return getCFIIndex() == Other.getCFIIndex();
|
||||
case MachineOperand::MO_Metadata:
|
||||
return getMetadata() == Other.getMetadata();
|
||||
case MachineOperand::MO_IntrinsicID:
|
||||
return getIntrinsicID() == Other.getIntrinsicID();
|
||||
}
|
||||
llvm_unreachable("Invalid machine operand type");
|
||||
}
|
||||
@ -300,18 +304,21 @@ hash_code llvm::hash_value(const MachineOperand &MO) {
|
||||
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getMCSymbol());
|
||||
case MachineOperand::MO_CFIIndex:
|
||||
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getCFIIndex());
|
||||
case MachineOperand::MO_IntrinsicID:
|
||||
return hash_combine(MO.getType(), MO.getTargetFlags(), MO.getIntrinsicID());
|
||||
}
|
||||
llvm_unreachable("Invalid machine operand type");
|
||||
}
|
||||
|
||||
void MachineOperand::print(raw_ostream &OS,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
void MachineOperand::print(raw_ostream &OS, const TargetRegisterInfo *TRI,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo) const {
|
||||
ModuleSlotTracker DummyMST(nullptr);
|
||||
print(OS, DummyMST, TRI);
|
||||
print(OS, DummyMST, TRI, IntrinsicInfo);
|
||||
}
|
||||
|
||||
void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI) const {
|
||||
const TargetRegisterInfo *TRI,
|
||||
const TargetIntrinsicInfo *IntrinsicInfo) const {
|
||||
switch (getType()) {
|
||||
case MachineOperand::MO_Register:
|
||||
OS << PrintReg(getReg(), TRI, getSubReg());
|
||||
@ -454,6 +461,16 @@ void MachineOperand::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
||||
case MachineOperand::MO_CFIIndex:
|
||||
OS << "<call frame instruction>";
|
||||
break;
|
||||
case MachineOperand::MO_IntrinsicID: {
|
||||
Intrinsic::ID ID = getIntrinsicID();
|
||||
if (ID < Intrinsic::num_intrinsics)
|
||||
OS << "<intrinsic:@" << Intrinsic::getName(ID) << ')';
|
||||
else if (IntrinsicInfo)
|
||||
OS << "<intrinsic:@" << IntrinsicInfo->getName(ID) << ')';
|
||||
else
|
||||
OS << "<intrinsic:" << ID << '>';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unsigned TF = getTargetFlags())
|
||||
@ -1698,12 +1715,15 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
||||
const TargetRegisterInfo *TRI = nullptr;
|
||||
const MachineRegisterInfo *MRI = nullptr;
|
||||
const TargetInstrInfo *TII = nullptr;
|
||||
const TargetIntrinsicInfo *IntrinsicInfo = nullptr;
|
||||
|
||||
if (const MachineBasicBlock *MBB = getParent()) {
|
||||
MF = MBB->getParent();
|
||||
if (MF) {
|
||||
MRI = &MF->getRegInfo();
|
||||
TRI = MF->getSubtarget().getRegisterInfo();
|
||||
TII = MF->getSubtarget().getInstrInfo();
|
||||
IntrinsicInfo = MF->getTarget().getIntrinsicInfo();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1717,7 +1737,7 @@ void MachineInstr::print(raw_ostream &OS, ModuleSlotTracker &MST,
|
||||
!getOperand(StartOp).isImplicit();
|
||||
++StartOp) {
|
||||
if (StartOp != 0) OS << ", ";
|
||||
getOperand(StartOp).print(OS, MST, TRI);
|
||||
getOperand(StartOp).print(OS, MST, TRI, IntrinsicInfo);
|
||||
unsigned Reg = getOperand(StartOp).getReg();
|
||||
if (TargetRegisterInfo::isVirtualRegister(Reg)) {
|
||||
VirtRegs.push_back(Reg);
|
||||
|
@ -488,9 +488,7 @@ static ArrayRef<const char *> findTargetSubtable(StringRef Name) {
|
||||
|
||||
/// \brief This does the actual lookup of an intrinsic ID which
|
||||
/// matches the given function name.
|
||||
static Intrinsic::ID lookupIntrinsicID(const ValueName *ValName) {
|
||||
StringRef Name = ValName->getKey();
|
||||
|
||||
Intrinsic::ID Function::lookupIntrinsicID(StringRef Name) {
|
||||
ArrayRef<const char *> NameTable = findTargetSubtable(Name);
|
||||
int Idx = Intrinsic::lookupLLVMIntrinsicByName(NameTable, Name);
|
||||
if (Idx == -1)
|
||||
@ -513,7 +511,7 @@ void Function::recalculateIntrinsicID() {
|
||||
IntID = Intrinsic::not_intrinsic;
|
||||
return;
|
||||
}
|
||||
IntID = lookupIntrinsicID(ValName);
|
||||
IntID = lookupIntrinsicID(ValName->getKey());
|
||||
}
|
||||
|
||||
/// Returns a stable mangling for the type specified for use in the name
|
||||
|
@ -657,6 +657,8 @@ static bool IsAnAddressOperand(const MachineOperand &MO) {
|
||||
return true;
|
||||
case MachineOperand::MO_CFIIndex:
|
||||
return false;
|
||||
case MachineOperand::MO_IntrinsicID:
|
||||
llvm_unreachable("should not exist post-isel");
|
||||
}
|
||||
llvm_unreachable("unhandled machine operand type");
|
||||
}
|
||||
|
18
test/CodeGen/MIR/AArch64/intrinsics.mir
Normal file
18
test/CodeGen/MIR/AArch64/intrinsics.mir
Normal file
@ -0,0 +1,18 @@
|
||||
# RUN: llc -mtriple=aarch64-none-linux-gnu -run-pass none -o - %s | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define void @use_intrin() {
|
||||
ret void
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
# Completely invalid code, but it checks that intrinsics round-trip properly.
|
||||
# CHECK: %x0 = COPY intrinsic(@llvm.returnaddress)
|
||||
name: use_intrin
|
||||
body: |
|
||||
bb.0:
|
||||
%x0 = COPY intrinsic(@llvm.returnaddress)
|
||||
RET_ReallyLR
|
||||
...
|
19
test/CodeGen/MIR/AMDGPU/intrinsics.mir
Normal file
19
test/CodeGen/MIR/AMDGPU/intrinsics.mir
Normal file
@ -0,0 +1,19 @@
|
||||
# RUN: llc -mtriple=amdgcn -run-pass none -o - %s | FileCheck %s
|
||||
|
||||
--- |
|
||||
|
||||
define void @use_intrin() {
|
||||
ret void
|
||||
}
|
||||
|
||||
...
|
||||
---
|
||||
# Completely invalid code, but it checks that intrinsics round-trip properly.
|
||||
# CHECK: %0(64) = COPY intrinsic(@llvm.AMDGPU.bfe.i32)
|
||||
name: use_intrin
|
||||
registers:
|
||||
- { id: 0, class: _ }
|
||||
body: |
|
||||
bb.0:
|
||||
%0(64) = COPY intrinsic(@llvm.AMDGPU.bfe.i32)
|
||||
...
|
Loading…
x
Reference in New Issue
Block a user