From 0803eea97984f8ef0f881e01a475cdaa189ca2df Mon Sep 17 00:00:00 2001 From: Jiaxin Xiong Date: Mon, 11 Nov 2024 23:03:23 +0000 Subject: [PATCH 1/4] [XVM] Bug Fixes Fix most csmith incorrect checksum errors. Fix 'Cannot select brcond' error. Fix stack size incorrectly being counted. Fix error where sometimes an immediate would be greater than 14 bits. Fix various ldr/str address issues. Signed-off-by: Jiaxin Xiong --- clang/lib/CodeGen/TargetInfo.cpp | 5 + llvm-build/build.py | 43 +- llvm/lib/Target/XVM/CMakeLists.txt | 2 + .../XVM/MCTargetDesc/XVMInstPrinter.cpp | 103 +- .../Target/XVM/MCTargetDesc/XVMInstPrinter.h | 12 +- .../XVM/MCTargetDesc/XVMMCTargetDesc.cpp | 1 + llvm/lib/Target/XVM/XVMAsmPrinter.cpp | 207 ++- llvm/lib/Target/XVM/XVMCFGSort.cpp | 367 ++-- llvm/lib/Target/XVM/XVMCFGStackify.cpp | 535 +++--- llvm/lib/Target/XVM/XVMCFGStructure.cpp | 6 +- llvm/lib/Target/XVM/XVMErrorMsg.h | 43 + llvm/lib/Target/XVM/XVMExpandPseudoInsts.cpp | 22 +- llvm/lib/Target/XVM/XVMFrameLowering.cpp | 9 +- llvm/lib/Target/XVM/XVMISelDAGToDAG.cpp | 139 +- llvm/lib/Target/XVM/XVMISelLowering.cpp | 822 ++++----- llvm/lib/Target/XVM/XVMISelLowering.h | 20 +- llvm/lib/Target/XVM/XVMInstrInfo.cpp | 156 +- llvm/lib/Target/XVM/XVMInstrInfo.h | 3 +- llvm/lib/Target/XVM/XVMInstrInfo.td | 12 +- llvm/lib/Target/XVM/XVMMCInstLower.cpp | 44 +- llvm/lib/Target/XVM/XVMRegisterInfo.cpp | 97 +- llvm/lib/Target/XVM/XVMRegisterInfo.h | 4 +- llvm/lib/Target/XVM/XVMSelectionDAGInfo.cpp | 1 + llvm/lib/Target/XVM/XVMSubtarget.cpp | 1 - llvm/lib/Target/XVM/XVMTargetMachine.cpp | 49 +- llvm/lib/Target/XVM/XVMTargetMachine.h | 8 +- llvm/lib/Target/XVM/XVMTargetTransformInfo.h | 13 +- .../lib/Target/XVM/XVMUpdateRefInstrForMI.cpp | 1524 +++++++++++++---- llvm/lib/Target/XVM/XVM_def.h | 18 + 29 files changed, 2666 insertions(+), 1600 deletions(-) create mode 100644 llvm/lib/Target/XVM/XVMErrorMsg.h diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index fc8fca3fe463..53b623819d8b 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5537,6 +5537,11 @@ public: llvm::AttrBuilder B(GV->getContext()); B.addAttribute("xvm-export-name", Attr->getExportName()); Fn->addFnAttrs(B); + } else { + if (FD->isStatic()) { + llvm::Function *Fn = cast(GV); + Fn->addFnAttr(llvm::Attribute::AlwaysInline); + } } } } diff --git a/llvm-build/build.py b/llvm-build/build.py index 0b43005266b3..da01534dd752 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,11 @@ 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) + 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 +988,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 +1096,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 +1200,7 @@ class LlvmCore(BuildUtils): '-Wl,--gc-sections', '-stdlib=libc++', '--rtlib=compiler-rt', - '-lunwind', + '-lunwind', '-Wl,--dynamicbase', '-Wl,--nxcompat', '-lucrt', @@ -1282,6 +1290,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 +2377,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 f203cf837bb3..4f891b2895dd 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 2974ec81313c..79efd4ec38a4 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 33e8860810f0..abd335ba511b 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 8480f9b8819c..d95446097c7b 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 30a67c159b83..97333b8e181f 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 d8e5d803d4e0..905277d5f8a8 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 6215156e3947..ad5d438fd01b 100644 --- a/llvm/lib/Target/XVM/XVMCFGStackify.cpp +++ b/llvm/lib/Target/XVM/XVMCFGStackify.cpp @@ -22,7 +22,6 @@ //===----------------------------------------------------------------------===// #ifdef XVM_DYLIB_MODE - #include "XVM.h" #include "XVMSortRegion.h" #include "XVMSubtarget.h" @@ -37,9 +36,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,17 +55,17 @@ 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); @@ -83,52 +81,49 @@ class XVMCFGStackify final : public MachineFunctionPass { const MachineBasicBlock *MBB); 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); + void unregisterScope(MachineInstr *Start); 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,64 @@ 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; + +// 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) { @@ -255,21 +248,70 @@ void XVMCFGStackify::fixBackEdgesOfLoops(MachineFunction &MF) { 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; + 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; + } + // Check if we need to add a break statement at the end of loop + int LevelBreakAfterLoop = -1; + if (action_opcode == XVM::CONTINUE) { + // 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); + 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); + } } } } @@ -413,230 +455,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,7 +711,7 @@ void XVMCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { // Now rewrite references to basic blocks to be depth immediates. std::map CondBranchsWithDepth; TII = MF.getSubtarget().getInstrInfo(); - SmallVector Stack; + SmallVector Stack; std::set SetEndBlockLoop; SmallVector EHPadStack; for (auto &MBB : reverse(MF)) { @@ -700,8 +736,8 @@ void XVMCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { 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) { + if (PrevMI != NULL) { + if (PrevMI->getOpcode() == XVM::END_BLOCK || PrevMI->getOpcode() == XVM::END_LOOP) { SetEndBlockLoop.insert(&MBB); } } @@ -710,7 +746,7 @@ void XVMCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { default: if (MI.isTerminator()) { // Rewrite MBB operands to be depth immediates. - SmallVector Ops(MI.operands()); + SmallVector Ops(MI.operands()); unsigned int Opcode = MI.getOpcode(); unsigned int depth = 0; while (MI.getNumOperands() > 0) @@ -738,9 +774,9 @@ void XVMCFGStackify::rewriteDepthImmediates(MachineFunction &MF) { } void XVMCFGStackify::cleanupFunctionData(MachineFunction &MF) { - if (FakeCallerBB) - MF.deleteMachineBasicBlock(FakeCallerBB); - AppendixBB = FakeCallerBB = nullptr; + if (FakeBBlockCaller) + MF.deleteMachineBasicBlock(FakeBBlockCaller); + AppendixBBlock = FakeBBlockCaller = nullptr; } void XVMCFGStackify::releaseMemory() { @@ -753,7 +789,6 @@ 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. diff --git a/llvm/lib/Target/XVM/XVMCFGStructure.cpp b/llvm/lib/Target/XVM/XVMCFGStructure.cpp index db76d9468f30..d7c8cd4ce02e 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 000000000000..c1e468ab85aa --- /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 5e75f124bf2a..f908e62beb33 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 bacd68abd954..5b544d4b2e8a 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 2909d9bfbeeb..9317eafa7f1a 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 b22b034e1d28..179486601186 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) { 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 e631e358d278..a9feb909343a 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 c4b233cc6576..6eb071424afa 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 6e51f3969687..c62e22c80ee3 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 8bb08ae9ac94..09e5e0d6f0d3 100644 --- a/llvm/lib/Target/XVM/XVMInstrInfo.td +++ b/llvm/lib/Target/XVM/XVMInstrInfo.td @@ -189,7 +189,7 @@ let isBranch = 1, hasCtrlDep = 1 in { def BREAK_IMM : ControFlowNoArgs<0b00001000, (outs), (ins uimm6:$imm), "break #$imm", []>; def CONTINUE : ControFlowNoArgs<0b00000000, (outs), (ins), "continue", []>; def THEN : ControFlowNoArgs<0b00000000, (outs), (ins), "(then", []>; - def END_THEN : ControFlowNoArgs<0b00000000, (outs), (ins), ")", []>; + def END_THEN : ControFlowNoArgs<0b00000000, (outs), (ins), ") ;; end_then", []>; def ELSE : ControFlowNoArgs<0b00000000, (outs), (ins), "(else", []>; def END_ELSE : ControFlowNoArgs<0b00000000, (outs), (ins), ")", []>; def END_IF : ControFlowNoArgs<0b00000000, (outs), (ins), ")", []>; @@ -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) >; diff --git a/llvm/lib/Target/XVM/XVMMCInstLower.cpp b/llvm/lib/Target/XVM/XVMMCInstLower.cpp index ac58ad2c755b..6026d5d1a81c 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 4466b1826e31..9c08b9efcd8f 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,42 @@ 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(); + auto &MFI = MFunction.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 (MInstr.getOpcode() == XVM::MOV_rr) { + int 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) { - BuildMI(MBB, II, DL, TII.get(XVM::AddRef_ri), reg).addReg(reg).addImm(StackSize + Offset); + BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::AddRef_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)) + int 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); + BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::AddRef_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 +146,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 2a5221d08a11..ab1b79812745 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 c2462ef33869..9acd3e0ce9d2 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 722d55c35e09..ff7b89002d0c 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 f7435f9a193c..f136c1dd3382 100644 --- a/llvm/lib/Target/XVM/XVMTargetMachine.cpp +++ b/llvm/lib/Target/XVM/XVMTargetMachine.cpp @@ -16,21 +16,17 @@ #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" using namespace llvm; @@ -45,6 +41,8 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXVMTarget() { initializeXVMCFGStackifyPass(PR); initializeXVMCFGStructurePass(PR); initializeXVMUpdateRefInstrForMIPass(PR); + initializeDSELegacyPassPass(PR); + initializeJumpThreadingPass(PR); } extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXVMTargetCalledInDylib() { @@ -62,20 +60,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 +100,10 @@ public: bool XVMPassConfig::addPreISel() { addPass(createFlattenCFGPass()); addPass(createFixIrreduciblePass()); + addPass(createDeadStoreEliminationPass()); + addPass(createJumpThreadingPass(-1)); + addPass(createSpeculativeExecutionPass()); + addPass(createMergedLoadStoreMotionPass()); return false; } diff --git a/llvm/lib/Target/XVM/XVMTargetMachine.h b/llvm/lib/Target/XVM/XVMTargetMachine.h index 3b25b0f1e89a..6d4146c29b19 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 2194866b6ab0..ecf6960157c9 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 11bdb0aad565..4838884ca14d 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,69 @@ 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 updateRefInfoBasedInMBB(MachineBasicBlock &MBB); + + bool checkAndUpdateOrInMBB(MachineBasicBlock &MBB); void updatePtrRefInMBB(MachineBasicBlock &MBB); + void doubleCheckPhiMIWithRef(MachineBasicBlock &MBB); + void doubleCheckRefs(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 +128,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 +159,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 +216,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 +230,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,49 +254,49 @@ 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; @@ -227,9 +305,9 @@ static bool updateLoadMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { 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); + 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; } @@ -239,33 +317,48 @@ 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 +372,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 +384,62 @@ 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(2); + 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(0); + MachineOperand &MO_use1 = MI.getOperand(1); + MachineOperand &MO_use2 = MI.getOperand(2); + + 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 +455,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 +544,168 @@ 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(0); + MachineOperand &NewMO_use1 = MI.getOperand(1); + MachineOperand &NewMO_use2 = MI.getOperand(2); + + ReplaceMI->addOperand(NewMO_def); + ReplaceMI->addOperand(NewMO_use2); + ReplaceMI->addOperand(NewMO_use1); + MBB.remove_instr(&MI); + MRI.verifyUseLists(); + return true; + } + } + } +} + +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 +713,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 +729,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 +842,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 +860,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 +884,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 +900,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 +922,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,11 +940,11 @@ 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; } @@ -781,7 +956,7 @@ static bool updatePhiMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { } 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 +970,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 +1006,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 +1035,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 +1100,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,12 +1132,428 @@ bool XVMUpdateRefInstrForMI::runOnMachineFunction(MachineFunction &MF) { FindNonRefRegInFunc(MF); bool Modified = false; + // scan MBBs in MF + for (auto &MBB : MF) { + Modified |= scanRefInfoInMBB(MBB); + } + // update MBBs in MF for (auto &MBB : MF) { - Modified |= updateRefInfoInMBB(MBB); + Modified |= updateRefInfoBasedInMBB(MBB); } + + for (auto &MBB : MF) { + Modified |= checkAndUpdateOrInMBB(MBB); + Modified |= updateRegistersOfMIInMBB(MBB); + } + + for (auto &MBB : MF) { + doubleCheckRefs(MBB); + } + Modified |= finalFixRefs(); + 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()) + return Modified; + + 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(2); + 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(0); + MachineOperand &NewMO_use1 = MI->getOperand(1); + MachineOperand &NewMO_use2 = MI->getOperand(2); + + 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::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()); @@ -948,28 +1565,199 @@ 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); + checkAddSubMIWithRef(MI); + checkPhiMIWithRef(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; +} + +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 +1767,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 ac0910a01792..452d690b71c9 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 { -- Gitee From b062cbe0e5aecf6e69343b721539d6c051374518 Mon Sep 17 00:00:00 2001 From: z00645861 Date: Fri, 21 Feb 2025 22:00:59 +0000 Subject: [PATCH 2/4] [XVM] Bug Fixes Fix most csmith incorrect checksum errors. Fix 'Cannot select brcond' error. Fix stack size incorrectly being counted. Fix error where sometimes an immediate would be greater than 14 bits. Fix various ldr/str address issues. Fix issues with break immediates Reworked Loop Depth calculation Signed-off-by: z00645861 --- clang/lib/CodeGen/TargetInfo.cpp | 9 +- .../Target/XVM/MCTargetDesc/XVMInstPrinter.h | 4 +- llvm/lib/Target/XVM/XVMCFGStackify.cpp | 264 ++++++++++-------- llvm/lib/Target/XVM/XVMISelLowering.cpp | 2 +- llvm/lib/Target/XVM/XVMInstrInfo.td | 4 +- llvm/lib/Target/XVM/XVMRegisterInfo.cpp | 18 +- llvm/lib/Target/XVM/XVMTargetMachine.cpp | 66 +++++ .../lib/Target/XVM/XVMUpdateRefInstrForMI.cpp | 221 +++++++++++++-- 8 files changed, 430 insertions(+), 158 deletions(-) diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 53b623819d8b..619a33956760 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5538,9 +5538,14 @@ public: B.addAttribute("xvm-export-name", Attr->getExportName()); Fn->addFnAttrs(B); } else { - if (FD->isStatic()) { + if (FD->hasBody() && FD->isStatic()) { + const auto *NoInlineAttrVar = FD->getAttr(); llvm::Function *Fn = cast(GV); - Fn->addFnAttr(llvm::Attribute::AlwaysInline); + if (!NoInlineAttrVar) { + Fn->addFnAttr(llvm::Attribute::AlwaysInline); + } else { + Fn->addFnAttr(llvm::Attribute::NoInline); + } } } } diff --git a/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h b/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h index abd335ba511b..d28cb862843a 100644 --- a/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h +++ b/llvm/lib/Target/XVM/MCTargetDesc/XVMInstPrinter.h @@ -25,9 +25,9 @@ public: void printInst(const MCInst *MI, uint64_t Address, StringRef Annot, const MCSubtargetInfo &STI, raw_ostream &O) override; void printOperand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream, - const char *Mod = nullptr); + const char *Mod = nullptr); void printMemOperand(const MCInst *MInst, int OpNum, raw_ostream &OStream, - const char *Mod = nullptr); + const char *Mod = nullptr); void printImm64Operand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream); void printBrTargetOperand(const MCInst *MInst, unsigned OpNum, raw_ostream &OStream); diff --git a/llvm/lib/Target/XVM/XVMCFGStackify.cpp b/llvm/lib/Target/XVM/XVMCFGStackify.cpp index ad5d438fd01b..f6c8ec17b176 100644 --- a/llvm/lib/Target/XVM/XVMCFGStackify.cpp +++ b/llvm/lib/Target/XVM/XVMCFGStackify.cpp @@ -23,6 +23,7 @@ #ifdef XVM_DYLIB_MODE #include "XVM.h" +#include "XVM_def.h" #include "XVMSortRegion.h" #include "XVMSubtarget.h" #include "llvm/ADT/Statistic.h" @@ -72,13 +73,13 @@ class XVMCFGStackify final : public MachineFunctionPass { 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 &MFunction); @@ -120,7 +121,6 @@ class XVMCFGStackify final : public MachineFunctionPass { void registerScope(MachineInstr *Start, MachineInstr *Finish); void registerTryScope(MachineInstr *Start, MachineInstr *Finish, MachineBasicBlock *EHPad); - void unregisterScope(MachineInstr *Start); public: static char ID; // typeid replacement, for identification @@ -139,6 +139,11 @@ FunctionPass *llvm::createXVMCFGStackify() { return new XVMCFGStackify(); } +// 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 @@ -227,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(); @@ -241,58 +254,60 @@ 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) { + } 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 (&MBB == Loop->getBottomBlock() && - &MI == &*(--MBB.end()) && - MLI.getLoopFor(MBB.getFallThrough()) != Loop) { - TII->negateCondBranch(&MI); - action_opcode = XVM::BREAK; + 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; - if (action_opcode == XVM::CONTINUE) { - // 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; - } + + // 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; - } + } + 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); + 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) { @@ -323,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(); @@ -348,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(); @@ -711,66 +748,39 @@ 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) { - if (PrevMI->getOpcode() == XVM::END_BLOCK || PrevMI->getOpcode() == XVM::END_LOOP) { - 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) { @@ -785,15 +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/XVMISelLowering.cpp b/llvm/lib/Target/XVM/XVMISelLowering.cpp index 179486601186..11e92863c0b7 100644 --- a/llvm/lib/Target/XVM/XVMISelLowering.cpp +++ b/llvm/lib/Target/XVM/XVMISelLowering.cpp @@ -715,7 +715,7 @@ SDValue XVMTargetLowering::LowerBRCOND(SDValue Op, SelectionDAG &DAG) const { 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::SELECT || CondV.getOpcode() == ISD::SREM) { SDValue LHS = CondV; SDValue RHS = DAG.getConstant(0, DL, MVT::i64); SDValue TargetCC = DAG.getCondCode(ISD::SETNE); diff --git a/llvm/lib/Target/XVM/XVMInstrInfo.td b/llvm/lib/Target/XVM/XVMInstrInfo.td index 09e5e0d6f0d3..2a0fc34c246e 100644 --- a/llvm/lib/Target/XVM/XVMInstrInfo.td +++ b/llvm/lib/Target/XVM/XVMInstrInfo.td @@ -189,7 +189,7 @@ let isBranch = 1, hasCtrlDep = 1 in { def BREAK_IMM : ControFlowNoArgs<0b00001000, (outs), (ins uimm6:$imm), "break #$imm", []>; def CONTINUE : ControFlowNoArgs<0b00000000, (outs), (ins), "continue", []>; def THEN : ControFlowNoArgs<0b00000000, (outs), (ins), "(then", []>; - def END_THEN : ControFlowNoArgs<0b00000000, (outs), (ins), ") ;; end_then", []>; + def END_THEN : ControFlowNoArgs<0b00000000, (outs), (ins), ")", []>; def ELSE : ControFlowNoArgs<0b00000000, (outs), (ins), "(else", []>; def END_ELSE : ControFlowNoArgs<0b00000000, (outs), (ins), ")", []>; def END_IF : ControFlowNoArgs<0b00000000, (outs), (ins), ")", []>; @@ -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/XVMRegisterInfo.cpp b/llvm/lib/Target/XVM/XVMRegisterInfo.cpp index 9c08b9efcd8f..49d41e471861 100644 --- a/llvm/lib/Target/XVM/XVMRegisterInfo.cpp +++ b/llvm/lib/Target/XVM/XVMRegisterInfo.cpp @@ -93,22 +93,24 @@ void XVMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBIterato * Therefore, we use SP+(Stacksize + FP_offset) to mimic (FP + FP_offset) */ auto &MFI = MFunction.getFrameInfo(); - uint64_t StackSize = MFI.getStackSize(); + int64_t StackSize = (int64_t)MFI.getStackSize(); + int Offset = 0; if (MInstr.getOpcode() == XVM::MOV_rr) { - int Offset = MFunction.getFrameInfo().getObjectOffset(FrameIndex); + 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) { + 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)); } MInstr.eraseFromParent(); return; } - int Offset = MFunction.getFrameInfo().getObjectOffset(FrameIndex) + - MInstr.getOperand(counter + 1).getImm(); + Offset = MFunction.getFrameInfo().getObjectOffset(FrameIndex) + MInstr.getOperand(counter + 1).getImm(); if (!isInt(Offset)) llvm_unreachable("bug in frame offset"); @@ -121,7 +123,11 @@ void XVMRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MBBIterato // ADD_ri , imm Register reg = MInstr.getOperand(counter - 1).getReg(); BuildMI(MBBlock, ++MBBIterator, DLoc, TII.get(XVM::MOV_rr), reg).addReg(FrameReg); - BuildMI(MBBlock, MBBIterator, DLoc, TII.get(XVM::AddRef_ri), reg).addReg(reg).addImm(StackSize + Offset); + 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 MInstr.eraseFromParent(); diff --git a/llvm/lib/Target/XVM/XVMTargetMachine.cpp b/llvm/lib/Target/XVM/XVMTargetMachine.cpp index f136c1dd3382..40aaec7808e6 100644 --- a/llvm/lib/Target/XVM/XVMTargetMachine.cpp +++ b/llvm/lib/Target/XVM/XVMTargetMachine.cpp @@ -27,6 +27,10 @@ #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; @@ -43,6 +47,37 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXVMTarget() { 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() { @@ -104,6 +139,35 @@ bool XVMPassConfig::addPreISel() { 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; } @@ -137,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/XVMUpdateRefInstrForMI.cpp b/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp index 4838884ca14d..6b9fbc6dbe9f 100644 --- a/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp +++ b/llvm/lib/Target/XVM/XVMUpdateRefInstrForMI.cpp @@ -51,12 +51,14 @@ public: StringRef getPassName() const override { return XVM_REF_DETERMINE_NAME; } private: 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); @@ -302,17 +304,6 @@ static bool updateLoadMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) { 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() == NUM_MO_3); - MachineOperand &MO_def = MI.getOperand(MO_FIRST); - MachineOperand &MO_use = MI.getOperand(MO_SECOND); - setRefFlagFor2Ops(MO_def, MO_use); - return; - } -} - static void checkOrXorAndMIWithRef(MachineInstr &MI) { if (MI.getOpcode() == XVM::OR_ri || MI.getOpcode() == XVM::XOR_ri|| @@ -400,7 +391,7 @@ static inline bool updateAddMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) updateAddRiWithRef(MI, TII); } else { // It may be the case there use2 is a ref while use1 is not a ref - MachineOperand &MO_use2 = MI.getOperand(2); + MachineOperand &MO_use2 = MI.getOperand(MO_THIRD); Register regNoUse1 = MO_use1.getReg(); Register regNoUse2 = MO_use2.getReg(); std::map::iterator ItrUse1 = MapRefRegInFunc.find(regNoUse1); @@ -419,13 +410,14 @@ static inline bool updateAddMIWithRef(MachineInstr &MI, const XVMInstrInfo *TII) MachineRegisterInfo &MRI = MF->getRegInfo(); MachineInstr *ReplaceMI = BuildMI(MBB, II, DL, TII->get(XVM::AddRef_rr)); - MachineOperand &MO_def = MI.getOperand(0); - MachineOperand &MO_use1 = MI.getOperand(1); - MachineOperand &MO_use2 = MI.getOperand(2); + 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 { @@ -566,9 +558,9 @@ static inline bool switchOperandUse1Use2(MachineBasicBlock &MBB, MachineInstr &M MachineRegisterInfo &MRI = MF->getRegInfo(); MachineInstr *ReplaceMI = BuildMI(MBB, II, DL, TII->get(MI.getOpcode())); - MachineOperand &NewMO_def = MI.getOperand(0); - MachineOperand &NewMO_use1 = MI.getOperand(1); - MachineOperand &NewMO_use2 = MI.getOperand(2); + 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); @@ -579,6 +571,8 @@ static inline bool switchOperandUse1Use2(MachineBasicBlock &MBB, MachineInstr &M } } } + + return false; } static inline bool updateOrMIWithRef(MachineBasicBlock &MBB, MachineInstr &MI, const XVMInstrInfo *TII) { @@ -950,6 +944,15 @@ static void checkPhiMIWithRef(MachineInstr &MI) { } } +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; @@ -1132,10 +1135,20 @@ bool XVMUpdateRefInstrForMI::runOnMachineFunction(MachineFunction &MF) { FindNonRefRegInFunc(MF); bool Modified = false; + // force the ref info for shift MIs in MBB + for (auto &MBB : MF) { + Modified |= forceShiftRefInfoIbMBB(MBB); + } // scan MBBs in MF for (auto &MBB : MF) { Modified |= scanRefInfoInMBB(MBB); } + + // 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); @@ -1151,6 +1164,9 @@ bool XVMUpdateRefInstrForMI::runOnMachineFunction(MachineFunction &MF) { } Modified |= finalFixRefs(); + for (auto &MBB : MF) { + checkAndReplaceAddWithAddRefs(MBB); + } return Modified; } @@ -1163,7 +1179,7 @@ bool XVMUpdateRefInstrForMI::finalFixRefs(void) { MachineOperand &MO_def = MI->getOperand(MO_FIRST); if (!MO_def.isReg()) - return Modified; + continue; Register regNoDef = MO_def.getReg(); std::map::iterator IForDef = MapRefRegInFunc.find(regNoDef); @@ -1189,7 +1205,7 @@ bool XVMUpdateRefInstrForMI::finalFixRefs(void) { 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(2); + MachineOperand &MO_use2 = MI->getOperand(MO_THIRD); Register regNoUse2 = MO_use2.getReg(); std::map::iterator IForUse2 = MapRefRegInFunc.find(regNoUse2); if (IForUse2 != MapRefRegInFunc.end()) { @@ -1202,9 +1218,9 @@ bool XVMUpdateRefInstrForMI::finalFixRefs(void) { MachineRegisterInfo &MRI = MF->getRegInfo(); MachineInstr *ReplaceMI = BuildMI(*MBB, II, DL, TII->get(XVM::AddRef_rr)); - MachineOperand &NewMO_def = MI->getOperand(0); - MachineOperand &NewMO_use1 = MI->getOperand(1); - MachineOperand &NewMO_use2 = MI->getOperand(2); + 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); @@ -1258,6 +1274,54 @@ bool XVMUpdateRefInstrForMI::finalFixRefs(void) { 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()); @@ -1729,8 +1793,8 @@ bool XVMUpdateRefInstrForMI::scanRefInfoInMBB(MachineBasicBlock &MBB) { checkMovMIWithRef(MI); checkLoadMIWithRef(MI); checkStoreMIWithRef(MI); - checkAddSubMIWithRef(MI); checkPhiMIWithRef(MI); + checkFIMIWithRef(MI); R_MBBI = NMBBI; } // normal order @@ -1743,13 +1807,116 @@ bool XVMUpdateRefInstrForMI::scanRefInfoInMBB(MachineBasicBlock &MBB) { checkMovMIWithRef(MI); checkLoadMIWithRef(MI); checkStoreMIWithRef(MI); - checkAddSubMIWithRef(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; @@ -1805,7 +1972,7 @@ bool XVMUpdateRefInstrForMI::updateRefInfoBasedInMBB(MachineBasicBlock &MBB) { continue; } } - + return Modified; } -- Gitee From 53400469835d14140f292c214d401e2a26ba9d52 Mon Sep 17 00:00:00 2001 From: Jiaxin Xiong Date: Sat, 10 May 2025 16:23:41 +0800 Subject: [PATCH 3/4] [XVM] Remove extra optimization passes Fix csmith incorrect checksum error. Signed-off-by: Jiaxin Xiong --- llvm/lib/Target/XVM/XVMTargetMachine.cpp | 110 +++++++++++------------ 1 file changed, 55 insertions(+), 55 deletions(-) diff --git a/llvm/lib/Target/XVM/XVMTargetMachine.cpp b/llvm/lib/Target/XVM/XVMTargetMachine.cpp index 40aaec7808e6..eb05f7cc25aa 100644 --- a/llvm/lib/Target/XVM/XVMTargetMachine.cpp +++ b/llvm/lib/Target/XVM/XVMTargetMachine.cpp @@ -48,34 +48,34 @@ extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeXVMTarget() { 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); + // 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); } @@ -140,33 +140,33 @@ bool XVMPassConfig::addPreISel() { 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()); + // 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; } -- Gitee From 2e5384e10f7ce56c88977a3638a7cb25d270cdd4 Mon Sep 17 00:00:00 2001 From: Jiaxin Xiong Date: Fri, 13 Jun 2025 16:45:58 +0800 Subject: [PATCH 4/4] [XVM] Add comments on XVM bug fixes Add code comments on XVM bug fixes Signed-off-by: Jiaxin Xiong --- clang/lib/CodeGen/TargetInfo.cpp | 4 ++++ llvm-build/build.py | 2 ++ 2 files changed, 6 insertions(+) diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 619a33956760..3b8bf76575b6 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -5538,6 +5538,10 @@ public: 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); diff --git a/llvm-build/build.py b/llvm-build/build.py index da01534dd752..b24e3fa87719 100755 --- a/llvm-build/build.py +++ b/llvm-build/build.py @@ -817,6 +817,8 @@ 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: + # 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, -- Gitee