diff options
author | Stephen Hines <srhines@google.com> | 2014-04-23 16:57:46 -0700 |
---|---|---|
committer | Stephen Hines <srhines@google.com> | 2014-04-24 15:53:16 -0700 |
commit | 36b56886974eae4f9c5ebc96befd3e7bfe5de338 (patch) | |
tree | e6cfb69fbbd937f450eeb83bfb83b9da3b01275a /lib/Target/SystemZ | |
parent | 69a8640022b04415ae9fac62f8ab090601d8f889 (diff) | |
download | external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.zip external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.gz external_llvm-36b56886974eae4f9c5ebc96befd3e7bfe5de338.tar.bz2 |
Update to LLVM 3.5a.
Change-Id: Ifadecab779f128e62e430c2b4f6ddd84953ed617
Diffstat (limited to 'lib/Target/SystemZ')
55 files changed, 1763 insertions, 1419 deletions
diff --git a/lib/Target/SystemZ/AsmParser/CMakeLists.txt b/lib/Target/SystemZ/AsmParser/CMakeLists.txt index 78a5714..ad19a56 100644 --- a/lib/Target/SystemZ/AsmParser/CMakeLists.txt +++ b/lib/Target/SystemZ/AsmParser/CMakeLists.txt @@ -1,7 +1,3 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMSystemZAsmParser SystemZAsmParser.cpp ) - -add_dependencies(LLVMSystemZAsmParser SystemZCommonTableGen) diff --git a/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp index 763f40c..a3dd4b6 100644 --- a/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp +++ b/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp @@ -22,7 +22,7 @@ using namespace llvm; // Return true if Expr is in the range [MinValue, MaxValue]. static bool inRange(const MCExpr *Expr, int64_t MinValue, int64_t MaxValue) { - if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) { + if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { int64_t Value = CE->getValue(); return Value >= MinValue && Value <= MaxValue; } @@ -112,7 +112,7 @@ private: // Add as immediates when possible. Null MCExpr = 0. if (Expr == 0) Inst.addOperand(MCOperand::CreateImm(0)); - else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) + else if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) Inst.addOperand(MCOperand::CreateImm(CE->getValue())); else Inst.addOperand(MCOperand::CreateExpr(Expr)); @@ -162,7 +162,7 @@ public: } // Token operands - virtual bool isToken() const LLVM_OVERRIDE { + bool isToken() const override { return Kind == KindToken; } StringRef getToken() const { @@ -171,13 +171,13 @@ public: } // Register operands. - virtual bool isReg() const LLVM_OVERRIDE { + bool isReg() const override { return Kind == KindReg; } bool isReg(RegisterKind RegKind) const { return Kind == KindReg && Reg.Kind == RegKind; } - virtual unsigned getReg() const LLVM_OVERRIDE { + unsigned getReg() const override { assert(Kind == KindReg && "Not a register"); return Reg.Num; } @@ -189,7 +189,7 @@ public: } // Immediate operands. - virtual bool isImm() const LLVM_OVERRIDE { + bool isImm() const override { return Kind == KindImm; } bool isImm(int64_t MinValue, int64_t MaxValue) const { @@ -201,7 +201,7 @@ public: } // Memory operands. - virtual bool isMem() const LLVM_OVERRIDE { + bool isMem() const override { return Kind == KindMem; } bool isMem(RegisterKind RegKind, MemoryKind MemKind) const { @@ -221,9 +221,9 @@ public: } // Override MCParsedAsmOperand. - virtual SMLoc getStartLoc() const LLVM_OVERRIDE { return StartLoc; } - virtual SMLoc getEndLoc() const LLVM_OVERRIDE { return EndLoc; } - virtual void print(raw_ostream &OS) const LLVM_OVERRIDE; + SMLoc getStartLoc() const override { return StartLoc; } + SMLoc getEndLoc() const override { return EndLoc; } + void print(raw_ostream &OS) const override; // Used by the TableGen code to add particular types of operand // to an instruction. @@ -340,18 +340,16 @@ public: } // Override MCTargetAsmParser. - virtual bool ParseDirective(AsmToken DirectiveID) LLVM_OVERRIDE; - virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, - SMLoc &EndLoc) LLVM_OVERRIDE; - virtual bool ParseInstruction(ParseInstructionInfo &Info, - StringRef Name, SMLoc NameLoc, - SmallVectorImpl<MCParsedAsmOperand*> &Operands) - LLVM_OVERRIDE; - virtual bool - MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, - SmallVectorImpl<MCParsedAsmOperand*> &Operands, - MCStreamer &Out, unsigned &ErrorInfo, - bool MatchingInlineAsm) LLVM_OVERRIDE; + bool ParseDirective(AsmToken DirectiveID) override; + bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override; + bool ParseInstruction(ParseInstructionInfo &Info, + StringRef Name, SMLoc NameLoc, + SmallVectorImpl<MCParsedAsmOperand*> &Operands) + override; + bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, + SmallVectorImpl<MCParsedAsmOperand*> &Operands, + MCStreamer &Out, unsigned &ErrorInfo, + bool MatchingInlineAsm) override; // Used by the TableGen code to parse particular operand types. OperandMatchResultTy @@ -428,7 +426,7 @@ public: return parsePCRel(Operands, -(1LL << 32), (1LL << 32) - 1); } }; -} +} // end anonymous namespace #define GET_REGISTER_MATCHER #define GET_SUBTARGET_FEATURE_NAME @@ -715,7 +713,7 @@ MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode, default: break; case Match_Success: Inst.setLoc(IDLoc); - Out.EmitInstruction(Inst); + Out.EmitInstruction(Inst, STI); return false; case Match_MissingFeature: { @@ -781,7 +779,7 @@ parsePCRel(SmallVectorImpl<MCParsedAsmOperand*> &Operands, // For consistency with the GNU assembler, treat immediates as offsets // from ".". - if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr)) { + if (auto *CE = dyn_cast<MCConstantExpr>(Expr)) { int64_t Value = CE->getValue(); if ((Value & 1) || Value < MinVal || Value > MaxVal) { Error(StartLoc, "offset out of range"); diff --git a/lib/Target/SystemZ/CMakeLists.txt b/lib/Target/SystemZ/CMakeLists.txt index d21c0a8..4da2d0f 100644 --- a/lib/Target/SystemZ/CMakeLists.txt +++ b/lib/Target/SystemZ/CMakeLists.txt @@ -30,8 +30,6 @@ add_llvm_target(SystemZCodeGen SystemZTargetMachine.cpp ) -add_dependencies(LLVMSystemZCodeGen SystemZCommonTableGen intrinsics_gen) - add_subdirectory(AsmParser) add_subdirectory(Disassembler) add_subdirectory(InstPrinter) diff --git a/lib/Target/SystemZ/Disassembler/CMakeLists.txt b/lib/Target/SystemZ/Disassembler/CMakeLists.txt index 5bc1859..4b94bcd 100644 --- a/lib/Target/SystemZ/Disassembler/CMakeLists.txt +++ b/lib/Target/SystemZ/Disassembler/CMakeLists.txt @@ -1,7 +1,3 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMSystemZDisassembler SystemZDisassembler.cpp ) - -add_dependencies(LLVMSystemZDisassembler SystemZCommonTableGen) diff --git a/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp b/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp index fc3c38d..59a1fe9 100644 --- a/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp +++ b/lib/Target/SystemZ/Disassembler/SystemZDisassembler.cpp @@ -27,12 +27,10 @@ public: virtual ~SystemZDisassembler() {} // Override MCDisassembler. - virtual DecodeStatus getInstruction(MCInst &instr, - uint64_t &size, - const MemoryObject ®ion, - uint64_t address, - raw_ostream &vStream, - raw_ostream &cStream) const LLVM_OVERRIDE; + DecodeStatus getInstruction(MCInst &instr, uint64_t &size, + const MemoryObject ®ion, uint64_t address, + raw_ostream &vStream, + raw_ostream &cStream) const override; }; } // end anonymous namespace diff --git a/lib/Target/SystemZ/InstPrinter/CMakeLists.txt b/lib/Target/SystemZ/InstPrinter/CMakeLists.txt index ddbf82f..21b023c 100644 --- a/lib/Target/SystemZ/InstPrinter/CMakeLists.txt +++ b/lib/Target/SystemZ/InstPrinter/CMakeLists.txt @@ -1,7 +1,3 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMSystemZAsmPrinter SystemZInstPrinter.cpp ) - -add_dependencies(LLVMSystemZAsmPrinter SystemZCommonTableGen) diff --git a/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h b/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h index 734ecf0..dce482b 100644 --- a/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h +++ b/lib/Target/SystemZ/InstPrinter/SystemZInstPrinter.h @@ -38,10 +38,8 @@ public: static void printOperand(const MCOperand &MO, raw_ostream &O); // Override MCInstPrinter. - virtual void printRegName(raw_ostream &O, unsigned RegNo) const - LLVM_OVERRIDE; - virtual void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) - LLVM_OVERRIDE; + void printRegName(raw_ostream &O, unsigned RegNo) const override; + void printInst(const MCInst *MI, raw_ostream &O, StringRef Annot) override; private: // Print various types of operand. diff --git a/lib/Target/SystemZ/LLVMBuild.txt b/lib/Target/SystemZ/LLVMBuild.txt index 95e657f..7781318 100644 --- a/lib/Target/SystemZ/LLVMBuild.txt +++ b/lib/Target/SystemZ/LLVMBuild.txt @@ -31,5 +31,5 @@ has_jit = 1 type = Library name = SystemZCodeGen parent = SystemZ -required_libraries = AsmPrinter CodeGen Core MC SelectionDAG SystemZDesc SystemZInfo Support Target +required_libraries = AsmPrinter CodeGen Core MC Scalar SelectionDAG Support SystemZAsmPrinter SystemZDesc SystemZInfo Target add_to_library_groups = SystemZ diff --git a/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt b/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt index 3d13128..1aa8c76 100644 --- a/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt +++ b/lib/Target/SystemZ/MCTargetDesc/CMakeLists.txt @@ -5,5 +5,3 @@ add_llvm_library(LLVMSystemZDesc SystemZMCObjectWriter.cpp SystemZMCTargetDesc.cpp ) - -add_dependencies(LLVMSystemZDesc SystemZCommonTableGen) diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp index 26a8fae..6e7268d 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmBackend.cpp @@ -43,37 +43,27 @@ public: : OSABI(osABI) {} // Override MCAsmBackend - virtual unsigned getNumFixupKinds() const LLVM_OVERRIDE { + unsigned getNumFixupKinds() const override { return SystemZ::NumTargetFixupKinds; } - virtual const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const - LLVM_OVERRIDE; - virtual void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, - uint64_t Value) const LLVM_OVERRIDE; - virtual bool mayNeedRelaxation(const MCInst &Inst) const LLVM_OVERRIDE { + const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override; + void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, + uint64_t Value, bool IsPCRel) const override; + bool mayNeedRelaxation(const MCInst &Inst) const override { return false; } - virtual bool fixupNeedsRelaxation(const MCFixup &Fixup, - uint64_t Value, - const MCRelaxableFragment *Fragment, - const MCAsmLayout &Layout) const - LLVM_OVERRIDE { + bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, + const MCRelaxableFragment *Fragment, + const MCAsmLayout &Layout) const override { return false; } - virtual void relaxInstruction(const MCInst &Inst, - MCInst &Res) const LLVM_OVERRIDE { + void relaxInstruction(const MCInst &Inst, MCInst &Res) const override { llvm_unreachable("SystemZ does do not have assembler relaxation"); } - virtual bool writeNopData(uint64_t Count, - MCObjectWriter *OW) const LLVM_OVERRIDE; - virtual MCObjectWriter *createObjectWriter(raw_ostream &OS) const - LLVM_OVERRIDE { + bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override; + MCObjectWriter *createObjectWriter(raw_ostream &OS) const override { return createSystemZObjectWriter(OS, OSABI); } - virtual bool doesSectionRequireSymbols(const MCSection &Section) const - LLVM_OVERRIDE { - return false; - } }; } // end anonymous namespace @@ -95,7 +85,8 @@ SystemZMCAsmBackend::getFixupKindInfo(MCFixupKind Kind) const { } void SystemZMCAsmBackend::applyFixup(const MCFixup &Fixup, char *Data, - unsigned DataSize, uint64_t Value) const { + unsigned DataSize, uint64_t Value, + bool IsPCRel) const { MCFixupKind Kind = Fixup.getKind(); unsigned Offset = Fixup.getOffset(); unsigned Size = (getFixupKindInfo(Kind).TargetSize + 7) / 8; diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp index 965c41e..c46a36b 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.cpp @@ -19,8 +19,6 @@ SystemZMCAsmInfo::SystemZMCAsmInfo(StringRef TT) { IsLittleEndian = false; CommentString = "#"; - GlobalPrefix = ""; - PrivateGlobalPrefix = ".L"; ZeroDirective = "\t.space\t"; Data64bitsDirective = "\t.quad\t"; UsesELFSectionDirectiveForBSS = true; diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h index b9ac92a..1de97af 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCAsmInfo.h @@ -21,10 +21,9 @@ public: explicit SystemZMCAsmInfo(StringRef TT); // Override MCAsmInfo; - virtual const MCSection *getNonexecutableStackSection(MCContext &Ctx) const - LLVM_OVERRIDE; + const MCSection *getNonexecutableStackSection(MCContext &Ctx) const override; }; -} // namespace llvm +} // end namespace llvm #endif diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp index f07ea7b..df50863 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp @@ -34,34 +34,41 @@ public: ~SystemZMCCodeEmitter() {} // OVerride MCCodeEmitter. - virtual void EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const - LLVM_OVERRIDE; + void EncodeInstruction(const MCInst &MI, raw_ostream &OS, + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const override; private: // Automatically generated by TableGen. uint64_t getBinaryCodeForInstr(const MCInst &MI, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; // Called by the TableGen code to get the binary encoding of operand // MO in MI. Fixups is the list of fixups against MI. uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; // Called by the TableGen code to get the binary encoding of an address. // The index or length, if any, is encoded first, followed by the base, // followed by the displacement. In a 20-bit displacement, // the low 12 bits are encoded before the high 8 bits. uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const; // Operand OpNum of MI needs a PC-relative fixup of kind Kind at // Offset bytes from the start of MI. Add the fixup to Fixups @@ -72,15 +79,17 @@ private: unsigned Kind, int64_t Offset) const; uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC16DBL, 2); } uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { return getPCRelEncoding(MI, OpNum, Fixups, SystemZ::FK_390_PC32DBL, 2); } }; -} +} // end anonymous namespace MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, @@ -91,8 +100,9 @@ MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII, void SystemZMCCodeEmitter:: EncodeInstruction(const MCInst &MI, raw_ostream &OS, - SmallVectorImpl<MCFixup> &Fixups) const { - uint64_t Bits = getBinaryCodeForInstr(MI, Fixups); + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI); unsigned Size = MCII.get(MI.getOpcode()).getSize(); // Big-endian insertion of Size bytes. unsigned ShiftValue = (Size * 8) - 8; @@ -104,7 +114,8 @@ EncodeInstruction(const MCInst &MI, raw_ostream &OS, uint64_t SystemZMCCodeEmitter:: getMachineOpValue(const MCInst &MI, const MCOperand &MO, - SmallVectorImpl<MCFixup> &Fixups) const { + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { if (MO.isReg()) return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg()); if (MO.isImm()) @@ -114,38 +125,42 @@ getMachineOpValue(const MCInst &MI, const MCOperand &MO, uint64_t SystemZMCCodeEmitter:: getBDAddr12Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { - uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); assert(isUInt<4>(Base) && isUInt<12>(Disp)); return (Base << 12) | Disp; } uint64_t SystemZMCCodeEmitter:: getBDAddr20Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { - uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); assert(isUInt<4>(Base) && isInt<20>(Disp)); return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); } uint64_t SystemZMCCodeEmitter:: getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { - uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); - uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups); + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index)); return (Index << 16) | (Base << 12) | Disp; } uint64_t SystemZMCCodeEmitter:: getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { - uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); - uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups); + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI); assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index)); return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12); @@ -153,10 +168,11 @@ getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum, uint64_t SystemZMCCodeEmitter:: getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum, - SmallVectorImpl<MCFixup> &Fixups) const { - uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups); - uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups); - uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups) - 1; + SmallVectorImpl<MCFixup> &Fixups, + const MCSubtargetInfo &STI) const { + uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI); + uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI); + uint64_t Len = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1; assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len)); return (Len << 16) | (Base << 12) | Disp; } diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h index 9c94ebb..a3aab71 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCFixups.h @@ -14,18 +14,18 @@ namespace llvm { namespace SystemZ { - enum FixupKind { - // These correspond directly to R_390_* relocations. - FK_390_PC16DBL = FirstTargetFixupKind, - FK_390_PC32DBL, - FK_390_PLT16DBL, - FK_390_PLT32DBL, +enum FixupKind { + // These correspond directly to R_390_* relocations. + FK_390_PC16DBL = FirstTargetFixupKind, + FK_390_PC32DBL, + FK_390_PLT16DBL, + FK_390_PLT32DBL, - // Marker - LastTargetFixupKind, - NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind - }; -} + // Marker + LastTargetFixupKind, + NumTargetFixupKinds = LastTargetFixupKind - FirstTargetFixupKind +}; +} // end namespace SystemZ } // end namespace llvm #endif diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp index 36e3d83..54c6987 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCObjectWriter.cpp @@ -24,16 +24,10 @@ public: protected: // Override MCELFObjectTargetWriter. - virtual unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, bool IsRelocWithSymbol, - int64_t Addend) const LLVM_OVERRIDE; - virtual const MCSymbol *ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const LLVM_OVERRIDE; + unsigned GetRelocType(const MCValue &Target, const MCFixup &Fixup, + bool IsPCRel) const override; }; -} // end anonymouse namespace +} // end anonymous namespace SystemZObjectWriter::SystemZObjectWriter(uint8_t OSABI) : MCELFObjectTargetWriter(/*Is64Bit=*/true, OSABI, ELF::EM_S390, @@ -87,12 +81,8 @@ static unsigned getPLTReloc(unsigned Kind) { unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, const MCFixup &Fixup, - bool IsPCRel, - bool IsRelocWithSymbol, - int64_t Addend) const { - MCSymbolRefExpr::VariantKind Modifier = (Target.isAbsolute() ? - MCSymbolRefExpr::VK_None : - Target.getSymA()->getKind()); + bool IsPCRel) const { + MCSymbolRefExpr::VariantKind Modifier = Fixup.getAccessVariant(); unsigned Kind = Fixup.getKind(); switch (Modifier) { case MCSymbolRefExpr::VK_None: @@ -118,21 +108,6 @@ unsigned SystemZObjectWriter::GetRelocType(const MCValue &Target, } } -const MCSymbol *SystemZObjectWriter::ExplicitRelSym(const MCAssembler &Asm, - const MCValue &Target, - const MCFragment &F, - const MCFixup &Fixup, - bool IsPCRel) const { - // The addend in a PC-relative R_390_* relocation is always applied to - // the PC-relative part of the address. If some kind of indirection - // is applied to the symbol first, we can't use an addend there too. - if (!Target.isAbsolute() && - Target.getSymA()->getKind() != MCSymbolRefExpr::VK_None && - IsPCRel) - return &Target.getSymA()->getSymbol().AliasedSymbol(); - return NULL; -} - MCObjectWriter *llvm::createSystemZObjectWriter(raw_ostream &OS, uint8_t OSABI) { MCELFObjectTargetWriter *MOTW = new SystemZObjectWriter(OSABI); diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp index 9e1296b..8d1bac9 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.cpp @@ -185,9 +185,10 @@ static MCStreamer *createSystemZMCObjectStreamer(const Target &T, StringRef TT, MCAsmBackend &MAB, raw_ostream &OS, MCCodeEmitter *Emitter, + const MCSubtargetInfo &STI, bool RelaxAll, bool NoExecStack) { - return createELFStreamer(Ctx, 0, MAB, OS, Emitter, RelaxAll, NoExecStack); + return createELFStreamer(Ctx, MAB, OS, Emitter, RelaxAll, NoExecStack); } extern "C" void LLVMInitializeSystemZTargetMC() { diff --git a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h index 97e325b..cbaf9a8 100644 --- a/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h +++ b/lib/Target/SystemZ/MCTargetDesc/SystemZMCTargetDesc.h @@ -28,47 +28,47 @@ class raw_ostream; extern Target TheSystemZTarget; namespace SystemZMC { - // How many bytes are in the ABI-defined, caller-allocated part of - // a stack frame. - const int64_t CallFrameSize = 160; - - // The offset of the DWARF CFA from the incoming stack pointer. - const int64_t CFAOffsetFromInitialSP = CallFrameSize; - - // Maps of asm register numbers to LLVM register numbers, with 0 indicating - // an invalid register. In principle we could use 32-bit and 64-bit register - // classes directly, provided that we relegated the GPR allocation order - // in SystemZRegisterInfo.td to an AltOrder and left the default order - // as %r0-%r15. It seems better to provide the same interface for - // all classes though. - extern const unsigned GR32Regs[16]; - extern const unsigned GRH32Regs[16]; - extern const unsigned GR64Regs[16]; - extern const unsigned GR128Regs[16]; - extern const unsigned FP32Regs[16]; - extern const unsigned FP64Regs[16]; - extern const unsigned FP128Regs[16]; - - // Return the 0-based number of the first architectural register that - // contains the given LLVM register. E.g. R1D -> 1. - unsigned getFirstReg(unsigned Reg); - - // Return the given register as a GR64. - inline unsigned getRegAsGR64(unsigned Reg) { - return GR64Regs[getFirstReg(Reg)]; - } - - // Return the given register as a low GR32. - inline unsigned getRegAsGR32(unsigned Reg) { - return GR32Regs[getFirstReg(Reg)]; - } - - // Return the given register as a high GR32. - inline unsigned getRegAsGRH32(unsigned Reg) { - return GRH32Regs[getFirstReg(Reg)]; - } +// How many bytes are in the ABI-defined, caller-allocated part of +// a stack frame. +const int64_t CallFrameSize = 160; + +// The offset of the DWARF CFA from the incoming stack pointer. +const int64_t CFAOffsetFromInitialSP = CallFrameSize; + +// Maps of asm register numbers to LLVM register numbers, with 0 indicating +// an invalid register. In principle we could use 32-bit and 64-bit register +// classes directly, provided that we relegated the GPR allocation order +// in SystemZRegisterInfo.td to an AltOrder and left the default order +// as %r0-%r15. It seems better to provide the same interface for +// all classes though. +extern const unsigned GR32Regs[16]; +extern const unsigned GRH32Regs[16]; +extern const unsigned GR64Regs[16]; +extern const unsigned GR128Regs[16]; +extern const unsigned FP32Regs[16]; +extern const unsigned FP64Regs[16]; +extern const unsigned FP128Regs[16]; + +// Return the 0-based number of the first architectural register that +// contains the given LLVM register. E.g. R1D -> 1. +unsigned getFirstReg(unsigned Reg); + +// Return the given register as a GR64. +inline unsigned getRegAsGR64(unsigned Reg) { + return GR64Regs[getFirstReg(Reg)]; } +// Return the given register as a low GR32. +inline unsigned getRegAsGR32(unsigned Reg) { + return GR32Regs[getFirstReg(Reg)]; +} + +// Return the given register as a high GR32. +inline unsigned getRegAsGRH32(unsigned Reg) { + return GRH32Regs[getFirstReg(Reg)]; +} +} // end namespace SystemZMC + MCCodeEmitter *createSystemZMCCodeEmitter(const MCInstrInfo &MCII, const MCRegisterInfo &MRI, const MCSubtargetInfo &STI, diff --git a/lib/Target/SystemZ/README.txt b/lib/Target/SystemZ/README.txt index afa6cf0..e089047 100644 --- a/lib/Target/SystemZ/README.txt +++ b/lib/Target/SystemZ/README.txt @@ -166,13 +166,6 @@ See CodeGen/SystemZ/alloca-01.ll for an example. -- -Atomic loads and stores use the default compare-and-swap based implementation. -This is much too conservative in practice, since the architecture guarantees -that 1-, 2-, 4- and 8-byte loads and stores to aligned addresses are -inherently atomic. - --- - If needed, we can support 16-byte atomics using LPQ, STPQ and CSDG. -- diff --git a/lib/Target/SystemZ/SystemZ.h b/lib/Target/SystemZ/SystemZ.h index dcebbad..1579249 100644 --- a/lib/Target/SystemZ/SystemZ.h +++ b/lib/Target/SystemZ/SystemZ.h @@ -19,97 +19,98 @@ #include "llvm/Support/CodeGen.h" namespace llvm { - class SystemZTargetMachine; - class FunctionPass; - - namespace SystemZ { - // Condition-code mask values. - const unsigned CCMASK_0 = 1 << 3; - const unsigned CCMASK_1 = 1 << 2; - const unsigned CCMASK_2 = 1 << 1; - const unsigned CCMASK_3 = 1 << 0; - const unsigned CCMASK_ANY = CCMASK_0 | CCMASK_1 | CCMASK_2 | CCMASK_3; - - // Condition-code mask assignments for integer and floating-point - // comparisons. - const unsigned CCMASK_CMP_EQ = CCMASK_0; - const unsigned CCMASK_CMP_LT = CCMASK_1; - const unsigned CCMASK_CMP_GT = CCMASK_2; - const unsigned CCMASK_CMP_NE = CCMASK_CMP_LT | CCMASK_CMP_GT; - const unsigned CCMASK_CMP_LE = CCMASK_CMP_EQ | CCMASK_CMP_LT; - const unsigned CCMASK_CMP_GE = CCMASK_CMP_EQ | CCMASK_CMP_GT; - - // Condition-code mask assignments for floating-point comparisons only. - const unsigned CCMASK_CMP_UO = CCMASK_3; - const unsigned CCMASK_CMP_O = CCMASK_ANY ^ CCMASK_CMP_UO; - - // All condition-code values produced by comparisons. - const unsigned CCMASK_ICMP = CCMASK_0 | CCMASK_1 | CCMASK_2; - const unsigned CCMASK_FCMP = CCMASK_0 | CCMASK_1 | CCMASK_2 | CCMASK_3; - - // Condition-code mask assignments for CS. - const unsigned CCMASK_CS_EQ = CCMASK_0; - const unsigned CCMASK_CS_NE = CCMASK_1; - const unsigned CCMASK_CS = CCMASK_0 | CCMASK_1; - - // Condition-code mask assignments for a completed SRST loop. - const unsigned CCMASK_SRST_FOUND = CCMASK_1; - const unsigned CCMASK_SRST_NOTFOUND = CCMASK_2; - const unsigned CCMASK_SRST = CCMASK_1 | CCMASK_2; - - // Condition-code mask assignments for TEST UNDER MASK. - const unsigned CCMASK_TM_ALL_0 = CCMASK_0; - const unsigned CCMASK_TM_MIXED_MSB_0 = CCMASK_1; - const unsigned CCMASK_TM_MIXED_MSB_1 = CCMASK_2; - const unsigned CCMASK_TM_ALL_1 = CCMASK_3; - const unsigned CCMASK_TM_SOME_0 = CCMASK_TM_ALL_1 ^ CCMASK_ANY; - const unsigned CCMASK_TM_SOME_1 = CCMASK_TM_ALL_0 ^ CCMASK_ANY; - const unsigned CCMASK_TM_MSB_0 = CCMASK_0 | CCMASK_1; - const unsigned CCMASK_TM_MSB_1 = CCMASK_2 | CCMASK_3; - const unsigned CCMASK_TM = CCMASK_ANY; - - // The position of the low CC bit in an IPM result. - const unsigned IPM_CC = 28; - - // Mask assignments for PFD. - const unsigned PFD_READ = 1; - const unsigned PFD_WRITE = 2; - - // Return true if Val fits an LLILL operand. - static inline bool isImmLL(uint64_t Val) { - return (Val & ~0x000000000000ffffULL) == 0; - } - - // Return true if Val fits an LLILH operand. - static inline bool isImmLH(uint64_t Val) { - return (Val & ~0x00000000ffff0000ULL) == 0; - } - - // Return true if Val fits an LLIHL operand. - static inline bool isImmHL(uint64_t Val) { - return (Val & ~0x00000ffff00000000ULL) == 0; - } - - // Return true if Val fits an LLIHH operand. - static inline bool isImmHH(uint64_t Val) { - return (Val & ~0xffff000000000000ULL) == 0; - } - - // Return true if Val fits an LLILF operand. - static inline bool isImmLF(uint64_t Val) { - return (Val & ~0x00000000ffffffffULL) == 0; - } - - // Return true if Val fits an LLIHF operand. - static inline bool isImmHF(uint64_t Val) { - return (Val & ~0xffffffff00000000ULL) == 0; - } - } - - FunctionPass *createSystemZISelDag(SystemZTargetMachine &TM, - CodeGenOpt::Level OptLevel); - FunctionPass *createSystemZElimComparePass(SystemZTargetMachine &TM); - FunctionPass *createSystemZShortenInstPass(SystemZTargetMachine &TM); - FunctionPass *createSystemZLongBranchPass(SystemZTargetMachine &TM); -} // end namespace llvm; +class SystemZTargetMachine; +class FunctionPass; + +namespace SystemZ { +// Condition-code mask values. +const unsigned CCMASK_0 = 1 << 3; +const unsigned CCMASK_1 = 1 << 2; +const unsigned CCMASK_2 = 1 << 1; +const unsigned CCMASK_3 = 1 << 0; +const unsigned CCMASK_ANY = CCMASK_0 | CCMASK_1 | CCMASK_2 | CCMASK_3; + +// Condition-code mask assignments for integer and floating-point +// comparisons. +const unsigned CCMASK_CMP_EQ = CCMASK_0; +const unsigned CCMASK_CMP_LT = CCMASK_1; +const unsigned CCMASK_CMP_GT = CCMASK_2; +const unsigned CCMASK_CMP_NE = CCMASK_CMP_LT | CCMASK_CMP_GT; +const unsigned CCMASK_CMP_LE = CCMASK_CMP_EQ | CCMASK_CMP_LT; +const unsigned CCMASK_CMP_GE = CCMASK_CMP_EQ | CCMASK_CMP_GT; + +// Condition-code mask assignments for floating-point comparisons only. +const unsigned CCMASK_CMP_UO = CCMASK_3; +const unsigned CCMASK_CMP_O = CCMASK_ANY ^ CCMASK_CMP_UO; + +// All condition-code values produced by comparisons. +const unsigned CCMASK_ICMP = CCMASK_0 | CCMASK_1 | CCMASK_2; +const unsigned CCMASK_FCMP = CCMASK_0 | CCMASK_1 | CCMASK_2 | CCMASK_3; + +// Condition-code mask assignments for CS. +const unsigned CCMASK_CS_EQ = CCMASK_0; +const unsigned CCMASK_CS_NE = CCMASK_1; +const unsigned CCMASK_CS = CCMASK_0 | CCMASK_1; + +// Condition-code mask assignments for a completed SRST loop. +const unsigned CCMASK_SRST_FOUND = CCMASK_1; +const unsigned CCMASK_SRST_NOTFOUND = CCMASK_2; +const unsigned CCMASK_SRST = CCMASK_1 | CCMASK_2; + +// Condition-code mask assignments for TEST UNDER MASK. +const unsigned CCMASK_TM_ALL_0 = CCMASK_0; +const unsigned CCMASK_TM_MIXED_MSB_0 = CCMASK_1; +const unsigned CCMASK_TM_MIXED_MSB_1 = CCMASK_2; +const unsigned CCMASK_TM_ALL_1 = CCMASK_3; +const unsigned CCMASK_TM_SOME_0 = CCMASK_TM_ALL_1 ^ CCMASK_ANY; +const unsigned CCMASK_TM_SOME_1 = CCMASK_TM_ALL_0 ^ CCMASK_ANY; +const unsigned CCMASK_TM_MSB_0 = CCMASK_0 | CCMASK_1; +const unsigned CCMASK_TM_MSB_1 = CCMASK_2 | CCMASK_3; +const unsigned CCMASK_TM = CCMASK_ANY; + +// The position of the low CC bit in an IPM result. +const unsigned IPM_CC = 28; + +// Mask assignments for PFD. +const unsigned PFD_READ = 1; +const unsigned PFD_WRITE = 2; + +// Return true if Val fits an LLILL operand. +static inline bool isImmLL(uint64_t Val) { + return (Val & ~0x000000000000ffffULL) == 0; +} + +// Return true if Val fits an LLILH operand. +static inline bool isImmLH(uint64_t Val) { + return (Val & ~0x00000000ffff0000ULL) == 0; +} + +// Return true if Val fits an LLIHL operand. +static inline bool isImmHL(uint64_t Val) { + return (Val & ~0x00000ffff00000000ULL) == 0; +} + +// Return true if Val fits an LLIHH operand. +static inline bool isImmHH(uint64_t Val) { + return (Val & ~0xffff000000000000ULL) == 0; +} + +// Return true if Val fits an LLILF operand. +static inline bool isImmLF(uint64_t Val) { + return (Val & ~0x00000000ffffffffULL) == 0; +} + +// Return true if Val fits an LLIHF operand. +static inline bool isImmHF(uint64_t Val) { + return (Val & ~0xffffffff00000000ULL) == 0; +} +} // end namespace SystemZ + +FunctionPass *createSystemZISelDag(SystemZTargetMachine &TM, + CodeGenOpt::Level OptLevel); +FunctionPass *createSystemZElimComparePass(SystemZTargetMachine &TM); +FunctionPass *createSystemZShortenInstPass(SystemZTargetMachine &TM); +FunctionPass *createSystemZLongBranchPass(SystemZTargetMachine &TM); +} // end namespace llvm + #endif diff --git a/lib/Target/SystemZ/SystemZ.td b/lib/Target/SystemZ/SystemZ.td index abf5c8e..5f82903 100644 --- a/lib/Target/SystemZ/SystemZ.td +++ b/lib/Target/SystemZ/SystemZ.td @@ -53,20 +53,10 @@ def SystemZAsmParser : AsmParser { } //===----------------------------------------------------------------------===// -// Assembly writer -//===----------------------------------------------------------------------===// - -def SystemZAsmWriter : AsmWriter { - string AsmWriterClassName = "InstPrinter"; - bit isMCAsmWriter = 1; -} - -//===----------------------------------------------------------------------===// // Top-level target declaration //===----------------------------------------------------------------------===// def SystemZ : Target { let InstructionSet = SystemZInstrInfo; let AssemblyParsers = [SystemZAsmParser]; - let AssemblyWriters = [SystemZAsmWriter]; } diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.cpp b/lib/Target/SystemZ/SystemZAsmPrinter.cpp index 75cbda4..8b18bc1 100644 --- a/lib/Target/SystemZ/SystemZAsmPrinter.cpp +++ b/lib/Target/SystemZ/SystemZAsmPrinter.cpp @@ -18,11 +18,11 @@ #include "SystemZMCInstLower.h" #include "llvm/CodeGen/MachineModuleInfoImpls.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" +#include "llvm/IR/Mangler.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCInstBuilder.h" #include "llvm/MC/MCStreamer.h" #include "llvm/Support/TargetRegistry.h" -#include "llvm/Target/Mangler.h" using namespace llvm; @@ -151,11 +151,20 @@ void SystemZAsmPrinter::EmitInstruction(const MachineInstr *MI) { #undef LOWER_HIGH + case SystemZ::Serialize: + if (Subtarget->hasFastSerialization()) + LoweredMI = MCInstBuilder(SystemZ::AsmBCR) + .addImm(14).addReg(SystemZ::R0D); + else + LoweredMI = MCInstBuilder(SystemZ::AsmBCR) + .addImm(15).addReg(SystemZ::R0D); + break; + default: Lower.lower(MI, LoweredMI); break; } - OutStreamer.EmitInstruction(LoweredMI); + EmitToStreamer(OutStreamer, LoweredMI); } // Convert a SystemZ-specific constant pool modifier into the associated @@ -170,8 +179,7 @@ getModifierVariantKind(SystemZCP::SystemZCPModifier Modifier) { void SystemZAsmPrinter:: EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) { - SystemZConstantPoolValue *ZCPV = - static_cast<SystemZConstantPoolValue*>(MCPV); + auto *ZCPV = static_cast<SystemZConstantPoolValue*>(MCPV); const MCExpr *Expr = MCSymbolRefExpr::Create(getSymbol(ZCPV->getGlobalValue()), @@ -212,7 +220,7 @@ bool SystemZAsmPrinter::PrintAsmMemoryOperand(const MachineInstr *MI, void SystemZAsmPrinter::EmitEndOfAsmFile(Module &M) { if (Subtarget->isTargetELF()) { - const TargetLoweringObjectFileELF &TLOFELF = + auto &TLOFELF = static_cast<const TargetLoweringObjectFileELF &>(getObjFileLowering()); MachineModuleInfoELF &MMIELF = MMI->getObjFileInfo<MachineModuleInfoELF>(); diff --git a/lib/Target/SystemZ/SystemZAsmPrinter.h b/lib/Target/SystemZ/SystemZAsmPrinter.h index 4b6c51b..20093bc 100644 --- a/lib/Target/SystemZ/SystemZAsmPrinter.h +++ b/lib/Target/SystemZ/SystemZAsmPrinter.h @@ -32,20 +32,18 @@ public: } // Override AsmPrinter. - virtual const char *getPassName() const LLVM_OVERRIDE { + const char *getPassName() const override { return "SystemZ Assembly Printer"; } - virtual void EmitInstruction(const MachineInstr *MI) LLVM_OVERRIDE; - virtual void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) - LLVM_OVERRIDE; - virtual bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, const char *ExtraCode, - raw_ostream &OS) LLVM_OVERRIDE; - virtual bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, - unsigned AsmVariant, - const char *ExtraCode, - raw_ostream &OS) LLVM_OVERRIDE; - virtual void EmitEndOfAsmFile(Module &M) LLVM_OVERRIDE; + void EmitInstruction(const MachineInstr *MI) override; + void EmitMachineConstantPoolValue(MachineConstantPoolValue *MCPV) override; + bool PrintAsmOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS) override; + bool PrintAsmMemoryOperand(const MachineInstr *MI, unsigned OpNo, + unsigned AsmVariant, const char *ExtraCode, + raw_ostream &OS) override; + void EmitEndOfAsmFile(Module &M) override; }; } // end namespace llvm diff --git a/lib/Target/SystemZ/SystemZCallingConv.h b/lib/Target/SystemZ/SystemZCallingConv.h index 298985e..4b1569d 100644 --- a/lib/Target/SystemZ/SystemZCallingConv.h +++ b/lib/Target/SystemZ/SystemZCallingConv.h @@ -11,13 +11,13 @@ #define SYSTEMZCALLINGCONV_H namespace llvm { - namespace SystemZ { - const unsigned NumArgGPRs = 5; - extern const unsigned ArgGPRs[NumArgGPRs]; +namespace SystemZ { + const unsigned NumArgGPRs = 5; + extern const unsigned ArgGPRs[NumArgGPRs]; - const unsigned NumArgFPRs = 4; - extern const unsigned ArgFPRs[NumArgFPRs]; - } -} + const unsigned NumArgFPRs = 4; + extern const unsigned ArgFPRs[NumArgFPRs]; +} // end namespace SystemZ +} // end namespace llvm #endif diff --git a/lib/Target/SystemZ/SystemZConstantPoolValue.cpp b/lib/Target/SystemZ/SystemZConstantPoolValue.cpp index 6c70811..19cec21 100644 --- a/lib/Target/SystemZ/SystemZConstantPoolValue.cpp +++ b/lib/Target/SystemZ/SystemZConstantPoolValue.cpp @@ -43,7 +43,7 @@ getExistingMachineCPValue(MachineConstantPool *CP, unsigned Alignment) { for (unsigned I = 0, E = Constants.size(); I != E; ++I) { if (Constants[I].isMachineConstantPoolEntry() && (Constants[I].getAlignment() & AlignMask) == 0) { - SystemZConstantPoolValue *ZCPV = + auto *ZCPV = static_cast<SystemZConstantPoolValue *>(Constants[I].Val.MachineCPVal); if (ZCPV->GV == GV && ZCPV->Modifier == Modifier) return I; diff --git a/lib/Target/SystemZ/SystemZConstantPoolValue.h b/lib/Target/SystemZ/SystemZConstantPoolValue.h index 9927bdb..699718f 100644 --- a/lib/Target/SystemZ/SystemZConstantPoolValue.h +++ b/lib/Target/SystemZ/SystemZConstantPoolValue.h @@ -18,10 +18,10 @@ namespace llvm { class GlobalValue; namespace SystemZCP { - enum SystemZCPModifier { - NTPOFF - }; -} +enum SystemZCPModifier { + NTPOFF +}; +} // end namespace SystemZCP /// A SystemZ-specific constant pool value. At present, the only /// defined constant pool values are offsets of thread-local variables @@ -39,17 +39,17 @@ public: Create(const GlobalValue *GV, SystemZCP::SystemZCPModifier Modifier); // Override MachineConstantPoolValue. - virtual unsigned getRelocationInfo() const LLVM_OVERRIDE; - virtual int getExistingMachineCPValue(MachineConstantPool *CP, - unsigned Alignment) LLVM_OVERRIDE; - virtual void addSelectionDAGCSEId(FoldingSetNodeID &ID) LLVM_OVERRIDE; - virtual void print(raw_ostream &O) const LLVM_OVERRIDE; + unsigned getRelocationInfo() const override; + int getExistingMachineCPValue(MachineConstantPool *CP, + unsigned Alignment) override; + void addSelectionDAGCSEId(FoldingSetNodeID &ID) override; + void print(raw_ostream &O) const override; // Access SystemZ-specific fields. const GlobalValue *getGlobalValue() const { return GV; } SystemZCP::SystemZCPModifier getModifier() const { return Modifier; } }; -} // End llvm namespace +} // end namespace llvm #endif diff --git a/lib/Target/SystemZ/SystemZElimCompare.cpp b/lib/Target/SystemZ/SystemZElimCompare.cpp index b8a77db..fdf80a9 100644 --- a/lib/Target/SystemZ/SystemZElimCompare.cpp +++ b/lib/Target/SystemZ/SystemZElimCompare.cpp @@ -33,73 +33,72 @@ STATISTIC(EliminatedComparisons, "Number of eliminated comparisons"); STATISTIC(FusedComparisons, "Number of fused compare-and-branch instructions"); namespace { - // Represents the references to a particular register in one or more - // instructions. - struct Reference { - Reference() - : Def(false), Use(false), IndirectDef(false), IndirectUse(false) {} - - Reference &operator|=(const Reference &Other) { - Def |= Other.Def; - IndirectDef |= Other.IndirectDef; - Use |= Other.Use; - IndirectUse |= Other.IndirectUse; - return *this; - } +// Represents the references to a particular register in one or more +// instructions. +struct Reference { + Reference() + : Def(false), Use(false), IndirectDef(false), IndirectUse(false) {} + + Reference &operator|=(const Reference &Other) { + Def |= Other.Def; + IndirectDef |= Other.IndirectDef; + Use |= Other.Use; + IndirectUse |= Other.IndirectUse; + return *this; + } - operator bool() const { return Def || Use; } + operator bool() const { return Def || Use; } - // True if the register is defined or used in some form, either directly or - // via a sub- or super-register. - bool Def; - bool Use; + // True if the register is defined or used in some form, either directly or + // via a sub- or super-register. + bool Def; + bool Use; - // True if the register is defined or used indirectly, by a sub- or - // super-register. - bool IndirectDef; - bool IndirectUse; - }; + // True if the register is defined or used indirectly, by a sub- or + // super-register. + bool IndirectDef; + bool IndirectUse; +}; - class SystemZElimCompare : public MachineFunctionPass { - public: - static char ID; - SystemZElimCompare(const SystemZTargetMachine &tm) - : MachineFunctionPass(ID), TII(0), TRI(0) {} +class SystemZElimCompare : public MachineFunctionPass { +public: + static char ID; + SystemZElimCompare(const SystemZTargetMachine &tm) + : MachineFunctionPass(ID), TII(0), TRI(0) {} - virtual const char *getPassName() const { - return "SystemZ Comparison Elimination"; - } + const char *getPassName() const override { + return "SystemZ Comparison Elimination"; + } + + bool processBlock(MachineBasicBlock &MBB); + bool runOnMachineFunction(MachineFunction &F); - bool processBlock(MachineBasicBlock *MBB); - bool runOnMachineFunction(MachineFunction &F); - - private: - Reference getRegReferences(MachineInstr *MI, unsigned Reg); - bool convertToBRCT(MachineInstr *MI, MachineInstr *Compare, - SmallVectorImpl<MachineInstr *> &CCUsers); - bool convertToLoadAndTest(MachineInstr *MI); - bool adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare, - SmallVectorImpl<MachineInstr *> &CCUsers); - bool optimizeCompareZero(MachineInstr *Compare, +private: + Reference getRegReferences(MachineInstr *MI, unsigned Reg); + bool convertToBRCT(MachineInstr *MI, MachineInstr *Compare, + SmallVectorImpl<MachineInstr *> &CCUsers); + bool convertToLoadAndTest(MachineInstr *MI); + bool adjustCCMasksForInstr(MachineInstr *MI, MachineInstr *Compare, SmallVectorImpl<MachineInstr *> &CCUsers); - bool fuseCompareAndBranch(MachineInstr *Compare, - SmallVectorImpl<MachineInstr *> &CCUsers); + bool optimizeCompareZero(MachineInstr *Compare, + SmallVectorImpl<MachineInstr *> &CCUsers); + bool fuseCompareAndBranch(MachineInstr *Compare, + SmallVectorImpl<MachineInstr *> &CCUsers); - const SystemZInstrInfo *TII; - const TargetRegisterInfo *TRI; - }; + const SystemZInstrInfo *TII; + const TargetRegisterInfo *TRI; +}; - char SystemZElimCompare::ID = 0; -} // end of anonymous namespace +char SystemZElimCompare::ID = 0; +} // end anonymous namespace FunctionPass *llvm::createSystemZElimComparePass(SystemZTargetMachine &TM) { return new SystemZElimCompare(TM); } // Return true if CC is live out of MBB. -static bool isCCLiveOut(MachineBasicBlock *MBB) { - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); SI != SE; ++SI) +static bool isCCLiveOut(MachineBasicBlock &MBB) { + for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) if ((*SI)->isLiveIn(SystemZ::CC)) return true; return false; @@ -328,8 +327,8 @@ optimizeCompareZero(MachineInstr *Compare, // Search back for CC results that are based on the first operand. unsigned SrcReg = Compare->getOperand(0).getReg(); unsigned SrcSubReg = Compare->getOperand(0).getSubReg(); - MachineBasicBlock *MBB = Compare->getParent(); - MachineBasicBlock::iterator MBBI = Compare, MBBE = MBB->begin(); + MachineBasicBlock &MBB = *Compare->getParent(); + MachineBasicBlock::iterator MBBI = Compare, MBBE = MBB.begin(); Reference CCRefs; Reference SrcRefs; while (MBBI != MBBE) { @@ -424,7 +423,7 @@ fuseCompareAndBranch(MachineInstr *Compare, // Process all comparison instructions in MBB. Return true if something // changed. -bool SystemZElimCompare::processBlock(MachineBasicBlock *MBB) { +bool SystemZElimCompare::processBlock(MachineBasicBlock &MBB) { bool Changed = false; // Walk backwards through the block looking for comparisons, recording @@ -432,8 +431,8 @@ bool SystemZElimCompare::processBlock(MachineBasicBlock *MBB) { // instructions before it. bool CompleteCCUsers = !isCCLiveOut(MBB); SmallVector<MachineInstr *, 4> CCUsers; - MachineBasicBlock::iterator MBBI = MBB->end(); - while (MBBI != MBB->begin()) { + MachineBasicBlock::iterator MBBI = MBB.end(); + while (MBBI != MBB.begin()) { MachineInstr *MI = --MBBI; if (CompleteCCUsers && MI->isCompare() && @@ -463,9 +462,8 @@ bool SystemZElimCompare::runOnMachineFunction(MachineFunction &F) { TRI = &TII->getRegisterInfo(); bool Changed = false; - for (MachineFunction::iterator MFI = F.begin(), MFE = F.end(); - MFI != MFE; ++MFI) - Changed |= processBlock(MFI); + for (auto &MBB : F) + Changed |= processBlock(MBB); return Changed; } diff --git a/lib/Target/SystemZ/SystemZFrameLowering.cpp b/lib/Target/SystemZ/SystemZFrameLowering.cpp index acfb491..c856955 100644 --- a/lib/Target/SystemZ/SystemZFrameLowering.cpp +++ b/lib/Target/SystemZ/SystemZFrameLowering.cpp @@ -20,29 +20,29 @@ using namespace llvm; namespace { - // The ABI-defined register save slots, relative to the incoming stack - // pointer. - static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = { - { SystemZ::R2D, 0x10 }, - { SystemZ::R3D, 0x18 }, - { SystemZ::R4D, 0x20 }, - { SystemZ::R5D, 0x28 }, - { SystemZ::R6D, 0x30 }, - { SystemZ::R7D, 0x38 }, - { SystemZ::R8D, 0x40 }, - { SystemZ::R9D, 0x48 }, - { SystemZ::R10D, 0x50 }, - { SystemZ::R11D, 0x58 }, - { SystemZ::R12D, 0x60 }, - { SystemZ::R13D, 0x68 }, - { SystemZ::R14D, 0x70 }, - { SystemZ::R15D, 0x78 }, - { SystemZ::F0D, 0x80 }, - { SystemZ::F2D, 0x88 }, - { SystemZ::F4D, 0x90 }, - { SystemZ::F6D, 0x98 } - }; -} +// The ABI-defined register save slots, relative to the incoming stack +// pointer. +static const TargetFrameLowering::SpillSlot SpillOffsetTable[] = { + { SystemZ::R2D, 0x10 }, + { SystemZ::R3D, 0x18 }, + { SystemZ::R4D, 0x20 }, + { SystemZ::R5D, 0x28 }, + { SystemZ::R6D, 0x30 }, + { SystemZ::R7D, 0x38 }, + { SystemZ::R8D, 0x40 }, + { SystemZ::R9D, 0x48 }, + { SystemZ::R10D, 0x50 }, + { SystemZ::R11D, 0x58 }, + { SystemZ::R12D, 0x60 }, + { SystemZ::R13D, 0x68 }, + { SystemZ::R14D, 0x70 }, + { SystemZ::R15D, 0x78 }, + { SystemZ::F0D, 0x80 }, + { SystemZ::F2D, 0x88 }, + { SystemZ::F4D, 0x90 }, + { SystemZ::F6D, 0x98 } +}; +} // end anonymous namespace SystemZFrameLowering::SystemZFrameLowering(const SystemZTargetMachine &tm, const SystemZSubtarget &sti) @@ -312,7 +312,7 @@ static void emitIncrement(MachineBasicBlock &MBB, void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { MachineBasicBlock &MBB = MF.front(); MachineFrameInfo *MFFrame = MF.getFrameInfo(); - const SystemZInstrInfo *ZII = + auto *ZII = static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); MachineBasicBlock::iterator MBBI = MBB.begin(); @@ -333,16 +333,14 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { llvm_unreachable("Couldn't skip over GPR saves"); // Add CFI for the GPR saves. - MCSymbol *GPRSaveLabel = MMI.getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, DL, - ZII->get(TargetOpcode::PROLOG_LABEL)).addSym(GPRSaveLabel); - for (std::vector<CalleeSavedInfo>::const_iterator - I = CSI.begin(), E = CSI.end(); I != E; ++I) { - unsigned Reg = I->getReg(); + for (auto &Save : CSI) { + unsigned Reg = Save.getReg(); if (SystemZ::GR64BitRegClass.contains(Reg)) { int64_t Offset = SPOffsetFromCFA + RegSpillOffsets[Reg]; - MMI.addFrameInst(MCCFIInstruction::createOffset( - GPRSaveLabel, MRI->getDwarfRegNum(Reg, true), Offset)); + unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( + nullptr, MRI->getDwarfRegNum(Reg, true), Offset)); + BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); } } } @@ -354,11 +352,10 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { emitIncrement(MBB, MBBI, DL, SystemZ::R15D, Delta, ZII); // Add CFI for the allocation. - MCSymbol *AdjustSPLabel = MMI.getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)) - .addSym(AdjustSPLabel); - MMI.addFrameInst(MCCFIInstruction::createDefCfaOffset( - AdjustSPLabel, SPOffsetFromCFA + Delta)); + unsigned CFIIndex = MMI.addFrameInst( + MCCFIInstruction::createDefCfaOffset(nullptr, SPOffsetFromCFA + Delta)); + BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); SPOffsetFromCFA += Delta; } @@ -368,26 +365,23 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { .addReg(SystemZ::R15D); // Add CFI for the new frame location. - MCSymbol *SetFPLabel = MMI.getContext().CreateTempSymbol(); - BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)) - .addSym(SetFPLabel); unsigned HardFP = MRI->getDwarfRegNum(SystemZ::R11D, true); - MMI.addFrameInst( - MCCFIInstruction::createDefCfaRegister(SetFPLabel, HardFP)); + unsigned CFIIndex = MMI.addFrameInst( + MCCFIInstruction::createDefCfaRegister(nullptr, HardFP)); + BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); // Mark the FramePtr as live at the beginning of every block except // the entry block. (We'll have marked R11 as live on entry when // saving the GPRs.) - for (MachineFunction::iterator - I = llvm::next(MF.begin()), E = MF.end(); I != E; ++I) + for (auto I = std::next(MF.begin()), E = MF.end(); I != E; ++I) I->addLiveIn(SystemZ::R11D); } // Skip over the FPR saves. - MCSymbol *FPRSaveLabel = 0; - for (std::vector<CalleeSavedInfo>::const_iterator - I = CSI.begin(), E = CSI.end(); I != E; ++I) { - unsigned Reg = I->getReg(); + SmallVector<unsigned, 8> CFIIndexes; + for (auto &Save : CSI) { + unsigned Reg = Save.getReg(); if (SystemZ::FP64BitRegClass.contains(Reg)) { if (MBBI != MBB.end() && (MBBI->getOpcode() == SystemZ::STD || @@ -397,25 +391,25 @@ void SystemZFrameLowering::emitPrologue(MachineFunction &MF) const { llvm_unreachable("Couldn't skip over FPR save"); // Add CFI for the this save. - if (!FPRSaveLabel) - FPRSaveLabel = MMI.getContext().CreateTempSymbol(); - unsigned Reg = MRI->getDwarfRegNum(I->getReg(), true); - int64_t Offset = getFrameIndexOffset(MF, I->getFrameIdx()); - MMI.addFrameInst(MCCFIInstruction::createOffset( - FPRSaveLabel, Reg, SPOffsetFromCFA + Offset)); + unsigned DwarfReg = MRI->getDwarfRegNum(Reg, true); + int64_t Offset = getFrameIndexOffset(MF, Save.getFrameIdx()); + unsigned CFIIndex = MMI.addFrameInst(MCCFIInstruction::createOffset( + nullptr, DwarfReg, SPOffsetFromCFA + Offset)); + CFIIndexes.push_back(CFIIndex); } } // Complete the CFI for the FPR saves, modelling them as taking effect // after the last save. - if (FPRSaveLabel) - BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::PROLOG_LABEL)) - .addSym(FPRSaveLabel); + for (auto CFIIndex : CFIIndexes) { + BuildMI(MBB, MBBI, DL, ZII->get(TargetOpcode::CFI_INSTRUCTION)) + .addCFIIndex(CFIIndex); + } } void SystemZFrameLowering::emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const { MachineBasicBlock::iterator MBBI = MBB.getLastNonDebugInstr(); - const SystemZInstrInfo *ZII = + auto *ZII = static_cast<const SystemZInstrInfo*>(MF.getTarget().getInstrInfo()); SystemZMachineFunctionInfo *ZFI = MF.getInfo<SystemZMachineFunctionInfo>(); diff --git a/lib/Target/SystemZ/SystemZFrameLowering.h b/lib/Target/SystemZ/SystemZFrameLowering.h index 9b0a1d5..70e25fb 100644 --- a/lib/Target/SystemZ/SystemZFrameLowering.h +++ b/lib/Target/SystemZ/SystemZFrameLowering.h @@ -30,39 +30,31 @@ public: const SystemZSubtarget &sti); // Override TargetFrameLowering. - virtual bool isFPCloseToIncomingSP() const LLVM_OVERRIDE { return false; } - virtual const SpillSlot *getCalleeSavedSpillSlots(unsigned &NumEntries) const - LLVM_OVERRIDE; - virtual void - processFunctionBeforeCalleeSavedScan(MachineFunction &MF, - RegScavenger *RS) const LLVM_OVERRIDE; - virtual bool - spillCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const - LLVM_OVERRIDE; - virtual bool - restoreCalleeSavedRegisters(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBII, - const std::vector<CalleeSavedInfo> &CSI, - const TargetRegisterInfo *TRI) const - LLVM_OVERRIDE; - virtual void processFunctionBeforeFrameFinalized(MachineFunction &MF, - RegScavenger *RS) const; - virtual void emitPrologue(MachineFunction &MF) const LLVM_OVERRIDE; - virtual void emitEpilogue(MachineFunction &MF, - MachineBasicBlock &MBB) const LLVM_OVERRIDE; - virtual bool hasFP(const MachineFunction &MF) const LLVM_OVERRIDE; - virtual int getFrameIndexOffset(const MachineFunction &MF, - int FI) const LLVM_OVERRIDE; - virtual bool hasReservedCallFrame(const MachineFunction &MF) const - LLVM_OVERRIDE; - virtual void - eliminateCallFramePseudoInstr(MachineFunction &MF, - MachineBasicBlock &MBB, - MachineBasicBlock::iterator MI) const - LLVM_OVERRIDE; + bool isFPCloseToIncomingSP() const override { return false; } + const SpillSlot *getCalleeSavedSpillSlots(unsigned &NumEntries) const + override; + void processFunctionBeforeCalleeSavedScan(MachineFunction &MF, + RegScavenger *RS) const override; + bool spillCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const override; + bool restoreCalleeSavedRegisters(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBII, + const std::vector<CalleeSavedInfo> &CSI, + const TargetRegisterInfo *TRI) const + override; + void processFunctionBeforeFrameFinalized(MachineFunction &MF, + RegScavenger *RS) const override; + void emitPrologue(MachineFunction &MF) const override; + void emitEpilogue(MachineFunction &MF, MachineBasicBlock &MBB) const override; + bool hasFP(const MachineFunction &MF) const override; + int getFrameIndexOffset(const MachineFunction &MF, int FI) const override; + bool hasReservedCallFrame(const MachineFunction &MF) const override; + void eliminateCallFramePseudoInstr(MachineFunction &MF, + MachineBasicBlock &MBB, + MachineBasicBlock::iterator MI) const + override; // Return the number of bytes in the callee-allocated part of the frame. uint64_t getAllocatedStackSize(const MachineFunction &MF) const; diff --git a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp index f4a2773..f46eb16 100644 --- a/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp +++ b/lib/Target/SystemZ/SystemZISelDAGToDAG.cpp @@ -318,16 +318,14 @@ public: Subtarget(*TM.getSubtargetImpl()) { } // Override MachineFunctionPass. - virtual const char *getPassName() const LLVM_OVERRIDE { + const char *getPassName() const override { return "SystemZ DAG->DAG Pattern Instruction Selection"; } // Override SelectionDAGISel. - virtual SDNode *Select(SDNode *Node) LLVM_OVERRIDE; - virtual bool SelectInlineAsmMemoryOperand(const SDValue &Op, - char ConstraintCode, - std::vector<SDValue> &OutOps) - LLVM_OVERRIDE; + SDNode *Select(SDNode *Node) override; + bool SelectInlineAsmMemoryOperand(const SDValue &Op, char ConstraintCode, + std::vector<SDValue> &OutOps) override; // Include the pieces autogenerated from the target description. #include "SystemZGenDAGISel.inc" @@ -651,8 +649,7 @@ bool SystemZDAGToDAGISel::detectOrAndInsertion(SDValue &Op, return false; // We need a constant mask. - ConstantSDNode *MaskNode = - dyn_cast<ConstantSDNode>(Op.getOperand(1).getNode()); + auto *MaskNode = dyn_cast<ConstantSDNode>(Op.getOperand(1).getNode()); if (!MaskNode) return false; @@ -704,8 +701,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { if (RxSBG.Opcode == SystemZ::RNSBG) return false; - ConstantSDNode *MaskNode = - dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); + auto *MaskNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); if (!MaskNode) return false; @@ -729,8 +725,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { if (RxSBG.Opcode != SystemZ::RNSBG) return false; - ConstantSDNode *MaskNode = - dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); + auto *MaskNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); if (!MaskNode) return false; @@ -754,8 +749,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { // Any 64-bit rotate left can be merged into the RxSBG. if (RxSBG.BitSize != 64 || N.getValueType() != MVT::i64) return false; - ConstantSDNode *CountNode - = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); + auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); if (!CountNode) return false; @@ -764,9 +758,24 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { return true; } - case ISD::SIGN_EXTEND: + case ISD::ANY_EXTEND: + // Bits above the extended operand are don't-care. + RxSBG.Input = N.getOperand(0); + return true; + case ISD::ZERO_EXTEND: - case ISD::ANY_EXTEND: { + if (RxSBG.Opcode != SystemZ::RNSBG) { + // Restrict the mask to the extended operand. + unsigned InnerBitSize = N.getOperand(0).getValueType().getSizeInBits(); + if (!refineRxSBGMask(RxSBG, allOnes(InnerBitSize))) + return false; + + RxSBG.Input = N.getOperand(0); + return true; + } + // Fall through. + + case ISD::SIGN_EXTEND: { // Check that the extension bits are don't-care (i.e. are masked out // by the final mask). unsigned InnerBitSize = N.getOperand(0).getValueType().getSizeInBits(); @@ -778,8 +787,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { } case ISD::SHL: { - ConstantSDNode *CountNode = - dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); + auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); if (!CountNode) return false; @@ -806,8 +814,7 @@ bool SystemZDAGToDAGISel::expandRxSBG(RxSBGOperands &RxSBG) const { case ISD::SRL: case ISD::SRA: { - ConstantSDNode *CountNode = - dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); + auto *CountNode = dyn_cast<ConstantSDNode>(N.getOperand(1).getNode()); if (!CountNode) return false; @@ -876,7 +883,7 @@ SDNode *SystemZDAGToDAGISel::tryRISBGZero(SDNode *N) { SystemZ::isImmLF(~RISBG.Mask) || SystemZ::isImmHF(~RISBG.Mask)) { // Force the new mask into the DAG, since it may include known-one bits. - ConstantSDNode *MaskN = cast<ConstantSDNode>(N->getOperand(1).getNode()); + auto *MaskN = cast<ConstantSDNode>(N->getOperand(1).getNode()); if (MaskN->getZExtValue() != RISBG.Mask) { SDValue NewMask = CurDAG->getConstant(RISBG.Mask, VT); N = CurDAG->UpdateNodeOperands(N, N->getOperand(0), NewMask); @@ -928,7 +935,7 @@ SDNode *SystemZDAGToDAGISel::tryRxSBG(SDNode *N, unsigned Opcode) { // Prefer IC for character insertions from memory. if (Opcode == SystemZ::ROSBG && (RxSBG[I].Mask & 0xff) == 0) - if (LoadSDNode *Load = dyn_cast<LoadSDNode>(Op0.getNode())) + if (auto *Load = dyn_cast<LoadSDNode>(Op0.getNode())) if (Load->getMemoryVT() == MVT::i8) return 0; @@ -996,8 +1003,8 @@ bool SystemZDAGToDAGISel::canUseBlockOperation(StoreSDNode *Store, } bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const { - StoreSDNode *Store = cast<StoreSDNode>(N); - LoadSDNode *Load = cast<LoadSDNode>(Store->getValue()); + auto *Store = cast<StoreSDNode>(N); + auto *Load = cast<LoadSDNode>(Store->getValue()); // Prefer not to use MVC if either address can use ... RELATIVE LONG // instructions. @@ -1016,9 +1023,9 @@ bool SystemZDAGToDAGISel::storeLoadCanUseMVC(SDNode *N) const { bool SystemZDAGToDAGISel::storeLoadCanUseBlockBinary(SDNode *N, unsigned I) const { - StoreSDNode *StoreA = cast<StoreSDNode>(N); - LoadSDNode *LoadA = cast<LoadSDNode>(StoreA->getValue().getOperand(1 - I)); - LoadSDNode *LoadB = cast<LoadSDNode>(StoreA->getValue().getOperand(I)); + auto *StoreA = cast<StoreSDNode>(N); + auto *LoadA = cast<LoadSDNode>(StoreA->getValue().getOperand(1 - I)); + auto *LoadB = cast<LoadSDNode>(StoreA->getValue().getOperand(I)); return !LoadA->isVolatile() && canUseBlockOperation(StoreA, LoadB); } @@ -1049,7 +1056,7 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { // If this is a 64-bit operation in which both 32-bit halves are nonzero, // split the operation into two. if (!ResNode && Node->getValueType(0) == MVT::i64) - if (ConstantSDNode *Op1 = dyn_cast<ConstantSDNode>(Node->getOperand(1))) { + if (auto *Op1 = dyn_cast<ConstantSDNode>(Node->getOperand(1))) { uint64_t Val = Op1->getZExtValue(); if (!SystemZ::isImmLF(Val) && !SystemZ::isImmHF(Val)) Node = splitLargeImmediate(Opcode, Node, Node->getOperand(0), @@ -1064,6 +1071,7 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { case ISD::ROTL: case ISD::SHL: case ISD::SRL: + case ISD::ZERO_EXTEND: if (!ResNode) ResNode = tryRISBGZero(Node); break; @@ -1079,20 +1087,6 @@ SDNode *SystemZDAGToDAGISel::Select(SDNode *Node) { } break; - case ISD::ATOMIC_LOAD_SUB: - // Try to convert subtractions of constants to additions. - if (ConstantSDNode *Op2 = dyn_cast<ConstantSDNode>(Node->getOperand(2))) { - uint64_t Value = -Op2->getZExtValue(); - EVT VT = Node->getValueType(0); - if (VT == MVT::i32 || isInt<32>(Value)) { - SDValue Ops[] = { Node->getOperand(0), Node->getOperand(1), - CurDAG->getConstant(int32_t(Value), VT) }; - Node = CurDAG->MorphNodeTo(Node, ISD::ATOMIC_LOAD_ADD, - Node->getVTList(), Ops, array_lengthof(Ops)); - } - } - break; - case SystemZISD::SELECT_CCMASK: { SDValue Op0 = Node->getOperand(0); SDValue Op1 = Node->getOperand(1); diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index f6e1853..714b6c9 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -22,7 +22,6 @@ #include "llvm/CodeGen/MachineInstrBuilder.h" #include "llvm/CodeGen/MachineRegisterInfo.h" #include "llvm/CodeGen/TargetLoweringObjectFileImpl.h" - #include <cctype> using namespace llvm; @@ -38,7 +37,28 @@ struct IPMConversion { int64_t AddValue; unsigned Bit; }; -} + +// Represents information about a comparison. +struct Comparison { + Comparison(SDValue Op0In, SDValue Op1In) + : Op0(Op0In), Op1(Op1In), Opcode(0), ICmpType(0), CCValid(0), CCMask(0) {} + + // The operands to the comparison. + SDValue Op0, Op1; + + // The opcode that should be used to compare Op0 and Op1. + unsigned Opcode; + + // A SystemZICMP value. Only used for integer comparisons. + unsigned ICmpType; + + // The mask of CC values that Opcode can produce. + unsigned CCValid; + + // The mask of CC values for which the original condition is true. + unsigned CCMask; +}; +} // end anonymous namespace // Classify VT as either 32 or 64 bit. static bool is32Bit(EVT VT) { @@ -134,10 +154,14 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) setOperationAction(ISD::SDIVREM, VT, Custom); setOperationAction(ISD::UDIVREM, VT, Custom); - // Expand ATOMIC_LOAD and ATOMIC_STORE using ATOMIC_CMP_SWAP. - // FIXME: probably much too conservative. - setOperationAction(ISD::ATOMIC_LOAD, VT, Expand); - setOperationAction(ISD::ATOMIC_STORE, VT, Expand); + // Lower ATOMIC_LOAD and ATOMIC_STORE into normal volatile loads and + // stores, putting a serialization instruction after the stores. + setOperationAction(ISD::ATOMIC_LOAD, VT, Custom); + setOperationAction(ISD::ATOMIC_STORE, VT, Custom); + + // Lower ATOMIC_LOAD_SUB into ATOMIC_LOAD_ADD if LAA and LAAG are + // available, or if the operand is constant. + setOperationAction(ISD::ATOMIC_LOAD_SUB, VT, Custom); // No special instructions for these. setOperationAction(ISD::CTPOP, VT, Expand); @@ -152,8 +176,9 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) setOperationAction(ISD::SMUL_LOHI, VT, Custom); setOperationAction(ISD::UMUL_LOHI, VT, Custom); - // We have instructions for signed but not unsigned FP conversion. - setOperationAction(ISD::FP_TO_UINT, VT, Expand); + // Only z196 and above have native support for conversions to unsigned. + if (!Subtarget.hasFPExtension()) + setOperationAction(ISD::FP_TO_UINT, VT, Expand); } } @@ -173,10 +198,12 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) setOperationAction(ISD::ATOMIC_LOAD_UMAX, MVT::i32, Custom); setOperationAction(ISD::ATOMIC_CMP_SWAP, MVT::i32, Custom); - // We have instructions for signed but not unsigned FP conversion. + // z10 has instructions for signed but not unsigned FP conversion. // Handle unsigned 32-bit types as signed 64-bit types. - setOperationAction(ISD::UINT_TO_FP, MVT::i32, Promote); - setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); + if (!Subtarget.hasFPExtension()) { + setOperationAction(ISD::UINT_TO_FP, MVT::i32, Promote); + setOperationAction(ISD::UINT_TO_FP, MVT::i64, Expand); + } // We have native support for a 64-bit CTLZ, via FLOGR. setOperationAction(ISD::CTLZ, MVT::i32, Promote); @@ -266,6 +293,9 @@ SystemZTargetLowering::SystemZTargetLowering(SystemZTargetMachine &tm) setOperationAction(ISD::VACOPY, MVT::Other, Custom); setOperationAction(ISD::VAEND, MVT::Other, Expand); + // Codes for which we want to perform some z-specific combinations. + setTargetDAGCombine(ISD::SIGN_EXTEND); + // We want to use MVC in preference to even a single load/store pair. MaxStoresPerMemcpy = 0; MaxStoresPerMemcpyOptSize = 0; @@ -310,6 +340,7 @@ bool SystemZTargetLowering::isFPImmLegal(const APFloat &Imm, EVT VT) const { } bool SystemZTargetLowering::allowsUnalignedMemoryAccesses(EVT VT, + unsigned, bool *Fast) const { // Unaligned accesses should never be slower than the expanded version. // We check specifically for aligned accesses in the few cases where @@ -416,31 +447,31 @@ getSingleConstraintMatchWeight(AsmOperandInfo &info, break; case 'I': // Unsigned 8-bit constant - if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) + if (auto *C = dyn_cast<ConstantInt>(CallOperandVal)) if (isUInt<8>(C->getZExtValue())) weight = CW_Constant; break; case 'J': // Unsigned 12-bit constant - if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) + if (auto *C = dyn_cast<ConstantInt>(CallOperandVal)) if (isUInt<12>(C->getZExtValue())) weight = CW_Constant; break; case 'K': // Signed 16-bit constant - if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) + if (auto *C = dyn_cast<ConstantInt>(CallOperandVal)) if (isInt<16>(C->getSExtValue())) weight = CW_Constant; break; case 'L': // Signed 20-bit displacement (on all targets we support) - if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) + if (auto *C = dyn_cast<ConstantInt>(CallOperandVal)) if (isInt<20>(C->getSExtValue())) weight = CW_Constant; break; case 'M': // 0x7fffffff - if (ConstantInt *C = dyn_cast<ConstantInt>(CallOperandVal)) + if (auto *C = dyn_cast<ConstantInt>(CallOperandVal)) if (C->getZExtValue() == 0x7fffffff) weight = CW_Constant; break; @@ -533,35 +564,35 @@ LowerAsmOperandForConstraint(SDValue Op, std::string &Constraint, if (Constraint.length() == 1) { switch (Constraint[0]) { case 'I': // Unsigned 8-bit constant - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) + if (auto *C = dyn_cast<ConstantSDNode>(Op)) if (isUInt<8>(C->getZExtValue())) Ops.push_back(DAG.getTargetConstant(C->getZExtValue(), Op.getValueType())); return; case 'J': // Unsigned 12-bit constant - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) + if (auto *C = dyn_cast<ConstantSDNode>(Op)) if (isUInt<12>(C->getZExtValue())) Ops.push_back(DAG.getTargetConstant(C->getZExtValue(), Op.getValueType())); return; case 'K': // Signed 16-bit constant - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) + if (auto *C = dyn_cast<ConstantSDNode>(Op)) if (isInt<16>(C->getSExtValue())) Ops.push_back(DAG.getTargetConstant(C->getSExtValue(), Op.getValueType())); return; case 'L': // Signed 20-bit displacement (on all targets we support) - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) + if (auto *C = dyn_cast<ConstantSDNode>(Op)) if (isInt<20>(C->getSExtValue())) Ops.push_back(DAG.getTargetConstant(C->getSExtValue(), Op.getValueType())); return; case 'M': // 0x7fffffff - if (ConstantSDNode *C = dyn_cast<ConstantSDNode>(Op)) + if (auto *C = dyn_cast<ConstantSDNode>(Op)) if (C->getZExtValue() == 0x7fffffff) Ops.push_back(DAG.getTargetConstant(C->getZExtValue(), Op.getValueType())); @@ -642,8 +673,7 @@ LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, MachineRegisterInfo &MRI = MF.getRegInfo(); SystemZMachineFunctionInfo *FuncInfo = MF.getInfo<SystemZMachineFunctionInfo>(); - const SystemZFrameLowering *TFL = - static_cast<const SystemZFrameLowering *>(TM.getFrameLowering()); + auto *TFL = static_cast<const SystemZFrameLowering *>(TM.getFrameLowering()); // Assign locations to all of the incoming arguments. SmallVector<CCValAssign, 16> ArgLocs; @@ -852,10 +882,10 @@ SystemZTargetLowering::LowerCall(CallLoweringInfo &CLI, // associated Target* opcodes. Force %r1 to be used for indirect // tail calls. SDValue Glue; - if (GlobalAddressSDNode *G = dyn_cast<GlobalAddressSDNode>(Callee)) { + if (auto *G = dyn_cast<GlobalAddressSDNode>(Callee)) { Callee = DAG.getTargetGlobalAddress(G->getGlobal(), DL, PtrVT); Callee = DAG.getNode(SystemZISD::PCREL_WRAPPER, DL, PtrVT, Callee); - } else if (ExternalSymbolSDNode *E = dyn_cast<ExternalSymbolSDNode>(Callee)) { + } else if (auto *E = dyn_cast<ExternalSymbolSDNode>(Callee)) { Callee = DAG.getTargetExternalSymbol(E->getSymbol(), PtrVT); Callee = DAG.getNode(SystemZISD::PCREL_WRAPPER, DL, PtrVT, Callee); } else if (IsTailCall) { @@ -970,6 +1000,11 @@ SystemZTargetLowering::LowerReturn(SDValue Chain, RetOps.data(), RetOps.size()); } +SDValue SystemZTargetLowering:: +prepareVolatileOrAtomicLoad(SDValue Chain, SDLoc DL, SelectionDAG &DAG) const { + return DAG.getNode(SystemZISD::SERIALIZE, DL, MVT::Other, Chain); +} + // CC is a comparison that will be implemented using an integer or // floating-point comparison. Return the condition code mask for // a branch on true. In the integer case, CCMASK_CMP_UO is set for @@ -1044,7 +1079,7 @@ static IPMConversion getIPMConversion(unsigned CCValid, unsigned CCMask) { if (CCMask == (CCValid & (SystemZ::CCMASK_0 | SystemZ::CCMASK_3))) return IPMConversion(0, -(1 << SystemZ::IPM_CC), SystemZ::IPM_CC + 1); - // The remaing cases are 1, 2, 0/1/3 and 0/2/3. All these are + // The remaining cases are 1, 2, 0/1/3 and 0/2/3. All these are // can be done by inverting the low CC bit and applying one of the // sign-based extractions above. if (CCMask == (CCValid & SystemZ::CCMASK_1)) @@ -1065,109 +1100,100 @@ static IPMConversion getIPMConversion(unsigned CCValid, unsigned CCMask) { llvm_unreachable("Unexpected CC combination"); } -// If a comparison described by IsUnsigned, CCMask, CmpOp0 and CmpOp1 -// can be converted to a comparison against zero, adjust the operands +// If C can be converted to a comparison against zero, adjust the operands // as necessary. -static void adjustZeroCmp(SelectionDAG &DAG, bool &IsUnsigned, - SDValue &CmpOp0, SDValue &CmpOp1, - unsigned &CCMask) { - if (IsUnsigned) +static void adjustZeroCmp(SelectionDAG &DAG, Comparison &C) { + if (C.ICmpType == SystemZICMP::UnsignedOnly) return; - ConstantSDNode *ConstOp1 = dyn_cast<ConstantSDNode>(CmpOp1.getNode()); + auto *ConstOp1 = dyn_cast<ConstantSDNode>(C.Op1.getNode()); if (!ConstOp1) return; int64_t Value = ConstOp1->getSExtValue(); - if ((Value == -1 && CCMask == SystemZ::CCMASK_CMP_GT) || - (Value == -1 && CCMask == SystemZ::CCMASK_CMP_LE) || - (Value == 1 && CCMask == SystemZ::CCMASK_CMP_LT) || - (Value == 1 && CCMask == SystemZ::CCMASK_CMP_GE)) { - CCMask ^= SystemZ::CCMASK_CMP_EQ; - CmpOp1 = DAG.getConstant(0, CmpOp1.getValueType()); + if ((Value == -1 && C.CCMask == SystemZ::CCMASK_CMP_GT) || + (Value == -1 && C.CCMask == SystemZ::CCMASK_CMP_LE) || + (Value == 1 && C.CCMask == SystemZ::CCMASK_CMP_LT) || + (Value == 1 && C.CCMask == SystemZ::CCMASK_CMP_GE)) { + C.CCMask ^= SystemZ::CCMASK_CMP_EQ; + C.Op1 = DAG.getConstant(0, C.Op1.getValueType()); } } -// If a comparison described by IsUnsigned, CCMask, CmpOp0 and CmpOp1 -// is suitable for CLI(Y), CHHSI or CLHHSI, adjust the operands as necessary. -static void adjustSubwordCmp(SelectionDAG &DAG, bool &IsUnsigned, - SDValue &CmpOp0, SDValue &CmpOp1, - unsigned &CCMask) { +// If a comparison described by C is suitable for CLI(Y), CHHSI or CLHHSI, +// adjust the operands as necessary. +static void adjustSubwordCmp(SelectionDAG &DAG, Comparison &C) { // For us to make any changes, it must a comparison between a single-use // load and a constant. - if (!CmpOp0.hasOneUse() || - CmpOp0.getOpcode() != ISD::LOAD || - CmpOp1.getOpcode() != ISD::Constant) + if (!C.Op0.hasOneUse() || + C.Op0.getOpcode() != ISD::LOAD || + C.Op1.getOpcode() != ISD::Constant) return; // We must have an 8- or 16-bit load. - LoadSDNode *Load = cast<LoadSDNode>(CmpOp0); + auto *Load = cast<LoadSDNode>(C.Op0); unsigned NumBits = Load->getMemoryVT().getStoreSizeInBits(); if (NumBits != 8 && NumBits != 16) return; // The load must be an extending one and the constant must be within the // range of the unextended value. - ConstantSDNode *Constant = cast<ConstantSDNode>(CmpOp1); - uint64_t Value = Constant->getZExtValue(); + auto *ConstOp1 = cast<ConstantSDNode>(C.Op1); + uint64_t Value = ConstOp1->getZExtValue(); uint64_t Mask = (1 << NumBits) - 1; if (Load->getExtensionType() == ISD::SEXTLOAD) { - int64_t SignedValue = Constant->getSExtValue(); - if (uint64_t(SignedValue) + (1ULL << (NumBits - 1)) > Mask) + // Make sure that ConstOp1 is in range of C.Op0. + int64_t SignedValue = ConstOp1->getSExtValue(); + if (uint64_t(SignedValue) + (uint64_t(1) << (NumBits - 1)) > Mask) return; - // Unsigned comparison between two sign-extended values is equivalent - // to unsigned comparison between two zero-extended values. - if (IsUnsigned) + if (C.ICmpType != SystemZICMP::SignedOnly) { + // Unsigned comparison between two sign-extended values is equivalent + // to unsigned comparison between two zero-extended values. Value &= Mask; - else if (CCMask == SystemZ::CCMASK_CMP_EQ || - CCMask == SystemZ::CCMASK_CMP_NE) - // Any choice of IsUnsigned is OK for equality comparisons. - // We could use either CHHSI or CLHHSI for 16-bit comparisons, - // but since we use CLHHSI for zero extensions, it seems better - // to be consistent and do the same here. - Value &= Mask, IsUnsigned = true; - else if (NumBits == 8) { + } else if (NumBits == 8) { // Try to treat the comparison as unsigned, so that we can use CLI. // Adjust CCMask and Value as necessary. - if (Value == 0 && CCMask == SystemZ::CCMASK_CMP_LT) + if (Value == 0 && C.CCMask == SystemZ::CCMASK_CMP_LT) // Test whether the high bit of the byte is set. - Value = 127, CCMask = SystemZ::CCMASK_CMP_GT, IsUnsigned = true; - else if (Value == 0 && CCMask == SystemZ::CCMASK_CMP_GE) + Value = 127, C.CCMask = SystemZ::CCMASK_CMP_GT; + else if (Value == 0 && C.CCMask == SystemZ::CCMASK_CMP_GE) // Test whether the high bit of the byte is clear. - Value = 128, CCMask = SystemZ::CCMASK_CMP_LT, IsUnsigned = true; + Value = 128, C.CCMask = SystemZ::CCMASK_CMP_LT; else // No instruction exists for this combination. return; + C.ICmpType = SystemZICMP::UnsignedOnly; } } else if (Load->getExtensionType() == ISD::ZEXTLOAD) { if (Value > Mask) return; - // Signed comparison between two zero-extended values is equivalent - // to unsigned comparison. - IsUnsigned = true; + assert(C.ICmpType == SystemZICMP::Any && + "Signedness shouldn't matter here."); } else return; // Make sure that the first operand is an i32 of the right extension type. - ISD::LoadExtType ExtType = IsUnsigned ? ISD::ZEXTLOAD : ISD::SEXTLOAD; - if (CmpOp0.getValueType() != MVT::i32 || + ISD::LoadExtType ExtType = (C.ICmpType == SystemZICMP::SignedOnly ? + ISD::SEXTLOAD : + ISD::ZEXTLOAD); + if (C.Op0.getValueType() != MVT::i32 || Load->getExtensionType() != ExtType) - CmpOp0 = DAG.getExtLoad(ExtType, SDLoc(Load), MVT::i32, - Load->getChain(), Load->getBasePtr(), - Load->getPointerInfo(), Load->getMemoryVT(), - Load->isVolatile(), Load->isNonTemporal(), - Load->getAlignment()); + C.Op0 = DAG.getExtLoad(ExtType, SDLoc(Load), MVT::i32, + Load->getChain(), Load->getBasePtr(), + Load->getPointerInfo(), Load->getMemoryVT(), + Load->isVolatile(), Load->isNonTemporal(), + Load->getAlignment()); // Make sure that the second operand is an i32 with the right value. - if (CmpOp1.getValueType() != MVT::i32 || - Value != Constant->getZExtValue()) - CmpOp1 = DAG.getConstant(Value, MVT::i32); + if (C.Op1.getValueType() != MVT::i32 || + Value != ConstOp1->getZExtValue()) + C.Op1 = DAG.getConstant(Value, MVT::i32); } // Return true if Op is either an unextended load, or a load suitable // for integer register-memory comparisons of type ICmpType. static bool isNaturalMemoryOperand(SDValue Op, unsigned ICmpType) { - LoadSDNode *Load = dyn_cast<LoadSDNode>(Op.getNode()); + auto *Load = dyn_cast<LoadSDNode>(Op.getNode()); if (Load) { // There are no instructions to compare a register with a memory byte. if (Load->getMemoryVT() == MVT::i8) @@ -1187,53 +1213,163 @@ static bool isNaturalMemoryOperand(SDValue Op, unsigned ICmpType) { return false; } -// Return true if it is better to swap comparison operands Op0 and Op1. -// ICmpType is the type of an integer comparison. -static bool shouldSwapCmpOperands(SDValue Op0, SDValue Op1, - unsigned ICmpType) { +// Return true if it is better to swap the operands of C. +static bool shouldSwapCmpOperands(const Comparison &C) { // Leave f128 comparisons alone, since they have no memory forms. - if (Op0.getValueType() == MVT::f128) + if (C.Op0.getValueType() == MVT::f128) return false; // Always keep a floating-point constant second, since comparisons with // zero can use LOAD TEST and comparisons with other constants make a // natural memory operand. - if (isa<ConstantFPSDNode>(Op1)) + if (isa<ConstantFPSDNode>(C.Op1)) return false; // Never swap comparisons with zero since there are many ways to optimize // those later. - ConstantSDNode *COp1 = dyn_cast<ConstantSDNode>(Op1); - if (COp1 && COp1->getZExtValue() == 0) + auto *ConstOp1 = dyn_cast<ConstantSDNode>(C.Op1); + if (ConstOp1 && ConstOp1->getZExtValue() == 0) + return false; + + // Also keep natural memory operands second if the loaded value is + // only used here. Several comparisons have memory forms. + if (isNaturalMemoryOperand(C.Op1, C.ICmpType) && C.Op1.hasOneUse()) return false; // Look for cases where Cmp0 is a single-use load and Cmp1 isn't. // In that case we generally prefer the memory to be second. - if ((isNaturalMemoryOperand(Op0, ICmpType) && Op0.hasOneUse()) && - !(isNaturalMemoryOperand(Op1, ICmpType) && Op1.hasOneUse())) { + if (isNaturalMemoryOperand(C.Op0, C.ICmpType) && C.Op0.hasOneUse()) { // The only exceptions are when the second operand is a constant and // we can use things like CHHSI. - if (!COp1) + if (!ConstOp1) return true; // The unsigned memory-immediate instructions can handle 16-bit // unsigned integers. - if (ICmpType != SystemZICMP::SignedOnly && - isUInt<16>(COp1->getZExtValue())) + if (C.ICmpType != SystemZICMP::SignedOnly && + isUInt<16>(ConstOp1->getZExtValue())) return false; // The signed memory-immediate instructions can handle 16-bit // signed integers. - if (ICmpType != SystemZICMP::UnsignedOnly && - isInt<16>(COp1->getSExtValue())) + if (C.ICmpType != SystemZICMP::UnsignedOnly && + isInt<16>(ConstOp1->getSExtValue())) return false; return true; } + + // Try to promote the use of CGFR and CLGFR. + unsigned Opcode0 = C.Op0.getOpcode(); + if (C.ICmpType != SystemZICMP::UnsignedOnly && Opcode0 == ISD::SIGN_EXTEND) + return true; + if (C.ICmpType != SystemZICMP::SignedOnly && Opcode0 == ISD::ZERO_EXTEND) + return true; + if (C.ICmpType != SystemZICMP::SignedOnly && + Opcode0 == ISD::AND && + C.Op0.getOperand(1).getOpcode() == ISD::Constant && + cast<ConstantSDNode>(C.Op0.getOperand(1))->getZExtValue() == 0xffffffff) + return true; + return false; } +// Return a version of comparison CC mask CCMask in which the LT and GT +// actions are swapped. +static unsigned reverseCCMask(unsigned CCMask) { + return ((CCMask & SystemZ::CCMASK_CMP_EQ) | + (CCMask & SystemZ::CCMASK_CMP_GT ? SystemZ::CCMASK_CMP_LT : 0) | + (CCMask & SystemZ::CCMASK_CMP_LT ? SystemZ::CCMASK_CMP_GT : 0) | + (CCMask & SystemZ::CCMASK_CMP_UO)); +} + +// Check whether C tests for equality between X and Y and whether X - Y +// or Y - X is also computed. In that case it's better to compare the +// result of the subtraction against zero. +static void adjustForSubtraction(SelectionDAG &DAG, Comparison &C) { + if (C.CCMask == SystemZ::CCMASK_CMP_EQ || + C.CCMask == SystemZ::CCMASK_CMP_NE) { + for (auto I = C.Op0->use_begin(), E = C.Op0->use_end(); I != E; ++I) { + SDNode *N = *I; + if (N->getOpcode() == ISD::SUB && + ((N->getOperand(0) == C.Op0 && N->getOperand(1) == C.Op1) || + (N->getOperand(0) == C.Op1 && N->getOperand(1) == C.Op0))) { + C.Op0 = SDValue(N, 0); + C.Op1 = DAG.getConstant(0, N->getValueType(0)); + return; + } + } + } +} + +// Check whether C compares a floating-point value with zero and if that +// floating-point value is also negated. In this case we can use the +// negation to set CC, so avoiding separate LOAD AND TEST and +// LOAD (NEGATIVE/COMPLEMENT) instructions. +static void adjustForFNeg(Comparison &C) { + auto *C1 = dyn_cast<ConstantFPSDNode>(C.Op1); + if (C1 && C1->isZero()) { + for (auto I = C.Op0->use_begin(), E = C.Op0->use_end(); I != E; ++I) { + SDNode *N = *I; + if (N->getOpcode() == ISD::FNEG) { + C.Op0 = SDValue(N, 0); + C.CCMask = reverseCCMask(C.CCMask); + return; + } + } + } +} + +// Check whether C compares (shl X, 32) with 0 and whether X is +// also sign-extended. In that case it is better to test the result +// of the sign extension using LTGFR. +// +// This case is important because InstCombine transforms a comparison +// with (sext (trunc X)) into a comparison with (shl X, 32). +static void adjustForLTGFR(Comparison &C) { + // Check for a comparison between (shl X, 32) and 0. + if (C.Op0.getOpcode() == ISD::SHL && + C.Op0.getValueType() == MVT::i64 && + C.Op1.getOpcode() == ISD::Constant && + cast<ConstantSDNode>(C.Op1)->getZExtValue() == 0) { + auto *C1 = dyn_cast<ConstantSDNode>(C.Op0.getOperand(1)); + if (C1 && C1->getZExtValue() == 32) { + SDValue ShlOp0 = C.Op0.getOperand(0); + // See whether X has any SIGN_EXTEND_INREG uses. + for (auto I = ShlOp0->use_begin(), E = ShlOp0->use_end(); I != E; ++I) { + SDNode *N = *I; + if (N->getOpcode() == ISD::SIGN_EXTEND_INREG && + cast<VTSDNode>(N->getOperand(1))->getVT() == MVT::i32) { + C.Op0 = SDValue(N, 0); + return; + } + } + } + } +} + +// If C compares the truncation of an extending load, try to compare +// the untruncated value instead. This exposes more opportunities to +// reuse CC. +static void adjustICmpTruncate(SelectionDAG &DAG, Comparison &C) { + if (C.Op0.getOpcode() == ISD::TRUNCATE && + C.Op0.getOperand(0).getOpcode() == ISD::LOAD && + C.Op1.getOpcode() == ISD::Constant && + cast<ConstantSDNode>(C.Op1)->getZExtValue() == 0) { + auto *L = cast<LoadSDNode>(C.Op0.getOperand(0)); + if (L->getMemoryVT().getStoreSizeInBits() + <= C.Op0.getValueType().getSizeInBits()) { + unsigned Type = L->getExtensionType(); + if ((Type == ISD::ZEXTLOAD && C.ICmpType != SystemZICMP::SignedOnly) || + (Type == ISD::SEXTLOAD && C.ICmpType != SystemZICMP::UnsignedOnly)) { + C.Op0 = C.Op0.getOperand(0); + C.Op1 = DAG.getConstant(0, C.Op0.getValueType()); + } + } + } +} + // Return true if shift operation N has an in-range constant shift value. // Store it in ShiftVal if so. static bool isSimpleShift(SDValue N, unsigned &ShiftVal) { - ConstantSDNode *Shift = dyn_cast<ConstantSDNode>(N.getOperand(1)); + auto *Shift = dyn_cast<ConstantSDNode>(N.getOperand(1)); if (!Shift) return false; @@ -1341,118 +1477,143 @@ static unsigned getTestUnderMaskCond(unsigned BitSize, unsigned CCMask, return 0; } -// See whether the comparison (Opcode CmpOp0, CmpOp1, ICmpType) can be -// implemented as a TEST UNDER MASK instruction when the condition being -// tested is as described by CCValid and CCMask. Update the arguments -// with the TM version if so. -static void adjustForTestUnderMask(SelectionDAG &DAG, unsigned &Opcode, - SDValue &CmpOp0, SDValue &CmpOp1, - unsigned &CCValid, unsigned &CCMask, - unsigned &ICmpType) { +// See whether C can be implemented as a TEST UNDER MASK instruction. +// Update the arguments with the TM version if so. +static void adjustForTestUnderMask(SelectionDAG &DAG, Comparison &C) { // Check that we have a comparison with a constant. - ConstantSDNode *ConstCmpOp1 = dyn_cast<ConstantSDNode>(CmpOp1); - if (!ConstCmpOp1) + auto *ConstOp1 = dyn_cast<ConstantSDNode>(C.Op1); + if (!ConstOp1) return; - uint64_t CmpVal = ConstCmpOp1->getZExtValue(); + uint64_t CmpVal = ConstOp1->getZExtValue(); // Check whether the nonconstant input is an AND with a constant mask. - if (CmpOp0.getOpcode() != ISD::AND) - return; - SDValue AndOp0 = CmpOp0.getOperand(0); - SDValue AndOp1 = CmpOp0.getOperand(1); - ConstantSDNode *Mask = dyn_cast<ConstantSDNode>(AndOp1.getNode()); - if (!Mask) - return; - uint64_t MaskVal = Mask->getZExtValue(); + Comparison NewC(C); + uint64_t MaskVal; + ConstantSDNode *Mask = 0; + if (C.Op0.getOpcode() == ISD::AND) { + NewC.Op0 = C.Op0.getOperand(0); + NewC.Op1 = C.Op0.getOperand(1); + Mask = dyn_cast<ConstantSDNode>(NewC.Op1); + if (!Mask) + return; + MaskVal = Mask->getZExtValue(); + } else { + // There is no instruction to compare with a 64-bit immediate + // so use TMHH instead if possible. We need an unsigned ordered + // comparison with an i64 immediate. + if (NewC.Op0.getValueType() != MVT::i64 || + NewC.CCMask == SystemZ::CCMASK_CMP_EQ || + NewC.CCMask == SystemZ::CCMASK_CMP_NE || + NewC.ICmpType == SystemZICMP::SignedOnly) + return; + // Convert LE and GT comparisons into LT and GE. + if (NewC.CCMask == SystemZ::CCMASK_CMP_LE || + NewC.CCMask == SystemZ::CCMASK_CMP_GT) { + if (CmpVal == uint64_t(-1)) + return; + CmpVal += 1; + NewC.CCMask ^= SystemZ::CCMASK_CMP_EQ; + } + // If the low N bits of Op1 are zero than the low N bits of Op0 can + // be masked off without changing the result. + MaskVal = -(CmpVal & -CmpVal); + NewC.ICmpType = SystemZICMP::UnsignedOnly; + } // Check whether the combination of mask, comparison value and comparison // type are suitable. - unsigned BitSize = CmpOp0.getValueType().getSizeInBits(); + unsigned BitSize = NewC.Op0.getValueType().getSizeInBits(); unsigned NewCCMask, ShiftVal; - if (ICmpType != SystemZICMP::SignedOnly && - AndOp0.getOpcode() == ISD::SHL && - isSimpleShift(AndOp0, ShiftVal) && - (NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal >> ShiftVal, + if (NewC.ICmpType != SystemZICMP::SignedOnly && + NewC.Op0.getOpcode() == ISD::SHL && + isSimpleShift(NewC.Op0, ShiftVal) && + (NewCCMask = getTestUnderMaskCond(BitSize, NewC.CCMask, + MaskVal >> ShiftVal, CmpVal >> ShiftVal, SystemZICMP::Any))) { - AndOp0 = AndOp0.getOperand(0); - AndOp1 = DAG.getConstant(MaskVal >> ShiftVal, AndOp0.getValueType()); - } else if (ICmpType != SystemZICMP::SignedOnly && - AndOp0.getOpcode() == ISD::SRL && - isSimpleShift(AndOp0, ShiftVal) && - (NewCCMask = getTestUnderMaskCond(BitSize, CCMask, + NewC.Op0 = NewC.Op0.getOperand(0); + MaskVal >>= ShiftVal; + } else if (NewC.ICmpType != SystemZICMP::SignedOnly && + NewC.Op0.getOpcode() == ISD::SRL && + isSimpleShift(NewC.Op0, ShiftVal) && + (NewCCMask = getTestUnderMaskCond(BitSize, NewC.CCMask, MaskVal << ShiftVal, CmpVal << ShiftVal, SystemZICMP::UnsignedOnly))) { - AndOp0 = AndOp0.getOperand(0); - AndOp1 = DAG.getConstant(MaskVal << ShiftVal, AndOp0.getValueType()); + NewC.Op0 = NewC.Op0.getOperand(0); + MaskVal <<= ShiftVal; } else { - NewCCMask = getTestUnderMaskCond(BitSize, CCMask, MaskVal, CmpVal, - ICmpType); + NewCCMask = getTestUnderMaskCond(BitSize, NewC.CCMask, MaskVal, CmpVal, + NewC.ICmpType); if (!NewCCMask) return; } // Go ahead and make the change. - Opcode = SystemZISD::TM; - CmpOp0 = AndOp0; - CmpOp1 = AndOp1; - ICmpType = (bool(NewCCMask & SystemZ::CCMASK_TM_MIXED_MSB_0) != - bool(NewCCMask & SystemZ::CCMASK_TM_MIXED_MSB_1)); - CCValid = SystemZ::CCMASK_TM; - CCMask = NewCCMask; -} - -// Return a target node that compares CmpOp0 with CmpOp1 and stores a -// 2-bit result in CC. Set CCValid to the CCMASK_* of all possible -// 2-bit results and CCMask to the subset of those results that are -// associated with Cond. -static SDValue emitCmp(const SystemZTargetMachine &TM, SelectionDAG &DAG, - SDLoc DL, SDValue CmpOp0, SDValue CmpOp1, - ISD::CondCode Cond, unsigned &CCValid, - unsigned &CCMask) { - bool IsUnsigned = false; - CCMask = CCMaskForCondCode(Cond); - unsigned Opcode, ICmpType = 0; - if (CmpOp0.getValueType().isFloatingPoint()) { - CCValid = SystemZ::CCMASK_FCMP; - Opcode = SystemZISD::FCMP; + C.Opcode = SystemZISD::TM; + C.Op0 = NewC.Op0; + if (Mask && Mask->getZExtValue() == MaskVal) + C.Op1 = SDValue(Mask, 0); + else + C.Op1 = DAG.getConstant(MaskVal, C.Op0.getValueType()); + C.CCValid = SystemZ::CCMASK_TM; + C.CCMask = NewCCMask; +} + +// Decide how to implement a comparison of type Cond between CmpOp0 with CmpOp1. +static Comparison getCmp(SelectionDAG &DAG, SDValue CmpOp0, SDValue CmpOp1, + ISD::CondCode Cond) { + Comparison C(CmpOp0, CmpOp1); + C.CCMask = CCMaskForCondCode(Cond); + if (C.Op0.getValueType().isFloatingPoint()) { + C.CCValid = SystemZ::CCMASK_FCMP; + C.Opcode = SystemZISD::FCMP; + adjustForFNeg(C); } else { - IsUnsigned = CCMask & SystemZ::CCMASK_CMP_UO; - CCValid = SystemZ::CCMASK_ICMP; - CCMask &= CCValid; - adjustZeroCmp(DAG, IsUnsigned, CmpOp0, CmpOp1, CCMask); - adjustSubwordCmp(DAG, IsUnsigned, CmpOp0, CmpOp1, CCMask); - Opcode = SystemZISD::ICMP; + C.CCValid = SystemZ::CCMASK_ICMP; + C.Opcode = SystemZISD::ICMP; // Choose the type of comparison. Equality and inequality tests can // use either signed or unsigned comparisons. The choice also doesn't // matter if both sign bits are known to be clear. In those cases we // want to give the main isel code the freedom to choose whichever // form fits best. - if (CCMask == SystemZ::CCMASK_CMP_EQ || - CCMask == SystemZ::CCMASK_CMP_NE || - (DAG.SignBitIsZero(CmpOp0) && DAG.SignBitIsZero(CmpOp1))) - ICmpType = SystemZICMP::Any; - else if (IsUnsigned) - ICmpType = SystemZICMP::UnsignedOnly; + if (C.CCMask == SystemZ::CCMASK_CMP_EQ || + C.CCMask == SystemZ::CCMASK_CMP_NE || + (DAG.SignBitIsZero(C.Op0) && DAG.SignBitIsZero(C.Op1))) + C.ICmpType = SystemZICMP::Any; + else if (C.CCMask & SystemZ::CCMASK_CMP_UO) + C.ICmpType = SystemZICMP::UnsignedOnly; else - ICmpType = SystemZICMP::SignedOnly; + C.ICmpType = SystemZICMP::SignedOnly; + C.CCMask &= ~SystemZ::CCMASK_CMP_UO; + adjustZeroCmp(DAG, C); + adjustSubwordCmp(DAG, C); + adjustForSubtraction(DAG, C); + adjustForLTGFR(C); + adjustICmpTruncate(DAG, C); } - if (shouldSwapCmpOperands(CmpOp0, CmpOp1, ICmpType)) { - std::swap(CmpOp0, CmpOp1); - CCMask = ((CCMask & SystemZ::CCMASK_CMP_EQ) | - (CCMask & SystemZ::CCMASK_CMP_GT ? SystemZ::CCMASK_CMP_LT : 0) | - (CCMask & SystemZ::CCMASK_CMP_LT ? SystemZ::CCMASK_CMP_GT : 0) | - (CCMask & SystemZ::CCMASK_CMP_UO)); + if (shouldSwapCmpOperands(C)) { + std::swap(C.Op0, C.Op1); + C.CCMask = reverseCCMask(C.CCMask); } - adjustForTestUnderMask(DAG, Opcode, CmpOp0, CmpOp1, CCValid, CCMask, - ICmpType); - if (Opcode == SystemZISD::ICMP || Opcode == SystemZISD::TM) - return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1, - DAG.getConstant(ICmpType, MVT::i32)); - return DAG.getNode(Opcode, DL, MVT::Glue, CmpOp0, CmpOp1); + adjustForTestUnderMask(DAG, C); + return C; +} + +// Emit the comparison instruction described by C. +static SDValue emitCmp(SelectionDAG &DAG, SDLoc DL, Comparison &C) { + if (C.Opcode == SystemZISD::ICMP) + return DAG.getNode(SystemZISD::ICMP, DL, MVT::Glue, C.Op0, C.Op1, + DAG.getConstant(C.ICmpType, MVT::i32)); + if (C.Opcode == SystemZISD::TM) { + bool RegisterOnly = (bool(C.CCMask & SystemZ::CCMASK_TM_MIXED_MSB_0) != + bool(C.CCMask & SystemZ::CCMASK_TM_MIXED_MSB_1)); + return DAG.getNode(SystemZISD::TM, DL, MVT::Glue, C.Op0, C.Op1, + DAG.getConstant(RegisterOnly, MVT::i32)); + } + return DAG.getNode(C.Opcode, DL, MVT::Glue, C.Op0, C.Op1); } // Implement a 32-bit *MUL_LOHI operation by extending both operands to @@ -1486,16 +1647,11 @@ static void lowerGR128Binary(SelectionDAG &DAG, SDLoc DL, EVT VT, Odd = DAG.getTargetExtractSubreg(SystemZ::odd128(Is32Bit), DL, VT, Result); } -SDValue SystemZTargetLowering::lowerSETCC(SDValue Op, - SelectionDAG &DAG) const { - SDValue CmpOp0 = Op.getOperand(0); - SDValue CmpOp1 = Op.getOperand(1); - ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); - SDLoc DL(Op); - - unsigned CCValid, CCMask; - SDValue Glue = emitCmp(TM, DAG, DL, CmpOp0, CmpOp1, CC, CCValid, CCMask); - +// Return an i32 value that is 1 if the CC value produced by Glue is +// in the mask CCMask and 0 otherwise. CC is known to have a value +// in CCValid, so other values can be ignored. +static SDValue emitSETCC(SelectionDAG &DAG, SDLoc DL, SDValue Glue, + unsigned CCValid, unsigned CCMask) { IPMConversion Conversion = getIPMConversion(CCValid, CCMask); SDValue Result = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, Glue); @@ -1516,6 +1672,18 @@ SDValue SystemZTargetLowering::lowerSETCC(SDValue Op, return Result; } +SDValue SystemZTargetLowering::lowerSETCC(SDValue Op, + SelectionDAG &DAG) const { + SDValue CmpOp0 = Op.getOperand(0); + SDValue CmpOp1 = Op.getOperand(1); + ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(2))->get(); + SDLoc DL(Op); + + Comparison C(getCmp(DAG, CmpOp0, CmpOp1, CC)); + SDValue Glue = emitCmp(DAG, DL, C); + return emitSETCC(DAG, DL, Glue, C.CCValid, C.CCMask); +} + SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDValue Chain = Op.getOperand(0); ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(1))->get(); @@ -1524,11 +1692,33 @@ SDValue SystemZTargetLowering::lowerBR_CC(SDValue Op, SelectionDAG &DAG) const { SDValue Dest = Op.getOperand(4); SDLoc DL(Op); - unsigned CCValid, CCMask; - SDValue Flags = emitCmp(TM, DAG, DL, CmpOp0, CmpOp1, CC, CCValid, CCMask); + Comparison C(getCmp(DAG, CmpOp0, CmpOp1, CC)); + SDValue Glue = emitCmp(DAG, DL, C); return DAG.getNode(SystemZISD::BR_CCMASK, DL, Op.getValueType(), - Chain, DAG.getConstant(CCValid, MVT::i32), - DAG.getConstant(CCMask, MVT::i32), Dest, Flags); + Chain, DAG.getConstant(C.CCValid, MVT::i32), + DAG.getConstant(C.CCMask, MVT::i32), Dest, Glue); +} + +// Return true if Pos is CmpOp and Neg is the negative of CmpOp, +// allowing Pos and Neg to be wider than CmpOp. +static bool isAbsolute(SDValue CmpOp, SDValue Pos, SDValue Neg) { + return (Neg.getOpcode() == ISD::SUB && + Neg.getOperand(0).getOpcode() == ISD::Constant && + cast<ConstantSDNode>(Neg.getOperand(0))->getZExtValue() == 0 && + Neg.getOperand(1) == Pos && + (Pos == CmpOp || + (Pos.getOpcode() == ISD::SIGN_EXTEND && + Pos.getOperand(0) == CmpOp))); +} + +// Return the absolute or negative absolute of Op; IsNegative decides which. +static SDValue getAbsolute(SelectionDAG &DAG, SDLoc DL, SDValue Op, + bool IsNegative) { + Op = DAG.getNode(SystemZISD::IABS, DL, Op.getValueType(), Op); + if (IsNegative) + Op = DAG.getNode(ISD::SUB, DL, Op.getValueType(), + DAG.getConstant(0, Op.getValueType()), Op); + return Op; } SDValue SystemZTargetLowering::lowerSELECT_CC(SDValue Op, @@ -1540,15 +1730,53 @@ SDValue SystemZTargetLowering::lowerSELECT_CC(SDValue Op, ISD::CondCode CC = cast<CondCodeSDNode>(Op.getOperand(4))->get(); SDLoc DL(Op); - unsigned CCValid, CCMask; - SDValue Flags = emitCmp(TM, DAG, DL, CmpOp0, CmpOp1, CC, CCValid, CCMask); + Comparison C(getCmp(DAG, CmpOp0, CmpOp1, CC)); + + // Check for absolute and negative-absolute selections, including those + // where the comparison value is sign-extended (for LPGFR and LNGFR). + // This check supplements the one in DAGCombiner. + if (C.Opcode == SystemZISD::ICMP && + C.CCMask != SystemZ::CCMASK_CMP_EQ && + C.CCMask != SystemZ::CCMASK_CMP_NE && + C.Op1.getOpcode() == ISD::Constant && + cast<ConstantSDNode>(C.Op1)->getZExtValue() == 0) { + if (isAbsolute(C.Op0, TrueOp, FalseOp)) + return getAbsolute(DAG, DL, TrueOp, C.CCMask & SystemZ::CCMASK_CMP_LT); + if (isAbsolute(C.Op0, FalseOp, TrueOp)) + return getAbsolute(DAG, DL, FalseOp, C.CCMask & SystemZ::CCMASK_CMP_GT); + } + + SDValue Glue = emitCmp(DAG, DL, C); + + // Special case for handling -1/0 results. The shifts we use here + // should get optimized with the IPM conversion sequence. + auto *TrueC = dyn_cast<ConstantSDNode>(TrueOp); + auto *FalseC = dyn_cast<ConstantSDNode>(FalseOp); + if (TrueC && FalseC) { + int64_t TrueVal = TrueC->getSExtValue(); + int64_t FalseVal = FalseC->getSExtValue(); + if ((TrueVal == -1 && FalseVal == 0) || (TrueVal == 0 && FalseVal == -1)) { + // Invert the condition if we want -1 on false. + if (TrueVal == 0) + C.CCMask ^= C.CCValid; + SDValue Result = emitSETCC(DAG, DL, Glue, C.CCValid, C.CCMask); + EVT VT = Op.getValueType(); + // Extend the result to VT. Upper bits are ignored. + if (!is32Bit(VT)) + Result = DAG.getNode(ISD::ANY_EXTEND, DL, VT, Result); + // Sign-extend from the low bit. + SDValue ShAmt = DAG.getConstant(VT.getSizeInBits() - 1, MVT::i32); + SDValue Shl = DAG.getNode(ISD::SHL, DL, VT, Result, ShAmt); + return DAG.getNode(ISD::SRA, DL, VT, Shl, ShAmt); + } + } SmallVector<SDValue, 5> Ops; Ops.push_back(TrueOp); Ops.push_back(FalseOp); - Ops.push_back(DAG.getConstant(CCValid, MVT::i32)); - Ops.push_back(DAG.getConstant(CCMask, MVT::i32)); - Ops.push_back(Flags); + Ops.push_back(DAG.getConstant(C.CCValid, MVT::i32)); + Ops.push_back(DAG.getConstant(C.CCMask, MVT::i32)); + Ops.push_back(Glue); SDVTList VTs = DAG.getVTList(Op.getValueType(), MVT::Glue); return DAG.getNode(SystemZISD::SELECT_CCMASK, DL, VTs, &Ops[0], Ops.size()); @@ -1949,12 +2177,33 @@ SDValue SystemZTargetLowering::lowerOR(SDValue Op, SelectionDAG &DAG) const { MVT::i64, HighOp, Low32); } +// Op is an atomic load. Lower it into a normal volatile load. +SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op, + SelectionDAG &DAG) const { + auto *Node = cast<AtomicSDNode>(Op.getNode()); + return DAG.getExtLoad(ISD::EXTLOAD, SDLoc(Op), Op.getValueType(), + Node->getChain(), Node->getBasePtr(), + Node->getMemoryVT(), Node->getMemOperand()); +} + +// Op is an atomic store. Lower it into a normal volatile store followed +// by a serialization. +SDValue SystemZTargetLowering::lowerATOMIC_STORE(SDValue Op, + SelectionDAG &DAG) const { + auto *Node = cast<AtomicSDNode>(Op.getNode()); + SDValue Chain = DAG.getTruncStore(Node->getChain(), SDLoc(Op), Node->getVal(), + Node->getBasePtr(), Node->getMemoryVT(), + Node->getMemOperand()); + return SDValue(DAG.getMachineNode(SystemZ::Serialize, SDLoc(Op), MVT::Other, + Chain), 0); +} + // Op is an 8-, 16-bit or 32-bit ATOMIC_LOAD_* operation. Lower the first // two into the fullword ATOMIC_LOADW_* operation given by Opcode. -SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op, - SelectionDAG &DAG, - unsigned Opcode) const { - AtomicSDNode *Node = cast<AtomicSDNode>(Op.getNode()); +SDValue SystemZTargetLowering::lowerATOMIC_LOAD_OP(SDValue Op, + SelectionDAG &DAG, + unsigned Opcode) const { + auto *Node = cast<AtomicSDNode>(Op.getNode()); // 32-bit operations need no code outside the main loop. EVT NarrowVT = Node->getMemoryVT(); @@ -1972,7 +2221,7 @@ SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op, // Convert atomic subtracts of constants into additions. if (Opcode == SystemZISD::ATOMIC_LOADW_SUB) - if (ConstantSDNode *Const = dyn_cast<ConstantSDNode>(Src2)) { + if (auto *Const = dyn_cast<ConstantSDNode>(Src2)) { Opcode = SystemZISD::ATOMIC_LOADW_ADD; Src2 = DAG.getConstant(-Const->getSExtValue(), Src2.getValueType()); } @@ -2023,11 +2272,49 @@ SDValue SystemZTargetLowering::lowerATOMIC_LOAD(SDValue Op, return DAG.getMergeValues(RetOps, 2, DL); } +// Op is an ATOMIC_LOAD_SUB operation. Lower 8- and 16-bit operations +// into ATOMIC_LOADW_SUBs and decide whether to convert 32- and 64-bit +// operations into additions. +SDValue SystemZTargetLowering::lowerATOMIC_LOAD_SUB(SDValue Op, + SelectionDAG &DAG) const { + auto *Node = cast<AtomicSDNode>(Op.getNode()); + EVT MemVT = Node->getMemoryVT(); + if (MemVT == MVT::i32 || MemVT == MVT::i64) { + // A full-width operation. + assert(Op.getValueType() == MemVT && "Mismatched VTs"); + SDValue Src2 = Node->getVal(); + SDValue NegSrc2; + SDLoc DL(Src2); + + if (auto *Op2 = dyn_cast<ConstantSDNode>(Src2)) { + // Use an addition if the operand is constant and either LAA(G) is + // available or the negative value is in the range of A(G)FHI. + int64_t Value = (-Op2->getAPIntValue()).getSExtValue(); + if (isInt<32>(Value) || TM.getSubtargetImpl()->hasInterlockedAccess1()) + NegSrc2 = DAG.getConstant(Value, MemVT); + } else if (TM.getSubtargetImpl()->hasInterlockedAccess1()) + // Use LAA(G) if available. + NegSrc2 = DAG.getNode(ISD::SUB, DL, MemVT, DAG.getConstant(0, MemVT), + Src2); + + if (NegSrc2.getNode()) + return DAG.getAtomic(ISD::ATOMIC_LOAD_ADD, DL, MemVT, + Node->getChain(), Node->getBasePtr(), NegSrc2, + Node->getMemOperand(), Node->getOrdering(), + Node->getSynchScope()); + + // Use the node as-is. + return Op; + } + + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_SUB); +} + // Node is an 8- or 16-bit ATOMIC_CMP_SWAP operation. Lower the first two // into a fullword ATOMIC_CMP_SWAPW operation. SDValue SystemZTargetLowering::lowerATOMIC_CMP_SWAP(SDValue Op, SelectionDAG &DAG) const { - AtomicSDNode *Node = cast<AtomicSDNode>(Op.getNode()); + auto *Node = cast<AtomicSDNode>(Op.getNode()); // We have native support for 32-bit compare and swap. EVT NarrowVT = Node->getMemoryVT(); @@ -2094,7 +2381,7 @@ SDValue SystemZTargetLowering::lowerPREFETCH(SDValue Op, bool IsWrite = cast<ConstantSDNode>(Op.getOperand(2))->getZExtValue(); unsigned Code = IsWrite ? SystemZ::PFD_WRITE : SystemZ::PFD_READ; - MemIntrinsicSDNode *Node = cast<MemIntrinsicSDNode>(Op.getNode()); + auto *Node = cast<MemIntrinsicSDNode>(Op.getNode()); SDValue Ops[] = { Op.getOperand(0), DAG.getConstant(Code, MVT::i32), @@ -2143,27 +2430,31 @@ SDValue SystemZTargetLowering::LowerOperation(SDValue Op, case ISD::OR: return lowerOR(Op, DAG); case ISD::ATOMIC_SWAP: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_SWAPW); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_SWAPW); + case ISD::ATOMIC_STORE: + return lowerATOMIC_STORE(Op, DAG); + case ISD::ATOMIC_LOAD: + return lowerATOMIC_LOAD(Op, DAG); case ISD::ATOMIC_LOAD_ADD: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_ADD); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_ADD); case ISD::ATOMIC_LOAD_SUB: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_SUB); + return lowerATOMIC_LOAD_SUB(Op, DAG); case ISD::ATOMIC_LOAD_AND: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_AND); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_AND); case ISD::ATOMIC_LOAD_OR: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_OR); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_OR); case ISD::ATOMIC_LOAD_XOR: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_XOR); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_XOR); case ISD::ATOMIC_LOAD_NAND: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_NAND); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_NAND); case ISD::ATOMIC_LOAD_MIN: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_MIN); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_MIN); case ISD::ATOMIC_LOAD_MAX: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_MAX); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_MAX); case ISD::ATOMIC_LOAD_UMIN: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_UMIN); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_UMIN); case ISD::ATOMIC_LOAD_UMAX: - return lowerATOMIC_LOAD(Op, DAG, SystemZISD::ATOMIC_LOADW_UMAX); + return lowerATOMIC_LOAD_OP(Op, DAG, SystemZISD::ATOMIC_LOADW_UMAX); case ISD::ATOMIC_CMP_SWAP: return lowerATOMIC_CMP_SWAP(Op, DAG); case ISD::STACKSAVE: @@ -2185,6 +2476,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(SIBCALL); OPCODE(PCREL_WRAPPER); OPCODE(PCREL_OFFSET); + OPCODE(IABS); OPCODE(ICMP); OPCODE(FCMP); OPCODE(TM); @@ -2210,6 +2502,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { OPCODE(STPCPY); OPCODE(SEARCH_STRING); OPCODE(IPM); + OPCODE(SERIALIZE); OPCODE(ATOMIC_SWAPW); OPCODE(ATOMIC_LOADW_ADD); OPCODE(ATOMIC_LOADW_SUB); @@ -2228,6 +2521,39 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { #undef OPCODE } +SDValue SystemZTargetLowering::PerformDAGCombine(SDNode *N, + DAGCombinerInfo &DCI) const { + SelectionDAG &DAG = DCI.DAG; + unsigned Opcode = N->getOpcode(); + if (Opcode == ISD::SIGN_EXTEND) { + // Convert (sext (ashr (shl X, C1), C2)) to + // (ashr (shl (anyext X), C1'), C2')), since wider shifts are as + // cheap as narrower ones. + SDValue N0 = N->getOperand(0); + EVT VT = N->getValueType(0); + if (N0.hasOneUse() && N0.getOpcode() == ISD::SRA) { + auto *SraAmt = dyn_cast<ConstantSDNode>(N0.getOperand(1)); + SDValue Inner = N0.getOperand(0); + if (SraAmt && Inner.hasOneUse() && Inner.getOpcode() == ISD::SHL) { + if (auto *ShlAmt = dyn_cast<ConstantSDNode>(Inner.getOperand(1))) { + unsigned Extra = (VT.getSizeInBits() - + N0.getValueType().getSizeInBits()); + unsigned NewShlAmt = ShlAmt->getZExtValue() + Extra; + unsigned NewSraAmt = SraAmt->getZExtValue() + Extra; + EVT ShiftVT = N0.getOperand(1).getValueType(); + SDValue Ext = DAG.getNode(ISD::ANY_EXTEND, SDLoc(Inner), VT, + Inner.getOperand(0)); + SDValue Shl = DAG.getNode(ISD::SHL, SDLoc(Inner), VT, Ext, + DAG.getConstant(NewShlAmt, ShiftVT)); + return DAG.getNode(ISD::SRA, SDLoc(N0), VT, Shl, + DAG.getConstant(NewSraAmt, ShiftVT)); + } + } + } + } + return SDValue(); +} + //===----------------------------------------------------------------------===// // Custom insertion //===----------------------------------------------------------------------===// @@ -2236,7 +2562,7 @@ const char *SystemZTargetLowering::getTargetNodeName(unsigned Opcode) const { static MachineBasicBlock *emitBlockAfter(MachineBasicBlock *MBB) { MachineFunction &MF = *MBB->getParent(); MachineBasicBlock *NewMBB = MF.CreateMachineBasicBlock(MBB->getBasicBlock()); - MF.insert(llvm::next(MachineFunction::iterator(MBB)), NewMBB); + MF.insert(std::next(MachineFunction::iterator(MBB)), NewMBB); return NewMBB; } @@ -2246,8 +2572,7 @@ static MachineBasicBlock *splitBlockAfter(MachineInstr *MI, MachineBasicBlock *MBB) { MachineBasicBlock *NewMBB = emitBlockAfter(MBB); NewMBB->splice(NewMBB->begin(), MBB, - llvm::next(MachineBasicBlock::iterator(MI)), - MBB->end()); + std::next(MachineBasicBlock::iterator(MI)), MBB->end()); NewMBB->transferSuccessorsAndUpdatePHIs(MBB); return NewMBB; } diff --git a/lib/Target/SystemZ/SystemZISelLowering.h b/lib/Target/SystemZ/SystemZISelLowering.h index c6dcca6..bceb25e 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.h +++ b/lib/Target/SystemZ/SystemZISelLowering.h @@ -22,170 +22,176 @@ namespace llvm { namespace SystemZISD { - enum { - FIRST_NUMBER = ISD::BUILTIN_OP_END, - - // Return with a flag operand. Operand 0 is the chain operand. - RET_FLAG, - - // Calls a function. Operand 0 is the chain operand and operand 1 - // is the target address. The arguments start at operand 2. - // There is an optional glue operand at the end. - CALL, - SIBCALL, - - // Wraps a TargetGlobalAddress that should be loaded using PC-relative - // accesses (LARL). Operand 0 is the address. - PCREL_WRAPPER, - - // Used in cases where an offset is applied to a TargetGlobalAddress. - // Operand 0 is the full TargetGlobalAddress and operand 1 is a - // PCREL_WRAPPER for an anchor point. This is used so that we can - // cheaply refer to either the full address or the anchor point - // as a register base. - PCREL_OFFSET, - - // Integer comparisons. There are three operands: the two values - // to compare, and an integer of type SystemZICMP. - ICMP, - - // Floating-point comparisons. The two operands are the values to compare. - FCMP, - - // Test under mask. The first operand is ANDed with the second operand - // and the condition codes are set on the result. The third operand is - // a boolean that is true if the condition codes need to distinguish - // between CCMASK_TM_MIXED_MSB_0 and CCMASK_TM_MIXED_MSB_1 (which the - // register forms do but the memory forms don't). - TM, - - // Branches if a condition is true. Operand 0 is the chain operand; - // operand 1 is the 4-bit condition-code mask, with bit N in - // big-endian order meaning "branch if CC=N"; operand 2 is the - // target block and operand 3 is the flag operand. - BR_CCMASK, - - // Selects between operand 0 and operand 1. Operand 2 is the - // mask of condition-code values for which operand 0 should be - // chosen over operand 1; it has the same form as BR_CCMASK. - // Operand 3 is the flag operand. - SELECT_CCMASK, - - // Evaluates to the gap between the stack pointer and the - // base of the dynamically-allocatable area. - ADJDYNALLOC, - - // Extracts the value of a 32-bit access register. Operand 0 is - // the number of the register. - EXTRACT_ACCESS, - - // Wrappers around the ISD opcodes of the same name. The output and - // first input operands are GR128s. The trailing numbers are the - // widths of the second operand in bits. - UMUL_LOHI64, - SDIVREM32, - SDIVREM64, - UDIVREM32, - UDIVREM64, - - // Use a series of MVCs to copy bytes from one memory location to another. - // The operands are: - // - the target address - // - the source address - // - the constant length - // - // This isn't a memory opcode because we'd need to attach two - // MachineMemOperands rather than one. - MVC, - - // Like MVC, but implemented as a loop that handles X*256 bytes - // followed by straight-line code to handle the rest (if any). - // The value of X is passed as an additional operand. - MVC_LOOP, - - // Similar to MVC and MVC_LOOP, but for logic operations (AND, OR, XOR). - NC, - NC_LOOP, - OC, - OC_LOOP, - XC, - XC_LOOP, - - // Use CLC to compare two blocks of memory, with the same comments - // as for MVC and MVC_LOOP. - CLC, - CLC_LOOP, - - // Use an MVST-based sequence to implement stpcpy(). - STPCPY, - - // Use a CLST-based sequence to implement strcmp(). The two input operands - // are the addresses of the strings to compare. - STRCMP, - - // Use an SRST-based sequence to search a block of memory. The first - // operand is the end address, the second is the start, and the third - // is the character to search for. CC is set to 1 on success and 2 - // on failure. - SEARCH_STRING, - - // Store the CC value in bits 29 and 28 of an integer. - IPM, - - // Wrappers around the inner loop of an 8- or 16-bit ATOMIC_SWAP or - // ATOMIC_LOAD_<op>. - // - // Operand 0: the address of the containing 32-bit-aligned field - // Operand 1: the second operand of <op>, in the high bits of an i32 - // for everything except ATOMIC_SWAPW - // Operand 2: how many bits to rotate the i32 left to bring the first - // operand into the high bits - // Operand 3: the negative of operand 2, for rotating the other way - // Operand 4: the width of the field in bits (8 or 16) - ATOMIC_SWAPW = ISD::FIRST_TARGET_MEMORY_OPCODE, - ATOMIC_LOADW_ADD, - ATOMIC_LOADW_SUB, - ATOMIC_LOADW_AND, - ATOMIC_LOADW_OR, - ATOMIC_LOADW_XOR, - ATOMIC_LOADW_NAND, - ATOMIC_LOADW_MIN, - ATOMIC_LOADW_MAX, - ATOMIC_LOADW_UMIN, - ATOMIC_LOADW_UMAX, - - // A wrapper around the inner loop of an ATOMIC_CMP_SWAP. - // - // Operand 0: the address of the containing 32-bit-aligned field - // Operand 1: the compare value, in the low bits of an i32 - // Operand 2: the swap value, in the low bits of an i32 - // Operand 3: how many bits to rotate the i32 left to bring the first - // operand into the high bits - // Operand 4: the negative of operand 2, for rotating the other way - // Operand 5: the width of the field in bits (8 or 16) - ATOMIC_CMP_SWAPW, - - // Prefetch from the second operand using the 4-bit control code in - // the first operand. The code is 1 for a load prefetch and 2 for - // a store prefetch. - PREFETCH - }; - - // Return true if OPCODE is some kind of PC-relative address. - inline bool isPCREL(unsigned Opcode) { - return Opcode == PCREL_WRAPPER || Opcode == PCREL_OFFSET; - } +enum { + FIRST_NUMBER = ISD::BUILTIN_OP_END, + + // Return with a flag operand. Operand 0 is the chain operand. + RET_FLAG, + + // Calls a function. Operand 0 is the chain operand and operand 1 + // is the target address. The arguments start at operand 2. + // There is an optional glue operand at the end. + CALL, + SIBCALL, + + // Wraps a TargetGlobalAddress that should be loaded using PC-relative + // accesses (LARL). Operand 0 is the address. + PCREL_WRAPPER, + + // Used in cases where an offset is applied to a TargetGlobalAddress. + // Operand 0 is the full TargetGlobalAddress and operand 1 is a + // PCREL_WRAPPER for an anchor point. This is used so that we can + // cheaply refer to either the full address or the anchor point + // as a register base. + PCREL_OFFSET, + + // Integer absolute. + IABS, + + // Integer comparisons. There are three operands: the two values + // to compare, and an integer of type SystemZICMP. + ICMP, + + // Floating-point comparisons. The two operands are the values to compare. + FCMP, + + // Test under mask. The first operand is ANDed with the second operand + // and the condition codes are set on the result. The third operand is + // a boolean that is true if the condition codes need to distinguish + // between CCMASK_TM_MIXED_MSB_0 and CCMASK_TM_MIXED_MSB_1 (which the + // register forms do but the memory forms don't). + TM, + + // Branches if a condition is true. Operand 0 is the chain operand; + // operand 1 is the 4-bit condition-code mask, with bit N in + // big-endian order meaning "branch if CC=N"; operand 2 is the + // target block and operand 3 is the flag operand. + BR_CCMASK, + + // Selects between operand 0 and operand 1. Operand 2 is the + // mask of condition-code values for which operand 0 should be + // chosen over operand 1; it has the same form as BR_CCMASK. + // Operand 3 is the flag operand. + SELECT_CCMASK, + + // Evaluates to the gap between the stack pointer and the + // base of the dynamically-allocatable area. + ADJDYNALLOC, + + // Extracts the value of a 32-bit access register. Operand 0 is + // the number of the register. + EXTRACT_ACCESS, + + // Wrappers around the ISD opcodes of the same name. The output and + // first input operands are GR128s. The trailing numbers are the + // widths of the second operand in bits. + UMUL_LOHI64, + SDIVREM32, + SDIVREM64, + UDIVREM32, + UDIVREM64, + + // Use a series of MVCs to copy bytes from one memory location to another. + // The operands are: + // - the target address + // - the source address + // - the constant length + // + // This isn't a memory opcode because we'd need to attach two + // MachineMemOperands rather than one. + MVC, + + // Like MVC, but implemented as a loop that handles X*256 bytes + // followed by straight-line code to handle the rest (if any). + // The value of X is passed as an additional operand. + MVC_LOOP, + + // Similar to MVC and MVC_LOOP, but for logic operations (AND, OR, XOR). + NC, + NC_LOOP, + OC, + OC_LOOP, + XC, + XC_LOOP, + + // Use CLC to compare two blocks of memory, with the same comments + // as for MVC and MVC_LOOP. + CLC, + CLC_LOOP, + + // Use an MVST-based sequence to implement stpcpy(). + STPCPY, + + // Use a CLST-based sequence to implement strcmp(). The two input operands + // are the addresses of the strings to compare. + STRCMP, + + // Use an SRST-based sequence to search a block of memory. The first + // operand is the end address, the second is the start, and the third + // is the character to search for. CC is set to 1 on success and 2 + // on failure. + SEARCH_STRING, + + // Store the CC value in bits 29 and 28 of an integer. + IPM, + + // Perform a serialization operation. (BCR 15,0 or BCR 14,0.) + SERIALIZE, + + // Wrappers around the inner loop of an 8- or 16-bit ATOMIC_SWAP or + // ATOMIC_LOAD_<op>. + // + // Operand 0: the address of the containing 32-bit-aligned field + // Operand 1: the second operand of <op>, in the high bits of an i32 + // for everything except ATOMIC_SWAPW + // Operand 2: how many bits to rotate the i32 left to bring the first + // operand into the high bits + // Operand 3: the negative of operand 2, for rotating the other way + // Operand 4: the width of the field in bits (8 or 16) + ATOMIC_SWAPW = ISD::FIRST_TARGET_MEMORY_OPCODE, + ATOMIC_LOADW_ADD, + ATOMIC_LOADW_SUB, + ATOMIC_LOADW_AND, + ATOMIC_LOADW_OR, + ATOMIC_LOADW_XOR, + ATOMIC_LOADW_NAND, + ATOMIC_LOADW_MIN, + ATOMIC_LOADW_MAX, + ATOMIC_LOADW_UMIN, + ATOMIC_LOADW_UMAX, + + // A wrapper around the inner loop of an ATOMIC_CMP_SWAP. + // + // Operand 0: the address of the containing 32-bit-aligned field + // Operand 1: the compare value, in the low bits of an i32 + // Operand 2: the swap value, in the low bits of an i32 + // Operand 3: how many bits to rotate the i32 left to bring the first + // operand into the high bits + // Operand 4: the negative of operand 2, for rotating the other way + // Operand 5: the width of the field in bits (8 or 16) + ATOMIC_CMP_SWAPW, + + // Prefetch from the second operand using the 4-bit control code in + // the first operand. The code is 1 for a load prefetch and 2 for + // a store prefetch. + PREFETCH +}; + +// Return true if OPCODE is some kind of PC-relative address. +inline bool isPCREL(unsigned Opcode) { + return Opcode == PCREL_WRAPPER || Opcode == PCREL_OFFSET; } +} // end namespace SystemZISD namespace SystemZICMP { - // Describes whether an integer comparison needs to be signed or unsigned, - // or whether either type is OK. - enum { - Any, - UnsignedOnly, - SignedOnly - }; -} +// Describes whether an integer comparison needs to be signed or unsigned, +// or whether either type is OK. +enum { + Any, + UnsignedOnly, + SignedOnly +}; +} // end namespace SystemZICMP class SystemZSubtarget; class SystemZTargetMachine; @@ -195,55 +201,51 @@ public: explicit SystemZTargetLowering(SystemZTargetMachine &TM); // Override TargetLowering. - virtual MVT getScalarShiftAmountTy(EVT LHSTy) const LLVM_OVERRIDE { + MVT getScalarShiftAmountTy(EVT LHSTy) const override { return MVT::i32; } - virtual EVT getSetCCResultType(LLVMContext &, EVT) const LLVM_OVERRIDE; - virtual bool isFMAFasterThanFMulAndFAdd(EVT VT) const LLVM_OVERRIDE; - virtual bool isFPImmLegal(const APFloat &Imm, EVT VT) const LLVM_OVERRIDE; - virtual bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const - LLVM_OVERRIDE; - virtual bool allowsUnalignedMemoryAccesses(EVT VT, bool *Fast) const - LLVM_OVERRIDE; - virtual bool isTruncateFree(Type *, Type *) const LLVM_OVERRIDE; - virtual bool isTruncateFree(EVT, EVT) const LLVM_OVERRIDE; - virtual const char *getTargetNodeName(unsigned Opcode) const LLVM_OVERRIDE; - virtual std::pair<unsigned, const TargetRegisterClass *> + EVT getSetCCResultType(LLVMContext &, EVT) const override; + bool isFMAFasterThanFMulAndFAdd(EVT VT) const override; + bool isFPImmLegal(const APFloat &Imm, EVT VT) const override; + bool isLegalAddressingMode(const AddrMode &AM, Type *Ty) const override; + bool allowsUnalignedMemoryAccesses(EVT VT, unsigned AS, + bool *Fast) const override; + bool isTruncateFree(Type *, Type *) const override; + bool isTruncateFree(EVT, EVT) const override; + const char *getTargetNodeName(unsigned Opcode) const override; + std::pair<unsigned, const TargetRegisterClass *> getRegForInlineAsmConstraint(const std::string &Constraint, - MVT VT) const LLVM_OVERRIDE; - virtual TargetLowering::ConstraintType - getConstraintType(const std::string &Constraint) const LLVM_OVERRIDE; - virtual TargetLowering::ConstraintWeight + MVT VT) const override; + TargetLowering::ConstraintType + getConstraintType(const std::string &Constraint) const override; + TargetLowering::ConstraintWeight getSingleConstraintMatchWeight(AsmOperandInfo &info, - const char *constraint) const LLVM_OVERRIDE; - virtual void - LowerAsmOperandForConstraint(SDValue Op, - std::string &Constraint, - std::vector<SDValue> &Ops, - SelectionDAG &DAG) const LLVM_OVERRIDE; - virtual MachineBasicBlock * - EmitInstrWithCustomInserter(MachineInstr *MI, - MachineBasicBlock *BB) const LLVM_OVERRIDE; - virtual SDValue LowerOperation(SDValue Op, - SelectionDAG &DAG) const LLVM_OVERRIDE; - virtual bool allowTruncateForTailCall(Type *, Type *) const LLVM_OVERRIDE; - virtual bool mayBeEmittedAsTailCall(CallInst *CI) const LLVM_OVERRIDE; - virtual SDValue - LowerFormalArguments(SDValue Chain, - CallingConv::ID CallConv, bool isVarArg, - const SmallVectorImpl<ISD::InputArg> &Ins, - SDLoc DL, SelectionDAG &DAG, - SmallVectorImpl<SDValue> &InVals) const LLVM_OVERRIDE; - virtual SDValue - LowerCall(CallLoweringInfo &CLI, - SmallVectorImpl<SDValue> &InVals) const LLVM_OVERRIDE; - - virtual SDValue - LowerReturn(SDValue Chain, - CallingConv::ID CallConv, bool IsVarArg, - const SmallVectorImpl<ISD::OutputArg> &Outs, - const SmallVectorImpl<SDValue> &OutVals, - SDLoc DL, SelectionDAG &DAG) const LLVM_OVERRIDE; + const char *constraint) const override; + void LowerAsmOperandForConstraint(SDValue Op, + std::string &Constraint, + std::vector<SDValue> &Ops, + SelectionDAG &DAG) const override; + MachineBasicBlock *EmitInstrWithCustomInserter(MachineInstr *MI, + MachineBasicBlock *BB) const + override; + SDValue LowerOperation(SDValue Op, SelectionDAG &DAG) const override; + bool allowTruncateForTailCall(Type *, Type *) const override; + bool mayBeEmittedAsTailCall(CallInst *CI) const override; + SDValue LowerFormalArguments(SDValue Chain, CallingConv::ID CallConv, + bool isVarArg, + const SmallVectorImpl<ISD::InputArg> &Ins, + SDLoc DL, SelectionDAG &DAG, + SmallVectorImpl<SDValue> &InVals) const override; + SDValue LowerCall(CallLoweringInfo &CLI, + SmallVectorImpl<SDValue> &InVals) const override; + + SDValue LowerReturn(SDValue Chain, CallingConv::ID CallConv, bool IsVarArg, + const SmallVectorImpl<ISD::OutputArg> &Outs, + const SmallVectorImpl<SDValue> &OutVals, + SDLoc DL, SelectionDAG &DAG) const override; + SDValue prepareVolatileOrAtomicLoad(SDValue Chain, SDLoc DL, + SelectionDAG &DAG) const override; + SDValue PerformDAGCombine(SDNode *N, DAGCombinerInfo &DCI) const override; private: const SystemZSubtarget &Subtarget; @@ -270,9 +272,13 @@ private: SDValue lowerUDIVREM(SDValue Op, SelectionDAG &DAG) const; SDValue lowerBITCAST(SDValue Op, SelectionDAG &DAG) const; SDValue lowerOR(SDValue Op, SelectionDAG &DAG) const; - SDValue lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG, - unsigned Opcode) const; + SDValue lowerATOMIC_LOAD(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerATOMIC_STORE(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerATOMIC_LOAD_OP(SDValue Op, SelectionDAG &DAG, + unsigned Opcode) const; + SDValue lowerATOMIC_LOAD_SUB(SDValue Op, SelectionDAG &DAG) const; SDValue lowerATOMIC_CMP_SWAP(SDValue Op, SelectionDAG &DAG) const; + SDValue lowerLOAD_SEQUENCE_POINT(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSTACKSAVE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerSTACKRESTORE(SDValue Op, SelectionDAG &DAG) const; SDValue lowerPREFETCH(SDValue Op, SelectionDAG &DAG) const; diff --git a/lib/Target/SystemZ/SystemZInstrBuilder.h b/lib/Target/SystemZ/SystemZInstrBuilder.h index fb699b9..84196e9 100644 --- a/lib/Target/SystemZ/SystemZInstrBuilder.h +++ b/lib/Target/SystemZ/SystemZInstrBuilder.h @@ -43,6 +43,6 @@ addFrameReference(const MachineInstrBuilder &MIB, int FI) { return MIB.addFrameIndex(FI).addImm(Offset).addReg(0).addMemOperand(MMO); } -} // End llvm namespace +} // end namespace llvm #endif diff --git a/lib/Target/SystemZ/SystemZInstrFP.td b/lib/Target/SystemZ/SystemZInstrFP.td index 6080046..a1e782c 100644 --- a/lib/Target/SystemZ/SystemZInstrFP.td +++ b/lib/Target/SystemZ/SystemZInstrFP.td @@ -46,9 +46,9 @@ let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0xF in { defm LTDBR : LoadAndTestRRE<"ltdb", 0xB312, FP64>; defm LTXBR : LoadAndTestRRE<"ltxb", 0xB342, FP128>; } -def : CompareZeroFP<LTEBRCompare, FP32>; -def : CompareZeroFP<LTDBRCompare, FP64>; -def : CompareZeroFP<LTXBRCompare, FP128>; +defm : CompareZeroFP<LTEBRCompare, FP32>; +defm : CompareZeroFP<LTDBRCompare, FP64>; +defm : CompareZeroFP<LTXBRCompare, FP128>; // Moves between 64-bit integer and floating-point registers. def LGDR : UnaryRRE<"lgd", 0xB3CD, bitconvert, GR64, FP64>; @@ -157,6 +157,25 @@ def CEGBR : UnaryRRE<"cegb", 0xB3A4, sint_to_fp, FP32, GR64>; def CDGBR : UnaryRRE<"cdgb", 0xB3A5, sint_to_fp, FP64, GR64>; def CXGBR : UnaryRRE<"cxgb", 0xB3A6, sint_to_fp, FP128, GR64>; +// Convert am unsigned integer register value to a floating-point one. +let Predicates = [FeatureFPExtension] in { + def CELFBR : UnaryRRF4<"celfbr", 0xB390, FP32, GR32>; + def CDLFBR : UnaryRRF4<"cdlfbr", 0xB391, FP64, GR32>; + def CXLFBR : UnaryRRF4<"cxlfbr", 0xB392, FP128, GR32>; + + def CELGBR : UnaryRRF4<"celgbr", 0xB3A0, FP32, GR64>; + def CDLGBR : UnaryRRF4<"cdlgbr", 0xB3A1, FP64, GR64>; + def CXLGBR : UnaryRRF4<"cxlgbr", 0xB3A2, FP128, GR64>; + + def : Pat<(f32 (uint_to_fp GR32:$src)), (CELFBR 0, GR32:$src, 0)>; + def : Pat<(f64 (uint_to_fp GR32:$src)), (CDLFBR 0, GR32:$src, 0)>; + def : Pat<(f128 (uint_to_fp GR32:$src)), (CXLFBR 0, GR32:$src, 0)>; + + def : Pat<(f32 (uint_to_fp GR64:$src)), (CELGBR 0, GR64:$src, 0)>; + def : Pat<(f64 (uint_to_fp GR64:$src)), (CDLGBR 0, GR64:$src, 0)>; + def : Pat<(f128 (uint_to_fp GR64:$src)), (CXLGBR 0, GR64:$src, 0)>; +} + // Convert a floating-point register value to a signed integer value, // with the second operand (modifier M3) specifying the rounding mode. let Defs = [CC] in { @@ -178,6 +197,28 @@ def : Pat<(i64 (fp_to_sint FP32:$src)), (CGEBR 5, FP32:$src)>; def : Pat<(i64 (fp_to_sint FP64:$src)), (CGDBR 5, FP64:$src)>; def : Pat<(i64 (fp_to_sint FP128:$src)), (CGXBR 5, FP128:$src)>; +// Convert a floating-point register value to an unsigned integer value. +let Predicates = [FeatureFPExtension] in { + let Defs = [CC] in { + def CLFEBR : UnaryRRF4<"clfebr", 0xB39C, GR32, FP32>; + def CLFDBR : UnaryRRF4<"clfdbr", 0xB39D, GR32, FP64>; + def CLFXBR : UnaryRRF4<"clfxbr", 0xB39E, GR32, FP128>; + + def CLGEBR : UnaryRRF4<"clgebr", 0xB3AC, GR64, FP32>; + def CLGDBR : UnaryRRF4<"clgdbr", 0xB3AD, GR64, FP64>; + def CLGXBR : UnaryRRF4<"clgxbr", 0xB3AE, GR64, FP128>; + } + + def : Pat<(i32 (fp_to_uint FP32:$src)), (CLFEBR 5, FP32:$src, 0)>; + def : Pat<(i32 (fp_to_uint FP64:$src)), (CLFDBR 5, FP64:$src, 0)>; + def : Pat<(i32 (fp_to_uint FP128:$src)), (CLFXBR 5, FP128:$src, 0)>; + + def : Pat<(i64 (fp_to_uint FP32:$src)), (CLGEBR 5, FP32:$src, 0)>; + def : Pat<(i64 (fp_to_uint FP64:$src)), (CLGDBR 5, FP64:$src, 0)>; + def : Pat<(i64 (fp_to_uint FP128:$src)), (CLGXBR 5, FP128:$src, 0)>; +} + + //===----------------------------------------------------------------------===// // Unary arithmetic //===----------------------------------------------------------------------===// @@ -217,15 +258,6 @@ def FIEBR : UnaryRRF<"fieb", 0xB357, FP32, FP32>; def FIDBR : UnaryRRF<"fidb", 0xB35F, FP64, FP64>; def FIXBR : UnaryRRF<"fixb", 0xB347, FP128, FP128>; -// Extended forms of the previous three instructions. M4 can be set to 4 -// to suppress detection of inexact conditions. -def FIEBRA : UnaryRRF4<"fiebra", 0xB357, FP32, FP32>, - Requires<[FeatureFPExtension]>; -def FIDBRA : UnaryRRF4<"fidbra", 0xB35F, FP64, FP64>, - Requires<[FeatureFPExtension]>; -def FIXBRA : UnaryRRF4<"fixbra", 0xB347, FP128, FP128>, - Requires<[FeatureFPExtension]>; - // frint rounds according to the current mode (modifier 0) and detects // inexact conditions. def : Pat<(frint FP32:$src), (FIEBR 0, FP32:$src)>; @@ -233,6 +265,12 @@ def : Pat<(frint FP64:$src), (FIDBR 0, FP64:$src)>; def : Pat<(frint FP128:$src), (FIXBR 0, FP128:$src)>; let Predicates = [FeatureFPExtension] in { + // Extended forms of the FIxBR instructions. M4 can be set to 4 + // to suppress detection of inexact conditions. + def FIEBRA : UnaryRRF4<"fiebra", 0xB357, FP32, FP32>; + def FIDBRA : UnaryRRF4<"fidbra", 0xB35F, FP64, FP64>; + def FIXBRA : UnaryRRF4<"fixbra", 0xB347, FP128, FP128>; + // fnearbyint is like frint but does not detect inexact conditions. def : Pat<(fnearbyint FP32:$src), (FIEBRA 0, FP32:$src, 4)>; def : Pat<(fnearbyint FP64:$src), (FIDBRA 0, FP64:$src, 4)>; diff --git a/lib/Target/SystemZ/SystemZInstrFormats.td b/lib/Target/SystemZ/SystemZInstrFormats.td index a8efe16..50badf8 100644 --- a/lib/Target/SystemZ/SystemZInstrFormats.td +++ b/lib/Target/SystemZ/SystemZInstrFormats.td @@ -531,6 +531,10 @@ class InstSS<bits<8> op, dag outs, dag ins, string asmstr, list<dag> pattern> // Ternary: // One register output operand and three register input operands. // +// LoadAndOp: +// One output operand and two input operands. The first input operand +// is a register and the second is an address. +// // CmpSwap: // One output operand and three input operands. The first two // operands are registers and the third is an address. The instruction @@ -1267,6 +1271,15 @@ class TernaryRXF<string mnemonic, bits<16> opcode, SDPatternOperator operator, let AccessBytes = bytes; } +class LoadAndOpRSY<string mnemonic, bits<16> opcode, SDPatternOperator operator, + RegisterOperand cls, AddressingMode mode = bdaddr20only> + : InstRSY<opcode, (outs cls:$R1), (ins cls:$R3, mode:$BD2), + mnemonic#"\t$R1, $R3, $BD2", + [(set cls:$R1, (operator mode:$BD2, cls:$R3))]> { + let mayLoad = 1; + let mayStore = 1; +} + class CmpSwapRS<string mnemonic, bits<8> opcode, SDPatternOperator operator, RegisterOperand cls, AddressingMode mode = bdaddr12only> : InstRS<opcode, (outs cls:$R1), (ins cls:$R1src, cls:$R3, mode:$BD2), diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index acfeed8..e20834c 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -12,8 +12,8 @@ //===----------------------------------------------------------------------===// #include "SystemZInstrInfo.h" -#include "SystemZTargetMachine.h" #include "SystemZInstrBuilder.h" +#include "SystemZTargetMachine.h" #include "llvm/CodeGen/LiveVariables.h" #include "llvm/CodeGen/MachineRegisterInfo.h" @@ -53,7 +53,7 @@ void SystemZInstrInfo::splitMove(MachineBasicBlock::iterator MI, MachineFunction &MF = *MBB->getParent(); // Get two load or store instructions. Use the original instruction for one - // of them (arbitarily the second here) and create a clone for the other. + // of them (arbitrarily the second here) and create a clone for the other. MachineInstr *EarlierMI = MF.CloneMachineInstr(MI); MBB->insert(MI, EarlierMI); @@ -280,8 +280,8 @@ bool SystemZInstrInfo::AnalyzeBranch(MachineBasicBlock &MBB, } // If the block has any instructions after a JMP, delete them. - while (llvm::next(I) != MBB.end()) - llvm::next(I)->eraseFromParent(); + while (std::next(I) != MBB.end()) + std::next(I)->eraseFromParent(); Cond.clear(); FBB = 0; @@ -628,16 +628,16 @@ static bool isSimpleBD12Move(const MachineInstr *MI, unsigned Flag) { } namespace { - struct LogicOp { - LogicOp() : RegSize(0), ImmLSB(0), ImmSize(0) {} - LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize) - : RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {} +struct LogicOp { + LogicOp() : RegSize(0), ImmLSB(0), ImmSize(0) {} + LogicOp(unsigned regSize, unsigned immLSB, unsigned immSize) + : RegSize(regSize), ImmLSB(immLSB), ImmSize(immSize) {} - operator bool() const { return RegSize; } + operator bool() const { return RegSize; } - unsigned RegSize, ImmLSB, ImmSize; - }; -} + unsigned RegSize, ImmLSB, ImmSize; +}; +} // end anonymous namespace static LogicOp interpretAndImmediate(unsigned Opcode) { switch (Opcode) { diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index be4c8fe..55f80af 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -26,89 +26,89 @@ namespace llvm { class SystemZTargetMachine; namespace SystemZII { - enum { - // See comments in SystemZInstrFormats.td. - SimpleBDXLoad = (1 << 0), - SimpleBDXStore = (1 << 1), - Has20BitOffset = (1 << 2), - HasIndex = (1 << 3), - Is128Bit = (1 << 4), - AccessSizeMask = (31 << 5), - AccessSizeShift = 5, - CCValuesMask = (15 << 10), - CCValuesShift = 10, - CompareZeroCCMaskMask = (15 << 14), - CompareZeroCCMaskShift = 14, - CCMaskFirst = (1 << 18), - CCMaskLast = (1 << 19), - IsLogical = (1 << 20) - }; - static inline unsigned getAccessSize(unsigned int Flags) { - return (Flags & AccessSizeMask) >> AccessSizeShift; - } - static inline unsigned getCCValues(unsigned int Flags) { - return (Flags & CCValuesMask) >> CCValuesShift; - } - static inline unsigned getCompareZeroCCMask(unsigned int Flags) { - return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift; - } - - // SystemZ MachineOperand target flags. - enum { - // Masks out the bits for the access model. - MO_SYMBOL_MODIFIER = (1 << 0), - - // @GOT (aka @GOTENT) - MO_GOT = (1 << 0) - }; - // Classifies a branch. - enum BranchType { - // An instruction that branches on the current value of CC. - BranchNormal, - - // An instruction that peforms a 32-bit signed comparison and branches - // on the result. - BranchC, - - // An instruction that peforms a 32-bit unsigned comparison and branches - // on the result. - BranchCL, - - // An instruction that peforms a 64-bit signed comparison and branches - // on the result. - BranchCG, - - // An instruction that peforms a 64-bit unsigned comparison and branches - // on the result. - BranchCLG, +enum { + // See comments in SystemZInstrFormats.td. + SimpleBDXLoad = (1 << 0), + SimpleBDXStore = (1 << 1), + Has20BitOffset = (1 << 2), + HasIndex = (1 << 3), + Is128Bit = (1 << 4), + AccessSizeMask = (31 << 5), + AccessSizeShift = 5, + CCValuesMask = (15 << 10), + CCValuesShift = 10, + CompareZeroCCMaskMask = (15 << 14), + CompareZeroCCMaskShift = 14, + CCMaskFirst = (1 << 18), + CCMaskLast = (1 << 19), + IsLogical = (1 << 20) +}; +static inline unsigned getAccessSize(unsigned int Flags) { + return (Flags & AccessSizeMask) >> AccessSizeShift; +} +static inline unsigned getCCValues(unsigned int Flags) { + return (Flags & CCValuesMask) >> CCValuesShift; +} +static inline unsigned getCompareZeroCCMask(unsigned int Flags) { + return (Flags & CompareZeroCCMaskMask) >> CompareZeroCCMaskShift; +} - // An instruction that decrements a 32-bit register and branches if - // the result is nonzero. - BranchCT, +// SystemZ MachineOperand target flags. +enum { + // Masks out the bits for the access model. + MO_SYMBOL_MODIFIER = (1 << 0), - // An instruction that decrements a 64-bit register and branches if - // the result is nonzero. - BranchCTG - }; - // Information about a branch instruction. - struct Branch { - // The type of the branch. - BranchType Type; + // @GOT (aka @GOTENT) + MO_GOT = (1 << 0) +}; +// Classifies a branch. +enum BranchType { + // An instruction that branches on the current value of CC. + BranchNormal, + + // An instruction that peforms a 32-bit signed comparison and branches + // on the result. + BranchC, + + // An instruction that peforms a 32-bit unsigned comparison and branches + // on the result. + BranchCL, + + // An instruction that peforms a 64-bit signed comparison and branches + // on the result. + BranchCG, + + // An instruction that peforms a 64-bit unsigned comparison and branches + // on the result. + BranchCLG, + + // An instruction that decrements a 32-bit register and branches if + // the result is nonzero. + BranchCT, + + // An instruction that decrements a 64-bit register and branches if + // the result is nonzero. + BranchCTG +}; +// Information about a branch instruction. +struct Branch { + // The type of the branch. + BranchType Type; - // CCMASK_<N> is set if CC might be equal to N. - unsigned CCValid; + // CCMASK_<N> is set if CC might be equal to N. + unsigned CCValid; - // CCMASK_<N> is set if the branch should be taken when CC == N. - unsigned CCMask; + // CCMASK_<N> is set if the branch should be taken when CC == N. + unsigned CCMask; - // The target of the branch. - const MachineOperand *Target; + // The target of the branch. + const MachineOperand *Target; - Branch(BranchType type, unsigned ccValid, unsigned ccMask, - const MachineOperand *target) - : Type(type), CCValid(ccValid), CCMask(ccMask), Target(target) {} - }; -} + Branch(BranchType type, unsigned ccValid, unsigned ccMask, + const MachineOperand *target) + : Type(type), CCValid(ccValid), CCMask(ccMask), Target(target) {} +}; +} // end namespace SystemZII class SystemZInstrInfo : public SystemZGenInstrInfo { const SystemZRegisterInfo RI; @@ -133,78 +133,63 @@ public: explicit SystemZInstrInfo(SystemZTargetMachine &TM); // Override TargetInstrInfo. - virtual unsigned isLoadFromStackSlot(const MachineInstr *MI, - int &FrameIndex) const LLVM_OVERRIDE; - virtual unsigned isStoreToStackSlot(const MachineInstr *MI, - int &FrameIndex) const LLVM_OVERRIDE; - virtual bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex, - int &SrcFrameIndex) const LLVM_OVERRIDE; - virtual bool AnalyzeBranch(MachineBasicBlock &MBB, - MachineBasicBlock *&TBB, - MachineBasicBlock *&FBB, - SmallVectorImpl<MachineOperand> &Cond, - bool AllowModify) const LLVM_OVERRIDE; - virtual unsigned RemoveBranch(MachineBasicBlock &MBB) const LLVM_OVERRIDE; - virtual unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, - MachineBasicBlock *FBB, - const SmallVectorImpl<MachineOperand> &Cond, - DebugLoc DL) const LLVM_OVERRIDE; + unsigned isLoadFromStackSlot(const MachineInstr *MI, + int &FrameIndex) const override; + unsigned isStoreToStackSlot(const MachineInstr *MI, + int &FrameIndex) const override; + bool isStackSlotCopy(const MachineInstr *MI, int &DestFrameIndex, + int &SrcFrameIndex) const override; + bool AnalyzeBranch(MachineBasicBlock &MBB, MachineBasicBlock *&TBB, + MachineBasicBlock *&FBB, + SmallVectorImpl<MachineOperand> &Cond, + bool AllowModify) const override; + unsigned RemoveBranch(MachineBasicBlock &MBB) const override; + unsigned InsertBranch(MachineBasicBlock &MBB, MachineBasicBlock *TBB, + MachineBasicBlock *FBB, + const SmallVectorImpl<MachineOperand> &Cond, + DebugLoc DL) const override; bool analyzeCompare(const MachineInstr *MI, unsigned &SrcReg, - unsigned &SrcReg2, int &Mask, int &Value) const - LLVM_OVERRIDE; + unsigned &SrcReg2, int &Mask, int &Value) const override; bool optimizeCompareInstr(MachineInstr *CmpInstr, unsigned SrcReg, unsigned SrcReg2, int Mask, int Value, - const MachineRegisterInfo *MRI) const LLVM_OVERRIDE; - virtual bool isPredicable(MachineInstr *MI) const LLVM_OVERRIDE; - virtual bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, - unsigned ExtraPredCycles, - const BranchProbability &Probability) const - LLVM_OVERRIDE; - virtual bool isProfitableToIfCvt(MachineBasicBlock &TMBB, - unsigned NumCyclesT, - unsigned ExtraPredCyclesT, - MachineBasicBlock &FMBB, - unsigned NumCyclesF, - unsigned ExtraPredCyclesF, - const BranchProbability &Probability) const - LLVM_OVERRIDE; - virtual bool - PredicateInstruction(MachineInstr *MI, - const SmallVectorImpl<MachineOperand> &Pred) const - LLVM_OVERRIDE; - virtual void copyPhysReg(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, DebugLoc DL, - unsigned DestReg, unsigned SrcReg, - bool KillSrc) const LLVM_OVERRIDE; - virtual void - storeRegToStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned SrcReg, bool isKill, int FrameIndex, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const LLVM_OVERRIDE; - virtual void - loadRegFromStackSlot(MachineBasicBlock &MBB, - MachineBasicBlock::iterator MBBI, - unsigned DestReg, int FrameIdx, - const TargetRegisterClass *RC, - const TargetRegisterInfo *TRI) const LLVM_OVERRIDE; - virtual MachineInstr * - convertToThreeAddress(MachineFunction::iterator &MFI, - MachineBasicBlock::iterator &MBBI, - LiveVariables *LV) const; - virtual MachineInstr * - foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, - const SmallVectorImpl<unsigned> &Ops, - int FrameIndex) const; - virtual MachineInstr * - foldMemoryOperandImpl(MachineFunction &MF, MachineInstr* MI, - const SmallVectorImpl<unsigned> &Ops, - MachineInstr* LoadMI) const; - virtual bool - expandPostRAPseudo(MachineBasicBlock::iterator MBBI) const LLVM_OVERRIDE; - virtual bool - ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const - LLVM_OVERRIDE; + const MachineRegisterInfo *MRI) const override; + bool isPredicable(MachineInstr *MI) const override; + bool isProfitableToIfCvt(MachineBasicBlock &MBB, unsigned NumCycles, + unsigned ExtraPredCycles, + const BranchProbability &Probability) const override; + bool isProfitableToIfCvt(MachineBasicBlock &TMBB, + unsigned NumCyclesT, unsigned ExtraPredCyclesT, + MachineBasicBlock &FMBB, + unsigned NumCyclesF, unsigned ExtraPredCyclesF, + const BranchProbability &Probability) const override; + bool PredicateInstruction(MachineInstr *MI, + const SmallVectorImpl<MachineOperand> &Pred) const + override; + void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator MBBI, + DebugLoc DL, unsigned DestReg, unsigned SrcReg, + bool KillSrc) const override; + void storeRegToStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned SrcReg, bool isKill, int FrameIndex, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; + void loadRegFromStackSlot(MachineBasicBlock &MBB, + MachineBasicBlock::iterator MBBI, + unsigned DestReg, int FrameIdx, + const TargetRegisterClass *RC, + const TargetRegisterInfo *TRI) const override; + MachineInstr *convertToThreeAddress(MachineFunction::iterator &MFI, + MachineBasicBlock::iterator &MBBI, + LiveVariables *LV) const override; + MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr *MI, + const SmallVectorImpl<unsigned> &Ops, + int FrameIndex) const override; + MachineInstr *foldMemoryOperandImpl(MachineFunction &MF, MachineInstr* MI, + const SmallVectorImpl<unsigned> &Ops, + MachineInstr* LoadMI) const override; + bool expandPostRAPseudo(MachineBasicBlock::iterator MBBI) const override; + bool ReverseBranchCondition(SmallVectorImpl<MachineOperand> &Cond) const + override; // Return the SystemZRegisterInfo, which this class owns. const SystemZRegisterInfo &getRegisterInfo() const { return RI; } diff --git a/lib/Target/SystemZ/SystemZInstrInfo.td b/lib/Target/SystemZ/SystemZInstrInfo.td index 6524e44..e70df92 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.td +++ b/lib/Target/SystemZ/SystemZInstrInfo.td @@ -595,22 +595,28 @@ let neverHasSideEffects = 1, isAsCheapAsAMove = 1, isMoveImm = 1, let Defs = [CC] in { let CCValues = 0xF, CompareZeroCCMask = 0x8 in { - def LPR : UnaryRR <"lp", 0x10, z_iabs32, GR32, GR32>; - def LPGR : UnaryRRE<"lpg", 0xB900, z_iabs64, GR64, GR64>; + def LPR : UnaryRR <"lp", 0x10, z_iabs, GR32, GR32>; + def LPGR : UnaryRRE<"lpg", 0xB900, z_iabs, GR64, GR64>; } let CCValues = 0xE, CompareZeroCCMask = 0xE in def LPGFR : UnaryRRE<"lpgf", 0xB910, null_frag, GR64, GR32>; } +def : Pat<(z_iabs32 GR32:$src), (LPR GR32:$src)>; +def : Pat<(z_iabs64 GR64:$src), (LPGR GR64:$src)>; +defm : SXU<z_iabs, LPGFR>; defm : SXU<z_iabs64, LPGFR>; let Defs = [CC] in { let CCValues = 0xF, CompareZeroCCMask = 0x8 in { - def LNR : UnaryRR <"ln", 0x11, z_inegabs32, GR32, GR32>; - def LNGR : UnaryRRE<"lng", 0xB901, z_inegabs64, GR64, GR64>; + def LNR : UnaryRR <"ln", 0x11, z_inegabs, GR32, GR32>; + def LNGR : UnaryRRE<"lng", 0xB901, z_inegabs, GR64, GR64>; } let CCValues = 0xE, CompareZeroCCMask = 0xE in def LNGFR : UnaryRRE<"lngf", 0xB911, null_frag, GR64, GR32>; } +def : Pat<(z_inegabs32 GR32:$src), (LNR GR32:$src)>; +def : Pat<(z_inegabs64 GR64:$src), (LNGR GR64:$src)>; +defm : SXU<z_inegabs, LNGFR>; defm : SXU<z_inegabs64, LNGFR>; let Defs = [CC] in { @@ -753,7 +759,7 @@ let Defs = [CC], Uses = [CC] in { // Subtraction //===----------------------------------------------------------------------===// -// Plain substraction. Although immediate forms exist, we use the +// Plain subtraction. Although immediate forms exist, we use the // add-immediate instruction instead. let Defs = [CC], CCValues = 0xF, CompareZeroCCMask = 0x8 in { // Subtraction of a register. @@ -1043,15 +1049,15 @@ let Defs = [CC] in { // Forms of RISBG that only affect one word of the destination register. // They do not set CC. -def RISBMux : RotateSelectRIEfPseudo<GRX32, GRX32>, Requires<[FeatureHighWord]>; -def RISBLL : RotateSelectAliasRIEf<GR32, GR32>, Requires<[FeatureHighWord]>; -def RISBLH : RotateSelectAliasRIEf<GR32, GRH32>, Requires<[FeatureHighWord]>; -def RISBHL : RotateSelectAliasRIEf<GRH32, GR32>, Requires<[FeatureHighWord]>; -def RISBHH : RotateSelectAliasRIEf<GRH32, GRH32>, Requires<[FeatureHighWord]>; -def RISBLG : RotateSelectRIEf<"risblg", 0xEC51, GR32, GR64>, - Requires<[FeatureHighWord]>; -def RISBHG : RotateSelectRIEf<"risbhg", 0xEC5D, GRH32, GR64>, - Requires<[FeatureHighWord]>; +let Predicates = [FeatureHighWord] in { + def RISBMux : RotateSelectRIEfPseudo<GRX32, GRX32>; + def RISBLL : RotateSelectAliasRIEf<GR32, GR32>; + def RISBLH : RotateSelectAliasRIEf<GR32, GRH32>; + def RISBHL : RotateSelectAliasRIEf<GRH32, GR32>; + def RISBHH : RotateSelectAliasRIEf<GRH32, GRH32>; + def RISBLG : RotateSelectRIEf<"risblg", 0xEC51, GR32, GR64>; + def RISBHG : RotateSelectRIEf<"risbhg", 0xEC5D, GRH32, GR64>; +} // Rotate second operand left and perform a logical operation with selected // bits of the first operand. The CC result only describes the selected bits, @@ -1195,58 +1201,89 @@ def PFDRL : PrefetchRILPC<"pfdrl", 0xC62, z_prefetch>; // Atomic operations //===----------------------------------------------------------------------===// -def ATOMIC_SWAPW : AtomicLoadWBinaryReg<z_atomic_swapw>; -def ATOMIC_SWAP_32 : AtomicLoadBinaryReg32<atomic_swap_32>; -def ATOMIC_SWAP_64 : AtomicLoadBinaryReg64<atomic_swap_64>; - -def ATOMIC_LOADW_AR : AtomicLoadWBinaryReg<z_atomic_loadw_add>; -def ATOMIC_LOADW_AFI : AtomicLoadWBinaryImm<z_atomic_loadw_add, simm32>; -def ATOMIC_LOAD_AR : AtomicLoadBinaryReg32<atomic_load_add_32>; -def ATOMIC_LOAD_AHI : AtomicLoadBinaryImm32<atomic_load_add_32, imm32sx16>; -def ATOMIC_LOAD_AFI : AtomicLoadBinaryImm32<atomic_load_add_32, simm32>; -def ATOMIC_LOAD_AGR : AtomicLoadBinaryReg64<atomic_load_add_64>; -def ATOMIC_LOAD_AGHI : AtomicLoadBinaryImm64<atomic_load_add_64, imm64sx16>; -def ATOMIC_LOAD_AGFI : AtomicLoadBinaryImm64<atomic_load_add_64, imm64sx32>; - -def ATOMIC_LOADW_SR : AtomicLoadWBinaryReg<z_atomic_loadw_sub>; -def ATOMIC_LOAD_SR : AtomicLoadBinaryReg32<atomic_load_sub_32>; -def ATOMIC_LOAD_SGR : AtomicLoadBinaryReg64<atomic_load_sub_64>; - -def ATOMIC_LOADW_NR : AtomicLoadWBinaryReg<z_atomic_loadw_and>; -def ATOMIC_LOADW_NILH : AtomicLoadWBinaryImm<z_atomic_loadw_and, imm32lh16c>; -def ATOMIC_LOAD_NR : AtomicLoadBinaryReg32<atomic_load_and_32>; -def ATOMIC_LOAD_NILL : AtomicLoadBinaryImm32<atomic_load_and_32, imm32ll16c>; -def ATOMIC_LOAD_NILH : AtomicLoadBinaryImm32<atomic_load_and_32, imm32lh16c>; -def ATOMIC_LOAD_NILF : AtomicLoadBinaryImm32<atomic_load_and_32, uimm32>; -def ATOMIC_LOAD_NGR : AtomicLoadBinaryReg64<atomic_load_and_64>; -def ATOMIC_LOAD_NILL64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64ll16c>; -def ATOMIC_LOAD_NILH64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64lh16c>; -def ATOMIC_LOAD_NIHL64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hl16c>; -def ATOMIC_LOAD_NIHH64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hh16c>; -def ATOMIC_LOAD_NILF64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64lf32c>; -def ATOMIC_LOAD_NIHF64 : AtomicLoadBinaryImm64<atomic_load_and_64, imm64hf32c>; +def Serialize : Alias<2, (outs), (ins), [(z_serialize)]>; + +let Predicates = [FeatureInterlockedAccess1], Defs = [CC] in { + def LAA : LoadAndOpRSY<"laa", 0xEBF8, atomic_load_add_32, GR32>; + def LAAG : LoadAndOpRSY<"laag", 0xEBE8, atomic_load_add_64, GR64>; + def LAAL : LoadAndOpRSY<"laal", 0xEBFA, null_frag, GR32>; + def LAALG : LoadAndOpRSY<"laalg", 0xEBEA, null_frag, GR64>; + def LAN : LoadAndOpRSY<"lan", 0xEBF4, atomic_load_and_32, GR32>; + def LANG : LoadAndOpRSY<"lang", 0xEBE4, atomic_load_and_64, GR64>; + def LAO : LoadAndOpRSY<"lao", 0xEBF6, atomic_load_or_32, GR32>; + def LAOG : LoadAndOpRSY<"laog", 0xEBE6, atomic_load_or_64, GR64>; + def LAX : LoadAndOpRSY<"lax", 0xEBF7, atomic_load_xor_32, GR32>; + def LAXG : LoadAndOpRSY<"laxg", 0xEBE7, atomic_load_xor_64, GR64>; +} + +def ATOMIC_SWAPW : AtomicLoadWBinaryReg<z_atomic_swapw>; +def ATOMIC_SWAP_32 : AtomicLoadBinaryReg32<atomic_swap_32>; +def ATOMIC_SWAP_64 : AtomicLoadBinaryReg64<atomic_swap_64>; + +def ATOMIC_LOADW_AR : AtomicLoadWBinaryReg<z_atomic_loadw_add>; +def ATOMIC_LOADW_AFI : AtomicLoadWBinaryImm<z_atomic_loadw_add, simm32>; +let Predicates = [FeatureNoInterlockedAccess1] in { + def ATOMIC_LOAD_AR : AtomicLoadBinaryReg32<atomic_load_add_32>; + def ATOMIC_LOAD_AHI : AtomicLoadBinaryImm32<atomic_load_add_32, imm32sx16>; + def ATOMIC_LOAD_AFI : AtomicLoadBinaryImm32<atomic_load_add_32, simm32>; + def ATOMIC_LOAD_AGR : AtomicLoadBinaryReg64<atomic_load_add_64>; + def ATOMIC_LOAD_AGHI : AtomicLoadBinaryImm64<atomic_load_add_64, imm64sx16>; + def ATOMIC_LOAD_AGFI : AtomicLoadBinaryImm64<atomic_load_add_64, imm64sx32>; +} + +def ATOMIC_LOADW_SR : AtomicLoadWBinaryReg<z_atomic_loadw_sub>; +def ATOMIC_LOAD_SR : AtomicLoadBinaryReg32<atomic_load_sub_32>; +def ATOMIC_LOAD_SGR : AtomicLoadBinaryReg64<atomic_load_sub_64>; + +def ATOMIC_LOADW_NR : AtomicLoadWBinaryReg<z_atomic_loadw_and>; +def ATOMIC_LOADW_NILH : AtomicLoadWBinaryImm<z_atomic_loadw_and, imm32lh16c>; +let Predicates = [FeatureNoInterlockedAccess1] in { + def ATOMIC_LOAD_NR : AtomicLoadBinaryReg32<atomic_load_and_32>; + def ATOMIC_LOAD_NILL : AtomicLoadBinaryImm32<atomic_load_and_32, + imm32ll16c>; + def ATOMIC_LOAD_NILH : AtomicLoadBinaryImm32<atomic_load_and_32, + imm32lh16c>; + def ATOMIC_LOAD_NILF : AtomicLoadBinaryImm32<atomic_load_and_32, uimm32>; + def ATOMIC_LOAD_NGR : AtomicLoadBinaryReg64<atomic_load_and_64>; + def ATOMIC_LOAD_NILL64 : AtomicLoadBinaryImm64<atomic_load_and_64, + imm64ll16c>; + def ATOMIC_LOAD_NILH64 : AtomicLoadBinaryImm64<atomic_load_and_64, + imm64lh16c>; + def ATOMIC_LOAD_NIHL64 : AtomicLoadBinaryImm64<atomic_load_and_64, + imm64hl16c>; + def ATOMIC_LOAD_NIHH64 : AtomicLoadBinaryImm64<atomic_load_and_64, + imm64hh16c>; + def ATOMIC_LOAD_NILF64 : AtomicLoadBinaryImm64<atomic_load_and_64, + imm64lf32c>; + def ATOMIC_LOAD_NIHF64 : AtomicLoadBinaryImm64<atomic_load_and_64, + imm64hf32c>; +} def ATOMIC_LOADW_OR : AtomicLoadWBinaryReg<z_atomic_loadw_or>; def ATOMIC_LOADW_OILH : AtomicLoadWBinaryImm<z_atomic_loadw_or, imm32lh16>; -def ATOMIC_LOAD_OR : AtomicLoadBinaryReg32<atomic_load_or_32>; -def ATOMIC_LOAD_OILL : AtomicLoadBinaryImm32<atomic_load_or_32, imm32ll16>; -def ATOMIC_LOAD_OILH : AtomicLoadBinaryImm32<atomic_load_or_32, imm32lh16>; -def ATOMIC_LOAD_OILF : AtomicLoadBinaryImm32<atomic_load_or_32, uimm32>; -def ATOMIC_LOAD_OGR : AtomicLoadBinaryReg64<atomic_load_or_64>; -def ATOMIC_LOAD_OILL64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64ll16>; -def ATOMIC_LOAD_OILH64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64lh16>; -def ATOMIC_LOAD_OIHL64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64hl16>; -def ATOMIC_LOAD_OIHH64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64hh16>; -def ATOMIC_LOAD_OILF64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64lf32>; -def ATOMIC_LOAD_OIHF64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64hf32>; +let Predicates = [FeatureNoInterlockedAccess1] in { + def ATOMIC_LOAD_OR : AtomicLoadBinaryReg32<atomic_load_or_32>; + def ATOMIC_LOAD_OILL : AtomicLoadBinaryImm32<atomic_load_or_32, imm32ll16>; + def ATOMIC_LOAD_OILH : AtomicLoadBinaryImm32<atomic_load_or_32, imm32lh16>; + def ATOMIC_LOAD_OILF : AtomicLoadBinaryImm32<atomic_load_or_32, uimm32>; + def ATOMIC_LOAD_OGR : AtomicLoadBinaryReg64<atomic_load_or_64>; + def ATOMIC_LOAD_OILL64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64ll16>; + def ATOMIC_LOAD_OILH64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64lh16>; + def ATOMIC_LOAD_OIHL64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64hl16>; + def ATOMIC_LOAD_OIHH64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64hh16>; + def ATOMIC_LOAD_OILF64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64lf32>; + def ATOMIC_LOAD_OIHF64 : AtomicLoadBinaryImm64<atomic_load_or_64, imm64hf32>; +} def ATOMIC_LOADW_XR : AtomicLoadWBinaryReg<z_atomic_loadw_xor>; def ATOMIC_LOADW_XILF : AtomicLoadWBinaryImm<z_atomic_loadw_xor, uimm32>; -def ATOMIC_LOAD_XR : AtomicLoadBinaryReg32<atomic_load_xor_32>; -def ATOMIC_LOAD_XILF : AtomicLoadBinaryImm32<atomic_load_xor_32, uimm32>; -def ATOMIC_LOAD_XGR : AtomicLoadBinaryReg64<atomic_load_xor_64>; -def ATOMIC_LOAD_XILF64 : AtomicLoadBinaryImm64<atomic_load_xor_64, imm64lf32>; -def ATOMIC_LOAD_XIHF64 : AtomicLoadBinaryImm64<atomic_load_xor_64, imm64hf32>; +let Predicates = [FeatureNoInterlockedAccess1] in { + def ATOMIC_LOAD_XR : AtomicLoadBinaryReg32<atomic_load_xor_32>; + def ATOMIC_LOAD_XILF : AtomicLoadBinaryImm32<atomic_load_xor_32, uimm32>; + def ATOMIC_LOAD_XGR : AtomicLoadBinaryReg64<atomic_load_xor_64>; + def ATOMIC_LOAD_XILF64 : AtomicLoadBinaryImm64<atomic_load_xor_64, imm64lf32>; + def ATOMIC_LOAD_XIHF64 : AtomicLoadBinaryImm64<atomic_load_xor_64, imm64hf32>; +} def ATOMIC_LOADW_NRi : AtomicLoadWBinaryReg<z_atomic_loadw_nand>; def ATOMIC_LOADW_NILHi : AtomicLoadWBinaryImm<z_atomic_loadw_nand, diff --git a/lib/Target/SystemZ/SystemZLongBranch.cpp b/lib/Target/SystemZ/SystemZLongBranch.cpp index ba027d4..1b88d06 100644 --- a/lib/Target/SystemZ/SystemZLongBranch.cpp +++ b/lib/Target/SystemZ/SystemZLongBranch.cpp @@ -71,99 +71,99 @@ using namespace llvm; STATISTIC(LongBranches, "Number of long branches."); namespace { - // Represents positional information about a basic block. - struct MBBInfo { - // The address that we currently assume the block has. - uint64_t Address; - - // The size of the block in bytes, excluding terminators. - // This value never changes. - uint64_t Size; - - // The minimum alignment of the block, as a log2 value. - // This value never changes. - unsigned Alignment; - - // The number of terminators in this block. This value never changes. - unsigned NumTerminators; - - MBBInfo() - : Address(0), Size(0), Alignment(0), NumTerminators(0) {} - }; - - // Represents the state of a block terminator. - struct TerminatorInfo { - // If this terminator is a relaxable branch, this points to the branch - // instruction, otherwise it is null. - MachineInstr *Branch; - - // The address that we currently assume the terminator has. - uint64_t Address; - - // The current size of the terminator in bytes. - uint64_t Size; - - // If Branch is nonnull, this is the number of the target block, - // otherwise it is unused. - unsigned TargetBlock; - - // If Branch is nonnull, this is the length of the longest relaxed form, - // otherwise it is zero. - unsigned ExtraRelaxSize; - - TerminatorInfo() : Branch(0), Size(0), TargetBlock(0), ExtraRelaxSize(0) {} - }; - - // Used to keep track of the current position while iterating over the blocks. - struct BlockPosition { - // The address that we assume this position has. - uint64_t Address; - - // The number of low bits in Address that are known to be the same - // as the runtime address. - unsigned KnownBits; - - BlockPosition(unsigned InitialAlignment) - : Address(0), KnownBits(InitialAlignment) {} - }; - - class SystemZLongBranch : public MachineFunctionPass { - public: - static char ID; - SystemZLongBranch(const SystemZTargetMachine &tm) - : MachineFunctionPass(ID), TII(0) {} - - virtual const char *getPassName() const { - return "SystemZ Long Branch"; - } +// Represents positional information about a basic block. +struct MBBInfo { + // The address that we currently assume the block has. + uint64_t Address; + + // The size of the block in bytes, excluding terminators. + // This value never changes. + uint64_t Size; + + // The minimum alignment of the block, as a log2 value. + // This value never changes. + unsigned Alignment; + + // The number of terminators in this block. This value never changes. + unsigned NumTerminators; + + MBBInfo() + : Address(0), Size(0), Alignment(0), NumTerminators(0) {} +}; + +// Represents the state of a block terminator. +struct TerminatorInfo { + // If this terminator is a relaxable branch, this points to the branch + // instruction, otherwise it is null. + MachineInstr *Branch; + + // The address that we currently assume the terminator has. + uint64_t Address; + + // The current size of the terminator in bytes. + uint64_t Size; + + // If Branch is nonnull, this is the number of the target block, + // otherwise it is unused. + unsigned TargetBlock; + + // If Branch is nonnull, this is the length of the longest relaxed form, + // otherwise it is zero. + unsigned ExtraRelaxSize; + + TerminatorInfo() : Branch(0), Size(0), TargetBlock(0), ExtraRelaxSize(0) {} +}; + +// Used to keep track of the current position while iterating over the blocks. +struct BlockPosition { + // The address that we assume this position has. + uint64_t Address; + + // The number of low bits in Address that are known to be the same + // as the runtime address. + unsigned KnownBits; + + BlockPosition(unsigned InitialAlignment) + : Address(0), KnownBits(InitialAlignment) {} +}; + +class SystemZLongBranch : public MachineFunctionPass { +public: + static char ID; + SystemZLongBranch(const SystemZTargetMachine &tm) + : MachineFunctionPass(ID), TII(0) {} + + const char *getPassName() const override { + return "SystemZ Long Branch"; + } - bool runOnMachineFunction(MachineFunction &F); - - private: - void skipNonTerminators(BlockPosition &Position, MBBInfo &Block); - void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator, - bool AssumeRelaxed); - TerminatorInfo describeTerminator(MachineInstr *MI); - uint64_t initMBBInfo(); - bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address); - bool mustRelaxABranch(); - void setWorstCaseAddresses(); - void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode); - void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode); - void relaxBranch(TerminatorInfo &Terminator); - void relaxBranches(); - - const SystemZInstrInfo *TII; - MachineFunction *MF; - SmallVector<MBBInfo, 16> MBBs; - SmallVector<TerminatorInfo, 16> Terminators; - }; - - char SystemZLongBranch::ID = 0; - - const uint64_t MaxBackwardRange = 0x10000; - const uint64_t MaxForwardRange = 0xfffe; -} // end of anonymous namespace + bool runOnMachineFunction(MachineFunction &F); + +private: + void skipNonTerminators(BlockPosition &Position, MBBInfo &Block); + void skipTerminator(BlockPosition &Position, TerminatorInfo &Terminator, + bool AssumeRelaxed); + TerminatorInfo describeTerminator(MachineInstr *MI); + uint64_t initMBBInfo(); + bool mustRelaxBranch(const TerminatorInfo &Terminator, uint64_t Address); + bool mustRelaxABranch(); + void setWorstCaseAddresses(); + void splitBranchOnCount(MachineInstr *MI, unsigned AddOpcode); + void splitCompareBranch(MachineInstr *MI, unsigned CompareOpcode); + void relaxBranch(TerminatorInfo &Terminator); + void relaxBranches(); + + const SystemZInstrInfo *TII; + MachineFunction *MF; + SmallVector<MBBInfo, 16> MBBs; + SmallVector<TerminatorInfo, 16> Terminators; +}; + +char SystemZLongBranch::ID = 0; + +const uint64_t MaxBackwardRange = 0x10000; +const uint64_t MaxForwardRange = 0xfffe; +} // end anonymous namespace FunctionPass *llvm::createSystemZLongBranchPass(SystemZTargetMachine &TM) { return new SystemZLongBranch(TM); @@ -321,9 +321,8 @@ bool SystemZLongBranch::mustRelaxBranch(const TerminatorInfo &Terminator, // Return true if, under current assumptions, any terminator needs // to be relaxed. bool SystemZLongBranch::mustRelaxABranch() { - for (SmallVectorImpl<TerminatorInfo>::iterator TI = Terminators.begin(), - TE = Terminators.end(); TI != TE; ++TI) - if (mustRelaxBranch(*TI, TI->Address)) + for (auto &Terminator : Terminators) + if (mustRelaxBranch(Terminator, Terminator.Address)) return true; return false; } @@ -333,10 +332,9 @@ bool SystemZLongBranch::mustRelaxABranch() { void SystemZLongBranch::setWorstCaseAddresses() { SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(); BlockPosition Position(MF->getAlignment()); - for (SmallVectorImpl<MBBInfo>::iterator BI = MBBs.begin(), BE = MBBs.end(); - BI != BE; ++BI) { - skipNonTerminators(Position, *BI); - for (unsigned BTI = 0, BTE = BI->NumTerminators; BTI != BTE; ++BTI) { + for (auto &Block : MBBs) { + skipNonTerminators(Position, Block); + for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) { skipTerminator(Position, *TI, true); ++TI; } @@ -435,10 +433,9 @@ void SystemZLongBranch::relaxBranch(TerminatorInfo &Terminator) { void SystemZLongBranch::relaxBranches() { SmallVector<TerminatorInfo, 16>::iterator TI = Terminators.begin(); BlockPosition Position(MF->getAlignment()); - for (SmallVectorImpl<MBBInfo>::iterator BI = MBBs.begin(), BE = MBBs.end(); - BI != BE; ++BI) { - skipNonTerminators(Position, *BI); - for (unsigned BTI = 0, BTE = BI->NumTerminators; BTI != BTE; ++BTI) { + for (auto &Block : MBBs) { + skipNonTerminators(Position, Block); + for (unsigned BTI = 0, BTE = Block.NumTerminators; BTI != BTE; ++BTI) { assert(Position.Address <= TI->Address && "Addresses shouldn't go forwards"); if (mustRelaxBranch(*TI, Position.Address)) diff --git a/lib/Target/SystemZ/SystemZMCInstLower.cpp b/lib/Target/SystemZ/SystemZMCInstLower.cpp index ff9a6c0..df561e2 100644 --- a/lib/Target/SystemZ/SystemZMCInstLower.cpp +++ b/lib/Target/SystemZ/SystemZMCInstLower.cpp @@ -9,9 +9,9 @@ #include "SystemZMCInstLower.h" #include "SystemZAsmPrinter.h" +#include "llvm/IR/Mangler.h" #include "llvm/MC/MCExpr.h" #include "llvm/MC/MCStreamer.h" -#include "llvm/Target/Mangler.h" using namespace llvm; diff --git a/lib/Target/SystemZ/SystemZMCInstLower.h b/lib/Target/SystemZ/SystemZMCInstLower.h index f6d5ac8..90447ff 100644 --- a/lib/Target/SystemZ/SystemZMCInstLower.h +++ b/lib/Target/SystemZ/SystemZMCInstLower.h @@ -11,8 +11,8 @@ #define LLVM_SYSTEMZMCINSTLOWER_H #include "llvm/MC/MCExpr.h" -#include "llvm/Support/DataTypes.h" #include "llvm/Support/Compiler.h" +#include "llvm/Support/DataTypes.h" namespace llvm { class MCInst; diff --git a/lib/Target/SystemZ/SystemZMachineFunctionInfo.h b/lib/Target/SystemZ/SystemZMachineFunctionInfo.h index 845291f..50865f1 100644 --- a/lib/Target/SystemZ/SystemZMachineFunctionInfo.h +++ b/lib/Target/SystemZ/SystemZMachineFunctionInfo.h @@ -63,6 +63,6 @@ public: void setManipulatesSP(bool MSP) { ManipulatesSP = MSP; } }; -} // end llvm namespace +} // end namespace llvm #endif diff --git a/lib/Target/SystemZ/SystemZOperators.td b/lib/Target/SystemZ/SystemZOperators.td index 31cabaa..a391961 100644 --- a/lib/Target/SystemZ/SystemZOperators.td +++ b/lib/Target/SystemZ/SystemZOperators.td @@ -103,6 +103,7 @@ def z_sibcall : SDNode<"SystemZISD::SIBCALL", SDT_ZCall, def z_pcrel_wrapper : SDNode<"SystemZISD::PCREL_WRAPPER", SDT_ZWrapPtr, []>; def z_pcrel_offset : SDNode<"SystemZISD::PCREL_OFFSET", SDT_ZWrapOffset, []>; +def z_iabs : SDNode<"SystemZISD::IABS", SDTIntUnaryOp, []>; def z_icmp : SDNode<"SystemZISD::ICMP", SDT_ZICmp, [SDNPOutGlue]>; def z_fcmp : SDNode<"SystemZISD::FCMP", SDT_ZCmp, [SDNPOutGlue]>; def z_tm : SDNode<"SystemZISD::TM", SDT_ZICmp, [SDNPOutGlue]>; @@ -119,6 +120,9 @@ def z_sdivrem64 : SDNode<"SystemZISD::SDIVREM64", SDT_ZGR128Binary64>; def z_udivrem32 : SDNode<"SystemZISD::UDIVREM32", SDT_ZGR128Binary32>; def z_udivrem64 : SDNode<"SystemZISD::UDIVREM64", SDT_ZGR128Binary64>; +def z_serialize : SDNode<"SystemZISD::SERIALIZE", SDTNone, + [SDNPHasChain, SDNPMayStore]>; + class AtomicWOp<string name, SDTypeProfile profile = SDT_ZAtomicLoadBinaryW> : SDNode<"SystemZISD::"##name, profile, [SDNPHasChain, SDNPMayStore, SDNPMayLoad, SDNPMemOperand]>; @@ -247,7 +251,7 @@ def anyextloadi32 : PatFrag<(ops node:$ptr), (anyextload node:$ptr), [{ // Aligned loads. class AlignedLoad<SDPatternOperator load> : PatFrag<(ops node:$addr), (load node:$addr), [{ - LoadSDNode *Load = cast<LoadSDNode>(N); + auto *Load = cast<LoadSDNode>(N); return Load->getAlignment() >= Load->getMemoryVT().getStoreSize(); }]>; def aligned_load : AlignedLoad<load>; @@ -259,7 +263,7 @@ def aligned_azextloadi32 : AlignedLoad<azextloadi32>; // Aligned stores. class AlignedStore<SDPatternOperator store> : PatFrag<(ops node:$src, node:$addr), (store node:$src, node:$addr), [{ - StoreSDNode *Store = cast<StoreSDNode>(N); + auto *Store = cast<StoreSDNode>(N); return Store->getAlignment() >= Store->getMemoryVT().getStoreSize(); }]>; def aligned_store : AlignedStore<store>; @@ -270,7 +274,7 @@ def aligned_truncstorei32 : AlignedStore<truncstorei32>; // location multiple times. class NonvolatileLoad<SDPatternOperator load> : PatFrag<(ops node:$addr), (load node:$addr), [{ - LoadSDNode *Load = cast<LoadSDNode>(N); + auto *Load = cast<LoadSDNode>(N); return !Load->isVolatile(); }]>; def nonvolatile_load : NonvolatileLoad<load>; @@ -281,7 +285,7 @@ def nonvolatile_anyextloadi32 : NonvolatileLoad<anyextloadi32>; // Non-volatile stores. class NonvolatileStore<SDPatternOperator store> : PatFrag<(ops node:$src, node:$addr), (store node:$src, node:$addr), [{ - StoreSDNode *Store = cast<StoreSDNode>(N); + auto *Store = cast<StoreSDNode>(N); return !Store->isVolatile(); }]>; def nonvolatile_store : NonvolatileStore<store>; @@ -346,6 +350,9 @@ def or_as_revinserti8 : PatFrag<(ops node:$src1, node:$src2), APInt::getLowBitsSet(BitWidth, 8)); }]>; +// Negative integer absolute. +def z_inegabs : PatFrag<(ops node:$src), (ineg (z_iabs node:$src))>; + // Integer absolute, matching the canonical form generated by DAGCombiner. def z_iabs32 : PatFrag<(ops node:$src), (xor (add node:$src, (sra node:$src, (i32 31))), diff --git a/lib/Target/SystemZ/SystemZPatterns.td b/lib/Target/SystemZ/SystemZPatterns.td index 7706351..c0f94ec 100644 --- a/lib/Target/SystemZ/SystemZPatterns.td +++ b/lib/Target/SystemZ/SystemZPatterns.td @@ -148,5 +148,8 @@ multiclass BlockLoadStore<SDPatternOperator load, ValueType vt, // Record that INSN is a LOAD AND TEST that can be used to compare // registers in CLS against zero. The instruction has separate R1 and R2 // operands, but they must be the same when the instruction is used like this. -class CompareZeroFP<Instruction insn, RegisterOperand cls> - : Pat<(z_fcmp cls:$reg, (fpimm0)), (insn cls:$reg, cls:$reg)>; +multiclass CompareZeroFP<Instruction insn, RegisterOperand cls> { + def : Pat<(z_fcmp cls:$reg, (fpimm0)), (insn cls:$reg, cls:$reg)>; + // The sign of the zero makes no difference. + def : Pat<(z_fcmp cls:$reg, (fpimmneg0)), (insn cls:$reg, cls:$reg)>; +} diff --git a/lib/Target/SystemZ/SystemZProcessors.td b/lib/Target/SystemZ/SystemZProcessors.td index f241fb0..e6b58f1 100644 --- a/lib/Target/SystemZ/SystemZProcessors.td +++ b/lib/Target/SystemZ/SystemZProcessors.td @@ -16,6 +16,9 @@ class SystemZFeature<string extname, string intname, string desc> AssemblerPredicate<"Feature"##intname, extname>, SubtargetFeature<extname, "Has"##intname, "true", desc>; +class SystemZMissingFeature<string intname> + : Predicate<"!Subtarget.has"##intname##"()">; + def FeatureDistinctOps : SystemZFeature< "distinct-ops", "DistinctOps", "Assume that the distinct-operands facility is installed" @@ -36,11 +39,24 @@ def FeatureFPExtension : SystemZFeature< "Assume that the floating-point extension facility is installed" >; +def FeatureFastSerialization : SystemZFeature< + "fast-serialization", "FastSerialization", + "Assume that the fast-serialization facility is installed" +>; + +def FeatureInterlockedAccess1 : SystemZFeature< + "interlocked-access1", "InterlockedAccess1", + "Assume that interlocked-access facility 1 is installed" +>; +def FeatureNoInterlockedAccess1 : SystemZMissingFeature<"InterlockedAccess1">; + def : Processor<"generic", NoItineraries, []>; def : Processor<"z10", NoItineraries, []>; def : Processor<"z196", NoItineraries, [FeatureDistinctOps, FeatureLoadStoreOnCond, FeatureHighWord, - FeatureFPExtension]>; + FeatureFPExtension, FeatureFastSerialization, + FeatureInterlockedAccess1]>; def : Processor<"zEC12", NoItineraries, [FeatureDistinctOps, FeatureLoadStoreOnCond, FeatureHighWord, - FeatureFPExtension]>; + FeatureFPExtension, FeatureFastSerialization, + FeatureInterlockedAccess1]>; diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.cpp b/lib/Target/SystemZ/SystemZRegisterInfo.cpp index b61ae88..1ac4e32 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.cpp +++ b/lib/Target/SystemZ/SystemZRegisterInfo.cpp @@ -63,8 +63,7 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, MachineBasicBlock &MBB = *MI->getParent(); MachineFunction &MF = *MBB.getParent(); - const SystemZInstrInfo &TII = - *static_cast<const SystemZInstrInfo*>(TM.getInstrInfo()); + auto *TII = static_cast<const SystemZInstrInfo*>(TM.getInstrInfo()); const TargetFrameLowering *TFI = MF.getTarget().getFrameLowering(); DebugLoc DL = MI->getDebugLoc(); @@ -84,7 +83,7 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, // See if the offset is in range, or if an equivalent instruction that // accepts the offset exists. unsigned Opcode = MI->getOpcode(); - unsigned OpcodeForOffset = TII.getOpcodeForOffset(Opcode, Offset); + unsigned OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); if (OpcodeForOffset) MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); else { @@ -94,7 +93,7 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, int64_t Mask = 0xffff; do { Offset = OldOffset & Mask; - OpcodeForOffset = TII.getOpcodeForOffset(Opcode, Offset); + OpcodeForOffset = TII->getOpcodeForOffset(Opcode, Offset); Mask >>= 1; assert(Mask && "One offset must be OK"); } while (!OpcodeForOffset); @@ -107,21 +106,21 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, && MI->getOperand(FIOperandNum + 2).getReg() == 0) { // Load the offset into the scratch register and use it as an index. // The scratch register then dies here. - TII.loadImmediate(MBB, MI, ScratchReg, HighOffset); + TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); MI->getOperand(FIOperandNum).ChangeToRegister(BasePtr, false); MI->getOperand(FIOperandNum + 2).ChangeToRegister(ScratchReg, false, false, true); } else { // Load the anchor address into a scratch register. - unsigned LAOpcode = TII.getOpcodeForOffset(SystemZ::LA, HighOffset); + unsigned LAOpcode = TII->getOpcodeForOffset(SystemZ::LA, HighOffset); if (LAOpcode) - BuildMI(MBB, MI, DL, TII.get(LAOpcode),ScratchReg) + BuildMI(MBB, MI, DL, TII->get(LAOpcode),ScratchReg) .addReg(BasePtr).addImm(HighOffset).addReg(0); else { // Load the high offset into the scratch register and use it as // an index. - TII.loadImmediate(MBB, MI, ScratchReg, HighOffset); - BuildMI(MBB, MI, DL, TII.get(SystemZ::AGR),ScratchReg) + TII->loadImmediate(MBB, MI, ScratchReg, HighOffset); + BuildMI(MBB, MI, DL, TII->get(SystemZ::AGR),ScratchReg) .addReg(ScratchReg, RegState::Kill).addReg(BasePtr); } @@ -130,7 +129,7 @@ SystemZRegisterInfo::eliminateFrameIndex(MachineBasicBlock::iterator MI, false, false, true); } } - MI->setDesc(TII.get(OpcodeForOffset)); + MI->setDesc(TII->get(OpcodeForOffset)); MI->getOperand(FIOperandNum + 1).ChangeToImmediate(Offset); } diff --git a/lib/Target/SystemZ/SystemZRegisterInfo.h b/lib/Target/SystemZ/SystemZRegisterInfo.h index 13f45fa..4ad8048 100644 --- a/lib/Target/SystemZ/SystemZRegisterInfo.h +++ b/lib/Target/SystemZ/SystemZRegisterInfo.h @@ -19,15 +19,15 @@ namespace llvm { namespace SystemZ { - // Return the subreg to use for referring to the even and odd registers - // in a GR128 pair. Is32Bit says whether we want a GR32 or GR64. - inline unsigned even128(bool Is32bit) { - return Is32bit ? subreg_hl32 : subreg_h64; - } - inline unsigned odd128(bool Is32bit) { - return Is32bit ? subreg_l32 : subreg_l64; - } +// Return the subreg to use for referring to the even and odd registers +// in a GR128 pair. Is32Bit says whether we want a GR32 or GR64. +inline unsigned even128(bool Is32bit) { + return Is32bit ? subreg_hl32 : subreg_h64; +} +inline unsigned odd128(bool Is32bit) { + return Is32bit ? subreg_l32 : subreg_l64; } +} // end namespace SystemZ class SystemZSubtarget; class SystemZInstrInfo; @@ -40,27 +40,22 @@ public: SystemZRegisterInfo(SystemZTargetMachine &tm); // Override TargetRegisterInfo.h. - virtual bool requiresRegisterScavenging(const MachineFunction &MF) const - LLVM_OVERRIDE { + bool requiresRegisterScavenging(const MachineFunction &MF) const override { return true; } - virtual bool requiresFrameIndexScavenging(const MachineFunction &MF) const - LLVM_OVERRIDE { + bool requiresFrameIndexScavenging(const MachineFunction &MF) const override { return true; } - virtual bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const - LLVM_OVERRIDE { + bool trackLivenessAfterRegAlloc(const MachineFunction &MF) const override { return true; } - virtual const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) - const LLVM_OVERRIDE; - virtual BitVector getReservedRegs(const MachineFunction &MF) - const LLVM_OVERRIDE; - virtual void eliminateFrameIndex(MachineBasicBlock::iterator MI, - int SPAdj, unsigned FIOperandNum, - RegScavenger *RS) const LLVM_OVERRIDE; - virtual unsigned getFrameRegister(const MachineFunction &MF) const - LLVM_OVERRIDE; + const uint16_t *getCalleeSavedRegs(const MachineFunction *MF = 0) const + override; + BitVector getReservedRegs(const MachineFunction &MF) const override; + void eliminateFrameIndex(MachineBasicBlock::iterator MI, + int SPAdj, unsigned FIOperandNum, + RegScavenger *RS) const override; + unsigned getFrameRegister(const MachineFunction &MF) const override; }; } // end namespace llvm diff --git a/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp b/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp index c7ebb5d..7635bdc 100644 --- a/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp +++ b/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp @@ -62,7 +62,7 @@ EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain, if (IsVolatile) return SDValue(); - if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) + if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) return emitMemMem(DAG, DL, SystemZISD::MVC, SystemZISD::MVC_LOOP, Chain, Dst, Src, CSize->getZExtValue()); return SDValue(); @@ -93,11 +93,11 @@ EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc DL, SDValue Chain, if (IsVolatile) return SDValue(); - if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) { + if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) { uint64_t Bytes = CSize->getZExtValue(); if (Bytes == 0) return SDValue(); - if (ConstantSDNode *CByte = dyn_cast<ConstantSDNode>(Byte)) { + if (auto *CByte = dyn_cast<ConstantSDNode>(Byte)) { // Handle cases that can be done using at most two of // MVI, MVHI, MVHHI and MVGHI. The latter two can only be // used if ByteVal is all zeros or all ones; in other casees, @@ -137,7 +137,7 @@ EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc DL, SDValue Chain, assert(Bytes >= 2 && "Should have dealt with 0- and 1-byte cases already"); // Handle the special case of a memset of 0, which can use XC. - ConstantSDNode *CByte = dyn_cast<ConstantSDNode>(Byte); + auto *CByte = dyn_cast<ConstantSDNode>(Byte); if (CByte && CByte->getZExtValue() == 0) return emitMemMem(DAG, DL, SystemZISD::XC, SystemZISD::XC_LOOP, Chain, Dst, Dst, Bytes); @@ -194,7 +194,7 @@ EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src1, SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const { - if (ConstantSDNode *CSize = dyn_cast<ConstantSDNode>(Size)) { + if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) { uint64_t Bytes = CSize->getZExtValue(); assert(Bytes > 0 && "Caller should have handled 0-size case"); Chain = emitCLC(DAG, DL, Chain, Src1, Src2, Bytes); diff --git a/lib/Target/SystemZ/SystemZSelectionDAGInfo.h b/lib/Target/SystemZ/SystemZSelectionDAGInfo.h index 281d1e2..79e7fab 100644 --- a/lib/Target/SystemZ/SystemZSelectionDAGInfo.h +++ b/lib/Target/SystemZ/SystemZSelectionDAGInfo.h @@ -25,56 +25,53 @@ public: explicit SystemZSelectionDAGInfo(const SystemZTargetMachine &TM); ~SystemZSelectionDAGInfo(); - virtual SDValue EmitTargetCodeForMemcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Dst, SDValue Src, SDValue Size, unsigned Align, bool IsVolatile, bool AlwaysInline, MachinePointerInfo DstPtrInfo, - MachinePointerInfo SrcPtrInfo) const - LLVM_OVERRIDE; + MachinePointerInfo SrcPtrInfo) const override; - virtual SDValue - EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc DL, - SDValue Chain, SDValue Dst, SDValue Byte, - SDValue Size, unsigned Align, bool IsVolatile, - MachinePointerInfo DstPtrInfo) const LLVM_OVERRIDE; + SDValue EmitTargetCodeForMemset(SelectionDAG &DAG, SDLoc DL, + SDValue Chain, SDValue Dst, SDValue Byte, + SDValue Size, unsigned Align, bool IsVolatile, + MachinePointerInfo DstPtrInfo) const override; - virtual std::pair<SDValue, SDValue> + std::pair<SDValue, SDValue> EmitTargetCodeForMemcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src1, SDValue Src2, SDValue Size, MachinePointerInfo Op1PtrInfo, - MachinePointerInfo Op2PtrInfo) const LLVM_OVERRIDE; + MachinePointerInfo Op2PtrInfo) const override; - virtual std::pair<SDValue, SDValue> + std::pair<SDValue, SDValue> EmitTargetCodeForMemchr(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src, SDValue Char, SDValue Length, - MachinePointerInfo SrcPtrInfo) const LLVM_OVERRIDE; + MachinePointerInfo SrcPtrInfo) const override; - virtual std::pair<SDValue, SDValue> + std::pair<SDValue, SDValue> EmitTargetCodeForStrcpy(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Dest, SDValue Src, MachinePointerInfo DestPtrInfo, MachinePointerInfo SrcPtrInfo, - bool isStpcpy) const LLVM_OVERRIDE; + bool isStpcpy) const override; - virtual std::pair<SDValue, SDValue> + std::pair<SDValue, SDValue> EmitTargetCodeForStrcmp(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src1, SDValue Src2, MachinePointerInfo Op1PtrInfo, - MachinePointerInfo Op2PtrInfo) const LLVM_OVERRIDE; + MachinePointerInfo Op2PtrInfo) const override; - virtual std::pair<SDValue, SDValue> + std::pair<SDValue, SDValue> EmitTargetCodeForStrlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, - SDValue Src, MachinePointerInfo SrcPtrInfo) const - LLVM_OVERRIDE; + SDValue Src, + MachinePointerInfo SrcPtrInfo) const override; - virtual std::pair<SDValue, SDValue> + std::pair<SDValue, SDValue> EmitTargetCodeForStrnlen(SelectionDAG &DAG, SDLoc DL, SDValue Chain, SDValue Src, SDValue MaxLength, - MachinePointerInfo SrcPtrInfo) const LLVM_OVERRIDE; + MachinePointerInfo SrcPtrInfo) const override; }; -} +} // end namespace llvm #endif diff --git a/lib/Target/SystemZ/SystemZShortenInst.cpp b/lib/Target/SystemZ/SystemZShortenInst.cpp index 537a545..9350779 100644 --- a/lib/Target/SystemZ/SystemZShortenInst.cpp +++ b/lib/Target/SystemZ/SystemZShortenInst.cpp @@ -21,32 +21,32 @@ using namespace llvm; namespace { - class SystemZShortenInst : public MachineFunctionPass { - public: - static char ID; - SystemZShortenInst(const SystemZTargetMachine &tm); +class SystemZShortenInst : public MachineFunctionPass { +public: + static char ID; + SystemZShortenInst(const SystemZTargetMachine &tm); - virtual const char *getPassName() const { - return "SystemZ Instruction Shortening"; - } + const char *getPassName() const override { + return "SystemZ Instruction Shortening"; + } - bool processBlock(MachineBasicBlock *MBB); - bool runOnMachineFunction(MachineFunction &F); + bool processBlock(MachineBasicBlock &MBB); + bool runOnMachineFunction(MachineFunction &F); - private: - bool shortenIIF(MachineInstr &MI, unsigned *GPRMap, unsigned LiveOther, - unsigned LLIxL, unsigned LLIxH); +private: + bool shortenIIF(MachineInstr &MI, unsigned *GPRMap, unsigned LiveOther, + unsigned LLIxL, unsigned LLIxH); - const SystemZInstrInfo *TII; + const SystemZInstrInfo *TII; - // LowGPRs[I] has bit N set if LLVM register I includes the low - // word of GPR N. HighGPRs is the same for the high word. - unsigned LowGPRs[SystemZ::NUM_TARGET_REGS]; - unsigned HighGPRs[SystemZ::NUM_TARGET_REGS]; - }; + // LowGPRs[I] has bit N set if LLVM register I includes the low + // word of GPR N. HighGPRs is the same for the high word. + unsigned LowGPRs[SystemZ::NUM_TARGET_REGS]; + unsigned HighGPRs[SystemZ::NUM_TARGET_REGS]; +}; - char SystemZShortenInst::ID = 0; -} // end of anonymous namespace +char SystemZShortenInst::ID = 0; +} // end anonymous namespace FunctionPass *llvm::createSystemZShortenInstPass(SystemZTargetMachine &TM) { return new SystemZShortenInst(TM); @@ -98,16 +98,15 @@ bool SystemZShortenInst::shortenIIF(MachineInstr &MI, unsigned *GPRMap, } // Process all instructions in MBB. Return true if something changed. -bool SystemZShortenInst::processBlock(MachineBasicBlock *MBB) { +bool SystemZShortenInst::processBlock(MachineBasicBlock &MBB) { bool Changed = false; // Work out which words are live on exit from the block. unsigned LiveLow = 0; unsigned LiveHigh = 0; - for (MachineBasicBlock::succ_iterator SI = MBB->succ_begin(), - SE = MBB->succ_end(); SI != SE; ++SI) { - for (MachineBasicBlock::livein_iterator LI = (*SI)->livein_begin(), - LE = (*SI)->livein_end(); LI != LE; ++LI) { + for (auto SI = MBB.succ_begin(), SE = MBB.succ_end(); SI != SE; ++SI) { + for (auto LI = (*SI)->livein_begin(), LE = (*SI)->livein_end(); + LI != LE; ++LI) { unsigned Reg = *LI; assert(Reg < SystemZ::NUM_TARGET_REGS && "Invalid register number"); LiveLow |= LowGPRs[Reg]; @@ -116,8 +115,7 @@ bool SystemZShortenInst::processBlock(MachineBasicBlock *MBB) { } // Iterate backwards through the block looking for instructions to change. - for (MachineBasicBlock::reverse_iterator MBBI = MBB->rbegin(), - MBBE = MBB->rend(); MBBI != MBBE; ++MBBI) { + for (auto MBBI = MBB.rbegin(), MBBE = MBB.rend(); MBBI != MBBE; ++MBBI) { MachineInstr &MI = *MBBI; unsigned Opcode = MI.getOpcode(); if (Opcode == SystemZ::IILF) @@ -128,8 +126,8 @@ bool SystemZShortenInst::processBlock(MachineBasicBlock *MBB) { SystemZ::LLIHH); unsigned UsedLow = 0; unsigned UsedHigh = 0; - for (MachineInstr::mop_iterator MOI = MI.operands_begin(), - MOE = MI.operands_end(); MOI != MOE; ++MOI) { + for (auto MOI = MI.operands_begin(), MOE = MI.operands_end(); + MOI != MOE; ++MOI) { MachineOperand &MO = *MOI; if (MO.isReg()) { if (unsigned Reg = MO.getReg()) { @@ -155,9 +153,8 @@ bool SystemZShortenInst::runOnMachineFunction(MachineFunction &F) { TII = static_cast<const SystemZInstrInfo *>(F.getTarget().getInstrInfo()); bool Changed = false; - for (MachineFunction::iterator MFI = F.begin(), MFE = F.end(); - MFI != MFE; ++MFI) - Changed |= processBlock(MFI); + for (auto &MBB : F) + Changed |= processBlock(MBB); return Changed; } diff --git a/lib/Target/SystemZ/SystemZSubtarget.cpp b/lib/Target/SystemZ/SystemZSubtarget.cpp index 3971d5e..33d7e06 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.cpp +++ b/lib/Target/SystemZ/SystemZSubtarget.cpp @@ -8,9 +8,9 @@ //===----------------------------------------------------------------------===// #include "SystemZSubtarget.h" +#include "MCTargetDesc/SystemZMCTargetDesc.h" #include "llvm/IR/GlobalValue.h" #include "llvm/Support/Host.h" -#include "MCTargetDesc/SystemZMCTargetDesc.h" #define GET_SUBTARGETINFO_TARGET_DESC #define GET_SUBTARGETINFO_CTOR @@ -26,6 +26,7 @@ SystemZSubtarget::SystemZSubtarget(const std::string &TT, const std::string &FS) : SystemZGenSubtargetInfo(TT, CPU, FS), HasDistinctOps(false), HasLoadStoreOnCond(false), HasHighWord(false), HasFPExtension(false), + HasFastSerialization(false), HasInterlockedAccess1(false), TargetTriple(TT) { std::string CPUName = CPU; if (CPUName.empty()) diff --git a/lib/Target/SystemZ/SystemZSubtarget.h b/lib/Target/SystemZ/SystemZSubtarget.h index 5817491..ffca2d8 100644 --- a/lib/Target/SystemZ/SystemZSubtarget.h +++ b/lib/Target/SystemZ/SystemZSubtarget.h @@ -32,6 +32,8 @@ protected: bool HasLoadStoreOnCond; bool HasHighWord; bool HasFPExtension; + bool HasFastSerialization; + bool HasInterlockedAccess1; private: Triple TargetTriple; @@ -41,7 +43,7 @@ public: const std::string &FS); // This is important for reducing register pressure in vector code. - virtual bool useAA() const LLVM_OVERRIDE { return true; } + bool useAA() const override { return true; } // Automatically generated by tblgen. void ParseSubtargetFeatures(StringRef CPU, StringRef FS); @@ -58,6 +60,12 @@ public: // Return true if the target has the floating-point extension facility. bool hasFPExtension() const { return HasFPExtension; } + // Return true if the target has the fast-serialization facility. + bool hasFastSerialization() const { return HasFastSerialization; } + + // Return true if the target has interlocked-access facility 1. + bool hasInterlockedAccess1() const { return HasInterlockedAccess1; } + // Return true if GV can be accessed using LARL for reloc model RM // and code model CM. bool isPC32DBLSymbol(const GlobalValue *GV, Reloc::Model RM, diff --git a/lib/Target/SystemZ/SystemZTargetMachine.cpp b/lib/Target/SystemZ/SystemZTargetMachine.cpp index dee92e9..4c9ce29 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.cpp +++ b/lib/Target/SystemZ/SystemZTargetMachine.cpp @@ -30,8 +30,7 @@ SystemZTargetMachine::SystemZTargetMachine(const Target &T, StringRef TT, // Make sure that global data has at least 16 bits of alignment by default, // so that we can refer to it using LARL. We don't have any special // requirements for stack variables though. - DL("E-p:64:64:64-i1:8:16-i8:8:16-i16:16-i32:32-i64:64" - "-f32:32-f64:64-f128:64-a0:8:16-n32:64"), + DL("E-m:e-i1:8:16-i8:8:16-i64:64-f128:64-a:8:16-n32:64"), InstrInfo(*this), TLInfo(*this), TSInfo(*this), FrameLowering(*this, Subtarget) { initAsmInfo(); @@ -48,10 +47,10 @@ public: return getTM<SystemZTargetMachine>(); } - virtual void addIRPasses() LLVM_OVERRIDE; - virtual bool addInstSelector() LLVM_OVERRIDE; - virtual bool addPreSched2() LLVM_OVERRIDE; - virtual bool addPreEmitPass() LLVM_OVERRIDE; + void addIRPasses() override; + bool addInstSelector() override; + bool addPreSched2() override; + bool addPreEmitPass() override; }; } // end anonymous namespace diff --git a/lib/Target/SystemZ/SystemZTargetMachine.h b/lib/Target/SystemZ/SystemZTargetMachine.h index a99a98e..1db717b 100644 --- a/lib/Target/SystemZ/SystemZTargetMachine.h +++ b/lib/Target/SystemZ/SystemZTargetMachine.h @@ -19,8 +19,8 @@ #include "SystemZISelLowering.h" #include "SystemZInstrInfo.h" #include "SystemZRegisterInfo.h" -#include "SystemZSubtarget.h" #include "SystemZSelectionDAGInfo.h" +#include "SystemZSubtarget.h" #include "llvm/IR/DataLayout.h" #include "llvm/Target/TargetFrameLowering.h" #include "llvm/Target/TargetMachine.h" @@ -42,31 +42,30 @@ public: CodeGenOpt::Level OL); // Override TargetMachine. - virtual const TargetFrameLowering *getFrameLowering() const LLVM_OVERRIDE { + const TargetFrameLowering *getFrameLowering() const override { return &FrameLowering; } - virtual const SystemZInstrInfo *getInstrInfo() const LLVM_OVERRIDE { + const SystemZInstrInfo *getInstrInfo() const override { return &InstrInfo; } - virtual const SystemZSubtarget *getSubtargetImpl() const LLVM_OVERRIDE { + const SystemZSubtarget *getSubtargetImpl() const override { return &Subtarget; } - virtual const DataLayout *getDataLayout() const LLVM_OVERRIDE { + const DataLayout *getDataLayout() const override { return &DL; } - virtual const SystemZRegisterInfo *getRegisterInfo() const LLVM_OVERRIDE { + const SystemZRegisterInfo *getRegisterInfo() const override { return &InstrInfo.getRegisterInfo(); } - virtual const SystemZTargetLowering *getTargetLowering() const LLVM_OVERRIDE { + const SystemZTargetLowering *getTargetLowering() const override { return &TLInfo; } - virtual const TargetSelectionDAGInfo *getSelectionDAGInfo() const - LLVM_OVERRIDE { + const TargetSelectionDAGInfo *getSelectionDAGInfo() const override { return &TSInfo; } // Override LLVMTargetMachine - virtual TargetPassConfig *createPassConfig(PassManagerBase &PM) LLVM_OVERRIDE; + TargetPassConfig *createPassConfig(PassManagerBase &PM) override; }; } // end namespace llvm diff --git a/lib/Target/SystemZ/TargetInfo/CMakeLists.txt b/lib/Target/SystemZ/TargetInfo/CMakeLists.txt index b6051d3..1ebc669 100644 --- a/lib/Target/SystemZ/TargetInfo/CMakeLists.txt +++ b/lib/Target/SystemZ/TargetInfo/CMakeLists.txt @@ -1,7 +1,3 @@ -include_directories( ${CMAKE_CURRENT_BINARY_DIR}/.. ${CMAKE_CURRENT_SOURCE_DIR}/.. ) - add_llvm_library(LLVMSystemZInfo SystemZTargetInfo.cpp ) - -add_dependencies(LLVMSystemZInfo SystemZCommonTableGen) diff --git a/lib/Target/SystemZ/TargetInfo/LLVMBuild.txt b/lib/Target/SystemZ/TargetInfo/LLVMBuild.txt index ea43736..a5547e6 100644 --- a/lib/Target/SystemZ/TargetInfo/LLVMBuild.txt +++ b/lib/Target/SystemZ/TargetInfo/LLVMBuild.txt @@ -19,5 +19,5 @@ type = Library name = SystemZInfo parent = SystemZ -required_libraries = MC Support Target +required_libraries = Support add_to_library_groups = SystemZ |