From 6b3bd61283afdfb7ce6d645ef4ed233bc60322a1 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Fri, 29 Jul 2016 20:32:59 +0000 Subject: [PATCH] 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 --- llvm/include/llvm/CodeGen/MachineInstrBuilder.h | 5 ++++ llvm/include/llvm/CodeGen/MachineOperand.h | 25 +++++++++++++++--- llvm/include/llvm/IR/Function.h | 2 ++ llvm/include/llvm/Target/TargetIntrinsicInfo.h | 5 ++++ llvm/lib/CodeGen/MIRParser/MILexer.cpp | 1 + llvm/lib/CodeGen/MIRParser/MILexer.h | 1 + llvm/lib/CodeGen/MIRParser/MIParser.cpp | 34 +++++++++++++++++++++++++ llvm/lib/CodeGen/MIRPrinter.cpp | 13 ++++++++++ llvm/lib/CodeGen/MachineInstr.cpp | 30 ++++++++++++++++++---- llvm/lib/IR/Function.cpp | 6 ++--- llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp | 2 ++ llvm/test/CodeGen/MIR/AArch64/intrinsics.mir | 18 +++++++++++++ llvm/test/CodeGen/MIR/AMDGPU/intrinsics.mir | 19 ++++++++++++++ 13 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 llvm/test/CodeGen/MIR/AArch64/intrinsics.mir create mode 100644 llvm/test/CodeGen/MIR/AMDGPU/intrinsics.mir diff --git a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h index 14cd29f..7119e0a 100644 --- a/llvm/include/llvm/CodeGen/MachineInstrBuilder.h +++ b/llvm/include/llvm/CodeGen/MachineInstrBuilder.h @@ -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)); diff --git a/llvm/include/llvm/CodeGen/MachineOperand.h b/llvm/include/llvm/CodeGen/MachineOperand.h index ee0a9cf..b7569c0 100644 --- a/llvm/include/llvm/CodeGen/MachineOperand.h +++ b/llvm/include/llvm/CodeGen/MachineOperand.h @@ -15,6 +15,7 @@ #define LLVM_CODEGEN_MACHINEOPERAND_H #include "llvm/Support/DataTypes.h" +#include "llvm/IR/Intrinsics.h" #include 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: diff --git a/llvm/include/llvm/IR/Function.h b/llvm/include/llvm/IR/Function.h index 2b4ce6d..46fba00 100644 --- a/llvm/include/llvm/IR/Function.h +++ b/llvm/include/llvm/IR/Function.h @@ -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. diff --git a/llvm/include/llvm/Target/TargetIntrinsicInfo.h b/llvm/include/llvm/Target/TargetIntrinsicInfo.h index c630f5b..41325a1 100644 --- a/llvm/include/llvm/Target/TargetIntrinsicInfo.h +++ b/llvm/include/llvm/Target/TargetIntrinsicInfo.h @@ -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 @@ -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; diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.cpp b/llvm/lib/CodeGen/MIRParser/MILexer.cpp index de9b773..1264571 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.cpp +++ b/llvm/lib/CodeGen/MIRParser/MILexer.cpp @@ -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) diff --git a/llvm/lib/CodeGen/MIRParser/MILexer.h b/llvm/lib/CodeGen/MIRParser/MILexer.h index 6f90612..6a09887 100644 --- a/llvm/lib/CodeGen/MIRParser/MILexer.h +++ b/llvm/lib/CodeGen/MIRParser/MILexer.h @@ -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, diff --git a/llvm/lib/CodeGen/MIRParser/MIParser.cpp b/llvm/lib/CodeGen/MIRParser/MIParser.cpp index 2675254..a5c049e 100644 --- a/llvm/lib/CodeGen/MIRParser/MIParser.cpp +++ b/llvm/lib/CodeGen/MIRParser/MIParser.cpp @@ -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(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: diff --git a/llvm/lib/CodeGen/MIRPrinter.cpp b/llvm/lib/CodeGen/MIRPrinter.cpp index 0cdb040..b42d45b 100644 --- a/llvm/lib/CodeGen/MIRPrinter.cpp +++ b/llvm/lib/CodeGen/MIRPrinter.cpp @@ -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; + } } } diff --git a/llvm/lib/CodeGen/MachineInstr.cpp b/llvm/lib/CodeGen/MachineInstr.cpp index aea33c7..8afa9ae 100644 --- a/llvm/lib/CodeGen/MachineInstr.cpp +++ b/llvm/lib/CodeGen/MachineInstr.cpp @@ -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 << ""; break; + case MachineOperand::MO_IntrinsicID: { + Intrinsic::ID ID = getIntrinsicID(); + if (ID < Intrinsic::num_intrinsics) + OS << "getName(ID) << ')'; + else + OS << "'; + 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); diff --git a/llvm/lib/IR/Function.cpp b/llvm/lib/IR/Function.cpp index e1223d0..54638ab 100644 --- a/llvm/lib/IR/Function.cpp +++ b/llvm/lib/IR/Function.cpp @@ -488,9 +488,7 @@ static ArrayRef 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 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 diff --git a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp index 63978c9..e74b1ab 100644 --- a/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/ARM/ARMExpandPseudoInsts.cpp @@ -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"); } diff --git a/llvm/test/CodeGen/MIR/AArch64/intrinsics.mir b/llvm/test/CodeGen/MIR/AArch64/intrinsics.mir new file mode 100644 index 0000000..b158c21 --- /dev/null +++ b/llvm/test/CodeGen/MIR/AArch64/intrinsics.mir @@ -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 +... diff --git a/llvm/test/CodeGen/MIR/AMDGPU/intrinsics.mir b/llvm/test/CodeGen/MIR/AMDGPU/intrinsics.mir new file mode 100644 index 0000000..b98432c --- /dev/null +++ b/llvm/test/CodeGen/MIR/AMDGPU/intrinsics.mir @@ -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) +... -- 2.7.4