diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index fc8fca3fe46322bb0a9c85590ff44c844d0e08ad..3b8bf76575b61e26514833cfdefbe7a9e540bef0 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5537,6 +5537,20 @@ public: llvm::AttrBuilder B(GV->getContext()); B.addAttribute("xvm-export-name", Attr->getExportName()); Fn->addFnAttrs(B); + } else { + // If the function is static and has a body, we add the always_inline + // attribute to it, unless it has a noinline attribute. + // This is to ensure that the function is inlined when possible. + // This is a common pattern in XVM to optimize performance. + if (FD->hasBody() && FD->isStatic()) { + const auto *NoInlineAttrVar = FD->getAttr(); + llvm::Function *Fn = cast(GV); + if (!NoInlineAttrVar) { + Fn->addFnAttr(llvm::Attribute::AlwaysInline); + } else { + Fn->addFnAttr(llvm::Attribute::NoInline); + } + } } } } diff --git a/llvm-build/build.py b/llvm-build/build.py index 0b43005266b30d50d95f77296fe84cd6f0ffe29f..b24e3fa87719223df64f7aed1010db95418e900b 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -775,6 +775,7 @@ class LlvmCore(BuildUtils): build_dir, install_dir, build_name, + need_compiler_rt, build_target=None, extra_defines=None, extra_env=None): @@ -816,10 +817,13 @@ class LlvmCore(BuildUtils): # First of all build compiler-rt because it's needed to be built before libunwind and etc. if not self.build_config.build_only and not 'windows-x86_64' in build_dir: - self.invoke_ninja(out_path=build_dir, - env=env, - target=["compiler-rt"], - install=install) + # Whether to build compiler-rt before other targets + # due to XVM do not need compiler-rt + if need_compiler_rt: + self.invoke_ninja(out_path=build_dir, + env=env, + target=["compiler-rt"], + install=install) self.invoke_ninja(out_path=build_dir, env=env, @@ -986,22 +990,25 @@ class LlvmCore(BuildUtils): if self.build_config.enable_monitoring: llvm_defines['LLDB_ENABLE_PERFORMANCE'] = 'ON' - def llvm_build_install_xvm_dylib_so(self, build_name, + def llvm_build_install_xvm_dylib_so(self, targets, + build_name, out_dir, build_target, llvm_extra_env, - debug_build): + debug_build, + llvm_defines): llvm_path = self.merge_out_path('llvm_make') llvm_path_dylib_so = self.merge_out_path('llvm_make_dylib_so') install_dir_dylib_so = self.merge_out_path('llvm-install-dylib-so') - llvm_defines_dylib_so = {} + llvm_defines_dylib_so = llvm_defines llvm_defines_dylib_so['LLVM_SPLIT_LLVM_DYLIB_TARGETS'] = 'ON' if debug_build: llvm_defines_dylib_so['CMAKE_BUILD_TYPE'] = 'Debug' - self.build_llvm(targets='XVM', + self.build_llvm(targets='AArch64;X86;XVM', build_dir=llvm_path_dylib_so, install_dir=install_dir_dylib_so, build_name=build_name, + need_compiler_rt=False, build_target=build_target, extra_defines=llvm_defines_dylib_so, extra_env=llvm_extra_env) @@ -1091,15 +1098,18 @@ class LlvmCore(BuildUtils): build_dir=llvm_path, install_dir=out_dir, build_name=build_name, + need_compiler_rt=True, build_target=build_target, extra_defines=llvm_defines, extra_env=llvm_extra_env) if build_xvm: - self.llvm_build_install_xvm_dylib_so(build_name, - out_dir, - build_target, - llvm_extra_env, - debug_build) + self.llvm_build_install_xvm_dylib_so(target_list, + build_name, + out_dir, + build_target, + llvm_extra_env, + debug_build, + llvm_defines) def llvm_compile_windows_defines(self, windows_defines, @@ -1192,7 +1202,7 @@ class LlvmCore(BuildUtils): '-Wl,--gc-sections', '-stdlib=libc++', '--rtlib=compiler-rt', - '-lunwind', + '-lunwind', '-Wl,--dynamicbase', '-Wl,--nxcompat', '-lucrt', @@ -1282,6 +1292,7 @@ class LlvmCore(BuildUtils): build_dir, windows64_install, build_name, + need_compiler_rt=True, extra_defines=windows_defines, extra_env=windows_extra_env) @@ -2368,17 +2379,17 @@ class LlvmLibs(BuildUtils): if multilib_suffix: baseline_abi_file_path = self.merge_out_path(self.build_config.LLVM_BUILD_DIR, "libcxx_abidiff", llvm_triple, multilib_suffix, "libc++_shared.abi") - elf_common_path = self.merge_out_path('lib', + elf_common_path = self.merge_out_path('lib', f"libunwind-libcxxabi-libcxx-ndk-{str(llvm_triple)}-{multilib_suffix}", 'lib', llvm_triple, multilib_suffix) else: baseline_abi_file_path = self.merge_out_path(self.build_config.LLVM_BUILD_DIR, "libcxx_abidiff", llvm_triple, "libc++_shared.abi") - elf_common_path = self.merge_out_path('lib', + elf_common_path = self.merge_out_path('lib', f"libunwind-libcxxabi-libcxx-ndk-{str(llvm_triple)}", 'lib', llvm_triple) elf_file_path = self.merge_out_path(elf_common_path, "libc++_shared.so") abi_file_path = self.merge_out_path(elf_common_path, "libc++_shared.abi") - header_dir = self.merge_out_path('lib', + header_dir = self.merge_out_path('lib', f"libunwind-libcxxabi-libcxx-ndk-{str(llvm_triple)}", 'include', "c++", "v1") res = self.run_abi_check(elf_file_path, abi_file_path, baseline_abi_file_path, header_dir) if res: diff --git a/llvm/lib/Target/XVM/CMakeLists.txt b/llvm/lib/Target/XVM/CMakeLists.txt index f203cf837bb3751c120f17abdcc93a34afa609bb..4f891b2895ddd134407497bbe366f4588a77bfc9 100644 --- a/llvm/lib/Target/XVM/CMakeLists.txt +++ b/llvm/lib/Target/XVM/CMakeLists.txt @@ -1,6 +1,7 @@ if(XVM IN_LIST LLVM_TARGETS_CALLED_VIA_DYLIB AND LLVM_SPLIT_LLVM_DYLIB_TARGETS) ADD_DEFINITIONS("-DXVM_DYLIB_MODE=1") + file(GLOB MCInstrAnalysisFN "${CMAKE_CURRENT_SOURCE_DIR}/../../MC/MCInstrAnalysis.cpp") endif() add_llvm_component_group(XVM) @@ -34,6 +35,7 @@ add_llvm_target(XVMCodeGen XVMExpandPseudoInsts.cpp XVMSelectionDAGInfo.cpp XVMUpdateRefInstrForMI.cpp + ${MCInstrAnalysisFN} LINK_COMPONENTS Analysis diff --git a/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.cpp b/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.cpp index 2974ec81313cd9741e8aa6f19c2a35da55884643..79efd4ec38a41015a35a183e7a6731cb880ddd0d 100644 --- a/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.cpp +++ b/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.cpp @@ -20,14 +20,19 @@ #include "llvm/Support/Casting.h" #include "llvm/Support/ErrorHandling.h" #include "llvm/Support/FormattedStream.h" + #define DEBUG_TYPE "asm-printer" #define GET_INSTRINFO_CTOR_DTOR // Include the auto-generated portion of the assembly writer. #include "XVMGenAsmWriter.inc" + using namespace llvm; using namespace std; +#define MIN_NUM_MO_CALL_INSTR 2 +#define MIN_NUM_MO_DATA_REF_INSTR 3 + void XVMInstPrinter::printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) { @@ -60,7 +65,7 @@ void XVMInstPrinter::printInst(const MCInst *MI, uint64_t Address, } void XVMInstPrinter::printCallInstructionImm(const MCInst *MI, raw_ostream &O) { - assert(MI->getNumOperands() >= 2); + assert(MI->getNumOperands() >= MIN_NUM_MO_CALL_INSTR); O << "\t"; auto MnemonicInfo = getMnemonic(MI); O << MnemonicInfo.first; @@ -81,7 +86,7 @@ void XVMInstPrinter::printMovWithFuncID(const MCInst *MI, raw_ostream &O) { } void XVMInstPrinter::printDataRefWithGlobalID(const MCInst *MI, raw_ostream &O) { - assert(MI->getNumOperands() >= 3); + assert(MI->getNumOperands() >= MIN_NUM_MO_DATA_REF_INSTR); const MCOperand &Op0 = MI->getOperand(0); assert(Op0.isReg()); const MCOperand &Op1 = MI->getOperand(1); @@ -93,7 +98,7 @@ void XVMInstPrinter::printDataRefWithGlobalID(const MCInst *MI, raw_ostream &O) } void XVMInstPrinter::printCallInstructionReg(const MCInst *MI, raw_ostream &O) { - assert(MI->getNumOperands() >= 2); + assert(MI->getNumOperands() >= MIN_NUM_MO_CALL_INSTR); O << "\t"; auto MnemonicInfo = getMnemonic(MI); O << MnemonicInfo.first; @@ -102,79 +107,77 @@ void XVMInstPrinter::printCallInstructionReg(const MCInst *MI, raw_ostream &O) { O << getRegisterName(MI->getOperand(1).getReg()); } -static void printExpr(const MCExpr *Expr, raw_ostream &O) { +static void printExpr(const MCExpr *Expression, raw_ostream &OStream) { #ifndef NDEBUG - const MCSymbolRefExpr *SRE; + const MCSymbolRefExpr *SRExpr; - if (const MCBinaryExpr *BE = dyn_cast(Expr)) - SRE = dyn_cast(BE->getLHS()); + if (const MCBinaryExpr *BExpr = dyn_cast(Expression)) + SRExpr = dyn_cast(BExpr->getLHS()); else - SRE = dyn_cast(Expr); - assert(SRE && "Unexpected MCExpr type."); + SRExpr = dyn_cast(Expression); + assert(SRExpr && "Unexpected MCExpr type."); - MCSymbolRefExpr::VariantKind Kind = SRE->getKind(); + MCSymbolRefExpr::VariantKind VarKind = SRExpr->getKind(); - assert(Kind == MCSymbolRefExpr::VK_None); + assert(VarKind == MCSymbolRefExpr::VK_None); #endif - O << *Expr; + OStream << *Expression; } -void XVMInstPrinter::printOperand(const MCInst *MI, unsigned OpNo, - raw_ostream &O, const char *Modifier) { - assert((Modifier == nullptr || Modifier[0] == 0) && "No modifiers supported"); - const MCOperand &Op = MI->getOperand(OpNo); - if (Op.isReg()) { - O << getRegisterName(Op.getReg()); - } else if (Op.isImm()) { - O << formatImm((int32_t)Op.getImm()); +void XVMInstPrinter::printOperand(const MCInst *MInst, unsigned OpNum, + raw_ostream &OStream, const char *Mod) { + assert((Mod == nullptr || Mod[0] == 0) && "No modifiers supported"); + const MCOperand &Oper = MInst->getOperand(OpNum); + if (Oper.isReg()) { + OStream << getRegisterName(Oper.getReg()); + } else if (Oper.isImm()) { + OStream << formatImm((int32_t)Oper.getImm()); } else { - assert(Op.isExpr() && "Expected an expression"); - printExpr(Op.getExpr(), O); + assert(Oper.isExpr() && "Expected an expression"); + printExpr(Oper.getExpr(), OStream); } } -void XVMInstPrinter::printMemOperand(const MCInst *MI, int OpNo, raw_ostream &O, - const char *Modifier) { - const MCOperand &RegOp = MI->getOperand(OpNo); - const MCOperand &OffsetOp = MI->getOperand(OpNo + 1); +void XVMInstPrinter::printMemOperand(const MCInst *MInst, int OpNum, + raw_ostream &OStream, const char *Mod) { + const MCOperand &ROp = MInst->getOperand(OpNum); + const MCOperand &OffOp = MInst->getOperand(OpNum + 1); // register - assert(RegOp.isReg() && "Register operand not a register"); - O << getRegisterName(RegOp.getReg()); + assert(ROp.isReg() && "Register operand not a register"); + OStream << getRegisterName(ROp.getReg()); // offset - if (OffsetOp.isImm()) { - auto Imm = OffsetOp.getImm(); - if (Imm == 0) - O << ", #" << formatImm(Imm); + if (OffOp.isImm()) { + auto I = OffOp.getImm(); + if (I == 0) + OStream << ", #" << formatImm(I); else - O << ", #" << formatImm(Imm); + OStream << ", #" << formatImm(I); } else { assert(0 && "Expected an immediate"); } } -void XVMInstPrinter::printImm64Operand(const MCInst *MI, unsigned OpNo, - raw_ostream &O) { - const MCOperand &Op = MI->getOperand(OpNo); - if (Op.isImm()) - O << formatImm(Op.getImm()); - else if (Op.isExpr()) - printExpr(Op.getExpr(), O); +void XVMInstPrinter::printImm64Operand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream) { + const MCOperand &Oper = MInst->getOperand(OpNum); + if (Oper.isImm()) + OStream << formatImm(Oper.getImm()); + else if (Oper.isExpr()) + printExpr(Oper.getExpr(), OStream); else - O << Op; + OStream << Oper; } -void XVMInstPrinter::printBrTargetOperand(const MCInst *MI, unsigned OpNo, - raw_ostream &O) { - const MCOperand &Op = MI->getOperand(OpNo); - if (Op.isImm()) { - int16_t Imm = Op.getImm(); - O << ((Imm >= 0) ? "+" : "") << formatImm(Imm); - } else if (Op.isExpr()) { - printExpr(Op.getExpr(), O); +void XVMInstPrinter::printBrTargetOperand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream) { + const MCOperand &Oper = MInst->getOperand(OpNum); + if (Oper.isImm()) { + int16_t I = Oper.getImm(); + OStream << ((I >= 0) ? "+" : "") << formatImm(I); + } else if (Oper.isExpr()) { + printExpr(Oper.getExpr(), OStream); } else { - O << Op; + OStream << Oper; } } diff --git a/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h b/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h index 33e8860810f0a33d5dfd0ba1147d7d4d8cf4f326..d28cb862843aebbee8b0dc91a0a706d677633516 100644 --- a/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h +++ b/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h @@ -24,12 +24,12 @@ public: void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override; - void printOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O, - const char *Modifier = nullptr); - void printMemOperand(const MCInst *MI, int OpNo, raw_ostream &O, - const char *Modifier = nullptr); - void printImm64Operand(const MCInst *MI, unsigned OpNo, raw_ostream &O); - void printBrTargetOperand(const MCInst *MI, unsigned OpNo, raw_ostream &O); + void printOperand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream, + const char *Mod = nullptr); + void printMemOperand(const MCInst *MInst, int OpNum, raw_ostream &OStream, + const char *Mod = nullptr); + void printImm64Operand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream); + void printBrTargetOperand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream); void printCallInstructionImm(const MCInst *MI, raw_ostream &O); void printCallInstructionReg(const MCInst *MI, raw_ostream &O); diff --git a/llvm/lib/Target/XVM/MCTargetDesc/XVMMCTargetDesc.cpp b/llvm/lib/Target/XVM/MCTargetDesc/XVMMCTargetDesc.cpp index 8480f9b8819c575be74a5642f5060c0ac4c770f1..d95446097c7b3b4d0efeb58910a0b11bda0d21f4 100644 --- a/llvm/lib/Target/XVM/MCTargetDesc/XVMMCTargetDesc.cpp +++ b/llvm/lib/Target/XVM/MCTargetDesc/XVMMCTargetDesc.cpp @@ -10,6 +10,7 @@ // //===----------------------------------------------------------------------===// #ifdef XVM_DYLIB_MODE + #include "MCTargetDesc/XVMMCTargetDesc.h" #include "MCTargetDesc/XVMInstPrinter.h" #include "MCTargetDesc/XVMMCAsmInfo.h" diff --git a/llvm/lib/Target/XVM/XVMAsmPrinter.cpp b/llvm/lib/Target/XVM/XVMAsmPrinter.cpp index 30a67c159b83af52f842d154dd8dda25b224930f..97333b8e181f7119e1cdb2e4392b087ad4ed498d 100644 --- a/llvm/lib/Target/XVM/XVMAsmPrinter.cpp +++ b/llvm/lib/Target/XVM/XVMAsmPrinter.cpp @@ -17,6 +17,7 @@ #include "XVMInstrInfo.h" #include "XVMTargetMachine.h" #include "XVMMCInstLower.h" +#include "XVMErrorMsg.h" #include "MCTargetDesc/XVMInstPrinter.h" #include "TargetInfo/XVMTargetInfo.h" #include "llvm/Analysis/ConstantFolding.h" @@ -25,6 +26,7 @@ #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstr.h" #include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DiagnosticInfo.h" #include "llvm/MC/MCAsmInfo.h" #include "llvm/MC/MCInst.h" #include "llvm/MC/MCStreamer.h" @@ -38,6 +40,15 @@ using namespace llvm; #define DEBUG_TYPE "asm-printer" +#define CHAT_LEN_IN_HEX 2 +#define REF_TYPE_LENGTH 8 +#define REF_TYPE_HEX_LENGTH 16 +#define NUM_BITS_PER_BYTE 8 +#define MAX_PTR_SIZE 8 +#define MAX_SIZE_CONSTANT_EXPRESSION 8 +#define INIT_SMALL_STR_SIZE 128 +#define NUM_MO_CTOR_DTOR 3 +#define MAX_FUNC_SIZE 32767 static cl::opt XVMExportAll("xvm-export-all", cl::Hidden, cl::init(false), @@ -87,17 +98,18 @@ private: void InitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, const Constant *BaseCV, - uint64_t Offset, XVMSectionInfo* SInfo); + uint64_t Offset, XVMSectionInfo* SInfo, Module *M); void InitGlobalConstantDataSequential(const DataLayout &DL, - const ConstantDataSequential *CDS, XVMSectionInfo* SInfo); + const ConstantDataSequential *CDS, + XVMSectionInfo* SInfo); void InitGlobalConstantArray(const DataLayout &DL, const ConstantArray *CA, const Constant *BaseCV, uint64_t Offset, - XVMSectionInfo* SInfo); + XVMSectionInfo* SInfo, Module *M); void InitGlobalConstantStruct(const DataLayout &DL, const ConstantStruct *CS, const Constant *BaseCV, uint64_t Offset, - XVMSectionInfo* SInfo); + XVMSectionInfo* SInfo, Module *M); }; } // namespace @@ -111,13 +123,12 @@ static std::map DataSectionNameIndexMap; static std::map DataSectionIndexInfoMap; template -inline std::string UnsignedIntTypeToHex(T V, size_t W = sizeof(T)*2) -{ +inline std::string UnsignedIntTypeToHex(T V, size_t W = sizeof(T)*CHAT_LEN_IN_HEX) { std::stringstream SS; std::string RS; SS << std::setfill('0') << std::setw(W) << std::hex << (V|0); - for (unsigned Index=0; Index>= 8; + Input >>= NUM_BITS_PER_BYTE; } return Result; } @@ -143,10 +154,11 @@ static inline uint64_t ReverseBytes(uint64_t Input, unsigned int Width) { #define DATA_SUB_SECTION 1 #define XVM_SD_SEG_START 4 +#define XVM_REF_OFFSET_BITS 44 static uint64_t CreateRefContent(int ToDataSecID, uint64_t ToOffset) { uint64_t seg_index = XVM_SD_SEG_START + ToDataSecID; uint64_t ReTRefData = 0; - ReTRefData = (seg_index & 0x00000000000FFFFF) << 44; + ReTRefData = (seg_index & 0x00000000000FFFFF) << XVM_REF_OFFSET_BITS; ReTRefData = ReTRefData | (ToOffset & 0x00000FFFFFFFFFFF); return ReTRefData; } @@ -318,10 +330,13 @@ static inline void PatchSectionInfo(void) { LLVM_DEBUG(dbgs() << "Add to Buf: " << UnsignedIntTypeToHex(ReverseBytes( CreateRefContent(DataSectionIndex, DataSectionOffset), - 8),8*2).c_str() - << " size=" << 8 << "\n"); - SInfo.SecBuf += UnsignedIntTypeToHex( - ReverseBytes(CreateRefContent(DataSectionIndex, DataSectionOffset), 8), 16); + REF_TYPE_LENGTH), REF_TYPE_HEX_LENGTH).c_str() + << " size=" << REF_TYPE_LENGTH << "\n" + << " DataSectionOffset=" << DataSectionOffset + << " PtrSecIndex=" << SInfo.PtrSecIndex + << " patch loc="<< EachPatch.LocInByte << "\n"); + SInfo.SecBuf.replace(EachPatch.LocInByte, REF_TYPE_LENGTH * 4, UnsignedIntTypeToHex( + ReverseBytes(CreateRefContent(DataSectionIndex, DataSectionOffset), REF_TYPE_LENGTH), REF_TYPE_HEX_LENGTH)); } } } @@ -407,9 +422,10 @@ void XVMAsmPrinter::InitGlobalConstantDataSequential( LLVM_DEBUG(dbgs() << "Add to Buf: " << UnsignedIntTypeToHex(ReverseBytes( CDS->getElementAsInteger(I), - ElementByteSize), ElementByteSize*2).c_str() + ElementByteSize), ElementByteSize*CHAT_LEN_IN_HEX).c_str() << " size=" << ElementByteSize << "\n"); - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(CDS->getElementAsInteger(I), ElementByteSize), ElementByteSize*2); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(CDS->getElementAsInteger(I), ElementByteSize), + ElementByteSize*CHAT_LEN_IN_HEX); } } else { llvm_unreachable("Should not have FP in sequential data"); @@ -421,25 +437,25 @@ void XVMAsmPrinter::InitGlobalConstantDataSequential( if (unsigned Padding = Size - EmittedSize) { LLVM_DEBUG(dbgs() << "\n------------Seq PADSIZE----------- " << Padding << "\n"); LLVM_DEBUG(dbgs() << "Add to Buf: " - << UnsignedIntTypeToHex(ReverseBytes(0, Padding), Padding*2).c_str() + << UnsignedIntTypeToHex(ReverseBytes(0, Padding), Padding*CHAT_LEN_IN_HEX).c_str() << " size=" << Padding << "\n"); - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, Padding), Padding*2); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, Padding), Padding*CHAT_LEN_IN_HEX); } } void XVMAsmPrinter::InitGlobalConstantArray(const DataLayout &DL, const ConstantArray *CA, const Constant *BaseCV, uint64_t Offset, - XVMSectionInfo* SInfo) { + XVMSectionInfo* SInfo, Module *M) { LLVM_DEBUG(dbgs() << "\n--------------------InitGlobalConstantArray-------------------\n"); for (unsigned I = 0, E = CA->getNumOperands(); I != E; ++I) { - InitGlobalConstantImpl(DL, CA->getOperand(I), BaseCV, Offset, SInfo); - Offset += DL.getTypeAllocSize(CA->getOperand(I)->getType()); + InitGlobalConstantImpl(DL, CA->getOperand(I), BaseCV, Offset, SInfo, M); + Offset += DL.getTypeAllocSize(CA->getOperand(I)->getType()); } } void XVMAsmPrinter::InitGlobalConstantStruct(const DataLayout &DL, const ConstantStruct *CS, const Constant *BaseCV, uint64_t Offset, - XVMSectionInfo* SInfo) { + XVMSectionInfo* SInfo, Module *M) { LLVM_DEBUG(dbgs() << "\n--------------------InitGlobalConstantStruct-------------------\n"); unsigned Size = DL.getTypeAllocSize(CS->getType()); const StructLayout *Layout = DL.getStructLayout(CS->getType()); @@ -448,7 +464,7 @@ void XVMAsmPrinter::InitGlobalConstantStruct(const DataLayout &DL, const Constan const Constant *Field = CS->getOperand(I); // Print the actual field value. - InitGlobalConstantImpl(DL, Field, BaseCV, Offset + SizeSoFar, SInfo); + InitGlobalConstantImpl(DL, Field, BaseCV, Offset + SizeSoFar, SInfo, M); // Check if padding is needed and insert one or more 0s. uint64_t FieldSize = DL.getTypeAllocSize(Field->getType()); @@ -461,9 +477,9 @@ void XVMAsmPrinter::InitGlobalConstantStruct(const DataLayout &DL, const Constan if (PadSize > 0) { LLVM_DEBUG(dbgs() << "\n------------Struct PADSIZE-----------" << PadSize << "\n"); LLVM_DEBUG(dbgs() << "Add to Buf: " - << UnsignedIntTypeToHex(ReverseBytes(0, PadSize), PadSize*2).c_str() + << UnsignedIntTypeToHex(ReverseBytes(0, PadSize), PadSize*CHAT_LEN_IN_HEX).c_str() << " size=" << PadSize << "\n"); - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, PadSize), PadSize*2); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, PadSize), PadSize*CHAT_LEN_IN_HEX); } SizeSoFar += FieldSize + PadSize; } @@ -474,7 +490,7 @@ void XVMAsmPrinter::InitGlobalConstantStruct(const DataLayout &DL, const Constan void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant *CV, const Constant *BaseCV, uint64_t Offset, - XVMSectionInfo* SInfo) { + XVMSectionInfo* SInfo, Module *M) { LLVM_DEBUG(dbgs() << "\n--------------------InitGlobalConstantImpl " << CV->getName().str().c_str() << "-------------------\n"); @@ -489,6 +505,7 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant if (isa(CV) || isa(CV)) { if (SInfo->BufType == XVM_SECTION_DATA_TYPE_UNKNOWN) { SInfo->BufType = XVM_SECTION_DATA_TYPE_BSS; + SInfo->SecSize = Size; LLVM_DEBUG(dbgs() << "\nemit in InitGlobalConstantImpl bss " << Size << " " << DL.getTypeStoreSize(CV->getType()) << " " @@ -500,23 +517,36 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant << DL.getTypeStoreSize(CV->getType()) << " " << DL.getTypeAllocSize(CV->getType()).getFixedSize() << "\n"); LLVM_DEBUG(dbgs() << "Add to Buf: " - << UnsignedIntTypeToHex(ReverseBytes(0, Size), Size*2).c_str() + << UnsignedIntTypeToHex(ReverseBytes(0, Size), Size*CHAT_LEN_IN_HEX).c_str() << " size=" << Size << "\n"); - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, Size), Size*2); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, Size), Size*CHAT_LEN_IN_HEX); return; } if (const ConstantInt *CI = dyn_cast(CV)) { const uint64_t StoreSize = DL.getTypeStoreSize(CV->getType()); - if (StoreSize <= 8) { + if (StoreSize <= MAX_PTR_SIZE) { SInfo->BufType = SInfo->BufType | XVM_SECTION_DATA_TYPE_NUMERIC; LLVM_DEBUG(dbgs() << "\nemit in InitGlobalConstantImpl int\n"); LLVM_DEBUG(dbgs() << "Add to Buf: " - << UnsignedIntTypeToHex(ReverseBytes(CI->getZExtValue(), StoreSize), StoreSize*2).c_str() + << UnsignedIntTypeToHex(ReverseBytes(CI->getZExtValue(), StoreSize), + StoreSize*CHAT_LEN_IN_HEX).c_str() << " size=" << StoreSize << "\n"); - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(CI->getZExtValue(), StoreSize), StoreSize*2); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(CI->getZExtValue(), StoreSize), StoreSize*CHAT_LEN_IN_HEX); } else { - llvm_unreachable("Should not have large int global value!"); + for (Function &F1 : M->getFunctionList()) { + for (BasicBlock &BB : F1) { + for (Instruction &I : BB) { + DebugLoc DL = I.getDebugLoc(); + ExportFailMsg(F1, DL, "Error: Large int globals are unsupported", (void*)&StoreSize); + LLVM_DEBUG(dbgs() << "XVM Error: Should not have large int global value!"); + exit(1); + break; + } + break; + } + break; + } } return; } @@ -528,7 +558,7 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant SInfo->BufType = SInfo->BufType | XVM_SECTION_DATA_TYPE_POINTER; LLVM_DEBUG(dbgs() << "\nemit in InitGlobalConstantImpl nullptr\n"); LLVM_DEBUG(dbgs() << "Add to Buf: \\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00" - << " size=" << 8 << "\n"); + << " size=" << MAX_PTR_SIZE << "\n"); SInfo->SecBuf += "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"; return; } @@ -536,25 +566,25 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant if (const ConstantDataSequential *CDS = dyn_cast(CV)) { SInfo->BufType = SInfo->BufType | XVM_SECTION_DATA_TYPE_STRING; return InitGlobalConstantDataSequential(DL, CDS, SInfo); - } + } if (const ConstantArray *CVA = dyn_cast(CV)) { SInfo->BufType = SInfo->BufType | XVM_SECTION_DATA_TYPE_ARRAY; - return InitGlobalConstantArray(DL, CVA, BaseCV, Offset, SInfo); + return InitGlobalConstantArray(DL, CVA, BaseCV, Offset, SInfo, M); } if (const ConstantStruct *CVS = dyn_cast(CV)) { SInfo->BufType = SInfo->BufType | XVM_SECTION_DATA_TYPE_STRUCT; - return InitGlobalConstantStruct(DL, CVS, BaseCV, Offset, SInfo); + return InitGlobalConstantStruct(DL, CVS, BaseCV, Offset, SInfo, M); } if (const ConstantExpr *CE = dyn_cast(CV)) { // Look through bitcasts, which might not be able to be MCExpr'ized (e.g. of // vectors). if (CE->getOpcode() == Instruction::BitCast) - return InitGlobalConstantImpl(DL, CE->getOperand(0), BaseCV, Offset, SInfo); + return InitGlobalConstantImpl(DL, CE->getOperand(0), BaseCV, Offset, SInfo, M); - if (Size > 8) { + if (Size > MAX_SIZE_CONSTANT_EXPRESSION) { // If the constant expression's size is greater than 64-bits, then we have // to emit the value in chunks. Try to constant fold the value and emit it // that way. @@ -565,16 +595,16 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant } if (const ConstantVector *V = dyn_cast(CV)) - llvm_unreachable("Should not have vector global value!"); + llvm_unreachable("Should not have vector global value!"); LLVM_DEBUG(dbgs() << "\nemit in InitGlobalConstantImpl ptr\n"); - int idx_func = GetFuncIndex(CV->getName().data()); + int idx_func = GetFuncIndex(CV->getName().data()); if (idx_func != -1) { SInfo->BufType = SInfo->BufType | XVM_SECTION_DATA_TYPE_POINTER; - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(idx_func, 8), 16); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(idx_func, REF_TYPE_LENGTH), REF_TYPE_HEX_LENGTH); LLVM_DEBUG(dbgs() << "\nsuccess in function pointer " - << UnsignedIntTypeToHex(ReverseBytes(idx_func, 8), 16).c_str() + << UnsignedIntTypeToHex(ReverseBytes(idx_func, REF_TYPE_LENGTH), REF_TYPE_HEX_LENGTH).c_str() << "\n"); return; } @@ -588,6 +618,8 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant PatchInfo.SymName = CV->getName().data(); PatchInfo.AddEnd = 0; + PatchInfo.LocInByte = SInfo->SecBuf.length(); + SInfo->SecBuf += "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"; SInfo->PatchListInfo.push_back(PatchInfo); return; } @@ -615,9 +647,12 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant PatchInfo.SymName = SymName; PatchInfo.AddEnd = (int)CE->getValue(); - if (DataSectionIndex != -1) { - SInfo->BufType = XVM_SECTION_DATA_TYPE_POINTER; - } + // Please note that if the variable is defined after, then + // no DataSectionIndex + SInfo->BufType = XVM_SECTION_DATA_TYPE_POINTER; + PatchInfo.LocInByte = SInfo->SecBuf.length(); + SInfo->SecBuf += "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"; + SInfo->PatchListInfo.push_back(PatchInfo); } else { SRE = dyn_cast(ME); @@ -629,17 +664,23 @@ void XVMAsmPrinter::InitGlobalConstantImpl(const DataLayout &DL, const Constant const auto &ConstA = cast(ME); const ConstantExpr *CExprA = dyn_cast(CV); assert(CExprA->getOpcode() == Instruction::IntToPtr); + PatchInfo.LocInByte = SInfo->SecBuf.length(); LLVM_DEBUG(dbgs() << "Add to Buf: " - << UnsignedIntTypeToHex(ReverseBytes(ConstA->getValue(), 8), 8*2).c_str() - << " size=" << 8 << "\n"); - SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(ConstA->getValue(), 8), 8*2); + << UnsignedIntTypeToHex(ReverseBytes(ConstA->getValue(), REF_TYPE_LENGTH), + REF_TYPE_HEX_LENGTH).c_str() + << " size=" << MAX_PTR_SIZE << "\n"); + SInfo->SecBuf += UnsignedIntTypeToHex(ReverseBytes(ConstA->getValue(), REF_TYPE_LENGTH), REF_TYPE_HEX_LENGTH); return; + } else if (ME->getKind() == llvm::MCExpr::SymbolRef) { + SInfo->BufType = XVM_SECTION_DATA_TYPE_POINTER; + PatchInfo.LocInByte = SInfo->SecBuf.length(); + SInfo->SecBuf += "\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00"; } rso << *ME; PatchInfo.SymName = StrME.data(); PatchInfo.AddEnd = 0; + SInfo->PatchListInfo.push_back(PatchInfo); } - SInfo->PatchListInfo.push_back(PatchInfo); return; } llvm_unreachable("unhandled global type!!"); @@ -677,13 +718,16 @@ void XVMAsmPrinter::InitDataSectionGlobalConstant(Module *M) { SInfo.SecBuf = ""; SInfo.SecComment = GV.getName().data(); SInfo.SymName = GV.getName().data(); - InitGlobalConstantImpl(DL, CV, nullptr, 0, &SInfo); + InitGlobalConstantImpl(DL, CV, nullptr, 0, &SInfo, M); } - LLVM_DEBUG(dbgs() << "buf is " - << SInfo.SecBuf.c_str() - << " size is " << Size << "\n"); + LLVM_DEBUG(dbgs() << "buf size is " << Size << " buf=" + << SInfo.SecBuf.c_str() << "\n"); // ser permission if (GV.isConstant()) { + if (SInfo.BufType == XVM_SECTION_DATA_TYPE_BSS) { + // zero init for constant should be in the ro with init + SInfo.SecBuf += UnsignedIntTypeToHex(ReverseBytes(0, SInfo.SecSize), SInfo.SecSize*2); + } SInfo.Permission = XVM_SECTION_PERM_RO; SInfo.SecName = "rodata"; } else { @@ -839,7 +883,7 @@ void XVMAsmPrinter::setFunctionCallInfo(MCInst *Inst) { void XVMAsmPrinter::setGlobalSymbolInfo(const MachineInstr *MI, MCInst* Inst) { unsigned int numOps = MI->getNumOperands(); bool hasGlobalSymbol = false; - for (unsigned int i=0; igetOperand(i); if (tmp.isGlobal()) { @@ -872,8 +916,10 @@ void XVMAsmPrinter::setGlobalSymbolInfo(const MachineInstr *MI, MCInst* Inst) { SymName = GetSymbolName(SymName); SymIndex = GetDataIndex(SymName.c_str(), DATA_SECTION); if (SymIndex == -1) { - report_fatal_error( - "Note: Add the support of non-func-global-var scenarios\n"); + const MachineFunction *F = MI->getParent()->getParent(); + ExportFailMsg(F->getFunction(), MI->getDebugLoc(), "Error: Externs aren't supported", NULL); + LLVM_DEBUG(dbgs() << "XVM TODO: Add the support of non-func-global-var scenarios\n"); + exit(1); } else { Inst->setFlags(GLOBAL_DATAREF_FLAG_MC_INST); MCOperand MCOp = MCOperand::createImm(SymIndex); @@ -902,7 +948,7 @@ void XVMAsmPrinter::emitInstruction(const MachineInstr *MI) { void XVMAsmPrinter::emitFunctionHeader() { const Function &F = MF->getFunction(); - SmallString<128> Str; + SmallString Str; raw_svector_ostream O(Str); int Index = GetDefFuncIndex(F.getName().data()); assert(Index != -1); @@ -938,14 +984,17 @@ void XVMAsmPrinter::emitFunctionReturnVal(const Function &F, raw_ostream &O) { } else if (Ty->isIntegerTy()) { O << " i64"; } else if (!Ty->isVoidTy()) { - llvm_unreachable("Invalid return type"); + DebugLoc DL; + ExportFailMsg(F, DL, "Invalid return type", NULL); + LLVM_DEBUG(dbgs() << "XVM Error: Invalid return type"); + exit(1); } O << ")"; } void XVMAsmPrinter::emitFunctionBodyEnd() { - SmallString<128> Str; + SmallString Str; raw_svector_ostream O(Str); O << "\t)"; if (MF->getFunction().hasFnAttribute("xvm-export-name")) @@ -972,7 +1021,10 @@ void XVMAsmPrinter::emitFunctionParamList(const Function &F, raw_ostream &O) { } else if (Ty->isIntegerTy()) { O << " i64"; } else { - llvm_unreachable("Invalid param type"); + DebugLoc DL; + ExportFailMsg(F, DL, "Invalid (non ref or interger) param type", NULL); + LLVM_DEBUG(dbgs() << "XVM Error: Invalid param type"); + exit(1); } } @@ -982,7 +1034,7 @@ void XVMAsmPrinter::emitFunctionParamList(const Function &F, raw_ostream &O) { void XVMAsmPrinter::emitStartOfAsmFile(Module &M) { InitModuleMapFuncnameIndex(&M); InitDataSectionGlobalConstant(&M); - SmallString<128> Str1; + SmallString Str1; raw_svector_ostream O(Str1); O << "(module"; @@ -1028,7 +1080,7 @@ static void emitConstructorsDestructors(raw_svector_ostream &O, Module &M, return; } StructType *ETy = dyn_cast(InitList->getType()->getElementType()); - if (!ETy || ETy->getNumElements() != 3 || + if (!ETy || ETy->getNumElements() != NUM_MO_CTOR_DTOR || !ETy->getTypeAtIndex(0U)->isIntegerTy() || !ETy->getTypeAtIndex(1U)->isPointerTy() || !ETy->getTypeAtIndex(2U)->isPointerTy()) { @@ -1059,7 +1111,7 @@ static void emitMetaDataSectionInfo(raw_svector_ostream &O, Module &M) { } void XVMAsmPrinter::emitEndOfAsmFile(Module &M) { - SmallString<128> Str1; + SmallString Str1; raw_svector_ostream O(Str1); emitDecls(M); emitDataSectionInfo(O); @@ -1069,7 +1121,7 @@ void XVMAsmPrinter::emitEndOfAsmFile(Module &M) { } void XVMAsmPrinter::emitDecls(const Module &M) { - SmallString<128> Str1; + SmallString Str1; raw_svector_ostream O(Str1); for (const Function &F : M.getFunctionList()) { if (GetDefFuncIndex(F.getName().data()) == -1 && @@ -1121,12 +1173,35 @@ void XVMAsmPrinter::GetMIIndent(MachineFunction &MF) { assert (CurrentIndent == 0 && "All the indents should be paired!"); } +static void checkFunctionSize(MachineFunction &MF) { + int count = 0; + + for (auto &MBB : MF) { + for (auto &MI : MBB) { + count++; + } + } + + if (count > MAX_FUNC_SIZE) { + DebugLoc DL; + Function &F = MF.getFunction(); + std::string ErrorMesg("Error: Function '"); + ErrorMesg += MF.getName().str().c_str(); + ErrorMesg += "' has "; + ErrorMesg += std::to_string(count); + ErrorMesg += " instructions. Max instructions is 32767.\n"; + ExportFailMsg(F, DL, ErrorMesg.data(), NULL); + exit(1); + } +} + void XVMAsmPrinter::emitGlobalVariable(const GlobalVariable *GV) {} bool XVMAsmPrinter::runOnMachineFunction(MachineFunction &MF) { SetupMachineFunction(MF); GetMIIndent(MF); emitFunctionBody(); + checkFunctionSize(MF); return false; } diff --git a/llvm/lib/Target/XVM/XVMCFGSort.cpp b/llvm/lib/Target/XVM/XVMCFGSort.cpp index d8e5d803d4e0196c1a77abacf0c09be0789cb1d1..905277d5f8a8978c62a0fc6bafbef0877e638cfc 100644 --- a/llvm/lib/Target/XVM/XVMCFGSort.cpp +++ b/llvm/lib/Target/XVM/XVMCFGSort.cpp @@ -19,35 +19,33 @@ #include "MCTargetDesc/XVMMCTargetDesc.h" #include "XVM.h" +#include "llvm/CodeGen/MachineLoopInfo.h" #include "XVMSortRegion.h" +#include "llvm/CodeGen/MachineDominators.h" #include "XVMSubtarget.h" #include "llvm/ADT/PriorityQueue.h" -#include "llvm/ADT/SetVector.h" -#include "llvm/CodeGen/MachineDominators.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineLoopInfo.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/raw_ostream.h" + +#define DEBUG_TYPE "xvm-cfg-sort" +#define INIT_SMALL_VECTOR_PREDS_SIZE 16 +#define INIT_SMALL_VECTOR_ENTRIES_SIZE 4 + using namespace llvm; using XVM::SortRegion; using XVM::SortRegionInfo; -#define DEBUG_TYPE "xvm-cfg-sort" - namespace { class XVMCFGSort final : public MachineFunctionPass { StringRef getPassName() const override { return "XVM CFG Sort"; } - void getAnalysisUsage(AnalysisUsage &AU) const override { - AU.setPreservesCFG(); - AU.addRequired(); - AU.addPreserved(); - AU.addRequired(); - AU.addPreserved(); - MachineFunctionPass::getAnalysisUsage(AU); + void getAnalysisUsage(AnalysisUsage &AUsage) const override + { + AUsage.setPreservesCFG(); + AUsage.addRequired(); + AUsage.addPreserved(); + AUsage.addRequired(); + AUsage.addPreserved(); + MachineFunctionPass::getAnalysisUsage(AUsage); } bool runOnMachineFunction(MachineFunction &MF) override; @@ -66,231 +64,220 @@ FunctionPass *llvm::createXVMCFGSort() { return new XVMCFGSort(); } -static void maybeUpdateTerminator(MachineBasicBlock *MBB) { +static void maybeUpdateTerminator(MachineBasicBlock *MBBlock) { #ifndef NDEBUG - bool AnyBarrier = false; + bool Barrier = false; #endif - bool AllAnalyzable = true; - for (const MachineInstr &Term : MBB->terminators()) { + bool Analyzable = true; + for (const MachineInstr &TermIter : MBBlock->terminators()) { #ifndef NDEBUG - AnyBarrier |= Term.isBarrier(); + Barrier |= TermIter.isBarrier(); #endif - AllAnalyzable &= Term.isBranch() && !Term.isIndirectBranch(); + Analyzable &= TermIter.isBranch() && !TermIter.isIndirectBranch(); } - assert((AnyBarrier || AllAnalyzable) && - "analyzeBranch needs to analyze any block with a fallthrough"); + assert((Barrier || Analyzable) && "all fallthrough blocks are processed by analyzeBranch"); - // Find the layout successor from the original block order. - MachineFunction *MF = MBB->getParent(); - MachineBasicBlock *OriginalSuccessor = - unsigned(MBB->getNumber() + 1) < MF->getNumBlockIDs() - ? MF->getBlockNumbered(MBB->getNumber() + 1) - : nullptr; + // Using the original block order find the layotu successor + MachineFunction *MFunction = MBBlock->getParent(); + MachineBasicBlock *OriginalNext = + unsigned(MBBlock->getNumber() + 1) < MFunction->getNumBlockIDs() + ? MFunction->getBlockNumbered(MBBlock->getNumber() + 1) : nullptr; - if (AllAnalyzable) - MBB->updateTerminator(OriginalSuccessor); + if (Analyzable) + MBBlock->updateTerminator(OriginalNext); } -namespace { -/// Sort blocks by their number. -struct CompareBlockNumbers { - bool operator()(const MachineBasicBlock *A, - const MachineBasicBlock *B) const { - return A->getNumber() > B->getNumber(); +/// Reverse Block sorting based on their number. +struct CompareBlockNumbersBackwards { + bool operator()(const MachineBasicBlock *First, + const MachineBasicBlock *Second) const { + return First->getNumber() < Second->getNumber(); } }; -/// Sort blocks by their number in the opposite order.. -struct CompareBlockNumbersBackwards { - bool operator()(const MachineBasicBlock *A, - const MachineBasicBlock *B) const { - return A->getNumber() < B->getNumber(); + +namespace { +/// Block sorting based on their number. +struct CompareBlockNumbers { + bool operator()(const MachineBasicBlock *First, + const MachineBasicBlock *Second) const { + return First->getNumber() > Second->getNumber(); } }; -/// Bookkeeping for a region to help ensure that we don't mix blocks not -/// dominated by the its header among its blocks. + +// So we don't mix blocks not dominated by its header +// amond its blocks we use bookkeeping struct Entry { - const SortRegion *TheRegion; - unsigned NumBlocksLeft; + const SortRegion *Region; + unsigned BlocksLeftCount; - /// List of blocks not dominated by Loop's header that are deferred until - /// after all of Loop's blocks have been seen. - std::vector Deferred; + // A List of blocks not dominated by Loop's header that + // are deferred until after all of the Loop's blocks have been seen. + std::vector Def; - explicit Entry(const SortRegion *R) - : TheRegion(R), NumBlocksLeft(R->getNumBlocks()) {} + explicit Entry(const SortRegion *SR) : Region(SR), BlocksLeftCount(SR->getNumBlocks()) {} }; -} // end anonymous namespace +} // anonymous namespace end -/// Sort the blocks, taking special care to make sure that regions are not -/// interrupted by blocks not dominated by their header. +// Making sure that regions are not inerrupted by blocks not +// dominated by their header sort the blocks /// Note: There are many opportunities for improving the heuristics here. /// Explore them. -static void sortBlocks(MachineFunction &MF, const MachineLoopInfo &MLI, - const MachineDominatorTree &MDT) { - // Remember original layout ordering, so we can update terminators after - // reordering to point to the original layout successor. - MF.RenumberBlocks(); +static void sortBlocks(MachineFunction &MFunction, const MachineLoopInfo &MLInfo, + const MachineDominatorTree &MDTree) { + // So we can update terminators after reordering to point to the + // original layout successor, remember original layout + MFunction.RenumberBlocks(); - // Prepare for a topological sort: Record the number of predecessors each - // block has, ignoring loop backedges. - SmallVector NumPredsLeft(MF.getNumBlockIDs(), 0); - for (MachineBasicBlock &MBB : MF) { - unsigned N = MBB.pred_size(); - if (MachineLoop *L = MLI.getLoopFor(&MBB)) - if (L->getHeader() == &MBB) - for (const MachineBasicBlock *Pred : MBB.predecessors()) - if (L->contains(Pred)) - --N; - NumPredsLeft[MBB.getNumber()] = N; + // Record the number of predecessors each block has, ignoring loop backedges, + // to prepare for a topological sort + SmallVector NumPredsLeft(MFunction.getNumBlockIDs(), 0); + for (MachineBasicBlock &MBBlock : MFunction) { + unsigned Size = MBBlock.pred_size(); + if (MachineLoop *Loop = MLInfo.getLoopFor(&MBBlock)) + if (Loop->getHeader() == &MBBlock) + for (const MachineBasicBlock *Prev : MBBlock.predecessors()) + if (Loop->contains(Prev)) + --Size; + NumPredsLeft[MBBlock.getNumber()] = Size; } + // Topological sort, but between a region header and the last block in + // the region, there can be no block not dominated by its header. + // AS well its desirable to preserve the original block order of possible + // Perfer has revenetly processed successors to help keep block order + // BlockReady has the remaining blocks + PriorityQueue, CompareBlockNumbers> + Prefer; + PriorityQueue, CompareBlockNumbersBackwards> + BlockReady; - // Topological sort the CFG, with additional constraints: - // - Between a region header and the last block in the region, there can be - // no blocks not dominated by its header. - // - It's desirable to preserve the original block order when possible. - // We use two ready lists; Preferred and Ready. Preferred has recently - // processed successors, to help preserve block sequences from the original - // order. Ready has the remaining ready blocks. - PriorityQueue, - CompareBlockNumbers> - Preferred; - PriorityQueue, - CompareBlockNumbersBackwards> - Ready; - - SortRegionInfo SRI(MLI); - SmallVector Entries; - for (MachineBasicBlock *MBB = &MF.front();;) { - const SortRegion *R = SRI.getRegionFor(MBB); - if (R) { - // If MBB is a region header, add it to the active region list. We can't - // put any blocks that it doesn't dominate until we see the end of the - // region. - if (R->getHeader() == MBB) - Entries.push_back(Entry(R)); - // For each active region the block is in, decrement the count. If MBB is - // the last block in an active region, take it off the list and pick up - // any blocks deferred because the header didn't dominate them. - for (Entry &E : Entries) - if (E.TheRegion->contains(MBB) && --E.NumBlocksLeft == 0) - for (auto DeferredBlock : E.Deferred) - Ready.push(DeferredBlock); - while (!Entries.empty() && Entries.back().NumBlocksLeft == 0) - Entries.pop_back(); + SortRegionInfo SRI(MLInfo); + SmallVector SEntries; + for (MachineBasicBlock *MBBlock = &MFunction.front();;) { + const SortRegion *SR = SRI.getRegionFor(MBBlock); + if (SR) { + // Can't put any blocks that it doesnt dominate until we see the end + // of the region if MBBlock is a header + if (SR->getHeader() == MBBlock) + SEntries.push_back(Entry(SR)); + // Decrement the count for each active region the block is a part of + // Take any MBBlock that is the last block in an active region off the list + // picking up any blocks deferred, since the header didnt dominate them. + for (Entry &Ent : SEntries) + if (Ent.Region->contains(MBBlock) && --Ent.BlocksLeftCount == 0) + for (auto DBlock : Ent.Def) + BlockReady.push(DBlock); + while (!SEntries.empty() && SEntries.back().BlocksLeftCount == 0) + SEntries.pop_back(); } - // The main topological sort logic. - for (MachineBasicBlock *Succ : MBB->successors()) { - // Ignore backedges. - if (MachineLoop *SuccL = MLI.getLoopFor(Succ)) - if (SuccL->getHeader() == Succ && SuccL->contains(MBB)) + for (MachineBasicBlock *Next : MBBlock->successors()) { // Topological sort logic. + if (MachineLoop *NextL = MLInfo.getLoopFor(Next)) // Backedges can be ignored. + if (NextL->getHeader() == Next && NextL->contains(MBBlock)) continue; - // Decrement the predecessor count. If it's now zero, it's ready. - if (--NumPredsLeft[Succ->getNumber()] == 0) { - // When we are in a SortRegion, we allow sorting of not only BBs that - // belong to the current (innermost) region but also BBs that are - // dominated by the current region header. - Preferred.push(Succ); + // Decrement how many are left. It's ready if its now 0. + if (--NumPredsLeft[Next->getNumber()] == 0) { + // We allow soritng of BBs that belong to the current region, and also + // BB's that are dominated bu the current region, when we are in a SortRegion + Prefer.push(Next); } } - // Determine the block to follow MBB. First try to find a preferred block, - // to preserve the original block order when possible. - MachineBasicBlock *Next = nullptr; - while (!Preferred.empty()) { - Next = Preferred.top(); - Preferred.pop(); - // If X isn't dominated by the top active region header, defer it until - // that region is done. - if (!Entries.empty() && - !MDT.dominates(Entries.back().TheRegion->getHeader(), Next)) { - Entries.back().Deferred.push_back(Next); - Next = nullptr; + // To find the block to follow MBBlock, try to find a preferred block to + // save the orinal block order if permitted + MachineBasicBlock *Successor = nullptr; + while (!Prefer.empty()) { + Successor = Prefer.top(); + Prefer.pop(); + // until the region is done, keep defering X until it is dominated + // by the top active region + if (!SEntries.empty() && + !MDTree.dominates(SEntries.back().Region->getHeader(), Successor)) { + SEntries.back().Def.push_back(Successor); + Successor = nullptr; continue; } - // If Next was originally ordered before MBB, and it isn't because it was - // loop-rotated above the header, it's not preferred. - if (Next->getNumber() < MBB->getNumber() && - (!R || !R->contains(Next) || - R->getHeader()->getNumber() < Next->getNumber())) { - Ready.push(Next); - Next = nullptr; + // Succcessor is not preferred ig it was originally ordered before MBBlock + // and that wasnt caused by it being loop-rotated above the header + if (Successor->getNumber() < MBBlock->getNumber() && + (!SR || !SR->contains(Successor) || + SR->getHeader()->getNumber() < Successor->getNumber())) { + BlockReady.push(Successor); + Successor = nullptr; continue; } break; } - // If we didn't find a suitable block in the Preferred list, check the - // general Ready list. - if (!Next) { - // If there are no more blocks to process, we're done. - if (Ready.empty()) { - maybeUpdateTerminator(MBB); + // Check the general Ready list, if we did't find suitable block in + // in the prefer list + if (!Successor) { + // We are done if ther are no more blocks to process + if (BlockReady.empty()) { + maybeUpdateTerminator(MBBlock); break; } for (;;) { - Next = Ready.top(); - Ready.pop(); - // If Next isn't dominated by the top active region header, defer it - // until that region is done. - if (!Entries.empty() && - !MDT.dominates(Entries.back().TheRegion->getHeader(), Next)) { - Entries.back().Deferred.push_back(Next); + Successor = BlockReady.top(); + BlockReady.pop(); + // Unitl the region is done, keep defering Successor if it + // isnt dominated by the top active region header + if (!SEntries.empty() && + !MDTree.dominates(SEntries.back().Region->getHeader(), Successor)) { + SEntries.back().Def.push_back(Successor); continue; } break; } } - // Move the next block into place and iterate. - Next->moveAfter(MBB); - maybeUpdateTerminator(MBB); - MBB = Next; + // Iterate and move the Successor block into place. + Successor->moveAfter(MBBlock); + maybeUpdateTerminator(MBBlock); + MBBlock = Successor; } - assert(Entries.empty() && "Active sort region list not finished"); - MF.RenumberBlocks(); + assert(SEntries.empty() && "Have to finish Active sort region"); + MFunction.RenumberBlocks(); #ifndef NDEBUG - SmallSetVector OnStack; + SmallSetVector OnS; - // Insert a sentinel representing the degenerate loop that starts at the - // function entry block and includes the entire function as a "loop" that - // executes once. - OnStack.insert(nullptr); + // Representing the degenerate loop that starts at the function entry, + // and includes the entire function as a loop that executes one, + // insert a sentinel + OnS.insert(nullptr); - for (auto &MBB : MF) { - assert(MBB.getNumber() >= 0 && "Renumbered blocks should be non-negative."); - const SortRegion *Region = SRI.getRegionFor(&MBB); + for (auto &MBBlock : MFunction) { + assert(MBBlock.getNumber() >= 0 && "Renumbered block is not non-negative."); + const SortRegion *SRegion = SRI.getRegionFor(&MBBlock); - if (Region && &MBB == Region->getHeader()) { - // Region header. - if (Region->isLoop()) { - // Loop header. The loop predecessor should be sorted above, and the - // other predecessors should be backedges below. - for (auto Pred : MBB.predecessors()) + if (SRegion && &MBBlock == SRegion->getHeader()) { // Region header. + if (SRegion->isLoop()) { + // Loop header, one predecossor should be backedges bellow, + // and the other should have been processed above + for (auto Prev : MBBlock.predecessors()) assert( - (Pred->getNumber() < MBB.getNumber() || Region->contains(Pred)) && - "Loop header predecessors must be loop predecessors or " - "backedges"); + (Prev->getNumber() < MBBlock.getNumber() || SRegion->contains(Prev)) && + "Loop header predecessors have to be loop backedges or " + "predecessors"); } else { - // Exception header. All predecessors should be sorted above. - for (auto Pred : MBB.predecessors()) - assert(Pred->getNumber() < MBB.getNumber() && - "Non-loop-header predecessors should be topologically sorted"); + // All predecessors should have all been sorted above. Exception header. + for (auto Prev : MBBlock.predecessors()) + assert(Prev->getNumber() < MBBlock.getNumber() && + "Non-loop-header predecessors have to be topologically sorted"); } - assert(OnStack.insert(Region) && - "Regions should be declared at most once."); + assert(OnS.insert(SRegion) && + "Can't declare regions more than once."); } else { - // Not a region header. All predecessors should be sorted above. - for (auto Pred : MBB.predecessors()) - assert(Pred->getNumber() < MBB.getNumber() && - "Non-loop-header predecessors should be topologically sorted"); - assert(OnStack.count(SRI.getRegionFor(&MBB)) && - "Blocks must be nested in their regions"); + // Predecessors should have all beeen sorted above. Not region header. + for (auto Prev : MBBlock.predecessors()) + assert(Prev->getNumber() < MBBlock.getNumber() && + "Non-loop-header predecessors are not topologically sorted"); + assert(OnS.count(SRI.getRegionFor(&MBBlock)) && + "Blocks are not nested in their regions"); } - while (OnStack.size() > 1 && &MBB == SRI.getBottom(OnStack.back())) - OnStack.pop_back(); + while (OnS.size() > 1 && &MBBlock == SRI.getBottom(OnS.back())) + OnS.pop_back(); } - assert(OnStack.pop_back_val() == nullptr && - "The function entry block shouldn't actually be a region header"); - assert(OnStack.empty() && - "Control flow stack pushes and pops should be balanced."); + assert(OnS.pop_back_val() == nullptr && + "A region header can't be the function entry block"); + assert(OnS.empty() && + "Control flow stack pops and stack pushes should be balanced."); #endif } @@ -310,4 +297,4 @@ bool XVMCFGSort::runOnMachineFunction(MachineFunction &MF) { return true; } -#endif \ No newline at end of file +#endif diff --git a/llvm/lib/Target/XVM/XVMCFGStackify.cpp b/llvm/lib/Target/XVM/XVMCFGStackify.cpp index 6215156e3947d7dd42ddfa2e7e9866dc3e8cf0d3..f6c8ec17b176a0afa3ed5197ba42ee512ffa1b86 100644 --- a/llvm/lib/Target/XVM/XVMCFGStackify.cpp +++ b/llvm/lib/Target/XVM/XVMCFGStackify.cpp @@ -22,8 +22,8 @@ //===----------------------------------------------------------------------===// #ifdef XVM_DYLIB_MODE - #include "XVM.h" +#include "XVM_def.h" #include "XVMSortRegion.h" #include "XVMSubtarget.h" #include "llvm/ADT/Statistic.h" @@ -37,9 +37,8 @@ using namespace llvm; using XVM::SortRegionInfo; #define DEBUG_TYPE "xvm-cfg-stackify" - -STATISTIC(NumCallUnwindMismatches, "Number of call unwind mismatches found"); -STATISTIC(NumCatchUnwindMismatches, "Number of catch unwind mismatches found"); +#define INIT_SMALL_VECTOR_SCOPESS_SIZE 8 +#define INIT_SMALL_VECTOR_MO_SIZE 4 namespace { class XVMCFGStackify final : public MachineFunctionPass { @@ -57,78 +56,74 @@ class XVMCFGStackify final : public MachineFunctionPass { // For each block whose label represents the end of a scope, record the block // which holds the beginning of the scope. This will allow us to quickly skip // over scoped regions when walking blocks. - SmallVector ScopeTops; - void updateScopeTops(MachineBasicBlock *Begin, MachineBasicBlock *End) { - int EndNo = End->getNumber(); - if (!ScopeTops[EndNo] || ScopeTops[EndNo]->getNumber() > Begin->getNumber()) - ScopeTops[EndNo] = Begin; + SmallVector ScopeTops; + void updateScopeTops(MachineBasicBlock *Start, MachineBasicBlock *Finish) { + int FinishNo = Finish->getNumber(); + if (!ScopeTops[FinishNo] || ScopeTops[FinishNo]->getNumber() > Start->getNumber()) + ScopeTops[FinishNo] = Start; } // Placing markers. - void placeMarkers(MachineFunction &MF); - void placeBlockMarker(MachineBasicBlock &MBB); - void placeLoopMarker(MachineBasicBlock &MBB); + void placeMarkers(MachineFunction &MFunction); + void placeBlockMarker(MachineBasicBlock &MBBlock); + void placeLoopMarker(MachineBasicBlock &MBBlock); const XVMInstrInfo *TII = nullptr; void extendCondStmt(std::map CondBranchsWithDepth, MachineFunction &MF); void insertWithBreak(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI); void insertRetBlock(MachineFunction &MF); void removeInFunctionRet(MachineFunction &MF); + void fillEndLoopMap(MachineFunction &MF); // Wrap-up using EndMarkerInfo = std::pair; - unsigned getBranchDepth(const SmallVectorImpl &Stack, - const std::set *SetEndBlockLoop, - const MachineBasicBlock *MBB); + unsigned getBranchDepth(MachineFunction &MF, + const MachineBasicBlock *MBB, MachineInstr *MI); void rewriteDepthImmediates(MachineFunction &MF); void fixBackEdgesOfLoops(MachineFunction &MF); - void fixEndsAtEndOfFunction(MachineFunction &MF); - void cleanupFunctionData(MachineFunction &MF); + void fixEndsAtEndOfFunction(MachineFunction &MFunction); + void cleanupFunctionData(MachineFunction &MFunction); - // For each BLOCK|LOOP|TRY, the corresponding END_(BLOCK|LOOP|TRY) or DELEGATE - // (in case of TRY). - DenseMap BeginToEnd; - // For each END_(BLOCK|LOOP|TRY) or DELEGATE, the corresponding - // BLOCK|LOOP|TRY. + // The correspinding BLOCK|LOOP|TRY for each END_(BLOCK|LOOP|TRY) DenseMap EndToBegin; + // The corresponding END_(BLOCK|LOOP|TRY) or DELEGATE for each BLOCK|LOOP|TRY + // (in the TRY case). + DenseMap BeginToEnd; // We need an appendix block to place 'end_loop' or 'end_try' marker when the // loop / exception bottom block is the last block in a function - MachineBasicBlock *AppendixBB = nullptr; - MachineBasicBlock *getAppendixBlock(MachineFunction &MF) { - AppendixBB = nullptr; - if (!AppendixBB) { - AppendixBB = MF.CreateMachineBasicBlock(); - // Give it a fake predecessor so that AsmPrinter prints its label. - AppendixBB->addSuccessor(AppendixBB); - MF.push_back(AppendixBB); + MachineBasicBlock *AppendixBBlock = nullptr; + MachineBasicBlock *getAppendixBlock(MachineFunction &MFunction){ + AppendixBBlock = nullptr; + if (!AppendixBBlock) { + AppendixBBlock = MFunction.CreateMachineBasicBlock(); + // For AsmPrinter to prints its label, we give it a fake predecessor + AppendixBBlock->addSuccessor(AppendixBBlock); + MFunction.push_back(AppendixBBlock); } - return AppendixBB; + return AppendixBBlock; } - // Before running rewriteDepthImmediates function, 'delegate' has a BB as its - // destination operand. getFakeCallerBlock() returns a fake BB that will be - // used for the operand when 'delegate' needs to rethrow to the caller. This - // will be rewritten as an immediate value that is the number of block depths - // + 1 in rewriteDepthImmediates, and this fake BB will be removed at the end - // of the pass. - MachineBasicBlock *FakeCallerBB = nullptr; - MachineBasicBlock *getFakeCallerBlock(MachineFunction &MF) { - if (!FakeCallerBB) - FakeCallerBB = MF.CreateMachineBasicBlock(); - return FakeCallerBB; + // "delegate" has a BB as its destincation operand, before running + // rewriteDEpthImmediated. Use a fake BB for the operand when "delegate" + // needs to rethrow to the caller, returned by getFakeCallerBlock. The + // number of block depths + 1 will be rewritten as an immediate value in + // rewriteDepthImmediates, and this fake BB will be removed at the end + MachineBasicBlock *FakeBBlockCaller = nullptr; + MachineBasicBlock *getFakeCallerBlock(MachineFunction &MFunction) { + if (!FakeBBlockCaller) + FakeBBlockCaller = MFunction.CreateMachineBasicBlock(); + return FakeBBlockCaller; } - // Helper functions to register / unregister scope information created by - // marker instructions. - void registerScope(MachineInstr *Begin, MachineInstr *End); - void registerTryScope(MachineInstr *Begin, MachineInstr *End, - MachineBasicBlock *EHPad); - void unregisterScope(MachineInstr *Begin); + //marker instructions created function to register/unregister scope info + void registerScope(MachineInstr *Start, MachineInstr *Finish); + void registerTryScope(MachineInstr *Start, + MachineInstr *Finish, MachineBasicBlock *EHPad); public: - static char ID; // Pass identification, replacement for typeid + static char ID; // typeid replacement, for identification XVMCFGStackify() : MachineFunctionPass(ID) {} ~XVMCFGStackify() override { releaseMemory(); } void releaseMemory() override; @@ -144,66 +139,69 @@ FunctionPass *llvm::createXVMCFGStackify() { return new XVMCFGStackify(); } -/// Test whether Pred has any terminators explicitly branching to MBB, as -/// opposed to falling through. Note that it's possible (eg. in unoptimized -/// code) for a branch instruction to both branch to a block and fallthrough -/// to it, so we check the actual branch operands to see if there are any -/// explicit mentions. -static bool explicitlyBranchesTo(MachineBasicBlock *Pred, - MachineBasicBlock *MBB) { - for (MachineInstr &MI : Pred->terminators()) - for (MachineOperand &MO : MI.explicit_operands()) - if (MO.isMBB() && MO.getMBB() == MBB) - return true; - return false; +// Map for EndLoops to MBB number +// Used for calculating Break Immediates +static std::map EndLoopToMBBnum; +// Map for mapping machine instruction to current header of loop if "continue" is used +static std::map ContinueMap; + +// As opposed to falling through, test whether Pre has any terminators +// explicitly branching to MBB. Note: We check to see if therey are any explicit +// mentions of a branch instruction both branching to and falling through +// to a block through the actual branch operands (e.g. unoptimzed code) +static bool explicitlyBranchesTo(MachineBasicBlock *Pre, MachineBasicBlock *MBBlock) { + bool ret = false; + for (MachineInstr &MInst : Pre->terminators()) + for (MachineOperand &MOp : MInst.explicit_operands()) + if (MOp.isMBB() && MOp.getMBB() == MBBlock) + ret = true; + return ret; } -// Returns an iterator to the earliest position possible within the MBB, -// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet -// contains instructions that should go before the marker, and AfterSet contains -// ones that should go after the marker. In this function, AfterSet is only -// used for validation checking. +// Satisfying the restriction set by Before and After; returns +// an iterator to the earliet position possible withtin the MBBlock +// Before and After hold the instructions that should go +// before and after the set respectivley. In this case After is +// only used for validation checking template -static MachineBasicBlock::iterator -getEarliestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, - const Container &AfterSet) { - auto InsertPos = MBB->end(); - while (InsertPos != MBB->begin()) { - if (BeforeSet.count(&*std::prev(InsertPos))) { -#ifndef NDEBUG - // Validation check - for (auto Pos = InsertPos, E = MBB->begin(); Pos != E; --Pos) - assert(!AfterSet.count(&*std::prev(Pos))); +static MachineBasicBlock::iterator getEarliestInsertPos(MachineBasicBlock *MBBlock, + const Container &Before, + const Container &After) { + auto InsertPosition = MBBlock->end(); + while (InsertPosition != MBBlock->begin()) { + if (Before.count(&*std::prev(InsertPosition))) { +#ifndef NDEBUG // Validation check + for (auto Position = InsertPosition, E = MBBlock->begin(); Position != E; --Position) + assert(!After.count(&*std::prev(Position))); #endif break; } - --InsertPos; + --InsertPosition; } - return InsertPos; + return InsertPosition; } -// Returns an iterator to the latest position possible within the MBB, -// satisfying the restrictions given by BeforeSet and AfterSet. BeforeSet -// contains instructions that should go before the marker, and AfterSet contains -// ones that should go after the marker. In this function, BeforeSet is only -// used for validation checking. +// Satisfying the restriction set by Before and After; returns +// an iterator to the earliet position possible withtin the MBBlock +// Before and After hold the instructions that should go +// before and after the set respectivley. In this case Before is +// only used for validation checking template -static MachineBasicBlock::iterator -getLatestInsertPos(MachineBasicBlock *MBB, const Container &BeforeSet, - const Container &AfterSet) { - auto InsertPos = MBB->begin(); - while (InsertPos != MBB->end()) { - if (AfterSet.count(&*InsertPos)) { -#ifndef NDEBUG - // Validation check - for (auto Pos = InsertPos, E = MBB->end(); Pos != E; ++Pos) - assert(!BeforeSet.count(&*Pos)); +static MachineBasicBlock::iterator getLatestInsertPos(MachineBasicBlock *MBBlock, + const Container &Before, + const Container &After) { + auto InsertPosition = MBBlock->begin(); + while (InsertPosition != MBBlock->end()) { + if (After.count(&*InsertPosition)) { +#ifndef NDEBUG // Validation check + for (auto Position = InsertPosition, E = MBBlock->end(); Position != E; ++Position) + assert(!Before.count(&*Position)); #endif break; } - ++InsertPos; + ++InsertPosition; } - return InsertPos; + return InsertPosition; } void ChangeBranchCondOpc(MachineInstr &MI, const XVMInstrInfo *TII) { @@ -234,6 +232,14 @@ void ChangeBranchCondOpc(MachineInstr &MI, const XVMInstrInfo *TII) { } } +static inline MachineBasicBlock *getNextBlock(MachineBasicBlock &MBB) { + MachineFunction::iterator I = MBB.getIterator(); + MachineFunction::iterator E = MBB.getParent()->end(); + if (++I == E) + return nullptr; + return &*I; +} + void XVMCFGStackify::fixBackEdgesOfLoops(MachineFunction &MF) { TII = MF.getSubtarget().getInstrInfo(); auto &MLI = getAnalysis(); @@ -248,28 +254,79 @@ void XVMCFGStackify::fixBackEdgesOfLoops(MachineFunction &MF) { if (MI.getNumOperands() <=0) { continue; } - if (TII->isUnCondBranch(&MI) && MI.getOperand(0).getMBB() == LoopHeader) { + if (TII->isUnCondBranch(&MI) && MI.getOperand(MO_FIRST).getMBB() == LoopHeader) { if (&MBB != Loop->getBottomBlock()) { BuildMI(MBB, MI, MI.getDebugLoc(), TII->get(XVM::CONTINUE)); + MI.eraseFromParent(); } - MI.eraseFromParent(); break; - } else if (TII->isCondBranch(&MI) && MI.getOperand(0).getMBB() == LoopHeader) { - uint32_t action_opcode = XVM::CONTINUE; - /* Fix Loop Exiting Fallthrough */ - if (&MBB == Loop->getBottomBlock() && &MI == &*(--MBB.end()) && MLI.getLoopFor(MBB.getFallThrough()) != Loop) { - TII->negateCondBranch(&MI); - action_opcode = XVM::BREAK; + } else if (TII->isCondBranch(&MI) && MI.getOperand(MO_FIRST).getMBB() == LoopHeader) { + uint32_t action_opcode = XVM::CONTINUE; + int BreakImmValue = getBranchDepth(MF, MI.getOperand(MO_FIRST).getMBB(), &MI); + /* Fix Loop Exiting Fallthrough */ + if (BreakImmValue > -1 && ContinueMap[&MI] != MI.getOperand(0).getMBB()->getNumber()) { + action_opcode = XVM::BREAK_IMM; + } + + // Check if we need to add a break statement at the end of loop + int LevelBreakAfterLoop = -1; + + // 1. if the last stmt of the BB is a conditional branch statement and + // 2. if the next BB is one of its successor and + // 3. if the first statements of the next BB are END_BLOCK/END_LOOP + // insert a break if the above conditions are true + MachineBasicBlock::reverse_iterator MBBI = MBB.rbegin(); + MachineInstr &MITmp = *MBBI; + if (MITmp.isTerminator() && TII->isCondBranch(&MITmp)) { + MachineBasicBlock *NextBB = MBB.getNextNode(); + bool NextBBIsSucc = false; + for (auto *Succ : MBB.successors()) { + if (Succ == NextBB) { + NextBBIsSucc = true; + break; + } + } + if (NextBBIsSucc) { + MachineBasicBlock::const_iterator MBBINext = NextBB->begin(), ENext = NextBB->end(); + while (MBBINext != ENext) { + MachineBasicBlock::const_iterator NMBBINext = std::next(MBBINext); + const MachineInstr &MINext = *MBBINext; + if (MINext.getOpcode() == XVM::END_BLOCK || MINext.getOpcode() == XVM::END_LOOP) { + LevelBreakAfterLoop ++; + } else { + break; + } + MBBINext = NMBBINext; + } } - MachineInstr *MIThen = MBB.getParent()->CreateMachineInstr(TII->get(XVM::THEN), DebugLoc()); - MBB.insertAfter(MI.getIterator(), MIThen); - MachineInstr *MIAction = MBB.getParent()->CreateMachineInstr(TII->get(action_opcode), DebugLoc()); - MBB.insertAfter(MIThen->getIterator(), MIAction); - MachineInstr *MIEndThen = MBB.getParent()->CreateMachineInstr(TII->get(XVM::END_THEN), DebugLoc()); - MBB.insertAfter(MIAction->getIterator(), MIEndThen); + } + + MachineInstr *MIThen = MBB.getParent()->CreateMachineInstr(TII->get(XVM::THEN), DebugLoc()); + MBB.insertAfter(MI.getIterator(), MIThen); + MachineInstr *MIAction = MBB.getParent()->CreateMachineInstr(TII->get(action_opcode), DebugLoc()); + MBB.insertAfter(MIThen->getIterator(), MIAction); + MachineInstrBuilder MIB(MF, MIAction); + if (BreakImmValue > -1 && action_opcode == XVM::BREAK_IMM) + MIB.addImm(BreakImmValue); + MachineInstr *MIEndThen = MBB.getParent()->CreateMachineInstr(TII->get(XVM::END_THEN), DebugLoc()); + MBB.insertAfter(MIAction->getIterator(), MIEndThen); + if (LevelBreakAfterLoop >= 0) { + MachineInstr *MIElse = MBB.getParent()->CreateMachineInstr(TII->get(XVM::ELSE), DebugLoc()); + MBB.insertAfter(MIEndThen->getIterator(), MIElse); + MachineInstr *MI_BREAK_IMM = MBB.getParent()->CreateMachineInstr(TII->get(XVM::BREAK_IMM), DebugLoc()); + MBB.insertAfter(MIElse->getIterator(), MI_BREAK_IMM); + MachineInstrBuilder MIB(MF, MI_BREAK_IMM); + MIB.addImm(LevelBreakAfterLoop); + MachineInstr *MIEndElse = MBB.getParent()->CreateMachineInstr(TII->get(XVM::END_ELSE), DebugLoc()); + MBB.insertAfter(MI_BREAK_IMM->getIterator(), MIEndElse); + MachineInstr *MIEndIf = MBB.getParent()->CreateMachineInstr(TII->get(XVM::END_IF), DebugLoc()); + MBB.insertAfter(MIEndElse->getIterator(), MIEndIf); + ChangeBranchCondOpc(MI, TII); + } else { MachineInstr *MIEndIf = MBB.getParent()->CreateMachineInstr(TII->get(XVM::END_IF), DebugLoc()); MBB.insertAfter(MIEndThen->getIterator(), MIEndIf); ChangeBranchCondOpc(MI, TII); + } } } } @@ -281,18 +338,10 @@ void XVMCFGStackify::registerScope(MachineInstr *Begin, EndToBegin[End] = Begin; } -void XVMCFGStackify::unregisterScope(MachineInstr *Begin) { - assert(BeginToEnd.count(Begin)); - MachineInstr *End = BeginToEnd[Begin]; - assert(EndToBegin.count(End)); - BeginToEnd.erase(Begin); - EndToBegin.erase(End); -} - static bool isChild(const MachineInstr &MI) { if (MI.getNumOperands() == 0) return false; - const MachineOperand &MO = MI.getOperand(0); + const MachineOperand &MO = MI.getOperand(MO_FIRST); if (!MO.isReg() || MO.isImplicit() || !MO.isDef()) return false; Register Reg = MO.getReg(); @@ -306,31 +355,61 @@ static bool isChild(const MachineInstr &MI) { * Note: we may find other approach for fixing this. */ unsigned XVMCFGStackify::getBranchDepth( - const SmallVectorImpl &Stack, - const std::set *SetEndBlockLoop, - const MachineBasicBlock *MBB) { - unsigned Depth = 0; - for (auto X : reverse(Stack)) { - if (X.first == MBB) { - std::set::iterator I = SetEndBlockLoop->find(MBB); - if (I != SetEndBlockLoop->end()) - ++Depth; - break; + MachineFunction &MF, + const MachineBasicBlock *MBB, + MachineInstr *MI) { + + int depth = -1; + int baseMBBnum = MI->getParent()->getNumber(); + auto MBBI = MF.begin(); + int targetMBBnum = MBB->getNumber(); + + while (MBBI->getNumber() != baseMBBnum) { + MBBI++; + } + + MBBI++; + + while (MBBI != MF.end()) { + MachineBasicBlock &CurMBB = *MBBI; + if (CurMBB.getNumber() == targetMBBnum) { + /* We are in the correct MBB, go to the first real instruction */ + for (auto MII = CurMBB.begin(); MII != CurMBB.end(); MII++) { + MachineInstr &CurMI = *MII; + if (CurMI.getOpcode() == XVM::END_LOOP || CurMI.getOpcode() == XVM::END_BLOCK) { + depth++; + } else { + return depth; + } + } + } else { + /* We are not in the right MBB yet, count all the loop and block markers + * Additionally check if any of these end_loops lead to the correct basic block + */ + for (auto MII = CurMBB.begin(); MII != CurMBB.end(); MII++) { + MachineInstr &CurMI = *MII; + if (CurMI.getOpcode() == XVM::LOOP || CurMI.getOpcode() == XVM::BLOCK) { + depth--; + } else if (CurMI.getOpcode() == XVM::END_BLOCK) { + depth++; + } else if (CurMI.getOpcode() == XVM::END_LOOP) { + /* Check if this ENDLOOP goes to the right MBB */ + if (EndLoopToMBBnum[&CurMI] == targetMBBnum) { + return depth; + } else { + depth++; + } + } + } } - ++Depth; + MBBI++; } - assert(Depth < Stack.size() && "Branch destination should be in scope"); - return Depth; -} -static inline MachineBasicBlock *getNextBlock(MachineBasicBlock &MBB) { - MachineFunction::iterator I = MBB.getIterator(); - MachineFunction::iterator E = MBB.getParent()->end(); - if (++I == E) - return nullptr; - return &*I; + return depth; } + + static inline MachineInstr *getNextInstruction(MachineInstr &MI) { MachineBasicBlock::iterator I = MI.getIterator(); MachineBasicBlock::iterator E = MI.getParent()->end(); @@ -413,230 +492,224 @@ void XVMCFGStackify::removeInFunctionRet(MachineFunction &MF) { } /// Insert LOOP/BLOCK markers at appropriate places. -void XVMCFGStackify::placeMarkers(MachineFunction &MF) { - // We allocate one more than the number of blocks in the function to - // accommodate for the possible fake block we may insert at the end. - ScopeTops.resize(MF.getNumBlockIDs() + 1); - // Place the LOOP for MBB if MBB is the header of a loop. - for (auto &MBB : MF) - placeLoopMarker(MBB); - - for (auto &MBB : MF) { +void XVMCFGStackify::placeMarkers(MachineFunction &MFunction) { + // To accommodate for the possible fake block we may insert at the end + // we allocate one more than the number of blocks in the func + ScopeTops.resize(MFunction.getNumBlockIDs() + 1); + // If MBB is the header of a loop, place the LOOP for MBB. + for (auto &MBBlock : MFunction) + placeLoopMarker(MBBlock); + + for (auto &MBBlock : MFunction) { // Place the BLOCK for MBB if MBB is branched to from above. - placeBlockMarker(MBB); + placeBlockMarker(MBBlock); } - removeInFunctionRet(MF); + removeInFunctionRet(MFunction); } /// Insert a BLOCK marker for branches to MBB (if needed). // Note: Consider a more generalized way of handling block (and also loop and // try) signatures when we implement the multi-value proposal later. -void XVMCFGStackify::placeBlockMarker(MachineBasicBlock &MBB) { - assert(!MBB.isEHPad()); - MachineFunction &MF = *MBB.getParent(); +void XVMCFGStackify::placeBlockMarker(MachineBasicBlock &MBBlock) { + assert(!MBBlock.isEHPad()); + MachineFunction &MFunction = *MBBlock.getParent(); auto &MDT = getAnalysis(); - const auto &TII = *MF.getSubtarget().getInstrInfo(); - - // First compute the nearest common dominator of all forward non-fallthrough - // predecessors so that we minimize the time that the BLOCK is on the stack, - // which reduces overall stack height. - MachineBasicBlock *Header = nullptr; - bool IsBranchedTo = false; - int MBBNumber = MBB.getNumber(); - for (MachineBasicBlock *Pred : MBB.predecessors()) { - if (Pred->getNumber() < MBBNumber) { - Header = Header ? MDT.findNearestCommonDominator(Header, Pred) : Pred; - if (explicitlyBranchesTo(Pred, &MBB)) - IsBranchedTo = true; + const auto &TII = *MFunction.getSubtarget().getInstrInfo(); + + // For all forward non-fallthrough predecessors, compute the nearest commomn + // dominator, reduceing stack height, by minimizing the time the block is on the stack + MachineBasicBlock *Head = nullptr; + bool BranchedTo = false; + int MBBlockNumber = MBBlock.getNumber(); + for (MachineBasicBlock *Predecessor : MBBlock.predecessors()) { + if (Predecessor->getNumber() < MBBlockNumber) { + Head = Head ? MDT.findNearestCommonDominator(Head, Predecessor) : Predecessor; + if (explicitlyBranchesTo(Predecessor, &MBBlock)) + BranchedTo = true; } } - if (!Header) - return; - if (!IsBranchedTo) + if (!(Head && BranchedTo)) return; - assert(&MBB != &MF.front() && "Header blocks shouldn't have predecessors"); - MachineBasicBlock *LayoutPred = MBB.getPrevNode(); + assert(&MBBlock != &MFunction.front() && "Header blocks shouldn't have predecessors"); + MachineBasicBlock *LayoutPredecessors = MBBlock.getPrevNode(); - // If the nearest common dominator is inside a more deeply nested context, - // walk out to the nearest scope which isn't more deeply nested. - for (MachineFunction::iterator I(LayoutPred), E(Header); I != E; --I) { - if (MachineBasicBlock *ScopeTop = ScopeTops[I->getNumber()]) { - if (ScopeTop->getNumber() > Header->getNumber()) { - // Skip over an intervening scope. - I = std::next(ScopeTop->getIterator()); + // walk out to the nearest scope which isnt more deeply nester, if the nearest + // common cominator is inside a more deeply nested context + for (MachineFunction::iterator Iter(LayoutPredecessors), E(Head); Iter != E; --Iter) { + if (MachineBasicBlock *ST = ScopeTops[Iter->getNumber()]) { + if (ST->getNumber() > Head->getNumber()) { + // Intervening scope, skip + Iter = std::next(ST->getIterator()); } else { - // We found a scope level at an appropriate depth. - Header = ScopeTop; + // scope level at an appropriate depth. end + Head = ST; break; } } } - // Decide where in Header to put the BLOCK. - - // Instructions that should go before the BLOCK. - SmallPtrSet BeforeSet; - // Instructions that should go after the BLOCK. - SmallPtrSet AfterSet; - for (const auto &MI : *Header) { - // If there is a previously placed LOOP marker and the bottom block of the - // loop is above MBB, it should be after the BLOCK, because the loop is - // nested in this BLOCK. Otherwise it should be before the BLOCK. - if (MI.getOpcode() == XVM::LOOP) { - auto *LoopBottom = BeginToEnd[&MI]->getParent()->getPrevNode(); - if (MBB.getNumber() > LoopBottom->getNumber()) - AfterSet.insert(&MI); + // Where in Head should we put the block + // pre block instruction set + SmallPtrSet Before; + // post block instruction set + SmallPtrSet After; + for (const auto &MInst : *Head) { + // If the bottom block of the loop is above MBB and there is a previosly placed + // LOOP marker, it should be after the BLOCK, because the loop is nested inside it + // Otherwise it should be before the BLOCK + if (MInst.getOpcode() == XVM::LOOP) { + auto *LoopBot = BeginToEnd[&MInst]->getParent()->getPrevNode(); + if (MBBlock.getNumber() > LoopBot->getNumber()) + After.insert(&MInst); #ifndef NDEBUG else - BeforeSet.insert(&MI); + Before.insert(&MInst); #endif } - // If there is a previously placed BLOCK/TRY marker and its corresponding - // END marker is before the current BLOCK's END marker, that should be - // placed after this BLOCK. Otherwise it should be placed before this BLOCK - // marker. - if (MI.getOpcode() == XVM::BLOCK) { - if (BeginToEnd[&MI]->getParent()->getNumber() <= MBB.getNumber()) - AfterSet.insert(&MI); + // If an END marker is before the current BLOCK's END marker, and its + // corresponding BLOCK/TRY has been previously places, that should be palced + // after this BLOCK, otherwise is hould before. + if (MInst.getOpcode() == XVM::BLOCK) { + if (BeginToEnd[&MInst]->getParent()->getNumber() <= MBBlock.getNumber()) + After.insert(&MInst); #ifndef NDEBUG else - BeforeSet.insert(&MI); + Before.insert(&MInst); #endif } -#ifndef NDEBUG - // All END_(BLOCK|LOOP|TRY) markers should be before the BLOCK. - if (MI.getOpcode() == XVM::END_BLOCK || - MI.getOpcode() == XVM::END_LOOP) - BeforeSet.insert(&MI); +#ifndef NDEBUG // END_(BLOCK|LOOP|TRY) markers should all be before the BLOCK. + if (MInst.getOpcode() == XVM::END_BLOCK || + MInst.getOpcode() == XVM::END_LOOP) + Before.insert(&MInst); #endif - // Terminators should go after the BLOCK. - if (MI.isTerminator()) - AfterSet.insert(&MI); + if (MInst.isTerminator()) // Terminators should go after the BLOCK. + After.insert(&MInst); } - // Local expression tree should go after the BLOCK. - for (auto I = Header->getFirstTerminator(), E = Header->begin(); I != E; - --I) { - if (std::prev(I)->isDebugInstr() || std::prev(I)->isPosition()) + // Local expression tree are placed after the BLOCK. + for (auto Iter = Head->getFirstTerminator(), E = Head->begin(); Iter != E; --Iter) { + if (std::prev(Iter)->isDebugInstr() || std::prev(Iter)->isPosition()) continue; - if (isChild(*std::prev(I))) - AfterSet.insert(&*std::prev(I)); + if (isChild(*std::prev(Iter))) + After.insert(&*std::prev(Iter)); else break; } // Add the BLOCK. // XVM::BlockType ReturnType = XVM::BlockType::Void; - auto InsertPos = getLatestInsertPos(Header, BeforeSet, AfterSet); + auto InsertPosition = getLatestInsertPos(Head, Before, After); MachineInstr *Begin = - BuildMI(*Header, InsertPos, Header->findDebugLoc(InsertPos), + BuildMI(*Head, InsertPosition, Head->findDebugLoc(InsertPosition), TII.get(XVM::BLOCK)); //Note: Check if we need it later - // Decide where in Header to put the END_BLOCK. - BeforeSet.clear(); - AfterSet.clear(); - for (auto &MI : MBB) { + // Decide where in Head to put the END_BLOCK. + Before.clear(); + After.clear(); + for (auto &MInst : MBBlock) { #ifndef NDEBUG // END_BLOCK should precede existing LOOP and TRY markers. - if (MI.getOpcode() == XVM::LOOP) - AfterSet.insert(&MI); + if (MInst.getOpcode() == XVM::LOOP) + After.insert(&MInst); #endif - // If there is a previously placed END_LOOP marker and the header of the - // loop is above this block's header, the END_LOOP should be placed after - // the BLOCK, because the loop contains this block. Otherwise the END_LOOP - // should be placed before the BLOCK. The same for END_TRY. - if (MI.getOpcode() == XVM::END_LOOP) { - if (EndToBegin[&MI]->getParent()->getNumber() >= Header->getNumber()) - BeforeSet.insert(&MI); + // If the head of the loop is above this block's head, and there is a + // previously places END_LOOP marker, the END_LOOp should be inserted + // after the BLOCK, since the loop contains this block, otherwise, it + // should be places before. the for END_TRY + if (MInst.getOpcode() == XVM::END_LOOP) { + if (EndToBegin[&MInst]->getParent()->getNumber() >= Head->getNumber()) + Before.insert(&MInst); #ifndef NDEBUG else - AfterSet.insert(&MI); + After.insert(&MInst); #endif } } - // Mark the end of the block. - InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); - MachineInstr *End = BuildMI(MBB, InsertPos, MBB.findPrevDebugLoc(InsertPos), + // End of the block marker. + InsertPosition = getEarliestInsertPos(&MBBlock, Before, After); + MachineInstr *End = BuildMI(MBBlock, InsertPosition, MBBlock.findPrevDebugLoc(InsertPosition), TII.get(XVM::END_BLOCK)); registerScope(Begin, End); // Track the farthest-spanning scope that ends at this point. - updateScopeTops(Header, &MBB); + updateScopeTops(Head, &MBBlock); } /// Insert a LOOP marker for a loop starting at MBB (if it's a loop header). -void XVMCFGStackify::placeLoopMarker(MachineBasicBlock &MBB) { - MachineFunction &MF = *MBB.getParent(); - const auto &MLI = getAnalysis(); - SortRegionInfo SRI(MLI); - const auto &TII = *MF.getSubtarget().getInstrInfo(); - - MachineLoop *Loop = MLI.getLoopFor(&MBB); - if (!Loop || Loop->getHeader() != &MBB) +void XVMCFGStackify::placeLoopMarker(MachineBasicBlock &MBBlock) { + MachineFunction &MFunction = *MBBlock.getParent(); + const auto &MLInfo = getAnalysis(); + SortRegionInfo SRI(MLInfo); + const auto &TII = *MFunction.getSubtarget().getInstrInfo(); + + MachineLoop *MLoop = MLInfo.getLoopFor(&MBBlock); + if (!MLoop || MLoop->getHeader() != &MBBlock) { return; + } // The operand of a LOOP is the first block after the loop. If the loop is the // bottom of the function, insert a dummy block at the end. - MachineBasicBlock *Bottom = SRI.getBottom(Loop); - auto Iter = std::next(Bottom->getIterator()); - if (Iter == MF.end()) { - getAppendixBlock(MF); - Iter = std::next(Bottom->getIterator()); + MachineBasicBlock *Bot = SRI.getBottom(MLoop); + auto I = std::next(Bot->getIterator()); + if (I == MFunction.end()) { + getAppendixBlock(MFunction); + I = std::next(Bot->getIterator()); } - MachineBasicBlock *AfterLoop = &*Iter; - - // Decide where in Header to put the LOOP. - SmallPtrSet BeforeSet; - SmallPtrSet AfterSet; - for (const auto &MI : MBB) { - // LOOP marker should be after any existing loop that ends here. Otherwise - // we assume the instruction belongs to the loop. - if (MI.getOpcode() == XVM::END_LOOP) - BeforeSet.insert(&MI); + MachineBasicBlock *AfterLoop = &*I; + + // Find where in Header to put the MLOOP. + SmallPtrSet Before; + SmallPtrSet After; + for (const auto &MInst : MBBlock) { + // Add a loop tag here, after any existing loop. + // Otherwise, we assume that the instruction is a loop. + if (MInst.getOpcode() == XVM::END_LOOP) + Before.insert(&MInst); #ifndef NDEBUG else - AfterSet.insert(&MI); + After.insert(&MInst); #endif } - // Mark the beginning of the loop. - auto InsertPos = getEarliestInsertPos(&MBB, BeforeSet, AfterSet); + // tag the start of the loop. + auto InsertPosition = getEarliestInsertPos(&MBBlock, Before, After); //Note: modify the form of the LOOP instruction - MachineInstr *Begin = BuildMI(MBB, InsertPos, MBB.findDebugLoc(InsertPos), + MachineInstr *Begin = BuildMI(MBBlock, InsertPosition, MBBlock.findDebugLoc(InsertPosition), TII.get(XVM::LOOP)); // Decide where in Header to put the END_LOOP. - BeforeSet.clear(); - AfterSet.clear(); + Before.clear(); + After.clear(); #ifndef NDEBUG - for (const auto &MI : MBB) - // Existing END_LOOP markers belong to parent loops of this loop - if (MI.getOpcode() == XVM::END_LOOP) - AfterSet.insert(&MI); + for (const auto &MInst : MBBlock) + // The current loop is not associated with the existing END_LOOP markers, + // which belong to the parent loops. + if (MInst.getOpcode() == XVM::END_LOOP) + After.insert(&MInst); #endif // Mark the end of the loop (using arbitrary debug location that branched to // the loop end as its location). - InsertPos = getEarliestInsertPos(AfterLoop, BeforeSet, AfterSet); + InsertPosition = getEarliestInsertPos(AfterLoop, Before, After); DebugLoc EndDL = AfterLoop->pred_empty() - ? DebugLoc() - : (*AfterLoop->pred_rbegin())->findBranchDebugLoc(); - MachineInstr *End = - BuildMI(*AfterLoop, InsertPos, EndDL, TII.get(XVM::END_LOOP)); + ? DebugLoc() + : (*AfterLoop->pred_rbegin())->findBranchDebugLoc(); + + MachineInstr *End = BuildMI(*AfterLoop, InsertPosition, EndDL, TII.get(XVM::END_LOOP)); registerScope(Begin, End); assert((!ScopeTops[AfterLoop->getNumber()] || - ScopeTops[AfterLoop->getNumber()]->getNumber() < MBB.getNumber()) && - "With block sorting the outermost loop for a block should be first."); - updateScopeTops(&MBB, AfterLoop); + ScopeTops[AfterLoop->getNumber()]->getNumber() < MBBlock.getNumber()) && + "With block sorting the outermost loop for a block should be first."); + updateScopeTops(&MBBlock, AfterLoop); } void XVMCFGStackify::extendCondStmt(std::map CondBranchsWithDepth, @@ -675,72 +748,45 @@ void XVMCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { // Now rewrite references to basic blocks to be depth immediates. std::map CondBranchsWithDepth; TII = MF.getSubtarget().getInstrInfo(); - SmallVector Stack; - std::set SetEndBlockLoop; - SmallVector EHPadStack; + int TargetMBB; + for (auto &MBB : reverse(MF)) { for (MachineInstr &MI : llvm::reverse(MBB)) { - switch (MI.getOpcode()) { - case XVM::BLOCK: - assert(ScopeTops[Stack.back().first->getNumber()]->getNumber() <= - MBB.getNumber() && - "Block/try marker should be balanced"); - Stack.pop_back(); - break; - - case XVM::LOOP: - assert(Stack.back().first == &MBB && "Loop top should be balanced"); - Stack.pop_back(); - break; - - case XVM::END_BLOCK: - Stack.push_back(std::make_pair(&MBB, &MI)); - break; - - case XVM::END_LOOP: { - Stack.push_back(std::make_pair(EndToBegin[&MI]->getParent(), &MI)); - MachineInstr *PrevMI = MI.getPrevNode(); - if (PrevMI != NULL && PrevMI == MBB.begin()) { - if (PrevMI->getOpcode() == XVM::END_BLOCK) { - SetEndBlockLoop.insert(&MBB); + if (MI.isTerminator()) { + // Rewrite MBB operands to be depth immediates. + SmallVector Ops(MI.operands()); + unsigned int Opcode = MI.getOpcode(); + unsigned int Depth = 0; + while (MI.getNumOperands() > 0) + MI.removeOperand(MI.getNumOperands() - 1); + for (auto MO : Ops) { + if (MO.isMBB()) { + TargetMBB = MO.getMBB()->getNumber(); + Depth = getBranchDepth(MF, MO.getMBB(), &MI); + MO = MachineOperand::CreateImm(Depth); } + MI.addOperand(MF, MO); } - break; - } - default: - if (MI.isTerminator()) { - // Rewrite MBB operands to be depth immediates. - SmallVector Ops(MI.operands()); - unsigned int Opcode = MI.getOpcode(); - unsigned int depth = 0; - while (MI.getNumOperands() > 0) - MI.removeOperand(MI.getNumOperands() - 1); - for (auto MO : Ops) { - if (MO.isMBB()) { - depth = getBranchDepth(Stack, &SetEndBlockLoop, MO.getMBB()); - MO = MachineOperand::CreateImm(depth); - } - MI.addOperand(MF, MO); - } - if (Opcode == XVM::BR) { + if (Opcode == XVM::BR) { + if (Depth == -1 && ContinueMap[&MI] == TargetMBB) { + MI.setDesc(TII->get(XVM::CONTINUE)); + } else { MI.setDesc(TII->get(XVM::BREAK_IMM)); - } else if (TII->isCondBranch(&MI) && !TII->isCondBranchProcessed(&MI)) { - /** add the following instructions: THEN, BRREAK_IMM and END_THEN */ - CondBranchsWithDepth.insert(std::make_pair(&MI, depth)); } + } else if (TII->isCondBranch(&MI) && !TII->isCondBranchProcessed(&MI)) { + /** add the following instructions: THEN, BRREAK_IMM and END_THEN */ + CondBranchsWithDepth.insert(std::make_pair(&MI, Depth)); } - break; } } } extendCondStmt(CondBranchsWithDepth, MF); - assert(Stack.empty() && "Control flow should be balanced"); } void XVMCFGStackify::cleanupFunctionData(MachineFunction &MF) { - if (FakeCallerBB) - MF.deleteMachineBasicBlock(FakeCallerBB); - AppendixBB = FakeCallerBB = nullptr; + if (FakeBBlockCaller) + MF.deleteMachineBasicBlock(FakeBBlockCaller); + AppendixBBlock = FakeBBlockCaller = nullptr; } void XVMCFGStackify::releaseMemory() { @@ -749,16 +795,33 @@ void XVMCFGStackify::releaseMemory() { EndToBegin.clear(); } +void XVMCFGStackify::fillEndLoopMap(MachineFunction &MF) { + std::vector stack; + stack.push_back(-1); + for (auto &MBB : MF) { + for (MachineInstr &MI : MBB) { + if (MI.getOpcode() == XVM::LOOP) { + stack.push_back(MBB.getNumber()); + } else if (MI.getOpcode() == XVM::END_LOOP) { + EndLoopToMBBnum[&MI] = EndToBegin[&MI]->getParent()->getNumber(); + stack.pop_back(); + } else { + ContinueMap[&MI] = stack.back(); + } + } + } +} + bool XVMCFGStackify::runOnMachineFunction(MachineFunction &MF) { LLVM_DEBUG(dbgs() << "********** CFG Stackifying **********\n" "********** Function: " << MF.getName() << '\n'); - releaseMemory(); - // Place the BLOCK/LOOP/TRY markers to indicate the beginnings of scopes. placeMarkers(MF); + fillEndLoopMap(MF); + // Place the continue statements for each backedge of loops. fixBackEdgesOfLoops(MF); diff --git a/llvm/lib/Target/XVM/XVMCFGStructure.cpp b/llvm/lib/Target/XVM/XVMCFGStructure.cpp index db76d9468f30813d7d6c114d46d5bb0c0e160df3..d7c8cd4ce02ed29ed91a99fbf03c1a02dcc2e2ec 100644 --- a/llvm/lib/Target/XVM/XVMCFGStructure.cpp +++ b/llvm/lib/Target/XVM/XVMCFGStructure.cpp @@ -13,6 +13,8 @@ using namespace llvm; #define DEBUG_TYPE "xvm-cfg-structure" +#define INIT_SMALL_VECTOR_MO_SIZE 4 +#define INIT_SMALL_VECTOR_LOOP_SIZE 16 namespace { class XVMCFGStructure final : public MachineFunctionPass { @@ -203,10 +205,10 @@ void XVMCFGStructure::fixLoops(MachineBasicBlock &MBB) { auto &MLI = getAnalysis(); const auto &TII = MF->getSubtarget().getInstrInfo(); MachineLoop *Loop = MLI.getLoopFor(&MBB); - SmallVector ExitingBlocks; + SmallVector ExitingBlocks; auto &MPDT = getAnalysis(); using DomTreeT = PostDomTreeBase; - SmallVector PDTUpdates; + SmallVector PDTUpdates; if (!Loop || Loop->getHeader() != &MBB) // MBB must be loop head return; diff --git a/llvm/lib/Target/XVM/XVMErrorMsg.h b/llvm/lib/Target/XVM/XVMErrorMsg.h new file mode 100644 index 0000000000000000000000000000000000000000..c1e468ab85aa5a751641342637c0e3ee01e2a042 --- /dev/null +++ b/llvm/lib/Target/XVM/XVMErrorMsg.h @@ -0,0 +1,43 @@ +//===-- XVMErrorMsg.h - Error Message interface for XVM Backend ------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===---------------------------------------------------------------------------===// + +#ifndef __XVM__ERROR_MSG__HH__ +#define __XVM__ERROR_MSG__HH__ + +#include "llvm/Analysis/ConstantFolding.h" +#include "llvm/CodeGen/AsmPrinter.h" +#include "llvm/CodeGen/MachineConstantPool.h" +#include "llvm/CodeGen/MachineFunctionPass.h" +#include "llvm/CodeGen/MachineInstr.h" +#include "llvm/CodeGen/MachineModuleInfo.h" +#include "llvm/IR/DiagnosticInfo.h" +#include "llvm/MC/MCAsmInfo.h" +#include "llvm/MC/MCInst.h" +#include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSymbol.h" +#include "llvm/MC/TargetRegistry.h" +#include "llvm/Support/raw_ostream.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include +#include +#include + +using namespace llvm; + +static inline void ExportFailMsg(const Function &Func, DebugLoc DL, const char *Msg, void *Val) { + std::string Str; + raw_string_ostream OS(Str); + OS << Msg; + if (Val != NULL) { + uint64_t *ValToPrint = (uint64_t *)Val; + OS << ":" << *ValToPrint; + } + Func.getContext().diagnose(DiagnosticInfoUnsupported(Func, Str, DL)); +} + +#endif // __XVM__ERROR_MSG__HH__ diff --git a/llvm/lib/Target/XVM/XVMExpandPseudoInsts.cpp b/llvm/lib/Target/XVM/XVMExpandPseudoInsts.cpp index 5e75f124bf2aa5dbb32d4b9c8edde156f84bb1af..f908e62beb3335a2f34254ad23468eecb80e7e15 100644 --- a/llvm/lib/Target/XVM/XVMExpandPseudoInsts.cpp +++ b/llvm/lib/Target/XVM/XVMExpandPseudoInsts.cpp @@ -1,3 +1,15 @@ +//===-- XVMExpandPseudoInsts.cpp - XVM Pseudo Instruction Expander ----------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------------------===// +// +// This file contains the XVM implementation of replacing certain Pseudoinstructions. +// +//===----------------------------------------------------------------------------------===// + #ifdef XVM_DYLIB_MODE #include "XVM.h" @@ -9,6 +21,9 @@ using namespace llvm; #define XVM_EXPAND_PSEUDO_NAME "XVM pseudo instruction expansion pass" +#define MO_FIRST 0 +#define MO_SECOND 1 +#define MO_THIRD 2 namespace { class XVMExpandPseudo : public MachineFunctionPass { @@ -124,8 +139,8 @@ bool XVMExpandPseudo::expandSelectCC(MachineBasicBlock &MBB, unsigned NewCC = getBranchOpcodeFromSelectCC(MI); BuildMI(MBB, MBBI, DL, TII->get(NewCC)).addMBB(TMBB) - .add(MI.getOperand(1)) - .add(MI.getOperand(2)); + .add(MI.getOperand(MO_SECOND)) + .add(MI.getOperand(MO_THIRD)); BuildMI(MBB, MBBI, DL, TII->get(XVM::BR)).addMBB(FMBB); MBB.addSuccessor(TMBB); MBB.addSuccessor(FMBB); @@ -170,8 +185,7 @@ bool XVMExpandPseudo::expandSelectCC(MachineBasicBlock &MBB, INITIALIZE_PASS(XVMExpandPseudo, "xvm-expand-pseudo", XVM_EXPAND_PSEUDO_NAME, false, false) namespace llvm { - -FunctionPass *createXVMExpandPseudoPass() { return new XVMExpandPseudo(); } + FunctionPass *createXVMExpandPseudoPass() { return new XVMExpandPseudo(); } } #endif diff --git a/llvm/lib/Target/XVM/XVMFrameLowering.cpp b/llvm/lib/Target/XVM/XVMFrameLowering.cpp index bacd68abd954b085fa48cf184dc611c7798a8c83..5b544d4b2e8ada77dcd11a66d181eee922006952 100644 --- a/llvm/lib/Target/XVM/XVMFrameLowering.cpp +++ b/llvm/lib/Target/XVM/XVMFrameLowering.cpp @@ -53,8 +53,7 @@ XVMFrameLowering::getOpcGlobSet(const MachineFunction &MF) { } void XVMFrameLowering::emitPrologue(MachineFunction &MF, - MachineBasicBlock &MBB) const -{ + MachineBasicBlock &MBB) const { auto &MFI = MF.getFrameInfo(); if (!needsSP(MF)) { return; @@ -74,8 +73,7 @@ void XVMFrameLowering::emitPrologue(MachineFunction &MF, } void XVMFrameLowering::emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const -{ + MachineBasicBlock &MBB) const { uint64_t StackSize = MF.getFrameInfo().getStackSize(); if (!needsSP(MF)) { return; @@ -96,8 +94,7 @@ void XVMFrameLowering::emitEpilogue(MachineFunction &MF, void XVMFrameLowering::determineCalleeSaves(MachineFunction &MF, BitVector &SavedRegs, - RegScavenger *RS) const -{ + RegScavenger *RS) const { TargetFrameLowering::determineCalleeSaves(MF, SavedRegs, RS); } diff --git a/llvm/lib/Target/XVM/XVMISelDAGToDAG.cpp b/llvm/lib/Target/XVM/XVMISelDAGToDAG.cpp index 2909d9bfbeeba3cb3ec7ec16eaaeddc45aedb275..9317eafa7f1a3626984feab7be51a209df95072c 100644 --- a/llvm/lib/Target/XVM/XVMISelDAGToDAG.cpp +++ b/llvm/lib/Target/XVM/XVMISelDAGToDAG.cpp @@ -34,6 +34,7 @@ using namespace llvm; #define DEBUG_TYPE "xvm-isel" +#define TEMPLATE_INT_16 16 // Instruction Selector Implementation namespace { @@ -51,20 +52,22 @@ public: return "XVM DAG->DAG Pattern Instruction Selection"; } - bool runOnMachineFunction(MachineFunction &MF) override { + bool runOnMachineFunction(MachineFunction &MFunc) override { LLVM_DEBUG(dbgs() << "********** XVMDAGToDAGISel **********\n" "********** Function: " - << MF.getName() << '\n'); + << MFunc.getName() << '\n'); // Reset the subtarget each time through. - Subtarget = &MF.getSubtarget(); - return SelectionDAGISel::runOnMachineFunction(MF); + Subtarget = &MFunc.getSubtarget(); + return SelectionDAGISel::runOnMachineFunction(MFunc); } void PreprocessISelDAG() override; + bool SelectInlineAsmMemoryOperand(const SDValue &Op, unsigned ConstraintCode, std::vector &OutOps) override; + private: -// Include the pieces autogenerated from the target description. +// The pieces autogenerated from the target description are included. #include "XVMGenDAGISel.inc" void Select(SDNode *N) override; @@ -76,113 +79,108 @@ private: } // namespace // ComplexPattern used on XVM Load/Store instructions -bool XVMDAGToDAGISel::SelectAddr(SDValue Addr, SDValue &Base, SDValue &Offset) { +bool XVMDAGToDAGISel::SelectAddr(SDValue Address, SDValue &Bas, SDValue &Offs) { // if Address is FI, get the TargetFrameIndex. - SDLoc DL(Addr); - if (auto *FIN = dyn_cast(Addr)) { - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); - Offset = CurDAG->getTargetConstant(0, DL, MVT::i64); + SDLoc DL(Address); + if (auto *FIN = dyn_cast(Address)) { + Bas = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + Offs = CurDAG->getTargetConstant(0, DL, MVT::i64); return true; } - if (Addr.getOpcode() == ISD::TargetExternalSymbol || - Addr.getOpcode() == ISD::TargetGlobalAddress) + if (Address.getOpcode() == ISD::TargetExternalSymbol || + Address.getOpcode() == ISD::TargetGlobalAddress) return false; // Addresses of the form Addr+const or Addr|const - if (CurDAG->isBaseWithConstantOffset(Addr)) { - auto *CN = cast(Addr.getOperand(1)); - if (isInt<16>(CN->getSExtValue())) { + if (CurDAG->isBaseWithConstantOffset(Address)) { + auto *CN = cast(Address.getOperand(1)); + if (isInt(CN->getSExtValue())) { // If the first operand is a FI, get the TargetFI Node - if (auto *FIN = dyn_cast(Addr.getOperand(0))) - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + if (auto *FIN = dyn_cast(Address.getOperand(0))) + Bas = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); else - Base = Addr.getOperand(0); + Bas = Address.getOperand(0); - Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64); + Offs = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64); return true; } } - Base = Addr; - Offset = CurDAG->getTargetConstant(0, DL, MVT::i64); + Bas = Address; + Offs = CurDAG->getTargetConstant(0, DL, MVT::i64); return true; } // ComplexPattern used on XVM FI instruction -bool XVMDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, - SDValue &Offset) { +bool XVMDAGToDAGISel::SelectFIAddr(SDValue Addr, SDValue &Base, SDValue &Offs) { SDLoc DL(Addr); - if (!CurDAG->isBaseWithConstantOffset(Addr)) { - return false; - } - - // Addresses of the form Addr+const or Addr|const - auto *CN = cast(Addr.getOperand(1)); - if (isInt<16>(CN->getSExtValue())) { - // If the first operand is a FI, get the TargetFI Node - if (auto *FIN = dyn_cast(Addr.getOperand(0))) - Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); - else { - return false; + if (CurDAG->isBaseWithConstantOffset(Addr)) { + auto *CN = cast(Addr.getOperand(1)); + if (isInt(CN->getSExtValue())) { + if (auto *FIN = dyn_cast(Addr.getOperand(0))) { + Base = CurDAG->getTargetFrameIndex(FIN->getIndex(), MVT::i64); + Offs = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64); + return true; + } } - Offset = CurDAG->getTargetConstant(CN->getSExtValue(), DL, MVT::i64); - return true; } return false; } bool XVMDAGToDAGISel::SelectInlineAsmMemoryOperand( - const SDValue &Op, unsigned ConstraintCode, std::vector &OutOps) { - SDValue Op0, Op1; + const SDValue &Operand, unsigned ConstraintCode, std::vector &OutOps) { + bool ret = false; + SDValue Operand0, Operand1; switch (ConstraintCode) { - default: - return true; case InlineAsm::Constraint_m: // memory - if (!SelectAddr(Op, Op0, Op1)) { - return true; + if (!SelectAddr(Operand, Operand0, Operand1)) { + ret = true; } break; + default: + ret = true; } - SDLoc DL(Op); - SDValue AluOp = CurDAG->getTargetConstant(ISD::ADD, DL, MVT::i32);; - OutOps.push_back(Op0); - OutOps.push_back(Op1); - OutOps.push_back(AluOp); - return false; + if (ret == false) { + SDLoc DL(Operand); + SDValue AluOperand = CurDAG->getTargetConstant(ISD::ADD, DL, MVT::i32); + OutOps.push_back(Operand0); + OutOps.push_back(Operand1); + OutOps.push_back(AluOperand); + } + + return ret; } -void XVMDAGToDAGISel::Select(SDNode *Node) { - unsigned Opcode = Node->getOpcode(); +void XVMDAGToDAGISel::Select(SDNode *CNode) { + unsigned Op = CNode->getOpcode(); - // If we have a custom node, we already have selected! - if (Node->isMachineOpcode()) { - LLVM_DEBUG(dbgs() << "== "; Node->dump(CurDAG); dbgs() << '\n'); + // We have already selected if we have a custom node + if (CNode->isMachineOpcode()) { + LLVM_DEBUG(dbgs() << "== "; + CNode->dump(CurDAG); dbgs() << '\n'); return; } - // tablegen selection should be handled here. - switch (Opcode) { - default: - break; - case ISD::FrameIndex: { - int FI = cast(Node)->getIndex(); - EVT VT = Node->getValueType(0); + switch (Op) { // handle table gen selection + case ISD::FrameIndex: + { + int FI = cast(CNode)->getIndex(); + EVT VT = CNode->getValueType(0); SDValue TFI = CurDAG->getTargetFrameIndex(FI, VT); unsigned Opc = XVM::MOV_rr; - if (Node->hasOneUse()) { - CurDAG->SelectNodeTo(Node, Opc, VT, TFI); - return; - } - ReplaceNode(Node, CurDAG->getMachineNode(Opc, SDLoc(Node), VT, TFI)); - return; + if (CNode->hasOneUse()) + CurDAG->SelectNodeTo(CNode, Opc, VT, TFI); + else + ReplaceNode(CNode, CurDAG->getMachineNode(Opc, SDLoc(CNode), VT, TFI)); } + break; + default: + SelectCode(CNode); // select default instr } - - // Select the default instruction - SelectCode(Node); + return; } void XVMDAGToDAGISel::PreprocessISelDAG() { @@ -191,4 +189,5 @@ void XVMDAGToDAGISel::PreprocessISelDAG() { FunctionPass *llvm::createXVMISelDag(XVMTargetMachine &TM) { return new XVMDAGToDAGISel(TM); } + #endif diff --git a/llvm/lib/Target/XVM/XVMISelLowering.cpp b/llvm/lib/Target/XVM/XVMISelLowering.cpp index b22b034e1d28c308c219061812d92161d4d64608..11e92863c0b7fdb5b1845972c315cb9345be5d6c 100644 --- a/llvm/lib/Target/XVM/XVMISelLowering.cpp +++ b/llvm/lib/Target/XVM/XVMISelLowering.cpp @@ -10,7 +10,6 @@ // selection DAG. // //===----------------------------------------------------------------------===// - #ifdef XVM_DYLIB_MODE #include "XVM_def.h" @@ -22,16 +21,7 @@ #include "llvm/Analysis/ConstantFolding.h" #include "llvm/CodeGen/CallingConvLower.h" #include "llvm/CodeGen/MachineFrameInfo.h" -#include "llvm/CodeGen/MachineFunction.h" -#include "llvm/CodeGen/MachineInstrBuilder.h" -#include "llvm/CodeGen/MachineRegisterInfo.h" -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/CodeGen/ValueTypes.h" #include "llvm/IR/DiagnosticInfo.h" -#include "llvm/IR/DiagnosticPrinter.h" -#include "llvm/Support/Debug.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" #include #include #include @@ -39,6 +29,22 @@ using namespace llvm; #define DEBUG_TYPE "xvm-lower" +#define ALIGN_NUM_BYTES 8 +#define INIT_SMALL_VECTOR_SIZE 16 +#define INIT_SMALL_VECTOR_REGS_SIZE 6 +#define INIT_SMALL_VECTOR_OP_CHAIN_SIZE 10 +#define INIT_SMALL_VECTOR_OPS_SIZE 8 +#define INIT_SMALL_VECTOR_RETOP_SIZE 4 + +#define NUM_BITS_PER_BYTE 8 +#define SIZE_REF_IN_BYTES 8 +#define XVM_MAX_RET_SIZE 1 + +#define CHAIN_FIRST 0 +#define CHAIN_SECOND 1 +#define CHAIN_THIRD 2 + +#define TEMPLATE_INT_32 32 static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg) { MachineFunction &MF = DAG.getMachineFunction(); @@ -46,12 +52,11 @@ static void fail(const SDLoc &DL, SelectionDAG &DAG, const Twine &Msg) { DiagnosticInfoUnsupported(MF.getFunction(), Msg, DL.getDebugLoc())); } -static int ShiftAndGet16Bits(uint64_t num, int n) { +static int shiftAndGet16Bits(uint64_t num, int n) { return (num >> n) & 0xFFFF; } -static bool is_valid_immediate_size(int32_t imm) -{ +static bool isValidImmediateSize(int32_t imm) { return imm <= 0x3FFF && imm >= 0; } @@ -59,8 +64,7 @@ static bool hasFP(const MachineFunction &MF) { return false; } -static bool needsSPForLocalFrame( - const MachineFunction &MF) { +static bool needsSPForLocalFrame(const MachineFunction &MF) { auto &MFI = MF.getFrameInfo(); return MFI.getStackSize() || MFI.adjustsStack() || hasFP(MF); } @@ -75,10 +79,10 @@ static unsigned getBranchOpcodeFromSelectCC(MachineInstr &MI) { "The instruction should be a pseudo select cc!"); bool IsRROp = MI.getOpcode() == XVM::PseudoSelectCC_rr; if (!IsRROp) { - int64_t imm32 = MI.getOperand(2).getImm(); - IsRROp = !(is_valid_immediate_size(imm32)); + int64_t imm32 = MI.getOperand(MO_THIRD).getImm(); + IsRROp = !(isValidImmediateSize(imm32)); } - unsigned Cond = MI.getOperand(3).getImm(); + unsigned Cond = MI.getOperand(MO_FOURTH).getImm(); unsigned NewCond; switch (Cond) { #define SET_NEWCC(X, Y) \ @@ -96,14 +100,14 @@ static unsigned getBranchOpcodeFromSelectCC(MachineInstr &MI) { SET_NEWCC(SETLE, BSLE); SET_NEWCC(SETULE, BULE); default: - report_fatal_error("unimplemented select CondCode " + Twine(Cond)); + report_fatal_error("unimplemented select CondCode " + Twine(Cond)); } return NewCond; } XVMTargetLowering::XVMTargetLowering(const TargetMachine &TM, const XVMSubtarget &STI) - : TargetLowering(TM), Subtarget(&STI) { + : TargetLowering(TM), Subtarget(STI) { // Set up the register classes. addRegisterClass(MVT::i64, &XVM::XVMGPRRegClass); @@ -118,8 +122,13 @@ XVMTargetLowering::XVMTargetLowering(const TargetMachine &TM, setOperationAction(ISD::SETCC, MVT::i64, Expand); setOperationAction(ISD::SELECT_CC, MVT::i64, Custom); + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::UREM, MVT::i64, Expand); + setOperationAction(ISD::SDIVREM, MVT::i64, Expand); + setOperationAction(ISD::UDIVREM, MVT::i64, Expand); + setOperationAction(ISD::BR_JT, MVT::Other, Expand); - setOperationAction(ISD::BRIND, MVT::Other, Expand); + setOperationAction(ISD::BRIND, MVT::Other, Custom); setOperationAction(ISD::GlobalAddress, MVT::i64, Custom); @@ -146,6 +155,25 @@ XVMTargetLowering::XVMTargetLowering(const TargetMachine &TM, setOperationAction(ISD::BSWAP, MVT::i64, Expand); + setOperationAction(ISD::BlockAddress, MVT::i64, Custom); + + setOperationAction(ISD::MULHU, MVT::i64, Custom); + setOperationAction(ISD::MULHS, MVT::i64, Custom); + setOperationAction(ISD::SMUL_LOHI, MVT::i64, Custom); + setOperationAction(ISD::UMUL_LOHI, MVT::i64, Custom); + + setOperationAction(ISD::ATOMIC_LOAD_ADD, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_AND, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_OR, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_LOAD_XOR, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_SWAP, MVT::i64, Custom); + setOperationAction(ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS, MVT::i64, Custom); + + setOperationAction(ISD::SREM, MVT::i64, Expand); + setOperationAction(ISD::UREM, MVT::i64, Expand); + setOperationAction(ISD::SDIVREM, MVT::i64, Expand); + setOperationAction(ISD::UDIVREM, MVT::i64, Expand); + // Extended load operations for i1 types must be promoted for (MVT VT : MVT::integer_valuetypes()) { setLoadExtAction(ISD::EXTLOAD, VT, MVT::i1, Promote); @@ -165,8 +193,8 @@ XVMTargetLowering::XVMTargetLowering(const TargetMachine &TM, setBooleanContents(ZeroOrOneBooleanContent); // Function alignments - setMinFunctionAlignment(Align(8)); - setPrefFunctionAlignment(Align(8)); + setMinFunctionAlignment(Align(ALIGN_NUM_BYTES)); + setPrefFunctionAlignment(Align(ALIGN_NUM_BYTES)); unsigned CommonMaxStores = (unsigned) 0xFFFFFFFF; MaxStoresPerMemset = MaxStoresPerMemsetOptSize = CommonMaxStores; @@ -206,50 +234,39 @@ bool XVMTargetLowering::isZExtFree(EVT VT1, EVT VT2) const { } XVMTargetLowering::ConstraintType -XVMTargetLowering::getConstraintType(StringRef Constraint) const { - if (Constraint.size() == 1) { - switch (Constraint[0]) { - default: - break; - case 'w': +XVMTargetLowering::getConstraintType(StringRef CType) const { + if (CType.size() == 1) + if (CType[0] == 'w') return C_RegisterClass; - } - } - return TargetLowering::getConstraintType(Constraint); + return TargetLowering::getConstraintType(CType); } std::pair XVMTargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, - StringRef Constraint, - MVT VT) const { - if (Constraint.size() == 1) - // GCC Constraint Letters - switch (Constraint[0]) { - case 'r': // GENERAL_REGS + StringRef CType, MVT VT) const { + if (CType.size() == 1) // GCC Constraint Letters + if (CType[0] == 'r') // GENERAL_REGS return std::make_pair(0U, &XVM::XVMGPRRegClass); - default: - break; - } - return TargetLowering::getRegForInlineAsmConstraint(TRI, Constraint, VT); + return TargetLowering::getRegForInlineAsmConstraint(TRI, CType, VT); } -void XVMTargetLowering::ReplaceNodeResults(SDNode *N, +void XVMTargetLowering::ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const { const char *err_msg = nullptr; - uint32_t Opcode = N->getOpcode(); - switch (Opcode) { - default: - report_fatal_error("Unhandled custom legalization"); - case ISD::ATOMIC_LOAD_ADD: + uint32_t Op = N->getOpcode(); + switch (Op) { + case ISD::ATOMIC_LOAD_XOR: case ISD::ATOMIC_LOAD_AND: case ISD::ATOMIC_LOAD_OR: - case ISD::ATOMIC_LOAD_XOR: - case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_LOAD_ADD: case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: + case ISD::ATOMIC_SWAP: break; + default: + report_fatal_error("Unhandled custom legalization"); } SDLoc DL(N); @@ -268,108 +285,142 @@ SDValue XVMTargetLowering::LowerOperation(SDValue Op, SelectionDAG &DAG) const { return LowerVASTART(Op, DAG); case ISD::VAARG: return LowerVAARG(Op, DAG); - case ISD::DYNAMIC_STACKALLOC: - report_fatal_error("Unsupported dynamic stack allocation"); - default: - llvm_unreachable("unimplemented operand"); + case ISD::DYNAMIC_STACKALLOC: { + SDNode *N = Op.getNode(); + SDLoc DL(N); + fail(DL, DAG, "Unsupported dynamic stack allocation"); + exit(1); + } + case ISD::BRIND: { + SDNode *N = Op.getNode(); + SDLoc DL(N); + fail(DL, DAG, "Unsupported Indirect Branch"); + exit(1); + } + case ISD::ATOMIC_LOAD_ADD: + case ISD::ATOMIC_LOAD_AND: + case ISD::ATOMIC_LOAD_OR: + case ISD::ATOMIC_LOAD_XOR: + case ISD::ATOMIC_SWAP: + case ISD::ATOMIC_CMP_SWAP_WITH_SUCCESS: { + SDNode *N = Op.getNode(); + SDLoc DL(N); + fail(DL, DAG, "Unsupported Atomic Instructions"); + exit(1); + } + case ISD::MULHU: + case ISD::MULHS: + case ISD::SMUL_LOHI: + case ISD::UMUL_LOHI: { + SDNode *N = Op.getNode(); + SDLoc DL(N); + fail(DL, DAG, "Unsupported multiplication overflow"); + exit(1); + } + case ISD::BlockAddress: { + SDNode *N = Op.getNode(); + SDLoc DL(N); + fail(DL, DAG, "BlockAddress currently unsupported"); + exit(1); + } + default: { + SDNode *N = Op.getNode(); + SDLoc DL(N); + fail(DL, DAG, "unimplemented operand"); + break; + } } } // Calling Convention Implementation #include "XVMGenCallingConv.inc" -SDValue XVMTargetLowering::LowerFormalArguments( - SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl &Ins, const SDLoc &DL, - SelectionDAG &DAG, SmallVectorImpl &InVals) const { - switch (CallConv) { - default: - report_fatal_error("Unsupported calling convention"); +SDValue XVMTargetLowering::LowerFormalArguments(SDValue Nodes, CallingConv::ID Call, bool IsVar, + const SmallVectorImpl &In, const SDLoc &DLoc, + SelectionDAG &DAGraph, SmallVectorImpl &Vals) const { + switch (Call) { case CallingConv::C: case CallingConv::Fast: break; + default: + report_fatal_error("Calling convention unsupported"); } - MachineFunction &MF = DAG.getMachineFunction(); - MachineRegisterInfo &RegInfo = MF.getRegInfo(); - - // Assign locations to all of the incoming arguments. - SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); - CCInfo.AnalyzeFormalArguments(Ins, CC_XVM64); - bool doesNeedSP = needsSP(MF); - - for (auto &VA : ArgLocs) { - if (VA.isRegLoc()) { - // Arguments passed in registers - EVT RegVT = VA.getLocVT(); - MVT::SimpleValueType SimpleTy = RegVT.getSimpleVT().SimpleTy; - switch (SimpleTy) { - default: { - errs() << "LowerFormalArguments Unhandled argument type: " - << RegVT.getEVTString() << '\n'; + MachineFunction &MFunction = DAGraph.getMachineFunction(); + MachineRegisterInfo &RInfo = MFunction.getRegInfo(); + + // All incoming arguments are assigned locations. + SmallVector ArgLoc; + CCState CCInfo(Call, IsVar, MFunction, ArgLoc, *DAGraph.getContext()); + CCInfo.AnalyzeFormalArguments(In, CC_XVM64); + bool doesNeedSP = needsSP(MFunction); + + for (auto &LocIterator : ArgLoc) { + if (LocIterator.isRegLoc()) { + // Register passed args + EVT VT = LocIterator.getLocVT(); + MVT::SimpleValueType SVT = VT.getSimpleVT().SimpleTy; + switch (SVT) { + default: + errs() << "LowerFormalArguments Unhandled argument type: " << VT.getEVTString() << '\n'; llvm_unreachable(nullptr); - } case MVT::i32: case MVT::i64: - Register VReg = RegInfo.createVirtualRegister(&XVM::XVMGPRRegClass); - RegInfo.addLiveIn(VA.getLocReg(), VReg); - SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, VReg, RegVT); - - // If this is an value that has been promoted to wider types, insert an - // assert[sz]ext to capture this, then truncate to the right size. - if (VA.getLocInfo() == CCValAssign::SExt) - ArgValue = DAG.getNode(ISD::AssertSext, DL, RegVT, ArgValue, - DAG.getValueType(VA.getValVT())); - else if (VA.getLocInfo() == CCValAssign::ZExt) - ArgValue = DAG.getNode(ISD::AssertZext, DL, RegVT, ArgValue, - DAG.getValueType(VA.getValVT())); - - if (VA.getLocInfo() != CCValAssign::Full) - ArgValue = DAG.getNode(ISD::TRUNCATE, DL, VA.getValVT(), ArgValue); - - InVals.push_back(ArgValue); - - break; + Register VRegister = RInfo.createVirtualRegister(&XVM::XVMGPRRegClass); + RInfo.addLiveIn(LocIterator.getLocReg(), VRegister); + SDValue ArgV = DAGraph.getCopyFromReg(Nodes, DLoc, VRegister, VT); + //insert an assert[sz]ext tp capture a value being promoted to a wider type + if (LocIterator.getLocInfo() == CCValAssign::SExt) + ArgV = DAGraph.getNode(ISD::AssertSext, DLoc, VT, ArgV, + DAGraph.getValueType(LocIterator.getValVT())); + else if (LocIterator.getLocInfo() == CCValAssign::ZExt) + ArgV = DAGraph.getNode(ISD::AssertZext, DLoc, VT, ArgV, + DAGraph.getValueType(LocIterator.getValVT())); + + if (LocIterator.getLocInfo() != CCValAssign::Full) + ArgV = DAGraph.getNode(ISD::TRUNCATE, DLoc, LocIterator.getValVT(), ArgV); + + Vals.push_back(ArgV); + break; } } else { - MVT LocVT = VA.getLocVT(); - MachineFrameInfo &MFI = MF.getFrameInfo(); - EVT ValVT = VA.getValVT(); - // sanity check - assert(VA.isMemLoc()); - /* The stack pointer offset is relative to the caller stack frame. - * we also need to add the offset created in in callee for saving callee saved regs - * we do not need to consider further callee stack offset, - * it will be handled later in eliminateFrameIndex - */ - int FI = 0; - if (doesNeedSP) { - const MCPhysReg *CSRegs = MF.getRegInfo().getCalleeSavedRegs(); - unsigned CSRcounter = 0; - for (; CSRegs[CSRcounter]; ++CSRcounter); - FI = MFI.CreateFixedObject(ValVT.getSizeInBits()/8, - VA.getLocMemOffset() + CSRcounter*8, true); - } else { - FI = MFI.CreateFixedObject(ValVT.getSizeInBits()/8, - VA.getLocMemOffset(), true); - } + MVT LocVT = LocIterator.getLocVT(); + MachineFrameInfo &MFI = MFunction.getFrameInfo(); + EVT ValVT = LocIterator.getValVT(); + // sanity check + assert(LocIterator.isMemLoc()); + /* The stack pointer offset is relative to the caller stack frame. + * we also need to add the offset created in in callee for saving callee saved regs + * we do not need to consider further callee stack offset, + * it will be handled later in eliminateFrameIndex + */ + int FI = 0; + if (doesNeedSP) { + const MCPhysReg *CSRegs = MFunction.getRegInfo().getCalleeSavedRegs(); + unsigned CSRcounter = 0; + for (; CSRegs[CSRcounter]; ++CSRcounter); + FI = MFI.CreateFixedObject(ValVT.getSizeInBits()/NUM_BITS_PER_BYTE, + LocIterator.getLocMemOffset() + CSRcounter*SIZE_REF_IN_BYTES, true); + } else { + FI = MFI.CreateFixedObject(ValVT.getSizeInBits()/NUM_BITS_PER_BYTE, + LocIterator.getLocMemOffset(), true); + } - // Create load nodes to retrieve arguments from the stack - SDValue FIN = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue Load = DAG.getLoad( - LocVT, DL, Chain, FIN, - MachinePointerInfo::getFixedStack(DAG.getMachineFunction(), FI)); - InVals.push_back(Load); + // Create load nodes to retrieve arguments from the stack + SDValue FIN = DAGraph.getFrameIndex(FI, getPointerTy(DAGraph.getDataLayout())); + SDValue Load = DAGraph.getLoad( + LocVT, DLoc, Nodes, FIN, + MachinePointerInfo::getFixedStack(DAGraph.getMachineFunction(), FI)); + Vals.push_back(Load); } } std::vector OutChains; - if (IsVarArg) { + if (IsVar) { const TargetRegisterClass *RC = &XVM::XVMGPRRegClass; - MachineFrameInfo &MFI = MF.getFrameInfo(); - MachineRegisterInfo &RegInfo = MF.getRegInfo(); - XVMMachineFunctionInfo *XFI = MF.getInfo(); + MachineFrameInfo &MFI = MFunction.getFrameInfo(); + MachineRegisterInfo &RegInfo = MFunction.getRegInfo(); + XVMMachineFunctionInfo *XFI = MFunction.getInfo(); static const MCPhysReg ArgGPRs[] = {XVM::R0, XVM::R1, XVM::R2, XVM::R3, XVM::R4, XVM::R5}; ArrayRef ArgRegs = makeArrayRef(ArgGPRs); @@ -382,12 +433,12 @@ SDValue XVMTargetLowering::LowerFormalArguments( VaArgOffset = CCInfo.getNextStackOffset(); VaArgsSaveSize = 0; } else { - VaArgsSaveSize = 8 * (ArgRegs.size() - FirstRegIdx); + VaArgsSaveSize = SIZE_REF_IN_BYTES * (ArgRegs.size() - FirstRegIdx); VaArgOffset = -VaArgsSaveSize; } XFI->SetVarArgsFrameIndex( - MFI.CreateFixedObject(8, // size + MFI.CreateFixedObject(SIZE_REF_IN_BYTES, // size VaArgOffset, // SPOffset true)); // IsImmutable // Copy the registers that have not been used for var argument passing @@ -395,10 +446,10 @@ SDValue XVMTargetLowering::LowerFormalArguments( for (unsigned I = FirstRegIdx; I < ArgRegs.size(); I++, VaArgOffset += 8) { const Register Reg = RegInfo.createVirtualRegister(RC); RegInfo.addLiveIn(ArgRegs[I], Reg); - SDValue ArgValue = DAG.getCopyFromReg(Chain, DL, Reg, MVT::i64); + SDValue ArgV = DAGraph.getCopyFromReg(Nodes, DLoc, Reg, MVT::i64); int FI = MFI.CreateFixedObject(8, VaArgOffset, true); - SDValue FrameIndex = DAG.getFrameIndex(FI, getPointerTy(DAG.getDataLayout())); - SDValue Store = DAG.getStore(Chain, DL, ArgValue, FrameIndex, MachinePointerInfo::getFixedStack(MF, FI)); + SDValue FrameIndex = DAGraph.getFrameIndex(FI, getPointerTy(DAGraph.getDataLayout())); + SDValue Store = DAGraph.getStore(Nodes, DLoc, ArgV, FrameIndex, MachinePointerInfo::getFixedStack(MFunction, FI)); // Init the mem operand always. cast(Store.getNode())->getMemOperand()->setValue((Value*)nullptr); OutChains.push_back(Store); @@ -406,216 +457,219 @@ SDValue XVMTargetLowering::LowerFormalArguments( } if (!OutChains.empty()) { - OutChains.push_back(Chain); - Chain = DAG.getNode(ISD::TokenFactor, DL, MVT::Other, OutChains); + OutChains.push_back(Nodes); + Nodes = DAGraph.getNode(ISD::TokenFactor, DLoc, MVT::Other, OutChains); } - return Chain; + return Nodes; } -SDValue XVMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const { - SelectionDAG &DAG = CLI.DAG; - auto &Outs = CLI.Outs; - auto &OutVals = CLI.OutVals; - auto &Ins = CLI.Ins; - SDValue Chain = CLI.Chain; - SDValue Callee = CLI.Callee; - bool &IsTailCall = CLI.IsTailCall; - CallingConv::ID CallConv = CLI.CallConv; - bool IsVarArg = CLI.IsVarArg; - MachineFunction &MF = DAG.getMachineFunction(); +SDValue XVMTargetLowering::LowerCall(TargetLowering::CallLoweringInfo &CLoweringInfo, + SmallVectorImpl &Vals) const { + auto &In = CLoweringInfo.Ins; + auto &Out = CLoweringInfo.Outs; + SDValue Nodes = CLoweringInfo.Chain; + auto &OutValues = CLoweringInfo.OutVals; + SDValue Called = CLoweringInfo.Callee; + bool IsVArg = CLoweringInfo.IsVarArg; + SelectionDAG &DAGraph = CLoweringInfo.DAG; + bool &IsTail = CLoweringInfo.IsTailCall; + CallingConv::ID CallConvention = CLoweringInfo.CallConv; + MachineFunction &MFunction = DAGraph.getMachineFunction(); // XVM target does not support tail call optimization. - IsTailCall = false; + IsTail = false; - switch (CallConv) { - default: - report_fatal_error("Unsupported calling convention"); - case CallingConv::Fast: + switch (CallConvention) { case CallingConv::C: + case CallingConv::Fast: break; + default: + report_fatal_error("calling convention unsupported"); } - const XVMRegisterInfo *TRI = Subtarget->getRegisterInfo(); - const uint32_t *Mask = TRI->getCallPreservedMask(MF, CallConv); + + const XVMRegisterInfo *TRI = Subtarget.getRegisterInfo(); + const uint32_t *Mask = TRI->getCallPreservedMask(MFunction, CallConvention); assert(Mask && "Missing call preserved mask for calling convention"); // Analyze operands of the call, assigning locations to each operand. - SmallVector ArgLocs; - CCState CCInfo(CallConv, IsVarArg, MF, ArgLocs, *DAG.getContext()); + SmallVector ArgLocs; + CCState CCInfo(CallConvention, IsVArg, MFunction, ArgLocs, *DAGraph.getContext()); - CCInfo.AnalyzeCallOperands(Outs, CC_XVM64); + CCInfo.AnalyzeCallOperands(Out, CC_XVM64); unsigned NumBytes = CCInfo.getNextStackOffset(); - for (auto &Arg : Outs) { + for (auto &Arg : Out) { ISD::ArgFlagsTy Flags = Arg.Flags; if (!Flags.isByVal()) continue; } - auto PtrVT = getPointerTy(MF.getDataLayout()); - Chain = DAG.getCALLSEQ_START(Chain, NumBytes, 0, CLI.DL); + auto PtrVT = getPointerTy(MFunction.getDataLayout()); + Nodes = DAGraph.getCALLSEQ_START(Nodes, NumBytes, 0, CLoweringInfo.DL); - SmallVector, 6> RegsToPass; - SmallVector MemOpChains; + SmallVector, INIT_SMALL_VECTOR_REGS_SIZE> PassingRegs; + SmallVector MemOpNodeChains; - SDValue StackPtr = DAG.getCopyFromReg(Chain, CLI.DL, XVM::SP, PtrVT); + SDValue StackP = DAGraph.getCopyFromReg(Nodes, CLoweringInfo.DL, XVM::SP, PtrVT); // Walk arg assignments - for (unsigned i = 0, e = Outs.size(); i != e; ++i) { - CCValAssign &VA = ArgLocs[i]; - SDValue Arg = OutVals[i]; + for (unsigned argnum = 0, e = Out.size(); argnum != e; ++argnum) { + SDValue Arg = OutValues[argnum]; + CCValAssign &CurrentArgloc = ArgLocs[argnum]; // Promote the value if needed. - switch (VA.getLocInfo()) { - default: - llvm_unreachable("Unknown loc info"); + switch (CurrentArgloc.getLocInfo()) { case CCValAssign::Full: break; case CCValAssign::SExt: - Arg = DAG.getNode(ISD::SIGN_EXTEND, CLI.DL, VA.getLocVT(), Arg); - break; - case CCValAssign::ZExt: - Arg = DAG.getNode(ISD::ZERO_EXTEND, CLI.DL, VA.getLocVT(), Arg); + Arg = DAGraph.getNode(ISD::SIGN_EXTEND, CLoweringInfo.DL, CurrentArgloc.getLocVT(), Arg); break; case CCValAssign::AExt: - Arg = DAG.getNode(ISD::ANY_EXTEND, CLI.DL, VA.getLocVT(), Arg); + Arg = DAGraph.getNode(ISD::ANY_EXTEND, CLoweringInfo.DL, CurrentArgloc.getLocVT(), Arg); + break; + case CCValAssign::ZExt: + Arg = DAGraph.getNode(ISD::ZERO_EXTEND, CLoweringInfo.DL, CurrentArgloc.getLocVT(), Arg); break; + default: + llvm_unreachable("Unknown loc info"); } - // Push arguments into RegsToPass vector - if (VA.isRegLoc()) - RegsToPass.push_back(std::make_pair(VA.getLocReg(), Arg)); + // Push arguments into Passingregs vector + if (CurrentArgloc.isRegLoc()) + PassingRegs.push_back(std::make_pair(CurrentArgloc.getLocReg(), Arg)); else { - assert(VA.isMemLoc()); + assert(CurrentArgloc.isMemLoc()); - int32_t Offset = VA.getLocMemOffset(); - SDValue PtrOff = DAG.getIntPtrConstant(Offset, CLI.DL); + int32_t Offset = CurrentArgloc.getLocMemOffset(); + SDValue PtrOff = DAGraph.getIntPtrConstant(Offset, CLoweringInfo.DL); - SDValue DstAddr = DAG.getNode(ISD::ADD, CLI.DL, PtrVT, StackPtr, PtrOff); - MachinePointerInfo DstInfo = MachinePointerInfo::getStack(MF, Offset); + SDValue DstAddr = DAGraph.getNode(ISD::ADD, CLoweringInfo.DL, PtrVT, StackP, PtrOff); + MachinePointerInfo DstInfo = MachinePointerInfo::getStack(MFunction, Offset); - SDValue Store = DAG.getStore(Chain, CLI.DL, Arg, DstAddr, DstInfo); - MemOpChains.push_back(Store); + SDValue Store = DAGraph.getStore(Nodes, CLoweringInfo.DL, Arg, DstAddr, DstInfo); + MemOpNodeChains.push_back(Store); } } - if (!MemOpChains.empty()) - Chain = DAG.getNode(ISD::TokenFactor, CLI.DL, MVT::Other, MemOpChains); + if (!MemOpNodeChains.empty()) + Nodes = DAGraph.getNode(ISD::TokenFactor, CLoweringInfo.DL, MVT::Other, MemOpNodeChains); - SDValue InFlag; + SDValue IFlag; - // Build a sequence of copy-to-reg nodes chained together with token chain and - // flag operands which copy the outgoing args into registers. The InFlag in - // necessary since all emitted instructions must be stuck together. - for (auto &Reg : RegsToPass) { - Chain = DAG.getCopyToReg(Chain, CLI.DL, Reg.first, Reg.second, InFlag); - InFlag = Chain.getValue(1); + // build a node dependency chain and flag operands that copy outgoing args to regs + // All emitted instructions have to be grouped togeher, hence IFLAG + for (auto &CurrentReg : PassingRegs) { + Nodes = DAGraph.getCopyToReg(Nodes, CLoweringInfo.DL, CurrentReg.first, CurrentReg.second, IFlag); + IFlag = Nodes.getValue(1); } - // If the callee is a GlobalAddress node (quite common, every direct call is) - // turn it into a TargetGlobalAddress node so that legalize doesn't hack it. - // Likewise ExternalSymbol -> TargetExternalSymbol. - if (GlobalAddressSDNode *G = dyn_cast(Callee)) { - Callee = DAG.getTargetGlobalAddress(G->getGlobal(), CLI.DL, PtrVT, - G->getOffset(), 0); - } else if (ExternalSymbolSDNode *E = dyn_cast(Callee)) { - Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT, 0); - fail(CLI.DL, DAG, Twine("A call to built-in function '" - + StringRef(E->getSymbol()) - + "' is not supported.")); + // if a GlobalAddress node is the "called" (every direct call is) + // change it to a TargetGlobalAddress so legalize doesnt hack it + // ExternelSymbol -> TargetExternelSymbol + if (GlobalAddressSDNode *GlblAddNode = dyn_cast(Called)) { + Called = DAGraph.getTargetGlobalAddress(GlblAddNode->getGlobal(), CLoweringInfo.DL, PtrVT, + GlblAddNode->getOffset(), 0); + } else if (ExternalSymbolSDNode *ExtSymbNode = dyn_cast(Called)) { + Called = DAGraph.getTargetExternalSymbol(ExtSymbNode->getSymbol(), PtrVT, 0); + if (strcmp(ExtSymbNode->getSymbol(), "__fixsfdi") == 0) { + fail(CLoweringInfo.DL, DAGraph, Twine("Floats are unsupported in XVM")); + exit(1); + } else { + fail(CLoweringInfo.DL, DAGraph, Twine("A call to built-in function '" + + StringRef(ExtSymbNode->getSymbol()) + + "' is not supported.")); + exit(1); + } } - // Returns a chain & a flag for retval copy to use. - SDVTList NodeTys = DAG.getVTList(MVT::Other, MVT::Glue); - SmallVector Ops; - Ops.push_back(Chain); - Ops.push_back(Callee); - Ops.push_back(DAG.getRegisterMask(Mask)); - - // Add argument registers to the end of the list so that they are - // known live into the call. - for (auto &Reg : RegsToPass) - Ops.push_back(DAG.getRegister(Reg.first, Reg.second.getValueType())); - - if (InFlag.getNode()) - Ops.push_back(InFlag); - - Chain = DAG.getNode(XVMISD::CALL, CLI.DL, NodeTys, Ops); - InFlag = Chain.getValue(1); - - // Create the CALLSEQ_END node. - Chain = DAG.getCALLSEQ_END( - Chain, DAG.getConstant(NumBytes, CLI.DL, PtrVT, true), - DAG.getConstant(0, CLI.DL, PtrVT, true), InFlag, CLI.DL); - InFlag = Chain.getValue(1); - - // Handle result values, copying them out of physregs into vregs that we - // return. - return LowerCallResult(Chain, InFlag, CallConv, IsVarArg, Ins, CLI.DL, DAG, - InVals); -} - -SDValue -XVMTargetLowering::LowerReturn(SDValue Chain, CallingConv::ID CallConv, - bool IsVarArg, - const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, - const SDLoc &DL, SelectionDAG &DAG) const { + // Return a chain of nodes and a flag that retval copy can use. + SDVTList NodeTypes = DAGraph.getVTList(MVT::Other, MVT::Glue); + SmallVector Ops; + Ops.push_back(Nodes); + Ops.push_back(Called); + Ops.push_back(DAGraph.getRegisterMask(Mask)); + + // Make argument registers line into the call by appending them to the list + for (auto &RegIter : PassingRegs) + Ops.push_back(DAGraph.getRegister(RegIter.first, RegIter.second.getValueType())); + + if (IFlag.getNode()) + Ops.push_back(IFlag); + + Nodes = DAGraph.getNode(XVMISD::CALL, CLoweringInfo.DL, NodeTypes, Ops); + IFlag = Nodes.getValue(1); + + // CALLSEQ_END node created. + Nodes = DAGraph.getCALLSEQ_END(Nodes, + DAGraph.getConstant(NumBytes, CLoweringInfo.DL, PtrVT, true), + DAGraph.getConstant(0, CLoweringInfo.DL, PtrVT, true), + IFlag, CLoweringInfo.DL); + IFlag = Nodes.getValue(1); + + // copt result values from pregs to the returned vregs + return LowerCallResult(Nodes, IFlag, CallConvention, IsVArg, In, CLoweringInfo.DL, DAGraph, + Vals); +} + +SDValue XVMTargetLowering::LowerReturn(SDValue Nodes, CallingConv::ID CallConv, + bool IsVarArg, + const SmallVectorImpl &Outs, + const SmallVectorImpl &OutVals, + const SDLoc &DLoc, SelectionDAG &DAGraph) const { unsigned Opc = XVMISD::RET_FLAG; // CCValAssign - represent the assignment of the return value to a location - SmallVector RVLocs; - MachineFunction &MF = DAG.getMachineFunction(); + SmallVector RVLocs; + MachineFunction &MFunction = DAGraph.getMachineFunction(); - // CCState - Info about the registers and stack slot. - CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); + // CCState - register and stack slot info. + CCState CCInfo(CallConv, IsVarArg, MFunction, RVLocs, *DAGraph.getContext()); - if (MF.getFunction().getReturnType()->isAggregateType()) { - fail(DL, DAG, "only integer returns supported"); - return DAG.getNode(Opc, DL, MVT::Other, Chain); + if (MFunction.getFunction().getReturnType()->isAggregateType()) { + fail(DLoc, DAGraph, "only integer returns supported"); + return DAGraph.getNode(Opc, DLoc, MVT::Other, Nodes); } - // Analize return values. + // return value analysis CCInfo.AnalyzeReturn(Outs, RetCC_XVM64); - SDValue Flag; - SmallVector RetOps(1, Chain); + SDValue IFlag; + SmallVector RetOps(1, Nodes); - // Copy the result values into the output registers. - for (unsigned i = 0; i != RVLocs.size(); ++i) { - CCValAssign &VA = RVLocs[i]; - assert(VA.isRegLoc() && "Can only return in registers!"); + // insert our results into the output reg. + for (unsigned counter = 0; counter != RVLocs.size(); ++counter) { + CCValAssign &ValIter = RVLocs[counter]; + assert(ValIter.isRegLoc() && "Can only return in registers!"); - Chain = DAG.getCopyToReg(Chain, DL, VA.getLocReg(), OutVals[i], Flag); + Nodes = DAGraph.getCopyToReg(Nodes, DLoc, ValIter.getLocReg(), OutVals[counter], IFlag); // Guarantee that all emitted copies are stuck together, // avoiding something bad. - Flag = Chain.getValue(1); - RetOps.push_back(DAG.getRegister(VA.getLocReg(), VA.getLocVT())); + IFlag = Nodes.getValue(1); + RetOps.push_back(DAGraph.getRegister(ValIter.getLocReg(), ValIter.getLocVT())); } - RetOps[0] = Chain; // Update chain. + RetOps[0] = Nodes; // Update chain. // Add the flag if we have it. - if (Flag.getNode()) - RetOps.push_back(Flag); + if (IFlag.getNode()) + RetOps.push_back(IFlag); - return DAG.getNode(Opc, DL, MVT::Other, RetOps); + return DAGraph.getNode(Opc, DLoc, MVT::Other, RetOps); } SDValue XVMTargetLowering::LowerCallResult( SDValue Chain, SDValue InFlag, CallingConv::ID CallConv, bool IsVarArg, const SmallVectorImpl &Ins, const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const { - MachineFunction &MF = DAG.getMachineFunction(); // Assign locations to each value returned by this call. - SmallVector RVLocs; + SmallVector RVLocs; CCState CCInfo(CallConv, IsVarArg, MF, RVLocs, *DAG.getContext()); - if (Ins.size() >= 2) { + if (Ins.size() >= XVM_MAX_RET_SIZE + 1) { fail(DL, DAG, "only small returns supported"); for (unsigned i = 0, e = Ins.size(); i != e; ++i) InVals.push_back(DAG.getConstant(0, DL, Ins[i].VT)); @@ -627,58 +681,58 @@ SDValue XVMTargetLowering::LowerCallResult( // Copy all of the result registers out of their specified physreg. for (auto &Val : RVLocs) { Chain = DAG.getCopyFromReg(Chain, DL, Val.getLocReg(), - Val.getValVT(), InFlag).getValue(1); - InFlag = Chain.getValue(2); - InVals.push_back(Chain.getValue(0)); + Val.getValVT(), InFlag).getValue(CHAIN_SECOND); + InFlag = Chain.getValue(CHAIN_THIRD); + InVals.push_back(Chain.getValue(CHAIN_FIRST)); } return Chain; } SDValue XVMTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { - SDValue CondV = Op.getOperand(1); + SDValue CondV = Op.getOperand(MO_SECOND); SDLoc DL(Op); if (CondV.getOpcode() == ISD::SETCC && - CondV.getOperand(0).getValueType() == MVT::i64) { - SDValue LHS = CondV.getOperand(0); - SDValue RHS = CondV.getOperand(1); + CondV.getOperand(MO_FIRST).getValueType() == MVT::i64) { + SDValue LHS = CondV.getOperand(MO_FIRST); + SDValue RHS = CondV.getOperand(MO_SECOND); - SDValue TargetCC = CondV.getOperand(2); + SDValue TargetCC = CondV.getOperand(MO_THIRD); return DAG.getNode(XVMISD::BR_CC, DL, Op.getValueType(), - Op.getOperand(0), LHS, RHS, TargetCC, Op.getOperand(2)); + Op.getOperand(MO_FIRST), LHS, RHS, TargetCC, Op.getOperand(MO_THIRD)); } else if (CondV.getOpcode() == ISD::AssertZext && - CondV.getOperand(0).getValueType() == MVT::i64) { - SDValue LHS = CondV.getOperand(0); + CondV.getOperand(MO_FIRST).getValueType() == MVT::i64) { + SDValue LHS = CondV.getOperand(MO_FIRST); SDValue RHS = DAG.getConstant(1, DL, MVT::i64); SDValue TargetCC = DAG.getCondCode(ISD::SETEQ); return DAG.getNode(XVMISD::BR_CC, DL, Op.getValueType(), - Op.getOperand(0), LHS, RHS, TargetCC, Op.getOperand(2)); + Op.getOperand(MO_FIRST), LHS, RHS, TargetCC, Op.getOperand(MO_THIRD)); } else if (CondV.getOpcode() == ISD::AND || CondV.getOpcode() == ISD::OR || - CondV.getOpcode() == ISD::XOR || CondV.getOpcode() == ISD::Constant) { + CondV.getOpcode() == ISD::XOR || CondV.getOpcode() == ISD::Constant || + CondV.getOpcode() == ISD::UADDO || CondV.getOpcode() == ISD::SELECT_CC || + CondV.getOpcode() == ISD::UREM || CondV.getOpcode() == ISD::SRL || + CondV.getOpcode() == ISD::SELECT || CondV.getOpcode() == ISD::SREM) { SDValue LHS = CondV; - if (CondV.getNumOperands()>0) { - LHS = CondV.getOperand(0); - } SDValue RHS = DAG.getConstant(0, DL, MVT::i64); SDValue TargetCC = DAG.getCondCode(ISD::SETNE); return DAG.getNode(XVMISD::BR_CC, DL, Op.getValueType(), - Op.getOperand(0), LHS, RHS, TargetCC, Op.getOperand(2)); + Op.getOperand(MO_FIRST), LHS, RHS, TargetCC, Op.getOperand(MO_THIRD)); } //Note: complete the lowering for other cases later return Op; } SDValue XVMTargetLowering::LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const { - SDValue LHS = Op.getOperand(0); - SDValue RHS = Op.getOperand(1); - SDValue TrueV = Op.getOperand(2); - SDValue FalseV = Op.getOperand(3); - ISD::CondCode CC = cast(Op.getOperand(4))->get(); + SDValue LHS = Op.getOperand(MO_FIRST); + SDValue RHS = Op.getOperand(MO_SECOND); + SDValue TrueV = Op.getOperand(MO_THIRD); + SDValue FalseV = Op.getOperand(MO_FOURTH); + ISD::CondCode CC = cast(Op.getOperand(MO_FIFTH))->get(); SDLoc DL(Op); SDValue TargetCC = DAG.getConstant(CC, DL, LHS.getValueType()); @@ -695,7 +749,7 @@ SDValue XVMTargetLowering::LowerVASTART(SDValue Op, SelectionDAG &DAG) const { int VarArgsFrameIndex = MF.getInfo()->GetVarArgsFrameIndex(); SDValue FrameIndex = DAG.getFrameIndex(VarArgsFrameIndex, getPointerTy(MF.getDataLayout())); - SDValue RetSDValue = DAG.getStore(Op.getOperand(0), SDLoc(Op), FrameIndex, Op.getOperand(1), + SDValue RetSDValue = DAG.getStore(Op.getOperand(MO_FIRST), SDLoc(Op), FrameIndex, Op.getOperand(MO_SECOND), MachinePointerInfo()); // unsigned AddressSpace = 0, int64_t offset = 0 return RetSDValue; @@ -708,10 +762,10 @@ SDValue XVMTargetLowering::LowerVAARG(SDValue Op, SelectionDAG &DAG) const { SDLoc DL(Op); MachinePointerInfo MPI(0U, 0L); EVT PointerType = getPointerTy(DAG.getMachineFunction().getDataLayout()); - SDValue LoadPointer = DAG.getLoad(PointerType, DL, Op.getOperand(0), Op.getOperand(1), MPI); + SDValue LoadPointer = DAG.getLoad(PointerType, DL, Op.getOperand(MO_FIRST), Op.getOperand(MO_SECOND), MPI); SDValue Offset = DAG.getConstant(8, DL, MVT::i64); SDValue AddPointer = DAG.getNode(ISD::ADD, DL, PointerType, LoadPointer, Offset); - SDValue StorePointer = DAG.getStore(LoadPointer.getValue(1), DL, AddPointer, Op.getOperand(1), MPI); + SDValue StorePointer = DAG.getStore(LoadPointer.getValue(1), DL, AddPointer, Op.getOperand(MO_SECOND), MPI); SDValue RetSDValue = DAG.getLoad(Op.getValueType(), DL, StorePointer, LoadPointer, MPI); return RetSDValue; } @@ -737,16 +791,16 @@ const char *XVMTargetLowering::getTargetNodeName(unsigned Opcode) const { } } -SDValue XVMTargetLowering::LowerGlobalAddress(SDValue Op, - SelectionDAG &DAG) const { - auto N = cast(Op); - assert(N->getOffset() == 0 && "Invalid offset for global address"); +SDValue XVMTargetLowering::LowerGlobalAddress(SDValue Oper, + SelectionDAG &DAGraph) const { + auto NIter = cast(Oper); + assert(NIter->getOffset() == 0 && "global address offset invalid"); - SDLoc DL(Op); - const GlobalValue *GV = N->getGlobal(); - SDValue GA = DAG.getTargetGlobalAddress(GV, DL, MVT::i64); + SDLoc DLoc(Oper); + const GlobalValue *GlobVal = NIter->getGlobal(); + SDValue GlobalAdd = DAGraph.getTargetGlobalAddress(GlobVal, DLoc, MVT::i64); - return DAG.getNode(XVMISD::Wrapper, DL, MVT::i64, GA); + return DAGraph.getNode(XVMISD::Wrapper, DLoc, MVT::i64, GlobalAdd); } unsigned @@ -769,55 +823,54 @@ XVMTargetLowering::EmitInstrWithCustomInserterSelectCC(MachineInstr &MI, assert((isSelectRROp || isSelectRIOp) && "Unexpected instr type to insert"); #endif - // To "insert" a SELECT instruction, we actually have to insert the diamond - // control-flow pattern. The incoming instruction knows the destination vreg - // to set, the condition code register to branch on, the true/false values to - // select between, and a branch opcode to use. - const BasicBlock *LLVM_BB = BB->getBasicBlock(); - MachineFunction::iterator I = ++BB->getIterator(); - - // ThisMBB: - // ... - // TrueVal = ... - // jmp_XX r1, r2 goto Copy1MBB - // fallthrough --> Copy0MBB - MachineBasicBlock *ThisMBB = BB; - MachineFunction *F = BB->getParent(); - MachineBasicBlock *Copy0MBB = F->CreateMachineBasicBlock(LLVM_BB); - MachineBasicBlock *Copy1MBB = F->CreateMachineBasicBlock(LLVM_BB); - - F->insert(I, Copy0MBB); - F->insert(I, Copy1MBB); - // Update machine-CFG edges by transferring all successors of the current - // block to the new block which will contain the Phi node for the select. - Copy1MBB->splice(Copy1MBB->begin(), BB, - std::next(MachineBasicBlock::iterator(MI)), BB->end()); - Copy1MBB->transferSuccessorsAndUpdatePHIs(BB); - // Next, add the true and fallthrough blocks as its successors. - BB->addSuccessor(Copy0MBB); - BB->addSuccessor(Copy1MBB); - - // Insert Branch if Flag + // We insert a diamond control-flow pattern, to insert a SELECT instruction + // The incoming instruction holds the branch opcode, the true/false values, + // the condition code register to branch on and the dest vreg + const BasicBlock *LLVM_BasicB = BB->getBasicBlock(); + MachineFunction::iterator Iter = ++BB->getIterator(); + + // CurrentMBBlock: + // TrueValue = ... + // jmp_XX r1, r2 goto Copy1MBBlock + // fallthrough --> Copy0MBBlock + MachineBasicBlock *CurrentMBBlock = BB; + MachineFunction *MFunc = BB->getParent(); + MachineBasicBlock *Copy0MBBlock = MFunc->CreateMachineBasicBlock(LLVM_BasicB); + MachineBasicBlock *Copy1MBBlock = MFunc->CreateMachineBasicBlock(LLVM_BasicB); + + MFunc->insert(Iter, Copy0MBBlock); + MFunc->insert(Iter, Copy1MBBlock); + // The Phi node for the select will be in the new block, transferring + // all successors of the current block to the new one will update the + // machien-CFG edges + Copy1MBBlock->splice(Copy1MBBlock->begin(), BB, + std::next(MachineBasicBlock::iterator(MI)), BB->end()); + Copy1MBBlock->transferSuccessorsAndUpdatePHIs(BB); + // Add the true/fallthrough blocks as its successors. + BB->addSuccessor(Copy0MBBlock); + BB->addSuccessor(Copy1MBBlock); + + // if Flag insert branch int NewCC = getBranchOpcodeFromSelectCC(MI); - Register LHS = MI.getOperand(1).getReg(); + Register LHS = MI.getOperand(MO_SECOND).getReg(); if (isSelectRROp) { - Register RHS = MI.getOperand(2).getReg(); - BuildMI(BB, DL, TII.get(NewCC)).addMBB(Copy1MBB).addReg(LHS).addReg(RHS); + Register RHS = MI.getOperand(MO_THIRD).getReg(); + BuildMI(BB, DL, TII.get(NewCC)).addMBB(Copy1MBBlock).addReg(LHS).addReg(RHS); } else { - int64_t imm32 = MI.getOperand(2).getImm(); + int64_t imm32 = MI.getOperand(MO_THIRD).getImm(); // Check before we build J*_ri instruction. - assert (isInt<32>(imm32)); - if (is_valid_immediate_size(imm32)) { - BuildMI(BB, DL, TII.get(NewCC)).addMBB(Copy1MBB).addReg(LHS).addImm(imm32); + assert (isInt(imm32)); + if (isValidImmediateSize(imm32)) { + BuildMI(BB, DL, TII.get(NewCC)).addMBB(Copy1MBBlock).addReg(LHS).addImm(imm32); } else { Register ScratchReg; - MachineRegisterInfo &MRI = F->getRegInfo(); + MachineRegisterInfo &MRI = MFunc->getRegInfo(); ScratchReg = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); - uint64_t MostSignificantBits = ShiftAndGet16Bits(imm32, 48); - uint64_t UpperMiddleBits = ShiftAndGet16Bits(imm32, 32); - uint64_t LowerMiddleBits = ShiftAndGet16Bits(imm32, 16); - uint64_t LeastSignificantBits = ShiftAndGet16Bits(imm32, 0); + uint64_t MostSignificantBits = shiftAndGet16Bits(imm32, MOST_SIGNIFICANT); + uint64_t UpperMiddleBits = shiftAndGet16Bits(imm32, UPPER_MIDDLE); + uint64_t LowerMiddleBits = shiftAndGet16Bits(imm32, LOWER_MIDDLE); + uint64_t LeastSignificantBits = shiftAndGet16Bits(imm32, LEAST_SIGNIFICANT); Register VRegForMov = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); BuildMI(BB, DL, TII.get(XVM::MOV_ri), VRegForMov).addImm(0); @@ -825,47 +878,47 @@ XVMTargetLowering::EmitInstrWithCustomInserterSelectCC(MachineInstr &MI, if (LeastSignificantBits) { Register VRegForMovk1 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); BuildMI(BB, DL, TII.get(XVM::MOVK_ri), VRegForMovk1) - .addReg(PrevReg).addImm(LeastSignificantBits).addImm(0); + .addReg(PrevReg).addImm(LeastSignificantBits).addImm(MOVK_SHIFT_0); PrevReg = VRegForMovk1; } if (LowerMiddleBits) { Register VRegForMovk2 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); BuildMI(BB, DL, TII.get(XVM::MOVK_ri), VRegForMovk2) - .addReg(PrevReg).addImm(LowerMiddleBits).addImm(0); + .addReg(PrevReg).addImm(LowerMiddleBits).addImm(MOVK_SHIFT_16); PrevReg = VRegForMovk2; } if (UpperMiddleBits) { Register VRegForMovk3 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); BuildMI(BB, DL, TII.get(XVM::MOVK_ri), VRegForMovk3) - .addReg(PrevReg).addImm(UpperMiddleBits).addImm(0); + .addReg(PrevReg).addImm(UpperMiddleBits).addImm(MOVK_SHIFT_32); PrevReg = VRegForMovk3; } if (MostSignificantBits) { Register VRegForMovk4 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); BuildMI(BB, DL, TII.get(XVM::MOVK_ri), VRegForMovk4) - .addReg(PrevReg).addImm(MostSignificantBits).addImm(0); + .addReg(PrevReg).addImm(MostSignificantBits).addImm(MOVK_SHIFT_48); + PrevReg = VRegForMovk4; } - BuildMI(BB, DL, TII.get(NewCC)).addMBB(Copy1MBB).addReg(LHS).addReg(PrevReg); + BuildMI(BB, DL, TII.get(NewCC)).addMBB(Copy1MBBlock).addReg(LHS).addReg(PrevReg); } } - // Copy0MBB: + // Copy0MBBlock: // %FalseValue = ... - // # fallthrough to Copy1MBB - BB = Copy0MBB; - - // Update machine-CFG edges - BB->addSuccessor(Copy1MBB); - - // Copy1MBB: - // %Result = phi [ %FalseValue, Copy0MBB ], [ %TrueValue, ThisMBB ] - // ... - BB = Copy1MBB; - BuildMI(*BB, BB->begin(), DL, TII.get(XVM::PHI), MI.getOperand(0).getReg()) - .addReg(MI.getOperand(5).getReg()) - .addMBB(Copy0MBB) - .addReg(MI.getOperand(4).getReg()) - .addMBB(ThisMBB); + // # fallthrough to Copy1MBBlock + BB = Copy0MBBlock; + + // machine-CFG edges, update + BB->addSuccessor(Copy1MBBlock); + + // Copy1MBBlock: + // %Result = phi [ %FalseValue, Copy0MBBlock ], [ %TrueValue, CurrentMBBlock ] + BB = Copy1MBBlock; + BuildMI(*BB, BB->begin(), DL, TII.get(XVM::PHI), MI.getOperand(MO_FIRST).getReg()) + .addReg(MI.getOperand(MO_SIXTH).getReg()) + .addMBB(Copy0MBBlock) + .addReg(MI.getOperand(MO_FIFTH).getReg()) + .addMBB(CurrentMBBlock); MI.eraseFromParent(); // The pseudo instruction is gone now. return BB; @@ -877,11 +930,11 @@ XVMTargetLowering::EmitInstrWithCustomInserter(MachineInstr &MI, DebugLoc DL = MI.getDebugLoc(); unsigned Opc = MI.getOpcode(); switch (Opc) { - case XVM::PseudoSelectCC_rr: - case XVM::PseudoSelectCC_ri: - return EmitInstrWithCustomInserterSelectCC(MI, BB); - default: - return BB; + case XVM::PseudoSelectCC_rr: + case XVM::PseudoSelectCC_ri: + return EmitInstrWithCustomInserterSelectCC(MI, BB); + default: + return BB; } } @@ -895,26 +948,25 @@ MVT XVMTargetLowering::getScalarShiftAmountTy(const DataLayout &DL, return MVT::i64; } -bool XVMTargetLowering::isLegalAddressingMode(const DataLayout &DL, - const AddrMode &AM, Type *Ty, - unsigned AS, - Instruction *I) const { - // No global is ever allowed as a base. - if (AM.BaseGV) - return false; - - switch (AM.Scale) { - case 0: // "r+i" or just "i", depending on HasBaseReg. - break; - case 1: - if (!AM.HasBaseReg) // allow "r+i". +bool XVMTargetLowering::isLegalAddressingMode(const DataLayout &DLayout, const AddrMode &AMode, + Type *T, unsigned AS, Instruction *Inst) const { + // Globals are never allowed as a base + bool ret = true; + if (AMode.BaseGV) + ret = false; + else + switch (AMode.Scale) { + case 0: // "r+i" or "i", depends on HasBaseReg. break; - return false; // disallow "r+r" or "r+r+i". - default: - return false; - } + case 1: + if (!AMode.HasBaseReg) // "r+i", allowed + break; + ret = false; // "r+r" or "r+r+i", not allowed + default: + ret = false; + } - return true; + return ret; } #endif diff --git a/llvm/lib/Target/XVM/XVMISelLowering.h b/llvm/lib/Target/XVM/XVMISelLowering.h index e631e358d27877e9db1319e63adc74099ed4ab7d..a9feb909343aaf311648e59835842655c2708fd0 100644 --- a/llvm/lib/Target/XVM/XVMISelLowering.h +++ b/llvm/lib/Target/XVM/XVMISelLowering.h @@ -51,7 +51,7 @@ public: bool isOffsetFoldingLegal(const GlobalAddressSDNode *GA) const override; XVMTargetLowering::ConstraintType - getConstraintType(StringRef Constraint) const override; + getConstraintType(StringRef CType) const override; std::pair getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, @@ -67,7 +67,7 @@ public: MVT getScalarShiftAmountTy(const DataLayout &, EVT) const override; private: - const XVMSubtarget *Subtarget; + const XVMSubtarget &Subtarget; SDValue LowerBRCOND(SDValue Op, SelectionDAG &DAG) const; SDValue LowerSELECT_CC(SDValue Op, SelectionDAG &DAG) const; SDValue LowerGlobalAddress(SDValue Op, SelectionDAG &DAG) const; @@ -88,8 +88,8 @@ private: static const unsigned MaxArgs; // Lower a call into CALLSEQ_START - XVMISD:CALL - CALLSEQ_END chain - SDValue LowerCall(TargetLowering::CallLoweringInfo &CLI, - SmallVectorImpl &InVals) const override; + SDValue LowerCall(TargetLowering::CallLoweringInfo &CLoweringInfo, + SmallVectorImpl &Vals) const override; // Lower incoming arguments, copy physregs into vregs SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, @@ -98,10 +98,11 @@ private: const SDLoc &DL, SelectionDAG &DAG, SmallVectorImpl &InVals) const override; - SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + SDValue LowerReturn(SDValue Nodes, CallingConv::ID CallConv, + bool IsVarArg, const SmallVectorImpl &Outs, - const SmallVectorImpl &OutVals, const SDLoc &DL, - SelectionDAG &DAG) const override; + const SmallVectorImpl &OutVals, + const SDLoc &DLoc, SelectionDAG &DAGraph) const override; void ReplaceNodeResults(SDNode *N, SmallVectorImpl &Results, SelectionDAG &DAG) const override; @@ -131,9 +132,8 @@ private: return false; } - bool isLegalAddressingMode(const DataLayout &DL, const AddrMode &AM, - Type *Ty, unsigned AS, - Instruction *I = nullptr) const override; + bool isLegalAddressingMode(const DataLayout &DLayout, const AddrMode &AMode, + Type *T, unsigned AS, Instruction *Inst = nullptr) const override; // isTruncateFree - Return true if it's free to truncate a value of // type Ty1 to type Ty2. e.g. On XVM at alu32 mode, it's free to truncate diff --git a/llvm/lib/Target/XVM/XVMInstrInfo.cpp b/llvm/lib/Target/XVM/XVMInstrInfo.cpp index c4b233cc6576fd3433e8119ad786491cc7ba579d..6eb071424afa97bfcc1b18f8d25626854440897c 100644 --- a/llvm/lib/Target/XVM/XVMInstrInfo.cpp +++ b/llvm/lib/Target/XVM/XVMInstrInfo.cpp @@ -27,73 +27,80 @@ #include "XVMGenInstrInfo.inc" using namespace llvm; +#define NUM_MO_BRANCH_INSTR 3 +#define MO_FIRST 0 +#define MO_SECOND 1 +#define MO_THIRD 2 +#define MO_FOURTH 3 -static CondCode getCondFromBranchOpc(unsigned Opc) { +#define NUM_OF_BRANCHES 2 + +static XVM::CondCode getCondFromBranchOpc(unsigned Opc) { switch (Opc) { default: - return COND_INVALID; + return XVM::COND_INVALID; case XVM::BUEQ_rr: case XVM::BUEQ_ri: case XVM::BSEQ_ri: - return COND_EQ; + return XVM::COND_EQ; case XVM::BSNEQ_rr: case XVM::BSNEQ_ri: - return COND_NE; + return XVM::COND_NE; case XVM::BSGE_rr: case XVM::BSGE_ri: - return COND_GE; + return XVM::COND_GE; case XVM::BUGE_rr: case XVM::BUGE_ri: - return COND_UGE; + return XVM::COND_UGE; case XVM::BSLE_rr: case XVM::BSLE_ri: - return COND_LE; + return XVM::COND_LE; case XVM::BULE_rr: case XVM::BULE_ri: - return COND_ULE; + return XVM::COND_ULE; case XVM::BSGT_rr: case XVM::BSGT_ri: - return COND_GT; + return XVM::COND_GT; case XVM::BUGT_rr: case XVM::BUGT_ri: - return COND_UGT; + return XVM::COND_UGT; case XVM::BSLT_rr: case XVM::BSLT_ri: - return COND_LT; + return XVM::COND_LT; case XVM::BULT_rr: case XVM::BULT_ri: - return COND_ULT; + return XVM::COND_ULT; } } static unsigned getBranchOpcFromCond(ArrayRef &Cond) { - assert(Cond.size() == 3 && "Expected an operation and 2 operands!"); - assert(Cond[0].isImm() && "Expected an imm for operation!"); + assert(Cond.size() == NUM_MO_BRANCH_INSTR && "Expected an operation and 2 operands!"); + assert(Cond[MO_FIRST].isImm() && "Expected an imm for operation!"); - switch (Cond[0].getImm()) { + switch (Cond[MO_FIRST].getImm()) { default: //Invalid operation, bail out return 0; - case COND_EQ: - return Cond[2].isImm() ? XVM::BSEQ_ri : XVM::BUEQ_rr; - case COND_NE: - return Cond[2].isImm() ? XVM::BSNEQ_ri : XVM::BSNEQ_rr; - case COND_GE: - return Cond[2].isImm() ? XVM::BSGE_ri : XVM::BSGE_rr; - case COND_UGE: - return Cond[2].isImm() ? XVM::BUGE_ri : XVM::BUGE_rr; - case COND_LE: - return Cond[2].isImm() ? XVM::BSLE_ri : XVM::BSLE_rr; - case COND_ULE: - return Cond[2].isImm() ? XVM::BULE_ri : XVM::BULE_rr; - case COND_GT: - return Cond[2].isImm() ? XVM::BSGT_ri : XVM::BSGT_rr; - case COND_UGT: - return Cond[2].isImm() ? XVM::BUGT_ri : XVM::BUGT_rr; - case COND_LT: - return Cond[2].isImm() ? XVM::BSLT_ri : XVM::BSLT_rr; - case COND_ULT: - return Cond[2].isImm() ? XVM::BULT_ri : XVM::BULT_rr; + case XVM::COND_EQ: + return Cond[MO_THIRD].isImm() ? XVM::BSEQ_ri : XVM::BUEQ_rr; + case XVM::COND_NE: + return Cond[MO_THIRD].isImm() ? XVM::BSNEQ_ri : XVM::BSNEQ_rr; + case XVM::COND_GE: + return Cond[MO_THIRD].isImm() ? XVM::BSGE_ri : XVM::BSGE_rr; + case XVM::COND_UGE: + return Cond[MO_THIRD].isImm() ? XVM::BUGE_ri : XVM::BUGE_rr; + case XVM::COND_LE: + return Cond[MO_THIRD].isImm() ? XVM::BSLE_ri : XVM::BSLE_rr; + case XVM::COND_ULE: + return Cond[MO_THIRD].isImm() ? XVM::BULE_ri : XVM::BULE_rr; + case XVM::COND_GT: + return Cond[MO_THIRD].isImm() ? XVM::BSGT_ri : XVM::BSGT_rr; + case XVM::COND_UGT: + return Cond[MO_THIRD].isImm() ? XVM::BUGT_ri : XVM::BUGT_rr; + case XVM::COND_LT: + return Cond[MO_THIRD].isImm() ? XVM::BSLT_ri : XVM::BSLT_rr; + case XVM::COND_ULT: + return Cond[MO_THIRD].isImm() ? XVM::BULT_ri : XVM::BULT_rr; } } @@ -114,43 +121,42 @@ void XVMInstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } -static int ShiftAndGet16Bits(uint64_t num, int n) { +static int shiftAndGet16Bits(uint64_t num, int n) { return (num >> n) & 0xFFFF; } -static inline void replace_imm_with_movk(MachineBasicBlock *BB, - MachineBasicBlock::iterator MI, - DebugLoc dl) -{ +static inline void ReplaceImmWithMovk(MachineBasicBlock *BB, + MachineBasicBlock::iterator MI, + DebugLoc dl) { const TargetInstrInfo &TII = *BB->getParent()->getSubtarget().getInstrInfo(); - uint64_t imm = MI->getOperand(2).getImm(); - uint64_t most_significant_bits = ShiftAndGet16Bits(imm, 48); - uint64_t upper_significant_bits = ShiftAndGet16Bits(imm, 32); - uint64_t lower_significant_bits = ShiftAndGet16Bits(imm, 16); - uint64_t least_significant_bits = ShiftAndGet16Bits(imm, 0); - if (least_significant_bits) { + uint64_t imm = MI->getOperand(MO_THIRD).getImm(); + uint64_t MostSignificantBits = shiftAndGet16Bits(imm, MOST_SIGNIFICANT); + uint64_t UpperSignificantBits = shiftAndGet16Bits(imm, UPPER_MIDDLE); + uint64_t LowerSignificantBits = shiftAndGet16Bits(imm, LOWER_MIDDLE); + uint64_t LeastSignificantBits = shiftAndGet16Bits(imm, LEAST_SIGNIFICANT); + if (LeastSignificantBits) { BuildMI(*BB, MI, dl, TII.get(XVM::MOVK_ri)) - .addReg(XVM::R2, RegState::Define).addImm(0).addImm(least_significant_bits).addImm(0); + .addReg(XVM::R2, RegState::Define).addReg(XVM::R2).addImm(LeastSignificantBits).addImm(MOVK_SHIFT_0); } - if (lower_significant_bits) { + if (LowerSignificantBits) { BuildMI(*BB, MI, dl, TII.get(XVM::MOVK_ri)) - .addReg(XVM::R2, RegState::Define).addImm(0).addImm(lower_significant_bits).addImm(1); + .addReg(XVM::R2, RegState::Define).addReg(XVM::R2).addImm(LowerSignificantBits).addImm(MOVK_SHIFT_16); } - if (upper_significant_bits) { + if (UpperSignificantBits) { BuildMI(*BB, MI, dl, TII.get(XVM::MOVK_ri)) - .addReg(XVM::R2, RegState::Define).addImm(0).addImm(upper_significant_bits).addImm(2); + .addReg(XVM::R2, RegState::Define).addReg(XVM::R2).addImm(UpperSignificantBits).addImm(MOVK_SHIFT_32); } - if (most_significant_bits) { + if (MostSignificantBits) { BuildMI(*BB, MI, dl, TII.get(XVM::MOVK_ri)) - .addReg(XVM::R2, RegState::Define).addImm(0).addImm(most_significant_bits).addImm(3); + .addReg(XVM::R2, RegState::Define).addReg(XVM::R2).addImm(MostSignificantBits).addImm(MOVK_SHIFT_48); } } void XVMInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { int func_num = GetFuncIndex("memcpy"); MachineBasicBlock *BB = MI->getParent(); - Register DstReg = MI->getOperand(0).getReg(); - Register SrcReg = MI->getOperand(1).getReg(); + Register DstReg = MI->getOperand(MO_FIRST).getReg(); + Register SrcReg = MI->getOperand(MO_SECOND).getReg(); DebugLoc dl = MI->getDebugLoc(); BuildMI(*BB, MI, dl, get(XVM::LDD)) @@ -158,9 +164,9 @@ void XVMInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { BuildMI(*BB, MI, dl, get(XVM::LDD)) .addReg(XVM::R1, RegState::Define).addReg(SrcReg).addImm(0); if (MI->getOpcode() == XVM::MEMCPY_ri) { - replace_imm_with_movk(BB, MI, dl); + ReplaceImmWithMovk(BB, MI, dl); } else { - Register CopyLen = MI->getOperand(2).getReg(); + Register CopyLen = MI->getOperand(MO_THIRD).getReg(); BuildMI(*BB, MI, dl, get(XVM::LDD)) .addReg(XVM::R2, RegState::Define).addReg(CopyLen).addImm(0); } @@ -172,8 +178,8 @@ void XVMInstrInfo::expandMEMCPY(MachineBasicBlock::iterator MI) const { void XVMInstrInfo::expandMEMMOVE(MachineBasicBlock::iterator MI) const { int func_num = GetFuncIndex("memmove"); MachineBasicBlock *BB = MI->getParent(); - Register DstReg = MI->getOperand(0).getReg(); - Register SrcReg = MI->getOperand(1).getReg(); + Register DstReg = MI->getOperand(MO_FIRST).getReg(); + Register SrcReg = MI->getOperand(MO_SECOND).getReg(); DebugLoc dl = MI->getDebugLoc(); BuildMI(*BB, MI, dl, get(XVM::LDD)) @@ -181,9 +187,9 @@ void XVMInstrInfo::expandMEMMOVE(MachineBasicBlock::iterator MI) const { BuildMI(*BB, MI, dl, get(XVM::LDD)) .addReg(XVM::R1, RegState::Define).addReg(SrcReg).addImm(0); if (MI->getOpcode() == XVM::MEMMOV_ri) { - replace_imm_with_movk(BB, MI, dl); + ReplaceImmWithMovk(BB, MI, dl); } else { - Register CopyLen = MI->getOperand(2).getReg(); + Register CopyLen = MI->getOperand(MO_THIRD).getReg(); BuildMI(*BB, MI, dl, get(XVM::LDD)) .addReg(XVM::R2, RegState::Define).addReg(CopyLen).addImm(0); } @@ -195,8 +201,8 @@ void XVMInstrInfo::expandMEMMOVE(MachineBasicBlock::iterator MI) const { void XVMInstrInfo::expandMEMSET(MachineBasicBlock::iterator MI) const { int func_num = GetFuncIndex("memset"); MachineBasicBlock *BB = MI->getParent(); - Register DstReg = MI->getOperand(0).getReg(); - Register SrcReg = MI->getOperand(1).getReg(); + Register DstReg = MI->getOperand(MO_FIRST).getReg(); + Register SrcReg = MI->getOperand(MO_SECOND).getReg(); DebugLoc dl = MI->getDebugLoc(); BuildMI(*BB, MI, dl, get(XVM::LDD)) @@ -204,9 +210,9 @@ void XVMInstrInfo::expandMEMSET(MachineBasicBlock::iterator MI) const { BuildMI(*BB, MI, dl, get(XVM::LDD)) .addReg(XVM::R1, RegState::Define).addReg(SrcReg).addImm(0); if (MI->getOpcode() == XVM::MEMSET_ri) { - replace_imm_with_movk(BB, MI, dl); + ReplaceImmWithMovk(BB, MI, dl); } else { - Register CopyLen = MI->getOperand(2).getReg(); + Register CopyLen = MI->getOperand(MO_THIRD).getReg(); BuildMI(*BB, MI, dl, get(XVM::LDD)) .addReg(XVM::R2, RegState::Define).addReg(CopyLen).addImm(0); } @@ -288,9 +294,9 @@ bool XVMInstrInfo::analyzeBranch(MachineBasicBlock &MBB, return true; case XVM::BR : if (!HaveCond) - TBB = MI.getOperand(0).getMBB(); + TBB = MI.getOperand(MO_FIRST).getMBB(); else - FBB = MI.getOperand(0).getMBB(); + FBB = MI.getOperand(MO_FIRST).getMBB(); break; case XVM::BUEQ_rr : case XVM::BSNEQ_rr : @@ -316,11 +322,11 @@ bool XVMInstrInfo::analyzeBranch(MachineBasicBlock &MBB, case XVM::BULT_ri : if (HaveCond) return true; - CondCode CC = getCondFromBranchOpc(MI.getOpcode()); + XVM::CondCode CC = getCondFromBranchOpc(MI.getOpcode()); Cond.push_back(MachineOperand::CreateImm(CC)); - Cond.push_back(MI.getOperand(1)); - Cond.push_back(MI.getOperand(2)); - TBB = MI.getOperand(0).getMBB(); + Cond.push_back(MI.getOperand(MO_SECOND)); + Cond.push_back(MI.getOperand(MO_THIRD)); + TBB = MI.getOperand(MO_FIRST).getMBB(); HaveCond = true; break; } @@ -345,15 +351,15 @@ unsigned XVMInstrInfo::insertBranch(MachineBasicBlock &MBB, return 1; } - assert(Cond.size() == 3 && "Expected 2 operands and an operation!"); + assert(Cond.size() == NUM_MO_BRANCH_INSTR && "Expected 2 operands and an operation!"); BuildMI(&MBB, DL, get(getBranchOpcFromCond(Cond))).addMBB(TBB) - .add(Cond[1]) - .add(Cond[2]); + .add(Cond[MO_SECOND]) + .add(Cond[MO_THIRD]); if (!FBB) return 1; BuildMI(&MBB, DL, get(XVM::BR)).addMBB(FBB); - return 2; + return NUM_OF_BRANCHES; } unsigned XVMInstrInfo::removeBranch(MachineBasicBlock &MBB, diff --git a/llvm/lib/Target/XVM/XVMInstrInfo.h b/llvm/lib/Target/XVM/XVMInstrInfo.h index 6e51f396968763179ed5f4c3ffeb28961da835a7..c62e22c80ee3355fc2c97b27d7124062a9977d31 100644 --- a/llvm/lib/Target/XVM/XVMInstrInfo.h +++ b/llvm/lib/Target/XVM/XVMInstrInfo.h @@ -20,7 +20,7 @@ #include "XVMGenInstrInfo.inc" namespace llvm { - +namespace XVM { enum CondCode { COND_EQ, COND_NE, @@ -34,6 +34,7 @@ enum CondCode { COND_ULT, COND_INVALID }; +} class XVMInstrInfo : public XVMGenInstrInfo { const XVMRegisterInfo RI; diff --git a/llvm/lib/Target/XVM/XVMInstrInfo.td b/llvm/lib/Target/XVM/XVMInstrInfo.td index 8bb08ae9ac94248ef062d633c8865733feebae72..2a0fc34c246eac166e2ca36c284101bb5878305d 100644 --- a/llvm/lib/Target/XVM/XVMInstrInfo.td +++ b/llvm/lib/Target/XVM/XVMInstrInfo.td @@ -288,7 +288,7 @@ def : Pat < (sub 0, i64:$src2), (NEG_r i64:$src2)>; // mov combinations def GetMovImm : SDNodeXFormgetTargetConstant( (N->getSExtValue() & 0xffff), SDLoc(N), MVT::i64); + return CurDAG->getTargetConstant( (N->getSExtValue() & 0x7fff), SDLoc(N), MVT::i64); }]>; def GetMovk0Imm : SDNodeXFormgetTargetConstant( (N->getSExtValue() & 0xffff), SDLoc(N), MVT::i64); @@ -321,19 +321,19 @@ def IsOver48Bits : ImmLeaf; def : Pat< (i64 IsOver16Bits:$src1), - (MOVK_ri (MOVK_ri (MOV_ri 0), IsLess16Bits:$src1, 0), IsOver16Bits:$src1, 1) + (MOVK_ri (MOVK_ri (MOV_ri IsLess15Bits:$src1), IsLess16Bits:$src1, 0), IsOver16Bits:$src1, 1) >; def : Pat< (i64 IsOver32Bits:$src1), - (MOVK_ri (MOVK_ri (MOVK_ri (MOV_ri 0), IsLess16Bits:$src1, 0), IsOver16Bits:$src1, 1), IsOver32Bits:$src1, 2) + (MOVK_ri (MOVK_ri (MOVK_ri (MOV_ri IsLess15Bits:$src1), IsLess16Bits:$src1, 0), IsOver16Bits:$src1, 1), IsOver32Bits:$src1, 2) >; def : Pat< (i64 IsOver48Bits:$src1), - (MOVK_ri (MOVK_ri (MOVK_ri (MOVK_ri (MOV_ri 0), IsLess16Bits:$src1, 0), IsOver16Bits:$src1, 1), IsOver32Bits:$src1, 2), IsOver48Bits:$src1, 3) + (MOVK_ri (MOVK_ri (MOVK_ri (MOVK_ri (MOV_ri IsLess15Bits:$src1), IsLess16Bits:$src1, 0), IsOver16Bits:$src1, 1), IsOver32Bits:$src1, 2), IsOver48Bits:$src1, 3) >; @@ -458,4 +458,4 @@ def : Pat<(XVMbrccri i64:$op1, imm:$op2, SETLT, bb:$dst), def : Pat<(XVMbrccri i64:$op1, imm:$op2, SETULT, bb:$dst), (BULT_ri bb:$dst, XVMGPR:$op1, uimm16:$op2)>; -include "XVMInstrBulkMemory.td" \ No newline at end of file +include "XVMInstrBulkMemory.td" diff --git a/llvm/lib/Target/XVM/XVMMCInstLower.cpp b/llvm/lib/Target/XVM/XVMMCInstLower.cpp index ac58ad2c755b83870b41cbf26b14e6793d92ce00..6026d5d1a81c1919e5629df660d98856b61297fa 100644 --- a/llvm/lib/Target/XVM/XVMMCInstLower.cpp +++ b/llvm/lib/Target/XVM/XVMMCInstLower.cpp @@ -12,25 +12,16 @@ //===----------------------------------------------------------------------===// #ifdef XVM_DYLIB_MODE -#include "XVMMCInstLower.h" #include "llvm/CodeGen/AsmPrinter.h" -#include "llvm/CodeGen/MachineBasicBlock.h" -#include "llvm/CodeGen/MachineInstr.h" -#include "llvm/MC/MCAsmInfo.h" -#include "llvm/MC/MCContext.h" -#include "llvm/MC/MCExpr.h" -#include "llvm/MC/MCInst.h" -#include "llvm/Support/ErrorHandling.h" -#include "llvm/Support/raw_ostream.h" +#include "XVMMCInstLower.h" + using namespace llvm; -MCSymbol * -XVMMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { +MCSymbol *XVMMCInstLower::GetGlobalAddressSymbol(const MachineOperand &MO) const { return Printer.getSymbol(MO.getGlobal()); } -MCSymbol * -XVMMCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { +MCSymbol *XVMMCInstLower::GetExternalSymbolSymbol(const MachineOperand &MO) const { return Printer.GetExternalSymbolSymbol(MO.getSymbolName()); } @@ -50,33 +41,32 @@ void XVMMCInstLower::Lower(const MachineInstr *MI, MCInst &OutMI) const { for (const MachineOperand &MO : MI->operands()) { MCOperand MCOp; switch (MO.getType()) { - default: - MI->print(errs()); - llvm_unreachable("unknown operand type"); - case MachineOperand::MO_Register: - // Ignore all implicit register operands. - if (MO.isImplicit()) - continue; - MCOp = MCOperand::createReg(MO.getReg()); - break; case MachineOperand::MO_Immediate: MCOp = MCOperand::createImm(MO.getImm()); break; + case MachineOperand::MO_GlobalAddress: + MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); + break; case MachineOperand::MO_MachineBasicBlock: - MCOp = MCOperand::createExpr( - MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); + MCOp = MCOperand::createExpr(MCSymbolRefExpr::create(MO.getMBB()->getSymbol(), Ctx)); + break; + case MachineOperand::MO_Register: // Ignore all implicit register operands. + if (MO.isImplicit()) + continue; + MCOp = MCOperand::createReg(MO.getReg()); break; case MachineOperand::MO_RegisterMask: continue; case MachineOperand::MO_ExternalSymbol: MCOp = LowerSymbolOperand(MO, GetExternalSymbolSymbol(MO)); break; - case MachineOperand::MO_GlobalAddress: - MCOp = LowerSymbolOperand(MO, GetGlobalAddressSymbol(MO)); - break; + default: + MI->print(errs()); + llvm_unreachable("unknown operand type"); } OutMI.addOperand(MCOp); } } + #endif diff --git a/llvm/lib/Target/XVM/XVMRegisterInfo.cpp b/llvm/lib/Target/XVM/XVMRegisterInfo.cpp index 4466b1826e3187314b0cf6b15d0e3bcc2c162cd9..49d41e471861e23f8d47db38fd7b775bd106c413 100644 --- a/llvm/lib/Target/XVM/XVMRegisterInfo.cpp +++ b/llvm/lib/Target/XVM/XVMRegisterInfo.cpp @@ -29,6 +29,7 @@ using namespace llvm; #define XVM_STACK_SIZE_LIMIT 1024 +#define TEMPLATE_INT_32 32 XVMRegisterInfo::XVMRegisterInfo() : XVMGenRegisterInfo(XVM::R0) {} @@ -43,44 +44,43 @@ BitVector XVMRegisterInfo::getReservedRegs(const MachineFunction &MF) const { return Reserved; } -static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL) -{ - if (Offset <= -512) { - const Function &F = MF.getFunction(); - std::ostringstream OSS; - OSS << "Looks like the XVM stack limit of " << XVM_STACK_SIZE_LIMIT << " bytes is exceeded. " - << "Please move large on stack variables into XVM maps.\n"; - std::string StrCopy = OSS.str(); - DiagnosticInfoUnsupported DiagStackSize(F, StrCopy, DL); - F.getContext().diagnose(DiagStackSize); +static void WarnSize(int Offset, MachineFunction &MF, DebugLoc& DL) { + if (Offset <= -XVM_STACK_SIZE_LIMIT) { + const Function &F = MF.getFunction(); + std::ostringstream OSS; + OSS << "Looks like the XVM stack limit of " << XVM_STACK_SIZE_LIMIT << " bytes is exceeded. " + << "Please move large on stack variables into XVM maps.\n"; + std::string StrCopy = OSS.str(); + DiagnosticInfoUnsupported DiagStackSize(F, StrCopy, DL); + F.getContext().diagnose(DiagStackSize); } } -void XVMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, - int SPAdj, unsigned FIOperandNum, - RegScavenger *RS) const { - assert(SPAdj == 0 && "Unexpected"); - unsigned i = 0; - MachineInstr &MI = *II; - MachineBasicBlock &MBB = *MI.getParent(); - MachineFunction &MF = *MBB.getParent(); - DebugLoc DL = MI.getDebugLoc(); - if (!DL) +void XVMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBIterator, + int AdjStackP, unsigned FIOpNum, + RegScavenger *RegScav) const { + assert(AdjStackP == 0 && "Unexpected"); + unsigned counter = 0; + MachineInstr &MInstr = *MBBIterator; + MachineBasicBlock &MBBlock = *MInstr.getParent(); + MachineFunction &MFunction = *MBBlock.getParent(); + DebugLoc DLoc = MInstr.getDebugLoc(); + if (!DLoc) /* try harder to get some debug loc */ - for (auto &I : MBB) - if (I.getDebugLoc()) { - DL = I.getDebugLoc(); + for (auto &RetryIterator : MBBlock) + if (RetryIterator.getDebugLoc()) { + DLoc = RetryIterator.getDebugLoc(); break; } - while (!MI.getOperand(i).isFI()) { - ++i; - assert(i < MI.getNumOperands() && "Instr doesn't have FrameIndex operand!"); + while (!MInstr.getOperand(counter).isFI()) { + ++counter; + assert(counter < MInstr.getNumOperands() && "Instr doesn't have FrameIndex operand!"); } - Register FrameReg = getFrameRegister(MF); - int FrameIndex = MI.getOperand(i).getIndex(); - const TargetInstrInfo &TII = *MF.getSubtarget().getInstrInfo(); + Register FrameReg = getFrameRegister(MFunction); + int FrameIndex = MInstr.getOperand(counter).getIndex(); + const TargetInstrInfo &TII = *MFunction.getSubtarget().getInstrInfo(); /* Offset from frame index are offsets from FP, * which is pointing at current function's stack bottom (larger address) @@ -92,42 +92,48 @@ void XVMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator II, * it is pointing at (FP - StackSize), and it is fixed during function execution * Therefore, we use SP+(Stacksize + FP_offset) to mimic (FP + FP_offset) */ - auto &MFI = MF.getFrameInfo(); - uint64_t StackSize = MFI.getStackSize(); - - if (MI.getOpcode() == XVM::MOV_rr) { - int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex); - WarnSize(Offset, MF, DL); - Register reg = MI.getOperand(i - 1).getReg(); - BuildMI(MBB, ++II, DL, TII.get(XVM::MOV_rr), reg).addReg(XVM::SP); - if (StackSize + Offset) { - BuildMI(MBB, II, DL, TII.get(XVM::AddRef_ri), reg).addReg(reg).addImm(StackSize + Offset); + auto &MFI = MFunction.getFrameInfo(); + int64_t StackSize = (int64_t)MFI.getStackSize(); + int Offset = 0; + + if (MInstr.getOpcode() == XVM::MOV_rr) { + Offset = MFunction.getFrameInfo().getObjectOffset(FrameIndex); + WarnSize(Offset, MFunction, DLoc); + Register reg = MInstr.getOperand(counter - 1).getReg(); + BuildMI(MBBlock, ++MBBIterator, DLoc, TII.get(XVM::MOV_rr), reg).addReg(XVM::SP); + if (StackSize + Offset > 0) { + BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::AddRef_ri), reg).addReg(reg).addImm(StackSize + Offset); + } else { + BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::SubRef_ri), reg).addReg(reg).addImm(-(StackSize + Offset)); } - MI.eraseFromParent(); + MInstr.eraseFromParent(); return; } - int Offset = MF.getFrameInfo().getObjectOffset(FrameIndex) + - MI.getOperand(i + 1).getImm(); - if (!isInt<32>(Offset)) + Offset = MFunction.getFrameInfo().getObjectOffset(FrameIndex) + MInstr.getOperand(counter + 1).getImm(); + if (!isInt(Offset)) llvm_unreachable("bug in frame offset"); - WarnSize(Offset, MF, DL); + WarnSize(Offset, MFunction, DLoc); - if (MI.getOpcode() == XVM::FI_ri) { + if (MInstr.getOpcode() == XVM::FI_ri) { // Note: to be tested and modified later // architecture does not really support FI_ri, replace it with // MOV_rr , frame_reg // ADD_ri , imm - Register reg = MI.getOperand(i - 1).getReg(); - BuildMI(MBB, ++II, DL, TII.get(XVM::MOV_rr), reg).addReg(FrameReg); - BuildMI(MBB, II, DL, TII.get(XVM::AddRef_ri), reg).addReg(reg).addImm(StackSize + Offset); + Register reg = MInstr.getOperand(counter - 1).getReg(); + BuildMI(MBBlock, ++MBBIterator, DLoc, TII.get(XVM::MOV_rr), reg).addReg(FrameReg); + if (StackSize + Offset > 0) { + BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::AddRef_ri), reg).addReg(reg).addImm(StackSize + Offset); + } else { + BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::SubRef_ri), reg).addReg(reg).addImm(-(StackSize + Offset)); + } // Remove FI_ri instruction - MI.eraseFromParent(); + MInstr.eraseFromParent(); } else { - MI.getOperand(i).ChangeToRegister(FrameReg, false); - MI.getOperand(i + 1).ChangeToImmediate(StackSize + Offset); + MInstr.getOperand(counter).ChangeToRegister(FrameReg, false); + MInstr.getOperand(counter + 1).ChangeToImmediate(StackSize + Offset); } } @@ -146,4 +152,5 @@ XVMRegisterInfo::getCallPreservedMask(const MachineFunction &MF, CallingConv::ID CC) const { return CSR_RegMask; } + #endif diff --git a/llvm/lib/Target/XVM/XVMRegisterInfo.h b/llvm/lib/Target/XVM/XVMRegisterInfo.h index 2a5221d08a11d34b7d64e5b96b069d2665c62b35..ab1b798127454031094979629922de91c0ac68de 100644 --- a/llvm/lib/Target/XVM/XVMRegisterInfo.h +++ b/llvm/lib/Target/XVM/XVMRegisterInfo.h @@ -28,9 +28,9 @@ struct XVMRegisterInfo : public XVMGenRegisterInfo { BitVector getReservedRegs(const MachineFunction &MF) const override; - void eliminateFrameIndex(MachineBasicBlock::iterator MI, int SPAdj, + void eliminateFrameIndex(MachineBasicBlock::iterator MInstr, int AdjStackP, unsigned FIOperandNum, - RegScavenger *RS = nullptr) const override; + RegScavenger *RegScav = nullptr) const override; Register getFrameRegister(const MachineFunction &MF) const override; diff --git a/llvm/lib/Target/XVM/XVMSelectionDAGInfo.cpp b/llvm/lib/Target/XVM/XVMSelectionDAGInfo.cpp index c2462ef33869157688b2a47aa4bc96daa985d08b..9acd3e0ce9d2006be0e6be7173dc1dc47919b79d 100644 --- a/llvm/lib/Target/XVM/XVMSelectionDAGInfo.cpp +++ b/llvm/lib/Target/XVM/XVMSelectionDAGInfo.cpp @@ -71,4 +71,5 @@ SDValue XVMSelectionDAGInfo::EmitTargetCodeForMemset( } return Op1.getValue(0); } + #endif diff --git a/llvm/lib/Target/XVM/XVMSubtarget.cpp b/llvm/lib/Target/XVM/XVMSubtarget.cpp index 722d55c35e097556e11cb5721c50e864756a22a0..ff7b89002d0c2fd011cc5c8d0330a7f855cec622 100644 --- a/llvm/lib/Target/XVM/XVMSubtarget.cpp +++ b/llvm/lib/Target/XVM/XVMSubtarget.cpp @@ -16,7 +16,6 @@ #include "llvm/MC/TargetRegistry.h" #include "llvm/Support/Host.h" - #define DEBUG_TYPE "xvm-subtarget" #define GET_SUBTARGETINFO_TARGET_DESC diff --git a/llvm/lib/Target/XVM/XVMTargetMachine.cpp b/llvm/lib/Target/XVM/XVMTargetMachine.cpp index f7435f9a193c65b47e6914e074b5932a76f88065..eb05f7cc25aa260c8c4dc4c1559d295210467866 100644 --- a/llvm/lib/Target/XVM/XVMTargetMachine.cpp +++ b/llvm/lib/Target/XVM/XVMTargetMachine.cpp @@ -16,21 +16,21 @@ #include "XVM.h" #include "XVMTargetTransformInfo.h" #include "MCTargetDesc/XVMMCAsmInfo.h" -#include "TargetInfo/XVMTargetInfo.h" -#include "llvm/CodeGen/Passes.h" -#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" -#include "llvm/CodeGen/TargetPassConfig.h" -#include "llvm/IR/LegacyPassManager.h" -#include "llvm/IR/PassManager.h" #include "llvm/MC/TargetRegistry.h" -#include "llvm/Passes/PassBuilder.h" -#include "llvm/Support/FormattedStream.h" -#include "llvm/Target/TargetOptions.h" -#include "llvm/Transforms/IPO/PassManagerBuilder.h" +#include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "TargetInfo/XVMTargetInfo.h" #include "llvm/Transforms/Scalar.h" -#include "llvm/Transforms/Scalar/SimplifyCFG.h" -#include "llvm/Transforms/Utils/SimplifyCFGOptions.h" +#include "llvm/CodeGen/TargetPassConfig.h" #include "llvm/Transforms/Utils.h" +#include "llvm/Transforms/Scalar/DeadStoreElimination.h" +#include "llvm/InitializePasses.h" +#include "llvm/Transforms/Scalar/GVN.h" +#include "llvm/Transforms/Vectorize.h" +#include "llvm/Transforms/IPO.h" +#include "llvm/Transforms/InstCombine/InstCombine.h" +#include "llvm/Transforms/Scalar/SimpleLoopUnswitch.h" +#include "llvm/Transforms/AggressiveInstCombine/AggressiveInstCombine.h" + using namespace llvm; @@ -45,6 +45,39 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXVMTarget() { initializeXVMCFGStackifyPass(PR); initializeXVMCFGStructurePass(PR); initializeXVMUpdateRefInstrForMIPass(PR); + initializeDSELegacyPassPass(PR); + initializeJumpThreadingPass(PR); + + // initializeMachineCSEPass(PR); + // initializeCorrelatedValuePropagationPass(PR); + // initializeInstructionCombiningPassPass(PR); + // initializeSimpleLoopUnswitchLegacyPassPass(PR); + // initializeAggressiveInstCombinerLegacyPassPass(PR); + + // initializeCallSiteSplittingLegacyPassPass(PR); + // initializeFunctionSpecializationLegacyPassPass(PR); + + + // initializeConstantMergeLegacyPassPass(PR); + // initializeGlobalDCELegacyPassPass(PR); + // initializeEliminateAvailableExternallyLegacyPassPass(PR); + // initializeGVNLegacyPassPass(PR); + + // initializeLoopUnrollAndJamPass(PR); + // initializeLoopUnrollPass(PR); + + // // initializeLoopFuseLegacyPass(PR); + // initializeLoopDataPrefetchLegacyPassPass(PR); + // initializeLoopDeletionLegacyPassPass(PR); + // initializeLoopAccessLegacyAnalysisPass(PR); + // initializeLoopInstSimplifyLegacyPassPass(PR); + // initializeLoopInterchangeLegacyPassPass(PR); + // initializeLoopFlattenLegacyPassPass(PR); + // initializeLoopPredicationLegacyPassPass(PR); + // initializeLoopRotateLegacyPassPass(PR); + // initializeLoopStrengthReducePass(PR); + + // initializeBasicBlockSectionsPass(PR); } extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXVMTargetCalledInDylib() { @@ -62,20 +95,21 @@ static Reloc::Model getEffectiveRelocModel(Optional RM) { return RM.value_or(Reloc::PIC_); } -XVMTargetMachine::XVMTargetMachine(const Target &T, const Triple &TT, - StringRef CPU, StringRef FS, +XVMTargetMachine::XVMTargetMachine(const Target &Target, const Triple &TTriple, + StringRef Core, StringRef FString, const TargetOptions &Options, - Optional RM, - Optional CM, - CodeGenOpt::Level OL, bool JIT) - : LLVMTargetMachine(T, computeDataLayout(TT), TT, CPU, FS, Options, - getEffectiveRelocModel(RM), - getEffectiveCodeModel(CM, CodeModel::Small), OL), - TLOF(std::make_unique()), - Subtarget(TT, std::string(CPU), std::string(FS), *this) { + Optional RelocMdl, + Optional CodeMdl, + CodeGenOpt::Level OptLvl, bool JustInTime) + : LLVMTargetMachine(Target, computeDataLayout(TTriple), + TTriple, Core, FString, Options, + getEffectiveRelocModel(RelocMdl), + getEffectiveCodeModel(CodeMdl, CodeModel::Small), + OptLvl), + TLOF(std::make_unique()), + Subtarget(TTriple, std::string(Core), std::string(FString), *this) { initAsmInfo(); this->Options.EmitAddrsig = false; - setRequiresStructuredCFG(true); } @@ -101,6 +135,39 @@ public: bool XVMPassConfig::addPreISel() { addPass(createFlattenCFGPass()); addPass(createFixIrreduciblePass()); + addPass(createDeadStoreEliminationPass()); + addPass(createJumpThreadingPass(-1)); + addPass(createSpeculativeExecutionPass()); + addPass(createMergedLoadStoreMotionPass()); + + // addPass(createEarlyCSEPass()); + // addPass(createCorrelatedValuePropagationPass()); + // addPass(createInstructionCombiningPass()); + // addPass(createSimpleLoopUnswitchLegacyPass(true)); + // addPass(createAggressiveInstCombinerPass()); + // addPass(createCallSiteSplittingPass()); + // addPass(createFunctionSpecializationPass()); + + // addPass(createConstantMergePass()); + // addPass(createGlobalDCEPass()); + // addPass(createEliminateAvailableExternallyPass()); + // addPass(createTailCallEliminationPass()); + // addPass(createGVNPass(false)); + + // addPass(createLoopUnrollAndJamPass(3)); + // addPass(createLoopUnrollPass(3)); + + // // addPass(createLoopFusePass()); + // addPass(createLoopDataPrefetchPass()); + // addPass(createLoopDeletionPass()); + // // addPass(createLoopAccessLegacyAnalysisPass()); + // addPass(createLoopInstSimplifyPass()); + // addPass(createLoopInterchangePass()); + // addPass(createLoopFlattenPass()); + // addPass(createLoopPredicationPass()); + // addPass(createLoopRotatePass()); + // addPass(createLoopStrengthReducePass()); + return false; } @@ -134,6 +201,8 @@ void XVMPassConfig::addPreEmitPass() { // Sort the blocks of the CFG into topological order, // a prerequisite for BLOCK and LOOP markers. // Currently, the algorithm is from WebAssembly. + + // addPass(createBasicBlockSectionsPass()); addPass(createXVMCFGSort()); addPass(createXVMCFGStackify()); } diff --git a/llvm/lib/Target/XVM/XVMTargetMachine.h b/llvm/lib/Target/XVM/XVMTargetMachine.h index 3b25b0f1e89a9ce9c636b7af02bc0391b197f1bc..6d4146c29b1977ec0f0a7b55a068a86fb3639fe1 100644 --- a/llvm/lib/Target/XVM/XVMTargetMachine.h +++ b/llvm/lib/Target/XVM/XVMTargetMachine.h @@ -22,10 +22,10 @@ class XVMTargetMachine : public LLVMTargetMachine { XVMSubtarget Subtarget; public: - XVMTargetMachine(const Target &T, const Triple &TT, StringRef CPU, - StringRef FS, const TargetOptions &Options, - Optional RM, Optional CM, - CodeGenOpt::Level OL, bool JIT); + XVMTargetMachine(const Target &Target, const Triple &TTriple, + StringRef Core, StringRef FString, const TargetOptions &Options, + Optional RelocMdl, Optional CodeMdl, + CodeGenOpt::Level OptLvl, bool JustInTime); const XVMSubtarget *getSubtargetImpl() const { return &Subtarget; } const XVMSubtarget *getSubtargetImpl(const Function &) const override { diff --git a/llvm/lib/Target/XVM/XVMTargetTransformInfo.h b/llvm/lib/Target/XVM/XVMTargetTransformInfo.h index 2194866b6ab0ffb5fb834abf484aef2ddb24ae0d..ecf6960157c90946603c1c44c064a754fed2b5c3 100644 --- a/llvm/lib/Target/XVM/XVMTargetTransformInfo.h +++ b/llvm/lib/Target/XVM/XVMTargetTransformInfo.h @@ -20,6 +20,7 @@ #include "llvm/CodeGen/BasicTTIImpl.h" #include "llvm/Transforms/Utils/ScalarEvolutionExpander.h" +#define TEMPLATE_INT_32 32 namespace llvm { class XVMTTIImpl : public BasicTTIImplBase { typedef BasicTTIImplBase BaseT; @@ -38,7 +39,7 @@ public: TLI(ST->getTargetLowering()) {} int getIntImmCost(const APInt &Imm, Type *Ty, TTI::TargetCostKind CostKind) { - if (Imm.getBitWidth() <= 64 && isInt<32>(Imm.getSExtValue())) + if (Imm.getBitWidth() <= 64 && isInt(Imm.getSExtValue())) return TTI::TCC_Free; return TTI::TCC_Basic; @@ -56,11 +57,11 @@ public: } InstructionCost getArithmeticInstrCost( - unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, - TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, - TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, - TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, - TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None, + unsigned Opcode, Type *Ty, TTI::TargetCostKind CostKind, + TTI::OperandValueKind Opd1Info = TTI::OK_AnyValue, + TTI::OperandValueKind Opd2Info = TTI::OK_AnyValue, + TTI::OperandValueProperties Opd1PropInfo = TTI::OP_None, + TTI::OperandValueProperties Opd2PropInfo = TTI::OP_None, ArrayRef Args = ArrayRef(), const Instruction *CxtI = nullptr) { int ISD = TLI->InstructionOpcodeToISD(Opcode); diff --git a/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp b/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp index 11bdb0aad565bd82b0933de74e27a447b9b73f96..6b9fbc6dbe9f6d0a233ec6f29415d3ba45b80317 100644 --- a/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp +++ b/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp @@ -4,6 +4,7 @@ #include "XVM_def.h" #include "XVMInstrInfo.h" #include "XVMTargetMachine.h" +#include "XVMErrorMsg.h" #include "llvm/CodeGen/MachineFunctionPass.h" #include "llvm/CodeGen/MachineInstrBuilder.h" #include "MCTargetDesc/XVMInstPrinter.h" @@ -16,6 +17,27 @@ using namespace llvm; #define XVM_REF_DETERMINE_NAME "XVM pseudo instruction ref determine pass" #define XVM_SYM_REG_NON_REF 0b00000000 #define XVM_SYM_REG_REF 0b00000001 +#define XVM_MAX_NUM_PARAM 5 +#define SRET_REG_NUM 6 +#define NUM_MO_2 2 +#define NUM_MO_3 3 + +#define MO_FIRST 0 +#define MO_SECOND 1 +#define MO_THIRD 2 +#define MAX_IMM 8191 + +/** mov rd #simm (16 bits) + * movk rd, #uimm (16 bits), #shift (0:no 1:16bits 2:32bits 3:48bits) + * addref rd, rn, #uimm (14bits) + */ +#define NUM_OF_IMM_BITS_ADDREF 14 +#define NUM_OF_IMM_BITS_MOV 16 +#define NUM_OF_IMM_BITS_MOVK1 32 +#define NUM_OF_IMM_BITS_MOVK2 48 + +#define NUM_MO_PER_PHI_BRANCH 2 +#define INIT_SMALL_VECTOR_SIZE 4 namespace { class XVMUpdateRefInstrForMI : public MachineFunctionPass { @@ -28,17 +50,71 @@ public: bool runOnMachineFunction(MachineFunction &MF) override; StringRef getPassName() const override { return XVM_REF_DETERMINE_NAME; } private: - bool updateRefInfoInMBB(MachineBasicBlock &MBB); + bool scanRefInfoInMBB(MachineBasicBlock &MBB); + bool forceShiftRefInfoIbMBB(MachineBasicBlock &MBB); + bool forceAddSubRefInfoIbMBB(MachineBasicBlock &MBB); + bool updateRefInfoBasedInMBB(MachineBasicBlock &MBB); + bool checkAndUpdateOrInMBB(MachineBasicBlock &MBB); void updatePtrRefInMBB(MachineBasicBlock &MBB); + void doubleCheckPhiMIWithRef(MachineBasicBlock &MBB); + void doubleCheckRefs(MachineBasicBlock &MBB); + void checkAndReplaceAddWithAddRefs(MachineBasicBlock &MBB); + bool updateRegistersOfMIInMBB(MachineBasicBlock &MBB); + bool finalFixRefs(void); void FindNonRefRegInFunc(const MachineFunction &MF); }; char XVMUpdateRefInstrForMI::ID = 0; } +static std::map MapMIToBeFixed; static std::map MapRefRegInFunc; static std::map MapPtrRegInFunc; static std::set SetNonRefRegInFunc; +static bool IsValidRefOpCode(unsigned OpCode) { + switch (OpCode) { + case XVM::ADD_ri: + case XVM::ADD_rr: + case XVM::SUB_ri: + case XVM::SUB_rr: + case XVM::OR_ri: + case XVM::OR_rr: + case XVM::XOR_ri: + case XVM::XOR_rr: + case XVM::AND_ri: + case XVM::AND_rr: + case XVM::STW: + case XVM::STH: + case XVM::STB: + case XVM::STD: + case XVM::LDW_z: + case XVM::LDH_z: + case XVM::LDB_z: + case XVM::LDW: + case XVM::LDH: + case XVM::LDB: + case XVM::LDD: + case XVM::MOV_rr: + return true; + default: + return false; + } +} + +static inline void SetRegTypeForMO(MachineOperand &MO, unsigned char RegType) { + if (MO.isReg()) { + Register regNo = MO.getReg(); + std::map::iterator I = MapRefRegInFunc.find(regNo); + if (I == MapRefRegInFunc.end()) { + MapRefRegInFunc.insert(std::pair(regNo, RegType)); + } else { + if (IsValidRefOpCode(MO.getParent()->getOpcode())) { + MapRefRegInFunc[regNo] = MapRefRegInFunc[regNo] | RegType; + } + } + } +} + static void CheckFunctionReturn(Function &F) { Type *Ty = F.getReturnType(); /* Return is always r0 for xvm */ @@ -54,28 +130,28 @@ static void CheckFunctionReturn(Function &F) { } static Register inline getPhysicalRegister(unsigned index) { - switch (index) { - case 0: return XVM::R0; - case 1: return XVM::R1; - case 2: return XVM::R2; - case 3: return XVM::R3; - case 4: return XVM::R4; - case 5: return XVM::R5; - case 6: return XVM::R6; - case 7: return XVM::R7; - case 8: return XVM::R8; - case 9: return XVM::R9; - case 10: return XVM::R10; - case 11: return XVM::R11; - case 12: return XVM::R12; - case 13: return XVM::R13; - case 14: return XVM::R14; - case 15: return XVM::R15; - case 16: return XVM::R16; - case 17: return XVM::R17; - default: - llvm_unreachable("Invalid physical register index"); - } + switch (index) { + case 0: return XVM::R0; + case 1: return XVM::R1; + case 2: return XVM::R2; + case 3: return XVM::R3; + case 4: return XVM::R4; + case 5: return XVM::R5; + case 6: return XVM::R6; + case 7: return XVM::R7; + case 8: return XVM::R8; + case 9: return XVM::R9; + case 10: return XVM::R10; + case 11: return XVM::R11; + case 12: return XVM::R12; + case 13: return XVM::R13; + case 14: return XVM::R14; + case 15: return XVM::R15; + case 16: return XVM::R16; + case 17: return XVM::R17; + default: + llvm_unreachable("Invalid physical register index"); + } } static void CheckFunctionArgs(Function &F) { @@ -85,55 +161,56 @@ static void CheckFunctionArgs(Function &F) { * it is handled with check/update steps followed. */ for (Function::const_arg_iterator I = F.arg_begin(), E = F.arg_end(); I != E; ++I) { - if (idx > 5) { + if (idx > XVM_MAX_NUM_PARAM) { break; } Type *Ty = I->getType(); std::string regName = "r" + itostr(idx); if (auto *PTy = dyn_cast(Ty)) { - LLVM_DEBUG(dbgs() << "arg[" << idx << "]=" << I->getName().data() << ' is ref.\n'); + LLVM_DEBUG(dbgs() << "arg[" << idx << "]=" << I->getName().data() << " is ref.\n"); if (!I->hasAttribute(Attribute::StructRet)) { MapRefRegInFunc.insert(std::pair(getPhysicalRegister(idx), XVM_SYM_REG_REF)); } else { // R6 is used to pass the sret return - MapRefRegInFunc.insert(std::pair(getPhysicalRegister(6), XVM_SYM_REG_REF)); + MapRefRegInFunc.insert(std::pair(getPhysicalRegister(SRET_REG_NUM), + XVM_SYM_REG_REF)); } } else if (Ty->isIntegerTy()) { MapRefRegInFunc.insert(std::pair(getPhysicalRegister(idx), XVM_SYM_REG_NON_REF)); - LLVM_DEBUG(dbgs() << "arg[" << idx << "]=" << I->getName().data() << ' is not ref.\n'); + LLVM_DEBUG(dbgs() << "arg[" << idx << "]=" << I->getName().data() << " is not ref.\n"); } else { - llvm_unreachable("Invalid param type"); + LLVM_DEBUG(dbgs() << "XVM Error: Invalid param type"); } idx++; } } static void setRefFlagFor2Ops(MachineOperand &MO_def, MachineOperand &MO_use) { - /* verify def */ - if (MO_def.isReg()) { - if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { - llvm_unreachable("unhandled Operand!!"); - } + /* verify def */ + if (MO_def.isReg()) { + if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { + llvm_unreachable("unhandled Operand!!"); } - /* check use */ - if (MO_use.isReg()) { - if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { - llvm_unreachable("unhandled Operand!!"); - } - Register regNo = MO_use.getReg(); - std::map::iterator I = MapRefRegInFunc.find(regNo); - if (I == MapRefRegInFunc.end()) { - MapRefRegInFunc.insert(std::pair(MO_def.getReg(), XVM_SYM_REG_NON_REF)); - } else { - MapRefRegInFunc.insert(std::pair(MO_def.getReg(), I->second)); - } + } + /* check use */ + if (MO_use.isReg()) { + if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { + llvm_unreachable("unhandled Operand!!"); + } + Register regNo = MO_use.getReg(); + std::map::iterator I = MapRefRegInFunc.find(regNo); + if (I == MapRefRegInFunc.end()) { + SetRegTypeForMO(MO_def, XVM_SYM_REG_NON_REF); + } else { + SetRegTypeForMO(MO_def, I->second); } + } } static inline void updateRefMapForRefInst(MachineOperand &MO_use, unsigned char flag) { std::map::iterator I1 = MapRefRegInFunc.find(MO_use.getReg()); if (I1 == MapRefRegInFunc.end()) { - MapRefRegInFunc.insert(std::pair(MO_use.getReg(), flag)); + SetRegTypeForMO(MO_use, flag); } else I1->second = flag; @@ -141,9 +218,9 @@ static inline void updateRefMapForRefInst(MachineOperand &MO_use, unsigned char static void checkSimpleMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::COPY) { - assert(MI.getNumOperands() == 2); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_2); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); setRefFlagFor2Ops(MO_def, MO_use); } } @@ -155,15 +232,18 @@ static bool updateCopyMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { static void checkMovMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::MOV_rr) { - assert(MI.getNumOperands() == 2); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_2); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); setRefFlagFor2Ops(MO_def, MO_use); + if (MO_use.isFI()) { + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + } } if (MI.getOpcode() == XVM::MOV_ri) { - assert(MI.getNumOperands() == 2); - MachineOperand &MO_def = MI.getOperand(0); - MapRefRegInFunc.insert(std::pair(MO_def.getReg(), XVM_SYM_REG_NON_REF)); + assert(MI.getNumOperands() == NUM_MO_2); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + SetRegTypeForMO(MO_def, XVM_SYM_REG_NON_REF); } } @@ -176,96 +256,100 @@ static void checkLoadMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::LDB || MI.getOpcode() == XVM::LDH || MI.getOpcode() == XVM::LDW || MI.getOpcode() == XVM::LDB_z || MI.getOpcode() == XVM::LDH_z || MI.getOpcode() == XVM::LDW_z || MI.getOpcode() == XVM::LDD) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); /* verify def */ if (MO_def.isReg()) { - if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { - llvm_unreachable("unhandled Operand!!"); - } + if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { + llvm_unreachable("unhandled Operand!!"); + } } /* check use */ if (MO_use.isReg()) { - if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { - llvm_unreachable("unhandled Operand!!"); - } - // always be ref - MapRefRegInFunc.insert(std::pair(MO_use.getReg(), XVM_SYM_REG_REF)); + if (!MO_def.isDef() && !MO_def.isImplicit() && !MO_def.isKill()) { + llvm_unreachable("unhandled Operand!!"); + } + // always be ref + SetRegTypeForMO(MO_use, XVM_SYM_REG_REF); } } if (MI.getOpcode() == XVM::LD_global_imm64) { - assert(MI.getNumOperands() == 2); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_2); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); if (MO_use.isGlobal()) { - LLVM_DEBUG(dbgs() << "Global:" << MO_use.getGlobal()->getName().data() << ' to load.\n'); - MapRefRegInFunc.insert(std::pair(MO_def.getReg(), XVM_SYM_REG_REF)); + LLVM_DEBUG(dbgs() << "Global:" << MO_use.getGlobal()->getName().data() << " to load.\n"); + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); } } } static bool updateLoadMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { if (MI.getOpcode() == XVM::LDD) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be ldrref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - MI.setDesc(TII->get(XVM::LoadRef_ri)); - return true; - } + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + MI.setDesc(TII->get(XVM::LoadRef_ri)); + return true; + } } } return false; } -static void checkAddSubMIWithRef(MachineInstr &MI) { - if (MI.getOpcode() == XVM::ADD_ri || MI.getOpcode() == XVM::ADD_rr || - MI.getOpcode() == XVM::SUB_ri || MI.getOpcode() == XVM::SUB_rr) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); - setRefFlagFor2Ops(MO_def, MO_use); - return; - } -} - static void checkOrXorAndMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::OR_ri || MI.getOpcode() == XVM::XOR_ri|| MI.getOpcode() == XVM::AND_ri) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); setRefFlagFor2Ops(MO_def, MO_use); return; } if (MI.getOpcode() == XVM::OR_rr || MI.getOpcode() == XVM::XOR_rr|| MI.getOpcode() == XVM::AND_rr) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); - setRefFlagFor2Ops(MO_def, MO_use); - // MO_use2 should not be ref; - MachineOperand &MO_use2 = MI.getOperand(2); - updateRefMapForRefInst(MO_use2, XVM_SYM_REG_NON_REF); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + Register regNo1 = MO_use.getReg(); + Register regNo2 = MO_use2.getReg(); + std::map::iterator I1 = MapRefRegInFunc.find(regNo1); + std::map::iterator I2 = MapRefRegInFunc.find(regNo2); + if (I1 != MapRefRegInFunc.end() && I1->second == XVM_SYM_REG_REF) { + if (I2 != MapRefRegInFunc.end() && I2->second == XVM_SYM_REG_REF) { + ; + } else { + setRefFlagFor2Ops(MO_def, MO_use); + } + } else { + if (I2 != MapRefRegInFunc.end() && I2->second == XVM_SYM_REG_REF) { + setRefFlagFor2Ops(MO_def, MO_use); + setRefFlagFor2Ops(MO_def, MO_use2); + } else { + ; + } + } return; } } static inline bool updateAddSubWithSubAddForImm(MachineInstr &MI, const XVMInstrInfo *TII) { if (MI.getOpcode() == XVM::ADD_ri || MI.getOpcode() == XVM::SUB_ri) { - assert(MI.getOperand(2).isImm()); - int64_t imm = MI.getOperand(2).getImm(); + assert(MI.getOperand(MO_THIRD).isImm()); + int64_t imm = MI.getOperand(MO_THIRD).getImm(); if (imm < 0) { imm = -imm; - MI.getOperand(2).setImm(imm); + MI.getOperand(MO_THIRD).setImm(imm); if (MI.getOpcode() == XVM::ADD_ri) { MI.setDesc(TII->get(XVM::SUB_ri)); return true; @@ -279,11 +363,11 @@ static inline bool updateAddSubWithSubAddForImm(MachineInstr &MI, const XVMInstr } static inline void updateAddRiWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getOperand(2).isImm()); - int64_t imm = MI.getOperand(2).getImm(); + assert(MI.getOperand(MO_THIRD).isImm()); + int64_t imm = MI.getOperand(MO_THIRD).getImm(); if (imm < 0) { imm = -imm; - MI.getOperand(2).setImm(imm); + MI.getOperand(MO_THIRD).setImm(imm); MI.setDesc(TII->get(XVM::SubRef_ri)); } else { MI.setDesc(TII->get(XVM::AddRef_ri)); @@ -291,27 +375,63 @@ static inline void updateAddRiWithRef(MachineInstr &MI, const XVMInstrInfo *TII) } static inline bool updateAddMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be addref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); // Update instr if MO_def is ref if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - // Update MO_use to be ref if MO_def is ref - updateRefMapForRefInst(MO_use, XVM_SYM_REG_REF); - if (MI.getOpcode() == XVM::ADD_ri) + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + // Update MO_use1 to be ref if MO_def is ref + if (MI.getOpcode() == XVM::ADD_ri) { + updateRefMapForRefInst(MO_use1, XVM_SYM_REG_REF); updateAddRiWithRef(MI, TII); - else - MI.setDesc(TII->get(XVM::AddRef_rr)); + } else { + // It may be the case there use2 is a ref while use1 is not a ref + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + Register regNoUse1 = MO_use1.getReg(); + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator ItrUse1 = MapRefRegInFunc.find(regNoUse1); + std::map::iterator ItrUse2 = MapRefRegInFunc.find(regNoUse2); + if (ItrUse2 != MapRefRegInFunc.end()) { + if (ItrUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + // Now Use2 is a ref: we need to Switch Operand1 and Operand2 + updateRefMapForRefInst(MO_use1, XVM_SYM_REG_NON_REF); + + // by create a new MI + MachineBasicBlock::iterator II = MI.getIterator(); + MachineBasicBlock &MBB = *MI.getParent(); + MachineFunction *MF = MBB.getParent(); + DebugLoc DL = MI.getDebugLoc(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstr *ReplaceMI = BuildMI(MBB, II, DL, TII->get(XVM::AddRef_rr)); + + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + + ReplaceMI->addOperand(MO_def); + ReplaceMI->addOperand(MO_use2); + ReplaceMI->addOperand(MO_use1); + + MBB.remove_instr(&MI); + MRI.verifyUseLists(); + } else { + // Now Use2 is not ref, then Use1 should be ref + updateRefMapForRefInst(MO_use1, XVM_SYM_REG_REF); + MI.setDesc(TII->get(XVM::AddRef_rr)); + } + } + } return true; - } + } } - // Update instr if MO_use if ref - regNo = MO_use.getReg(); + // Update instr if MO_use1 if ref + regNo = MO_use1.getReg(); I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { if (I->second == XVM_SYM_REG_REF && @@ -327,79 +447,77 @@ static inline bool updateAddMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) } static inline bool updateSubriMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be subref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - updateRefMapForRefInst(MO_use, XVM_SYM_REG_REF); - if (MI.getOpcode() == XVM::SUB_ri) - MI.setDesc(TII->get(XVM::SubRef_ri)); - else - MI.setDesc(TII->get(XVM::SubRef_rr)); - return true; - } + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + updateRefMapForRefInst(MO_use, XVM_SYM_REG_REF); + if (MI.getOpcode() == XVM::SUB_ri) + MI.setDesc(TII->get(XVM::SubRef_ri)); + else + MI.setDesc(TII->get(XVM::SubRef_rr)); + return true; + } } regNo = MO_use.getReg(); I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - if (MI.getOpcode() == XVM::SUB_ri) - MI.setDesc(TII->get(XVM::SubRef_ri)); - else - MI.setDesc(TII->get(XVM::SubRef_rr)); - return true; - } + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + if (MI.getOpcode() == XVM::SUB_ri) + MI.setDesc(TII->get(XVM::SubRef_ri)); + else + MI.setDesc(TII->get(XVM::SubRef_rr)); + return true; + } } return false; } static inline bool updateSubrrMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use1 = MI.getOperand(1); - MachineOperand &MO_use2 = MI.getOperand(2); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be subref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - updateRefMapForRefInst(MO_use1, XVM_SYM_REG_REF); - I = MapRefRegInFunc.find(MO_use2.getReg()); - if (I != MapRefRegInFunc.end() && I->second == XVM_SYM_REG_REF) { - MI.setDesc(TII->get(XVM::DifRef_rr)); - } else { - MI.setDesc(TII->get(XVM::SubRef_rr)); - } - return true; + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + updateRefMapForRefInst(MO_use1, XVM_SYM_REG_REF); + I = MapRefRegInFunc.find(MO_use2.getReg()); + if (I != MapRefRegInFunc.end() && I->second == XVM_SYM_REG_REF) { + MI.setDesc(TII->get(XVM::DifRef_rr)); + } else { + MI.setDesc(TII->get(XVM::SubRef_rr)); } + return true; + } } regNo = MO_use1.getReg(); I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { if (MO_use2.isReg()) { - I = MapRefRegInFunc.find(MO_use2.getReg()); - if (I != MapRefRegInFunc.end() && I->second == XVM_SYM_REG_REF) { - MI.setDesc(TII->get(XVM::DifRef_rr)); - } else { - MI.setDesc(TII->get(XVM::SubRef_rr)); - } - return true; + I = MapRefRegInFunc.find(MO_use2.getReg()); + if (I != MapRefRegInFunc.end() && I->second == XVM_SYM_REG_REF) { + MI.setDesc(TII->get(XVM::DifRef_rr)); + } else { + MI.setDesc(TII->get(XVM::SubRef_rr)); + } + return true; } } } return false; } - // Update add/sub with sub/add if negative imm - static bool updateAddSubMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { bool Modified = false; @@ -418,126 +536,170 @@ static bool updateAddSubMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { } } -static inline bool updateOrMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); +static inline bool switchOperandUse1Use2(MachineBasicBlock &MBB, MachineInstr &MI, const XVMInstrInfo *TII) { + // we have cases where use1 is not ref while use2 is ref + if (MI.getOpcode() == XVM::OrRef_rr || + MI.getOpcode() == XVM::XorRef_rr || + MI.getOpcode() == XVM::AndRef_rr) { + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + Register regNo = MO_use2.getReg(); + std::map::iterator I = MapRefRegInFunc.find(regNo); + if (I != MapRefRegInFunc.end() && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + if (I->second == XVM_SYM_REG_REF) { + // MO_def has to be ref + updateRefMapForRefInst(MO_def, XVM_SYM_REG_REF); + // we need to Switch the order of use1 and use2 + MachineBasicBlock::iterator II = MI.getIterator(); + MachineFunction *MF = MBB.getParent(); + DebugLoc DL = MI.getDebugLoc(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstr *ReplaceMI = BuildMI(MBB, II, DL, TII->get(MI.getOpcode())); + + MachineOperand &NewMO_def = MI.getOperand(MO_FIRST); + MachineOperand &NewMO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &NewMO_use2 = MI.getOperand(MO_THIRD); + + ReplaceMI->addOperand(NewMO_def); + ReplaceMI->addOperand(NewMO_use2); + ReplaceMI->addOperand(NewMO_use1); + MBB.remove_instr(&MI); + MRI.verifyUseLists(); + return true; + } + } + } + + return false; +} + +static inline bool updateOrMIWithRef(MachineBasicBlock &MBB, MachineInstr &MI, const XVMInstrInfo *TII) { + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be orref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); // Update instr if MO_def is ref if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - // Update MO_use to be ref if MO_def is ref - updateRefMapForRefInst(MO_use, XVM_SYM_REG_REF); - if (MI.getOpcode() == XVM::OR_ri) - MI.setDesc(TII->get(XVM::OrRef_ri)); - else - MI.setDesc(TII->get(XVM::OrRef_rr)); - return true; + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + if (MI.getOpcode() == XVM::OR_ri) + MI.setDesc(TII->get(XVM::OrRef_ri)); + else { + MI.setDesc(TII->get(XVM::OrRef_rr)); + switchOperandUse1Use2(MBB, MI, TII); } + return true; + } } // Update instr if MO_use if ref regNo = MO_use.getReg(); I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - if (MI.getOpcode() == XVM::OR_ri) - MI.setDesc(TII->get(XVM::OrRef_ri)); - else - MI.setDesc(TII->get(XVM::OrRef_rr)); - return true; - } + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + // MO_def has to be ref + updateRefMapForRefInst(MO_def, XVM_SYM_REG_REF); + if (MI.getOpcode() == XVM::OR_ri) + MI.setDesc(TII->get(XVM::OrRef_ri)); + else + MI.setDesc(TII->get(XVM::OrRef_rr)); + return true; + } } return false; } -static inline bool updateXorMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); +static inline bool updateXorMIWithRef(MachineBasicBlock &MBB, MachineInstr &MI, const XVMInstrInfo *TII) { + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be xorref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); // Update instr if MO_def is ref if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - // Update MO_use to be ref if MO_def is ref - updateRefMapForRefInst(MO_use, XVM_SYM_REG_REF); - if (MI.getOpcode() == XVM::XOR_ri) - MI.setDesc(TII->get(XVM::XorRef_ri)); - else - MI.setDesc(TII->get(XVM::XorRef_rr)); - return true; + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + if (MI.getOpcode() == XVM::XOR_ri) + MI.setDesc(TII->get(XVM::XorRef_ri)); + else { + MI.setDesc(TII->get(XVM::XorRef_rr)); + switchOperandUse1Use2(MBB, MI, TII); } + return true; + } } // Update instr if MO_use if ref regNo = MO_use.getReg(); I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end() && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { if (I->second == XVM_SYM_REG_REF) { - if (MI.getOpcode() == XVM::XOR_ri) - MI.setDesc(TII->get(XVM::XorRef_ri)); - else - MI.setDesc(TII->get(XVM::XorRef_rr)); - return true; - } + // MO_def has to be ref + updateRefMapForRefInst(MO_def, XVM_SYM_REG_REF); + if (MI.getOpcode() == XVM::XOR_ri) + MI.setDesc(TII->get(XVM::XorRef_ri)); + else + MI.setDesc(TII->get(XVM::XorRef_rr)); + return true; + } } return false; } -static inline bool updateAndMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); +static inline bool updateAndMIWithRef(MachineBasicBlock &MBB, MachineInstr &MI, const XVMInstrInfo *TII) { + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); /* if MO_def is a ref (it is determined when it is used somewhere), then it should be andref */ Register regNo = MO_def.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); // Update instr if MO_def is ref if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - // Update MO_use to be ref if MO_def is ref - updateRefMapForRefInst(MO_use, XVM_SYM_REG_REF); - if (MI.getOpcode() == XVM::AND_ri) - MI.setDesc(TII->get(XVM::AndRef_ri)); - else - MI.setDesc(TII->get(XVM::AndRef_rr)); - return true; + if (I->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + if (MI.getOpcode() == XVM::AND_ri) + MI.setDesc(TII->get(XVM::AndRef_ri)); + else { + MI.setDesc(TII->get(XVM::AndRef_rr)); + switchOperandUse1Use2(MBB, MI, TII); } + return true; + } } - // Update instr if MO_use if ref + // Update instr if MO_use is ref regNo = MO_use.getReg(); I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end() && - SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { + SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { if (I->second == XVM_SYM_REG_REF) { - if (MI.getOpcode() == XVM::AND_ri) - MI.setDesc(TII->get(XVM::AndRef_ri)); - else - MI.setDesc(TII->get(XVM::AndRef_rr)); - return true; - } + // MO_def has to be ref + updateRefMapForRefInst(MO_def, XVM_SYM_REG_REF); + if (MI.getOpcode() == XVM::AND_ri) + MI.setDesc(TII->get(XVM::AndRef_ri)); + else + MI.setDesc(TII->get(XVM::AndRef_rr)); + return true; + } } return false; } -static bool updateOrXorAndMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { - switch (MI.getOpcode()) - { +static bool updateOrXorAndMIWithRef(MachineBasicBlock &MBB, MachineInstr &MI, const XVMInstrInfo *TII) { + switch (MI.getOpcode()) { case XVM::OR_ri: case XVM::OR_rr: - return updateOrMIWithRef(MI, TII); + return updateOrMIWithRef(MBB, MI, TII); case XVM::XOR_ri: case XVM::XOR_rr: - return updateXorMIWithRef(MI, TII); + return updateXorMIWithRef(MBB, MI, TII); case XVM::AND_ri: case XVM::AND_rr: - return updateAndMIWithRef(MI, TII); + return updateAndMIWithRef(MBB, MI, TII); default: return false; } @@ -545,14 +707,6 @@ static bool updateOrXorAndMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { static std::map MORegReplaceMap; static std::set MachineInstrExceptionSet; -/** mov rd #simm (16 bits) - * movk rd, #uimm (16 bits), #shift (0:no 1:16bits 2:32bits 3:48bits) - * addref rd, rn, #uimm (14bits) - */ -#define NUM_OF_IMM_BITS_ADDREF 14 -#define NUM_OF_IMM_BITS_MOV 16 -#define NUM_OF_IMM_BITS_MOVK1 32 -#define NUM_OF_IMM_BITS_MOVK2 48 static void handleOffsetWithInstr(MachineInstr &MI, const char *GlobalName) { uint64_t SubSecOffset = GetSubSecOffsetForGlobal(GlobalName); @@ -569,96 +723,112 @@ static void handleOffsetWithInstr(MachineInstr &MI, const char *GlobalName) { /* Addref */ Register VRegForAddref = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *AddrefMI = BuildMI(MB, ++II, DL, TII->get(XVM::AddRef_ri), VRegForAddref) - .addReg(MO_def.getReg()).addImm(SubSecOffset); + .addReg(MO_def.getReg()).addImm(SubSecOffset); MachineInstrExceptionSet.insert(AddrefMI); - MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(0))); + MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(MO_FIRST))); } else if (SubSecOffset < ((1 << NUM_OF_IMM_BITS_MOV) -1)) { /* Mov */ Register VRegForMov = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); - MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov) - .addImm(SubSecOffset); + MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov).addImm(0); MachineInstrExceptionSet.insert(MovMI); + /* Movk */ + Register VRegForMovk = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + MachineInstr *MovkMI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk) + .addReg(VRegForMov).addImm(SubSecOffset).addImm(MOVK_SHIFT_0); + MachineInstrExceptionSet.insert(MovkMI); /* Addref */ Register VRegForAddref = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *AddrefMI = BuildMI(MB, II, DL, TII->get(XVM::AddRef_rr), VRegForAddref) - .addReg(MO_def.getReg()).addReg(VRegForMov); + .addReg(MO_def.getReg()).addReg(VRegForMovk); MachineInstrExceptionSet.insert(AddrefMI); - MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(0))); + MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(MO_FIRST))); } else if (SubSecOffset < ((1UL << NUM_OF_IMM_BITS_MOVK1) -1)) { /* Mov */ - unsigned int imm1 = SubSecOffset & 0X000000000000FFFF; Register VRegForMov = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); - MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov) - .addImm(imm1); + MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov).addImm(0); MachineInstrExceptionSet.insert(MovMI); /* Movk */ - unsigned int imm2 = (SubSecOffset & 0X00000000FFFF0000)>>16; + unsigned int imm1 = SubSecOffset & 0X000000000000FFFF; + Register VRegForMovk0 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + MachineInstr *Movk0MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk0) + .addReg(VRegForMov).addImm(imm1).addImm(MOVK_SHIFT_0); + MachineInstrExceptionSet.insert(Movk0MI); + /* Movk */ + unsigned int imm2 = (SubSecOffset & 0X00000000FFFF0000) >> NUM_OF_IMM_BITS_MOV; Register VRegForMovk1 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); - MachineInstr *MovkMI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk1) - .addReg(VRegForMov).addImm(imm2).addImm(1); - MachineInstrExceptionSet.insert(MovkMI); + MachineInstr *Movk1MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk1) + .addReg(VRegForMovk0).addImm(imm2).addImm(MOVK_SHIFT_16); + MachineInstrExceptionSet.insert(Movk1MI); /* Addref only*/ Register VRegForAddref = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *AddrefMI = BuildMI(MB, II, DL, TII->get(XVM::AddRef_rr), VRegForAddref) - .addReg(MO_def.getReg()).addReg(VRegForMovk1); + .addReg(MO_def.getReg()).addReg(VRegForMovk1); MachineInstrExceptionSet.insert(AddrefMI); - MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(0))); + MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(MO_FIRST))); } else if (SubSecOffset < ((1UL << NUM_OF_IMM_BITS_MOVK2) -1)) { /* Mov */ - unsigned int imm1 = SubSecOffset & 0X000000000000FFFF; Register VRegForMov = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); - MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov) - .addImm(imm1); + MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov).addImm(0); MachineInstrExceptionSet.insert(MovMI); /* Movk */ - unsigned int imm2 = (SubSecOffset & 0X00000000FFFF0000)>>16; + unsigned int imm1 = SubSecOffset & 0X000000000000FFFF; + Register VRegForMovk0 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + MachineInstr *MovkMIk0 = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk0) + .addReg(VRegForMov).addImm(imm1).addImm(MOVK_SHIFT_0); + MachineInstrExceptionSet.insert(MovkMIk0); + /* Movk */ + unsigned int imm2 = (SubSecOffset & 0X00000000FFFF0000) >> NUM_OF_IMM_BITS_MOV; Register VRegForMovk1 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *Movk1MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk1) - .addReg(VRegForMov).addImm(imm2).addImm(1); + .addReg(VRegForMovk0).addImm(imm2).addImm(MOVK_SHIFT_16); MachineInstrExceptionSet.insert(Movk1MI); /* Movk */ - unsigned int imm3 = (SubSecOffset & 0X0000FFFF00000000)>>32; + unsigned int imm3 = (SubSecOffset & 0X0000FFFF00000000) >> NUM_OF_IMM_BITS_MOVK1; Register VRegForMovk2 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *Movk2MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk2) - .addReg(VRegForMovk1).addImm(imm3).addImm(2); + .addReg(VRegForMovk1).addImm(imm3).addImm(MOVK_SHIFT_32); MachineInstrExceptionSet.insert(Movk2MI); /* Addref only*/ Register VRegForAddref = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *AddrefMI = BuildMI(MB, II, DL, TII->get(XVM::AddRef_rr), VRegForAddref) - .addReg(MO_def.getReg()).addReg(VRegForMovk2); + .addReg(MO_def.getReg()).addReg(VRegForMovk2); MachineInstrExceptionSet.insert(AddrefMI); - MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(0))); + MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(MO_FIRST))); } else { /* Mov */ - unsigned int imm1 = SubSecOffset & 0X000000000000FFFF; Register VRegForMov = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); - MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov) - .addImm(imm1); + MachineInstr *MovMI = BuildMI(MB, ++II, DL, TII->get(XVM::MOV_ri), VRegForMov).addImm(0); MachineInstrExceptionSet.insert(MovMI); /* Movk */ - unsigned int imm2 = (SubSecOffset & 0X00000000FFFF0000)>>16; + unsigned int imm1 = SubSecOffset & 0X000000000000FFFF; + Register VRegForMovk0 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + MachineInstr *Movk0MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk0) + .addReg(VRegForMov).addImm(imm1).addImm(MOVK_SHIFT_0); + MachineInstrExceptionSet.insert(Movk0MI); + /* Movk */ + unsigned int imm2 = (SubSecOffset & 0X00000000FFFF0000) >> NUM_OF_IMM_BITS_MOV; Register VRegForMovk1 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *Movk1MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk1) - .addReg(VRegForMov).addImm(imm2).addImm(1); + .addReg(VRegForMovk0).addImm(imm2).addImm(MOVK_SHIFT_16); MachineInstrExceptionSet.insert(Movk1MI); /* Movk */ - unsigned int imm3 = (SubSecOffset & 0X0000FFFF00000000)>>32; + unsigned int imm3 = (SubSecOffset & 0X0000FFFF00000000) >> NUM_OF_IMM_BITS_MOVK1; Register VRegForMovk2 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *Movk2MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk2) - .addReg(VRegForMovk1).addImm(imm3).addImm(2); + .addReg(VRegForMovk1).addImm(imm3).addImm(MOVK_SHIFT_32); MachineInstrExceptionSet.insert(Movk2MI); /* Movk */ - unsigned int imm4 = (SubSecOffset & 0XFFFF000000000000)>>48; + unsigned int imm4 = (SubSecOffset & 0XFFFF000000000000) >> NUM_OF_IMM_BITS_MOVK2; Register VRegForMovk3 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *Movk3MI = BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk3) - .addReg(VRegForMovk2).addImm(imm4).addImm(3); + .addReg(VRegForMovk2).addImm(imm4).addImm(MOVK_SHIFT_48); MachineInstrExceptionSet.insert(Movk3MI); /* Addref only*/ Register VRegForAddref = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); MachineInstr *AddrefMI = BuildMI(MB, II, DL, TII->get(XVM::AddRef_rr), VRegForAddref) - .addReg(MO_def.getReg()).addReg(VRegForMovk3); + .addReg(MO_def.getReg()).addReg(VRegForMovk3); MachineInstrExceptionSet.insert(AddrefMI); - MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(0))); + MORegReplaceMap.insert(std::pair(MO_def.getReg(), &AddrefMI->getOperand(MO_FIRST))); } } } @@ -666,13 +836,13 @@ static void handleOffsetWithInstr(MachineInstr &MI, const char *GlobalName) { static void updatePtrRegRefBasedGlobals(MachineInstr &MI) { switch (MI.getOpcode()) { case XVM::LD_global_imm64: { - assert(MI.getNumOperands() >= 2); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() >= NUM_MO_2); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); if (MO_use.isGlobal()) { const char *GlobalName = MO_use.getGlobal()->getName().data(); - LLVM_DEBUG(dbgs() << "Global:" << GlobalName << ' to load.\n'); - MapRefRegInFunc.insert(std::pair(MO_def.getReg(), XVM_SYM_REG_REF)); + LLVM_DEBUG(dbgs() << "Global:" << GlobalName << " to load.\n"); + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); unsigned int ptrLevel = GetPtrRegisterLevelBasedOnName(GlobalName); if (ptrLevel > 0) { MapPtrRegInFunc.insert(std::pair(MO_def.getReg(), ptrLevel)); @@ -684,16 +854,16 @@ static void updatePtrRegRefBasedGlobals(MachineInstr &MI) { break; } case XVM::LDD: { - assert(MI.getNumOperands() >= 2); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use = MI.getOperand(1); + assert(MI.getNumOperands() >= NUM_MO_2); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); if (MO_use.isReg()) { std::map::iterator I = MapPtrRegInFunc.find(MO_use.getReg()); if (I != MapPtrRegInFunc.end() && I->second >= 1) { - MapRefRegInFunc.insert(std::pair(MO_def.getReg(), XVM_SYM_REG_REF)); + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); // check the flags to see if the def is a ref - MachineOperand &MO_imm = MI.getOperand(2); + MachineOperand &MO_imm = MI.getOperand(MO_THIRD); if (MO_imm.isImm()) { int64_t imm = MO_imm.getImm(); if (imm == 0) { @@ -708,13 +878,12 @@ static void updatePtrRegRefBasedGlobals(MachineInstr &MI) { break; } case XVM::STD: { - assert(MI.getNumOperands() >= 2); - MachineOperand &MO_use1 = MI.getOperand(0); - MachineOperand &MO_use2 = MI.getOperand(1); + assert(MI.getNumOperands() >= NUM_MO_2); + MachineOperand &MO_use2 = MI.getOperand(MO_SECOND); if (MO_use2.isReg()) { std::map::iterator I = MapPtrRegInFunc.find(MO_use2.getReg()); if (I != MapPtrRegInFunc.end() && I->second >= 1) { - MapRefRegInFunc.insert(std::pair(MO_use1.getReg(), XVM_SYM_REG_REF)); + SetRegTypeForMO(MO_use2, XVM_SYM_REG_REF); } } break; @@ -725,20 +894,20 @@ static void updatePtrRegRefBasedGlobals(MachineInstr &MI) { static void checkStoreMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::STB || MI.getOpcode() == XVM::STH || MI.getOpcode() == XVM::STW || MI.getOpcode() == XVM::STD) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_use1 = MI.getOperand(0); - MachineOperand &MO_use2 = MI.getOperand(1); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_use1 = MI.getOperand(MO_FIRST); + MachineOperand &MO_use2 = MI.getOperand(MO_SECOND); assert(MO_use1.isUse()); if (MO_use2.isReg()) { // STW killed %48:xvmgpr, killed %54:xvmgpr, 0 :: (store (s32) into %ir.arrayidx5) assert(MO_use2.isUse()); // always be ref - MapRefRegInFunc.insert(std::pair(MO_use2.getReg(), XVM_SYM_REG_REF)); + SetRegTypeForMO(MO_use2, XVM_SYM_REG_REF); } else if (MO_use2.isFI()) { /* Note: we might need a fix for FI scenario: - STB killed %6:xvmgpr, %stack.2.atomic-temp, 0 :: (store (s8) into %ir.atomic-temp) - It will be handled in eliminateFrameIndex. - */ + * STB killed %6:xvmgpr, %stack.2.atomic-temp, 0 :: (store (s8) into %ir.atomic-temp) + * It will be handled in eliminateFrameIndex. + */ ; } return; @@ -747,16 +916,16 @@ static void checkStoreMIWithRef(MachineInstr &MI) { static bool updateStoreMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { if (MI.getOpcode() == XVM::STD) { - assert(MI.getNumOperands() == 3); - MachineOperand &MO_use1 = MI.getOperand(0); + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_use1 = MI.getOperand(MO_FIRST); Register regNo = MO_use1.getReg(); std::map::iterator I = MapRefRegInFunc.find(regNo); if (I != MapRefRegInFunc.end()) { - if (I->second == XVM_SYM_REG_REF && + if (I->second == XVM_SYM_REG_REF && SetNonRefRegInFunc.find(regNo) == SetNonRefRegInFunc.end()) { - MI.setDesc(TII->get(XVM::StoreRef_ri)); - return true; - } + MI.setDesc(TII->get(XVM::StoreRef_ri)); + return true; + } } } return false; @@ -765,23 +934,32 @@ static bool updateStoreMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { static void checkPhiMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::PHI) { unsigned numOfFrom = MI.getNumOperands() / 2; - assert(numOfFrom * 2 + 1 == MI.getNumOperands()); - MachineOperand &MO_def = MI.getOperand(0); + assert(numOfFrom * NUM_MO_PER_PHI_BRANCH + 1 == MI.getNumOperands()); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); for (unsigned idx = 0; idx < numOfFrom; idx++) { - MachineOperand &MO_use = MI.getOperand(idx*2+1); - setRefFlagFor2Ops(MO_def, MO_use); + MachineOperand &MO_use = MI.getOperand(idx*2+1); + setRefFlagFor2Ops(MO_def, MO_use); } return; } } +static void checkFIMIWithRef(MachineInstr &MI) { + if (MI.getOpcode() == XVM::FI_ri) { + assert(NUM_MO_3 == MI.getNumOperands()); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + if (MO_def.isReg()) + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + } +} + static bool updatePhiMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { /* No update for Phi*/ return false; } static bool updateRegistersInMI(MachineInstr &MI, const XVMInstrInfo *TII) { - SmallVector OperandsInMI; + SmallVector OperandsInMI; bool replaceOperand = false; if (MachineInstrExceptionSet.find(&MI) == MachineInstrExceptionSet.end()) { for (unsigned int i = 0; i < MI.getNumOperands(); i++) { @@ -795,6 +973,14 @@ static bool updateRegistersInMI(MachineInstr &MI, const XVMInstrInfo *TII) { if (MO.isDef()) isDef = true; MachineOperand NewMO = MachineOperand::CreateReg((I->second)->getReg(), isDef); + // Update the ref information for replaced registers + std::map::iterator IterTmp = MapRefRegInFunc.find(MO.getReg()); + if (IterTmp != MapRefRegInFunc.end()) { + if (IterTmp->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(MO.getReg()) == SetNonRefRegInFunc.end()) { + MapRefRegInFunc[NewMO.getReg()] = XVM_SYM_REG_REF; + } + } OperandsInMI.push_back(NewMO); replaceOperand = true; } @@ -823,24 +1009,24 @@ static bool updateRegistersInMI(MachineInstr &MI, const XVMInstrInfo *TII) { /** * Propogate the non ref registers via COPY and MOV statements * - * */ + **/ static void propogateNonRefInfo(const MachineBasicBlock &MBB) { MachineBasicBlock::const_iterator MBBI = MBB.begin(), E = MBB.end(); while (MBBI != E) { - MachineBasicBlock::const_iterator NMBBI = std::next(MBBI); - const MachineInstr &MI = *MBBI; - MBBI = NMBBI; - // if MO_use is in SetNonRefRegInFunc, then MO_def should be in SetNonRefRegInFunc - if (MI.getOpcode() == XVM::COPY || MI.getOpcode() == XVM::MOV_rr) { - assert(MI.getNumOperands() == 2); - const MachineOperand &MO_def = MI.getOperand(0); - const MachineOperand &MO_use = MI.getOperand(1); - if (MO_def.isReg() && MO_use.isReg()) { - if (SetNonRefRegInFunc.find(MO_use.getReg()) != SetNonRefRegInFunc.end()) { - SetNonRefRegInFunc.insert(MO_def.getReg()); - } + MachineBasicBlock::const_iterator NMBBI = std::next(MBBI); + const MachineInstr &MI = *MBBI; + MBBI = NMBBI; + // if MO_use is in SetNonRefRegInFunc, then MO_def should be in SetNonRefRegInFunc + if (MI.getOpcode() == XVM::COPY || MI.getOpcode() == XVM::MOV_rr) { + assert(MI.getNumOperands() == NUM_MO_2); + const MachineOperand &MO_def = MI.getOperand(MO_FIRST); + const MachineOperand &MO_use = MI.getOperand(MO_SECOND); + if (MO_def.isReg() && MO_use.isReg()) { + if (SetNonRefRegInFunc.find(MO_use.getReg()) != SetNonRefRegInFunc.end()) { + SetNonRefRegInFunc.insert(MO_def.getReg()); } } + } } } @@ -852,44 +1038,44 @@ static void updateNonRefInfoViaCalls(const MachineBasicBlock &MBB, std::set &FuncSet) { MachineBasicBlock::const_iterator MBBI = MBB.begin(), E = MBB.end(); while (MBBI != E) { - MachineBasicBlock::const_iterator NMBBI = std::next(MBBI); - const MachineInstr &MI = *MBBI; - MBBI = NMBBI; - if (MI.getOpcode() == XVM::CALL_IMM) { - assert(MI.getNumOperands() >= 3); - const MachineOperand &MO_0 = MI.getOperand(0); - const MachineOperand &MO_2 = MI.getOperand(2); - if (!MO_0.isReg() && MO_0.isGlobal() && - MO_2.isReg() && MO_2.isImplicit() && MO_2.isDef() && !MO_2.isDead()) { - // Function without ptr as return - if (FuncSet.find(MO_0.getGlobal()->getName().str()) == FuncSet.end()) { - if (MBBI == E) { - return; - } - const MachineInstr &NextMI = *MBBI; - if (NextMI.getOpcode() == XVM::ADJCALLSTACKUP) { - // skip call stack up - MBBI = std::next(MBBI); - if (MBBI == E) { - return; - } - } - // save va reg from the copy with r0 - const MachineInstr &NextNextMI = *MBBI; - if (NextNextMI.getOpcode() == XVM::COPY || - NextNextMI.getOpcode() == XVM::MOV_rr) { - assert(NextNextMI.getNumOperands() == 2); - const MachineOperand &MO_def = NextNextMI.getOperand(0); - const MachineOperand &MO_use = NextNextMI.getOperand(1); - if (MO_def.isReg() && MO_use.isReg()) { - if (MO_use.getReg() == XVM::R0) { - SetNonRefRegInFunc.insert(MO_def.getReg()); - } - } + MachineBasicBlock::const_iterator NMBBI = std::next(MBBI); + const MachineInstr &MI = *MBBI; + MBBI = NMBBI; + if (MI.getOpcode() == XVM::CALL_IMM) { + assert(MI.getNumOperands() >= NUM_MO_3); + const MachineOperand &MO_0 = MI.getOperand(MO_FIRST); + const MachineOperand &MO_2 = MI.getOperand(MO_THIRD); + if (!MO_0.isReg() && MO_0.isGlobal() && + MO_2.isReg() && MO_2.isImplicit() && MO_2.isDef() && !MO_2.isDead()) { + // Function without ptr as return + if (FuncSet.find(MO_0.getGlobal()->getName().str()) == FuncSet.end()) { + if (MBBI == E) { + return; + } + const MachineInstr &NextMI = *MBBI; + if (NextMI.getOpcode() == XVM::ADJCALLSTACKUP) { + // skip call stack up + MBBI = std::next(MBBI); + if (MBBI == E) { + return; + } + } + // save va reg from the copy with r0 + const MachineInstr &NextNextMI = *MBBI; + if (NextNextMI.getOpcode() == XVM::COPY || + NextNextMI.getOpcode() == XVM::MOV_rr) { + assert(NextNextMI.getNumOperands() == NUM_MO_2); + const MachineOperand &MO_def = NextNextMI.getOperand(MO_FIRST); + const MachineOperand &MO_use = NextNextMI.getOperand(MO_SECOND); + if (MO_def.isReg() && MO_use.isReg()) { + if (MO_use.getReg() == XVM::R0) { + SetNonRefRegInFunc.insert(MO_def.getReg()); } } + } } } + } } } @@ -917,10 +1103,28 @@ void XVMUpdateRefInstrForMI::FindNonRefRegInFunc(const MachineFunction &MF) { } } +bool XVMUpdateRefInstrForMI::updateRegistersOfMIInMBB(MachineBasicBlock &MBB) { + int InstNumber = 0; + bool Modified = false; + + MachineBasicBlock::reverse_iterator MBBI = MBB.rbegin(), E = MBB.rend(); + // This needs to be done seperately since it may cross BBs + MBBI = MBB.rbegin(), E = MBB.rend(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::reverse_iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + Modified |= updateRegistersInMI(MI, TII); + MBBI = NMBBI; + } + return Modified; +} + bool XVMUpdateRefInstrForMI::runOnMachineFunction(MachineFunction &MF) { TII = MF.getSubtarget().getInstrInfo(); - LLVM_DEBUG(dbgs() << "Check/update refs in fun:" << MF.getFunction().getName().data() << '.\n'); + LLVM_DEBUG(dbgs() << "Check/update refs in fun:" << MF.getFunction().getName().data() << ".\n"); + MapMIToBeFixed.clear(); MapRefRegInFunc.clear(); MapPtrRegInFunc.clear(); MORegReplaceMap.clear(); @@ -931,14 +1135,491 @@ bool XVMUpdateRefInstrForMI::runOnMachineFunction(MachineFunction &MF) { FindNonRefRegInFunc(MF); bool Modified = false; + // force the ref info for shift MIs in MBB for (auto &MBB : MF) { - Modified |= updateRefInfoInMBB(MBB); + Modified |= forceShiftRefInfoIbMBB(MBB); + } + // scan MBBs in MF + for (auto &MBB : MF) { + Modified |= scanRefInfoInMBB(MBB); } - return Modified; -} -void XVMUpdateRefInstrForMI::updatePtrRefInMBB(MachineBasicBlock &MBB) { - MachineBasicBlock::iterator MBBI = MBB.begin(); + // force the ref info for Add_rr MIs in MBB + for (auto &MBB : MF) { + Modified |= forceAddSubRefInfoIbMBB(MBB); + } + + // update MBBs in MF + for (auto &MBB : MF) { + Modified |= updateRefInfoBasedInMBB(MBB); + } + + for (auto &MBB : MF) { + Modified |= checkAndUpdateOrInMBB(MBB); + Modified |= updateRegistersOfMIInMBB(MBB); + } + + for (auto &MBB : MF) { + doubleCheckRefs(MBB); + } + Modified |= finalFixRefs(); + + for (auto &MBB : MF) { + checkAndReplaceAddWithAddRefs(MBB); + } + return Modified; +} + +bool XVMUpdateRefInstrForMI::finalFixRefs(void) { + bool Modified = false; + std::map::iterator it; + for (it = MapMIToBeFixed.begin(); it != MapMIToBeFixed.end(); it++) { + MachineInstr *MI = it->first; + MachineBasicBlock *MBB = it->second; + + MachineOperand &MO_def = MI->getOperand(MO_FIRST); + if (!MO_def.isReg()) + continue; + + Register regNoDef = MO_def.getReg(); + std::map::iterator IForDef = MapRefRegInFunc.find(regNoDef); + switch (MI->getOpcode()) { + default: + break; + case XVM::ADD_ri: { + // make def to be ref + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + + if (IForDef == MapRefRegInFunc.end()) { + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + } else { + MapRefRegInFunc[regNoDef] = XVM_SYM_REG_REF; + } + // change it to be AddRef_ri and + MI->setDesc(TII->get(XVM::AddRef_ri)); + Modified = true; + break; + } + case XVM::ADD_rr: { + // make def to to ref + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + Modified = true; + // Switch the use 1 with use 2 if use 2 is a ref + MachineOperand &MO_use2 = MI->getOperand(MO_THIRD); + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + // by create a new MI + MachineBasicBlock::iterator II = MI->getIterator(); + MachineFunction *MF = MBB->getParent(); + DebugLoc DL = MI->getDebugLoc(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstr *ReplaceMI = BuildMI(*MBB, II, DL, TII->get(XVM::AddRef_rr)); + + MachineOperand &NewMO_def = MI->getOperand(MO_FIRST); + MachineOperand &NewMO_use1 = MI->getOperand(MO_SECOND); + MachineOperand &NewMO_use2 = MI->getOperand(MO_THIRD); + + ReplaceMI->addOperand(NewMO_def); + ReplaceMI->addOperand(NewMO_use2); + ReplaceMI->addOperand(NewMO_use1); + MBB->remove_instr(MI); + MRI.verifyUseLists(); + } + } + break; + } + case XVM::AddRef_ri: { + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + Modified = true; + break; + } + case XVM::AddRef_rr: { + MachineOperand &MO_use2 = MI->getOperand(MO_THIRD); + if ((IForDef != MapRefRegInFunc.end() && IForDef->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoDef) != SetNonRefRegInFunc.end()) { + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + } + // Switch the use 1 with use 2 if use 2 is a ref + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + Modified = true; + // by create a new MI + MachineBasicBlock::iterator II = MI->getIterator(); + MachineFunction *MF = MBB->getParent(); + DebugLoc DL = MI->getDebugLoc(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + MachineInstr *ReplaceMI = BuildMI(*MBB, II, DL, TII->get(XVM::AddRef_rr)); + + MachineOperand &MO_def = MI->getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI->getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI->getOperand(MO_THIRD); + + ReplaceMI->addOperand(MO_def); + ReplaceMI->addOperand(MO_use2); + ReplaceMI->addOperand(MO_use1); + MBB->remove_instr(MI); + MRI.verifyUseLists(); + } + } + break; + } + } + } + return Modified; +} + +void XVMUpdateRefInstrForMI::checkAndReplaceAddWithAddRefs(MachineBasicBlock &MBB) { + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + int InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + if (MI.getNumOperands() < 2) { + MBBI = NMBBI; + continue; + } + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + if (!MO_def.isReg()) { + MBBI = NMBBI; + continue; + } + const MachineFunction *F = MI.getParent()->getParent(); + switch (MI.getOpcode()) { + case XVM::ADD_rr: { + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + Register regNoDef = MO_def.getReg(); + std::map::iterator IForDef = MapRefRegInFunc.find(regNoDef); + Register regNoUse1 = MO_use1.getReg(); + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + bool DefOrUseIsRef = false; + + if ((IForDef != MapRefRegInFunc.end() && IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) || + (IForUse1 != MapRefRegInFunc.end() && IForUse1->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse1) == SetNonRefRegInFunc.end()) || + (IForUse2 != MapRefRegInFunc.end() && IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end())) { + DefOrUseIsRef = true; + } + if (DefOrUseIsRef) { + MI.setDesc(TII->get(XVM::AddRef_rr)); + } + break; + } + default: + break; + } + MBBI = NMBBI; + } +} + +void XVMUpdateRefInstrForMI::doubleCheckRefs(MachineBasicBlock &MBB) { + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + int InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + + if (MI.getNumOperands() < 2) { + MBBI = NMBBI; + continue; + } + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + if (!MO_def.isReg()) { + MBBI = NMBBI; + continue; + } + Register regNoDef = MO_def.getReg(); + std::map::iterator IForDef = MapRefRegInFunc.find(regNoDef); + + const MachineFunction *F = MI.getParent()->getParent(); + switch (MI.getOpcode()) { + case XVM::ADD_ri: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isImm()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of ADD_ri is not an imm", NULL); + exit(1); + } + if (IForDef != MapRefRegInFunc.end()) { + if (IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(ADD_ri): def is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if (IForUse1 != MapRefRegInFunc.end()) { + if (IForUse1->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse1) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(ADD_ri): use 1 is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + break; + } + case XVM::ADD_rr: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isReg()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of ADD_rr is not a reg", NULL); + exit(1); + } + if (IForDef != MapRefRegInFunc.end()) { + if (IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(ADD_rr): def is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + Register regNoUse1 = MO_use1.getReg(); + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + if (IForUse1 != MapRefRegInFunc.end()) { + if (IForUse1->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse1) == SetNonRefRegInFunc.end()) { + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: both use 1 and use2 of ADD_rr are ref", NULL); + exit(1); + } + } + } + } else { + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(ADD_ri): use 1 is not ref, use 2 is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + } + break; + } + case XVM::SUB_ri: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isImm()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of SUB_ri is not imm", NULL); + exit(1); + } + if (IForDef != MapRefRegInFunc.end()) { + if (IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SUB_ri): def is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if (IForUse1 != MapRefRegInFunc.end()) { + if (IForUse1->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse1) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SUB_ri): use 1 is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + break; + } + case XVM::SUB_rr: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isReg()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of SUB_rr is not a reg", NULL); + exit(1); + } + if (IForDef != MapRefRegInFunc.end()) { + if (IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SUB_rr): def is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if (IForUse1 != MapRefRegInFunc.end()) { + if (IForUse1->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse1) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SUB_rr): use 1 is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SUB_rr): use 2 is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + break; + } + case XVM::SubRef_ri: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isImm()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of SubRef_ri is not an imm", NULL); + exit(1); + } + if ((IForDef != MapRefRegInFunc.end() && IForDef->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoDef) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SubRef_ri): def is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if ((IForUse1 != MapRefRegInFunc.end() && IForUse1->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoUse1) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SubRef_ri): use 1 is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + break; + } + case XVM::AddRef_ri: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isImm()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(AddRef_ri): use 2 is not imm.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + exit(1); + } + if ((IForDef != MapRefRegInFunc.end() && IForDef->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoDef) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(AddRef_ri): def is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if ((IForUse1 != MapRefRegInFunc.end() && IForUse1->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoUse1) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(AddRef_ri): use 1 is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + break; + } + case XVM::SubRef_rr: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isReg()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of SubRef_rr is not a reg", NULL); + exit(1); + } + if ((IForDef != MapRefRegInFunc.end() && IForDef->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoDef) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SubRef_rr): def is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if ((IForUse1 != MapRefRegInFunc.end() && IForUse1->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoUse1) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SubRef_rr): use 1 is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(SubRef_rr): use 2 is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + if ((IForUse1 != MapRefRegInFunc.end() && IForUse1->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse1) == SetNonRefRegInFunc.end()) && + (IForUse2 != MapRefRegInFunc.end() && IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end())) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: both use 1 and use 2 of SubRef_rr are ref", NULL); + exit(1); + } + break; + } + case XVM::AddRef_rr: { + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + if (!MO_use2.isReg()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 2 of AddRef_rr is not a reg", NULL); + exit(1); + } + if ((IForDef != MapRefRegInFunc.end() && IForDef->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoDef) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(AddRef_rr): def is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if ((IForUse1 != MapRefRegInFunc.end() && IForUse1->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoUse1) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(AddRef_rr): use 1 is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + Register regNoUse2 = MO_use2.getReg(); + std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); + if (IForUse2 != MapRefRegInFunc.end()) { + if (IForUse2->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse2) == SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "\nTest To-be-fixed(AddRef_rr): use 2 is ref. Regno: " << regNoUse2 << " Reg1: " << regNoUse1 << "\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + break; + } + case XVM::MOV_rr: { + if (MO_use1.isFI()) { + // def has to be ref + if ((IForDef != MapRefRegInFunc.end() && IForDef->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoDef) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(MOV_rr): def is not ref for the case of use=sp.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } else { + // if def is ref, then use1 is ref + if (IForDef != MapRefRegInFunc.end()) { + if (IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) { + // check to see if use1 is ref + Register regNoUse1 = MO_use1.getReg(); + std::map::iterator IForUse1 = MapRefRegInFunc.find(regNoUse1); + if ((IForUse1 != MapRefRegInFunc.end() && IForUse1->second != XVM_SYM_REG_REF) || + SetNonRefRegInFunc.find(regNoUse1) != SetNonRefRegInFunc.end()) { + LLVM_DEBUG(dbgs() << "To-be-fixed(MOV_rr): def is ref while use is not ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + } + } + break; + } + case XVM::MOV_ri: { + if (!MO_use1.isImm()) { + ExportFailMsg(F->getFunction(), MI.getDebugLoc(), "Error: use 1 of MOV_ri is not an imm", NULL); + exit(1); + } + if (IForDef != MapRefRegInFunc.end()) { + if (IForDef->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoDef) == SetNonRefRegInFunc.end()) { + MI.print(dbgs()); + LLVM_DEBUG(dbgs() << "To-be-fixed(MOV_ri): def is ref.\n"); + MapMIToBeFixed.insert(std::pair(&MI, &MBB)); + } + } + break; + } + default: + break; + } + MBBI = NMBBI; + } +} + +void XVMUpdateRefInstrForMI::updatePtrRefInMBB(MachineBasicBlock &MBB) { + MachineBasicBlock::iterator MBBI = MBB.begin(); int InstNumber = std::distance(MBB.begin(), MBB.end()); for (int i = 0; i < InstNumber; i++) { MachineBasicBlock::iterator NMBBI = std::next(MBBI); @@ -948,28 +1629,302 @@ void XVMUpdateRefInstrForMI::updatePtrRefInMBB(MachineBasicBlock &MBB) { } } -bool XVMUpdateRefInstrForMI::updateRefInfoInMBB(MachineBasicBlock &MBB) { +/** + * We need to consider the static recurisive case. Here is an example + * %46:xvmgpr = ADD_ri %47:xvmgpr, 24 + * + * %47:xvmgpr = PHI %44:xvmgpr, %bb.75, %46:xvmgpr, %bb.45 + * + * In the above code, %47 depends on %44 and %46 while %46 depends on %47 + * Once we detect the %44 is ref, then we should conclude that both %46 and %47 are ref + * + * Also, we reverse scan the instructions: Phi instructions need double check. Here is an example: + * %85:xvmgpr = LD_global_imm64 @crc32_tab + * + * %0:xvmgpr = PHI %85:xvmgpr, %bb.0, %3:xvmgpr, %bb.60 <-- checking of %85 is done after that of PHI + **/ +void XVMUpdateRefInstrForMI::doubleCheckPhiMIWithRef(MachineBasicBlock &MBB) { + MachineBasicBlock::iterator MBBI = MBB.begin(), E = MBB.end(); + int InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + if (MI.getOpcode() != XVM::PHI) { + MBBI = NMBBI; + continue; + } + + unsigned numOfFrom = MI.getNumOperands() / 2; + assert(numOfFrom * NUM_MO_PER_PHI_BRANCH + 1 == MI.getNumOperands()); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + Register regNoDef = MO_def.getReg(); + + std::map::iterator IDef = MapRefRegInFunc.find(regNoDef); + if (IDef != MapRefRegInFunc.end() && IDef->second == XVM_SYM_REG_REF) { + // def is ref: all uses should be ref + for (unsigned idx = 0; idx < numOfFrom; idx++) { + MachineOperand &MO_use = MI.getOperand(idx*2+1); + Register regNoUse = MO_use.getReg(); + std::map::iterator IUse = MapRefRegInFunc.find(regNoUse); + if (IUse == MapRefRegInFunc.end() || IUse->second != XVM_SYM_REG_REF) { + SetRegTypeForMO(MO_use, XVM_SYM_REG_REF); + SetNonRefRegInFunc.erase(MO_use.getReg()); + } + } + } else { + // if any (def and uses) is ref, then all should be ref + bool anyIsRef = false; + for (unsigned idx = 0; idx < numOfFrom; idx++) { + MachineOperand &MO_use = MI.getOperand(idx*2+1); + Register regNoUse = MO_use.getReg(); + std::map::iterator IUse = MapRefRegInFunc.find(regNoUse); + if (IUse != MapRefRegInFunc.end() && IUse->second == XVM_SYM_REG_REF && + SetNonRefRegInFunc.find(regNoUse) == SetNonRefRegInFunc.end()) { + anyIsRef = true; + break; + } + } + if (anyIsRef) { + // make all reg to be ref + SetRegTypeForMO(MO_def, XVM_SYM_REG_REF); + for (unsigned idx = 0; idx < numOfFrom; idx++) { + MachineOperand &MO_use = MI.getOperand(idx*2+1); + SetRegTypeForMO(MO_use, XVM_SYM_REG_REF); + } + } + } + MBBI = NMBBI; + } +} + +static int ShiftAndGet16Bits(uint64_t num, int n) { + return (num >> n) & 0xFFFF; +} + +static void replaceImmWithMovk(MachineInstr &MI) { + MachineBasicBlock &MB = *MI.getParent(); + MachineFunction *MF = MB.getParent(); + const TargetInstrInfo *TII = MF->getSubtarget().getInstrInfo(); + MachineRegisterInfo &MRI = MF->getRegInfo(); + DebugLoc DL = MI.getDebugLoc(); + int64_t imm32 = MI.getOperand(MO_THIRD).getImm(); + MachineBasicBlock::iterator II = MI.getIterator(); + + Register ScratchReg; + ScratchReg = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + uint64_t MostSignificantBits = ShiftAndGet16Bits(imm32, MOST_SIGNIFICANT); + uint64_t UpperMiddleBits = ShiftAndGet16Bits(imm32, UPPER_MIDDLE); + uint64_t LowerMiddleBits = ShiftAndGet16Bits(imm32, LOWER_MIDDLE); + uint64_t LeastSignificantBits = ShiftAndGet16Bits(imm32, LEAST_SIGNIFICANT); + + Register VRegForMov = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + BuildMI(MB, II, DL, TII->get(XVM::MOV_ri), VRegForMov).addImm(0); + Register PrevReg = VRegForMov; + if (LeastSignificantBits) { + Register VRegForMovk1 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk1) + .addReg(PrevReg).addImm(LeastSignificantBits).addImm(MOVK_SHIFT_0); + PrevReg = VRegForMovk1; + } + if (LowerMiddleBits) { + Register VRegForMovk2 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk2) + .addReg(PrevReg).addImm(LowerMiddleBits).addImm(MOVK_SHIFT_16); + PrevReg = VRegForMovk2; + } + if (UpperMiddleBits) { + Register VRegForMovk3 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk3) + .addReg(PrevReg).addImm(UpperMiddleBits).addImm(MOVK_SHIFT_32); + PrevReg = VRegForMovk3; + } + if (MostSignificantBits) { + Register VRegForMovk4 = MRI.createVirtualRegister(&XVM::XVMGPRRegClass); + BuildMI(MB, II, DL, TII->get(XVM::MOVK_ri), VRegForMovk4) + .addReg(PrevReg).addImm(MostSignificantBits).addImm(MOVK_SHIFT_48); + PrevReg = VRegForMovk4; + } + + BuildMI(MB, II, DL, TII->get(XVM::AddRef_rr)).addReg(ScratchReg, RegState::Define) + .addReg(MI.getOperand(MO_SECOND).getReg()) + .addReg(PrevReg); + MI.getOperand(MO_SECOND).setReg(ScratchReg); + MI.getOperand(MO_SECOND).setIsKill(); + MI.getOperand(MO_THIRD).setImm(0); +} + +bool XVMUpdateRefInstrForMI::checkAndUpdateOrInMBB(MachineBasicBlock &MBB) { int InstNumber = 0; bool Modified = false; - updatePtrRefInMBB(MBB); - /* Note: the two passes may be merged for efficiency */ MachineBasicBlock::reverse_iterator MBBI = MBB.rbegin(), E = MBB.rend(); InstNumber = std::distance(MBB.begin(), MBB.end()); for (int i = 0; i < InstNumber; i++) { MachineBasicBlock::reverse_iterator NMBBI = std::next(MBBI); MachineInstr &MI = *MBBI; + checkOrXorAndMIWithRef(MI); + MBBI = NMBBI; + } + /* update the instructions */ + MBBI = MBB.rbegin(), E = MBB.rend(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::reverse_iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + Modified |= updateOrXorAndMIWithRef(MBB, MI, TII); + MBBI = NMBBI; + } + return Modified; +} + +bool XVMUpdateRefInstrForMI::scanRefInfoInMBB(MachineBasicBlock &MBB) { + int InstNumber = 0; + bool Modified = false; + updatePtrRefInMBB(MBB); + + /* Note: the two passes may be merged for efficiency */ + // reverse order + MachineBasicBlock::reverse_iterator R_MBBI = MBB.rbegin(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::reverse_iterator NMBBI = std::next(R_MBBI); + MachineInstr &MI = *R_MBBI; + checkSimpleMIWithRef(MI); + checkMovMIWithRef(MI); + checkLoadMIWithRef(MI); + checkStoreMIWithRef(MI); + checkPhiMIWithRef(MI); + checkFIMIWithRef(MI); + R_MBBI = NMBBI; + } + // normal order + MachineBasicBlock::iterator MBBI = MBB.begin(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; checkSimpleMIWithRef(MI); checkMovMIWithRef(MI); checkLoadMIWithRef(MI); checkStoreMIWithRef(MI); - checkAddSubMIWithRef(MI); - checkOrXorAndMIWithRef(MI); checkPhiMIWithRef(MI); MBBI = NMBBI; } + return Modified; +} + +static void forceShiftMIWithRef(MachineInstr &MI) { + if (MI.getOpcode() == XVM::LSL_ri || MI.getOpcode() == XVM::ASR_ri) { + assert(MI.getNumOperands() == NUM_MO_3); + // Force the def and use registers are non-ref + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); + SetRegTypeForMO(MO_def, XVM_SYM_REG_NON_REF); + SetRegTypeForMO(MO_use, XVM_SYM_REG_NON_REF); + SetNonRefRegInFunc.insert(MO_def.getReg()); + SetNonRefRegInFunc.insert(MO_use.getReg()); + return; + } + + if (MI.getOpcode() == XVM::LSL_rr || MI.getOpcode() == XVM::ASR_rr) { + assert(MI.getNumOperands() == NUM_MO_3); + // Force the def and use registers are non-ref + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + SetRegTypeForMO(MO_def, XVM_SYM_REG_NON_REF); + SetRegTypeForMO(MO_use1, XVM_SYM_REG_NON_REF); + SetRegTypeForMO(MO_use2, XVM_SYM_REG_NON_REF); + SetNonRefRegInFunc.insert(MO_def.getReg()); + SetNonRefRegInFunc.insert(MO_use1.getReg()); + SetNonRefRegInFunc.insert(MO_use2.getReg()); + return; + } +} + +bool XVMUpdateRefInstrForMI::forceShiftRefInfoIbMBB(MachineBasicBlock &MBB) { + int InstNumber = 0; + bool Modified = false; + + // reverse order + MachineBasicBlock::reverse_iterator R_MBBI = MBB.rbegin(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::reverse_iterator NMBBI = std::next(R_MBBI); + MachineInstr &MI = *R_MBBI; + forceShiftMIWithRef(MI); + R_MBBI = NMBBI; + } + // normal order + MachineBasicBlock::iterator MBBI = MBB.begin(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + forceShiftMIWithRef(MI); + MBBI = NMBBI; + } + return Modified; +} + +bool XVMUpdateRefInstrForMI::forceAddSubRefInfoIbMBB(MachineBasicBlock &MBB) { + int InstNumber = 0; + bool Modified = false; + + MachineBasicBlock::iterator MBBI = MBB.begin(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (int i = 0; i < InstNumber; i++) { + MachineBasicBlock::iterator NMBBI = std::next(MBBI); + MachineInstr &MI = *MBBI; + if (MI.getOpcode() == XVM::ADD_rr) { + assert(MI.getNumOperands() == NUM_MO_3); + // if def is ref and use1 is not ref: + // then use2 should be a ref + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use1 = MI.getOperand(MO_SECOND); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); + Register regNoDef = MO_def.getReg(); + Register regNo1 = MO_use1.getReg(); + Register regNo2 = MO_use2.getReg(); + std::map::iterator IDef = MapRefRegInFunc.find(regNoDef); + std::map::iterator IUse1 = MapRefRegInFunc.find(regNo1); + std::map::iterator IUse2 = MapRefRegInFunc.find(regNo2); + + if (IDef != MapRefRegInFunc.end() && IDef->second == XVM_SYM_REG_REF) { + // now def is a ref + if (SetNonRefRegInFunc.find(regNo1) != SetNonRefRegInFunc.end()) { + // now use1 is not a ref: set use2 as a ref + MapRefRegInFunc[regNo2] = XVM_SYM_REG_REF; + // Need to Switch: will be catched in the next phases + } + } else if (IDef == MapRefRegInFunc.end() || IDef->second == XVM_SYM_REG_NON_REF) { + // now def is not a ref + if (MapRefRegInFunc[regNo1] == XVM_SYM_REG_REF || MapRefRegInFunc[regNo2] == XVM_SYM_REG_REF) { + // Now either use1 is ref or use2 is ref: def has to be ref + MapRefRegInFunc[regNoDef] = XVM_SYM_REG_REF; + } + } + } else if (MI.getOpcode() == XVM::ADD_ri || + MI.getOpcode() == XVM::SUB_ri || + MI.getOpcode() == XVM::SUB_rr) { + assert(MI.getNumOperands() == NUM_MO_3); + MachineOperand &MO_def = MI.getOperand(MO_FIRST); + MachineOperand &MO_use = MI.getOperand(MO_SECOND); + setRefFlagFor2Ops(MO_def, MO_use); + } + MBBI = NMBBI; + } + return Modified; +} + +bool XVMUpdateRefInstrForMI::updateRefInfoBasedInMBB(MachineBasicBlock &MBB) { + int InstNumber = 0; + bool Modified = false; + updatePtrRefInMBB(MBB); + /* Note: the two passes may be merged for efficiency */ + doubleCheckPhiMIWithRef(MBB); /* update the instructions */ - MBBI = MBB.rbegin(), E = MBB.rend(); + MachineBasicBlock::reverse_iterator MBBI = MBB.rbegin(), E = MBB.rend(); InstNumber = std::distance(MBB.begin(), MBB.end()); for (int i = 0; i < InstNumber; i++) { MachineBasicBlock::reverse_iterator NMBBI = std::next(MBBI); @@ -979,11 +1934,45 @@ bool XVMUpdateRefInstrForMI::updateRefInfoInMBB(MachineBasicBlock &MBB) { Modified |= updateLoadMIWithRef(MI, TII); Modified |= updateStoreMIWithRef(MI, TII); Modified |= updateAddSubMIWithRef(MI, TII); - Modified |= updateOrXorAndMIWithRef(MI, TII); + // Modified |= updateOrXorAndMIWithRef(MI, TII); Modified |= updatePhiMIWithRef(MI, TII); - Modified |= updateRegistersInMI(MI, TII); MBBI = NMBBI; } + + MBBI = MBB.rbegin(), E = MBB.rend(); + InstNumber = std::distance(MBB.begin(), MBB.end()); + for (MachineBasicBlock::iterator MBBI = MBB.begin(), MBBE = MBB.end(); MBBI != MBBE; MBBI++) { + MachineInstr &MI = *MBBI; + switch (MI.getOpcode()) { + case XVM::STW: + case XVM::STH: + case XVM::STB: + case XVM::STD: + case XVM::LDW_z: + case XVM::LDH_z: + case XVM::LDB_z: + case XVM::LDW: + case XVM::LDH: + case XVM::LDB: + case XVM::LDD: + if (MI.getOperand(MO_THIRD).isImm()) { + int64_t imm32 = MI.getOperand(MO_THIRD).getImm(); + if (imm32 > MAX_IMM || imm32 < -(MAX_IMM + 1)) { + if (MI.getOperand(MO_SECOND).isFI()) { + MachineFunction *MF = MBB.getParent(); + const Function &F = MF->getFunction(); + ExportFailMsg(F.getFunction(), MI.getDebugLoc(), "Error: Max stack size (1024) reached", (void*)&imm32); + exit(1); + } + Modified = true; + replaceImmWithMovk(MI); + } + } + default: + continue; + } + } + return Modified; } diff --git a/llvm/lib/Target/XVM/XVM_def.h b/llvm/lib/Target/XVM/XVM_def.h index ac0910a01792a094a427d68b7c7063970aa3938e..452d690b71c909003b09700424dccce83db92b92 100644 --- a/llvm/lib/Target/XVM/XVM_def.h +++ b/llvm/lib/Target/XVM/XVM_def.h @@ -36,9 +36,27 @@ meaning: | reserved X W R #define XVM_SECTION_DATA_TYPE_STRUCT 0b00100000 #define XVM_SECTION_DATA_TYPE_BSS 0b01000000 +#define MOVK_SHIFT_0 0 +#define MOVK_SHIFT_16 1 +#define MOVK_SHIFT_32 2 +#define MOVK_SHIFT_48 3 + +#define MOST_SIGNIFICANT 48 +#define UPPER_MIDDLE 32 +#define LOWER_MIDDLE 16 +#define LEAST_SIGNIFICANT 0 + +#define MO_FIRST 0 +#define MO_SECOND 1 +#define MO_THIRD 2 +#define MO_FOURTH 3 +#define MO_FIFTH 4 +#define MO_SIXTH 5 + typedef struct XVMGVPatchInfo { std::string SymName; int AddEnd; + unsigned int LocInByte; } XVMGVPathInfo; typedef struct XVMSectionInfo {