diff options
author | Dimitry Andric <dim@FreeBSD.org> | 2019-02-15 20:48:51 +0000 |
---|---|---|
committer | Dimitry Andric <dim@FreeBSD.org> | 2019-02-15 20:48:51 +0000 |
commit | 519e1985aef0136fe593e52b5404e2934b077115 (patch) | |
tree | 2ed0abe9c0ca3ad3309b537d91c64bc91c8f0176 /lib | |
parent | e79719ce607b6130e41e23dbdc90cc6b4e0401e6 (diff) |
Notes
Diffstat (limited to 'lib')
29 files changed, 505 insertions, 348 deletions
diff --git a/lib/Analysis/TargetLibraryInfo.cpp b/lib/Analysis/TargetLibraryInfo.cpp index 4643f75da42d..ae86ee3d3650 100644 --- a/lib/Analysis/TargetLibraryInfo.cpp +++ b/lib/Analysis/TargetLibraryInfo.cpp @@ -161,25 +161,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, } if (T.isOSWindows() && !T.isOSCygMing()) { - // Win32 does not support long double + // XXX: The earliest documentation available at the moment is for VS2015/VC19: + // https://docs.microsoft.com/en-us/cpp/c-runtime-library/floating-point-support?view=vs-2015 + // XXX: In order to use an MSVCRT older than VC19, + // the specific library version must be explicit in the target triple, + // e.g., x86_64-pc-windows-msvc18. + bool hasPartialC99 = true; + if (T.isKnownWindowsMSVCEnvironment()) { + unsigned Major, Minor, Micro; + T.getEnvironmentVersion(Major, Minor, Micro); + hasPartialC99 = (Major == 0 || Major >= 19); + } + + // Latest targets support C89 math functions, in part. + bool isARM = (T.getArch() == Triple::aarch64 || + T.getArch() == Triple::arm); + bool hasPartialFloat = (isARM || + T.getArch() == Triple::x86_64); + + // Win32 does not support float C89 math functions, in general. + if (!hasPartialFloat) { + TLI.setUnavailable(LibFunc_acosf); + TLI.setUnavailable(LibFunc_asinf); + TLI.setUnavailable(LibFunc_atan2f); + TLI.setUnavailable(LibFunc_atanf); + TLI.setUnavailable(LibFunc_ceilf); + TLI.setUnavailable(LibFunc_cosf); + TLI.setUnavailable(LibFunc_coshf); + TLI.setUnavailable(LibFunc_expf); + TLI.setUnavailable(LibFunc_floorf); + TLI.setUnavailable(LibFunc_fmodf); + TLI.setUnavailable(LibFunc_log10f); + TLI.setUnavailable(LibFunc_logf); + TLI.setUnavailable(LibFunc_modff); + TLI.setUnavailable(LibFunc_powf); + TLI.setUnavailable(LibFunc_sinf); + TLI.setUnavailable(LibFunc_sinhf); + TLI.setUnavailable(LibFunc_sqrtf); + TLI.setUnavailable(LibFunc_tanf); + TLI.setUnavailable(LibFunc_tanhf); + } + if (!isARM) + TLI.setUnavailable(LibFunc_fabsf); + TLI.setUnavailable(LibFunc_frexpf); + TLI.setUnavailable(LibFunc_ldexpf); + + // Win32 does not support long double C89 math functions. TLI.setUnavailable(LibFunc_acosl); TLI.setUnavailable(LibFunc_asinl); - TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_atan2l); + TLI.setUnavailable(LibFunc_atanl); TLI.setUnavailable(LibFunc_ceill); - TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_cosl); TLI.setUnavailable(LibFunc_coshl); TLI.setUnavailable(LibFunc_expl); - TLI.setUnavailable(LibFunc_fabsf); // Win32 and Win64 both lack fabsf TLI.setUnavailable(LibFunc_fabsl); TLI.setUnavailable(LibFunc_floorl); - TLI.setUnavailable(LibFunc_fmaxl); - TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_fmodl); TLI.setUnavailable(LibFunc_frexpl); - TLI.setUnavailable(LibFunc_ldexpf); TLI.setUnavailable(LibFunc_ldexpl); + TLI.setUnavailable(LibFunc_log10l); TLI.setUnavailable(LibFunc_logl); TLI.setUnavailable(LibFunc_modfl); TLI.setUnavailable(LibFunc_powl); @@ -189,81 +230,66 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_tanl); TLI.setUnavailable(LibFunc_tanhl); - // Win32 only has C89 math - TLI.setUnavailable(LibFunc_acosh); - TLI.setUnavailable(LibFunc_acoshf); + // Win32 does not fully support C99 math functions. + if (!hasPartialC99) { + TLI.setUnavailable(LibFunc_acosh); + TLI.setUnavailable(LibFunc_acoshf); + TLI.setUnavailable(LibFunc_asinh); + TLI.setUnavailable(LibFunc_asinhf); + TLI.setUnavailable(LibFunc_atanh); + TLI.setUnavailable(LibFunc_atanhf); + TLI.setAvailableWithName(LibFunc_cabs, "_cabs"); + TLI.setUnavailable(LibFunc_cabsf); + TLI.setUnavailable(LibFunc_cbrt); + TLI.setUnavailable(LibFunc_cbrtf); + TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); + TLI.setAvailableWithName(LibFunc_copysignf, "_copysignf"); + TLI.setUnavailable(LibFunc_exp2); + TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_expm1); + TLI.setUnavailable(LibFunc_expm1f); + TLI.setUnavailable(LibFunc_fmax); + TLI.setUnavailable(LibFunc_fmaxf); + TLI.setUnavailable(LibFunc_fmin); + TLI.setUnavailable(LibFunc_fminf); + TLI.setUnavailable(LibFunc_log1p); + TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_log2); + TLI.setUnavailable(LibFunc_log2f); + TLI.setAvailableWithName(LibFunc_logb, "_logb"); + if (hasPartialFloat) + TLI.setAvailableWithName(LibFunc_logbf, "_logbf"); + else + TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_rint); + TLI.setUnavailable(LibFunc_rintf); + TLI.setUnavailable(LibFunc_round); + TLI.setUnavailable(LibFunc_roundf); + TLI.setUnavailable(LibFunc_trunc); + TLI.setUnavailable(LibFunc_truncf); + } + + // Win32 does not support long double C99 math functions. TLI.setUnavailable(LibFunc_acoshl); - TLI.setUnavailable(LibFunc_asinh); - TLI.setUnavailable(LibFunc_asinhf); TLI.setUnavailable(LibFunc_asinhl); - TLI.setUnavailable(LibFunc_atanh); - TLI.setUnavailable(LibFunc_atanhf); TLI.setUnavailable(LibFunc_atanhl); - TLI.setUnavailable(LibFunc_cabs); - TLI.setUnavailable(LibFunc_cabsf); TLI.setUnavailable(LibFunc_cabsl); - TLI.setUnavailable(LibFunc_cbrt); - TLI.setUnavailable(LibFunc_cbrtf); TLI.setUnavailable(LibFunc_cbrtl); - TLI.setUnavailable(LibFunc_exp2); - TLI.setUnavailable(LibFunc_exp2f); + TLI.setUnavailable(LibFunc_copysignl); TLI.setUnavailable(LibFunc_exp2l); - TLI.setUnavailable(LibFunc_expm1); - TLI.setUnavailable(LibFunc_expm1f); TLI.setUnavailable(LibFunc_expm1l); - TLI.setUnavailable(LibFunc_log2); - TLI.setUnavailable(LibFunc_log2f); - TLI.setUnavailable(LibFunc_log2l); - TLI.setUnavailable(LibFunc_log1p); - TLI.setUnavailable(LibFunc_log1pf); + TLI.setUnavailable(LibFunc_fmaxl); + TLI.setUnavailable(LibFunc_fminl); TLI.setUnavailable(LibFunc_log1pl); - TLI.setUnavailable(LibFunc_logb); - TLI.setUnavailable(LibFunc_logbf); + TLI.setUnavailable(LibFunc_log2l); TLI.setUnavailable(LibFunc_logbl); - TLI.setUnavailable(LibFunc_nearbyint); - TLI.setUnavailable(LibFunc_nearbyintf); TLI.setUnavailable(LibFunc_nearbyintl); - TLI.setUnavailable(LibFunc_rint); - TLI.setUnavailable(LibFunc_rintf); TLI.setUnavailable(LibFunc_rintl); - TLI.setUnavailable(LibFunc_round); - TLI.setUnavailable(LibFunc_roundf); TLI.setUnavailable(LibFunc_roundl); - TLI.setUnavailable(LibFunc_trunc); - TLI.setUnavailable(LibFunc_truncf); TLI.setUnavailable(LibFunc_truncl); - // Win32 provides some C99 math with mangled names - TLI.setAvailableWithName(LibFunc_copysign, "_copysign"); - - if (T.getArch() == Triple::x86) { - // Win32 on x86 implements single-precision math functions as macros - TLI.setUnavailable(LibFunc_acosf); - TLI.setUnavailable(LibFunc_asinf); - TLI.setUnavailable(LibFunc_atanf); - TLI.setUnavailable(LibFunc_atan2f); - TLI.setUnavailable(LibFunc_ceilf); - TLI.setUnavailable(LibFunc_copysignf); - TLI.setUnavailable(LibFunc_cosf); - TLI.setUnavailable(LibFunc_coshf); - TLI.setUnavailable(LibFunc_expf); - TLI.setUnavailable(LibFunc_floorf); - TLI.setUnavailable(LibFunc_fminf); - TLI.setUnavailable(LibFunc_fmaxf); - TLI.setUnavailable(LibFunc_fmodf); - TLI.setUnavailable(LibFunc_logf); - TLI.setUnavailable(LibFunc_log10f); - TLI.setUnavailable(LibFunc_modff); - TLI.setUnavailable(LibFunc_powf); - TLI.setUnavailable(LibFunc_sinf); - TLI.setUnavailable(LibFunc_sinhf); - TLI.setUnavailable(LibFunc_sqrtf); - TLI.setUnavailable(LibFunc_tanf); - TLI.setUnavailable(LibFunc_tanhf); - } - - // Win32 does *not* provide these functions, but they are - // generally available on POSIX-compliant systems: + // Win32 does not support these functions, but + // they are generally available on POSIX-compliant systems. TLI.setUnavailable(LibFunc_access); TLI.setUnavailable(LibFunc_bcmp); TLI.setUnavailable(LibFunc_bcopy); @@ -318,12 +344,6 @@ static void initialize(TargetLibraryInfoImpl &TLI, const Triple &T, TLI.setUnavailable(LibFunc_utime); TLI.setUnavailable(LibFunc_utimes); TLI.setUnavailable(LibFunc_write); - - // Win32 does *not* provide provide these functions, but they are - // specified by C99: - TLI.setUnavailable(LibFunc_atoll); - TLI.setUnavailable(LibFunc_frexpf); - TLI.setUnavailable(LibFunc_llabs); } switch (T.getOS()) { diff --git a/lib/MC/MCExpr.cpp b/lib/MC/MCExpr.cpp index 3c022199145f..0e4174a7a4c9 100644 --- a/lib/MC/MCExpr.cpp +++ b/lib/MC/MCExpr.cpp @@ -559,6 +559,11 @@ static void AttemptToFoldSymbolOffsetDifference( if (Asm->isThumbFunc(&SA)) Addend |= 1; + // If symbol is labeled as micromips, we set low-bit to ensure + // correct offset in .gcc_except_table + if (Asm->getBackend().isMicroMips(&SA)) + Addend |= 1; + // Clear the symbol expr pointers to indicate we have folded these // operands. A = B = nullptr; diff --git a/lib/MC/MCParser/AsmParser.cpp b/lib/MC/MCParser/AsmParser.cpp index cf42a6f7075b..a0506715be37 100644 --- a/lib/MC/MCParser/AsmParser.cpp +++ b/lib/MC/MCParser/AsmParser.cpp @@ -3364,10 +3364,11 @@ bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) { } if (FileNumber == -1) { - if (!getContext().getAsmInfo()->hasSingleParameterDotFile()) - return Error(DirectiveLoc, - "target does not support '.file' without a number"); - getStreamer().EmitFileDirective(Filename); + // Ignore the directive if there is no number and the target doesn't support + // numberless .file directives. This allows some portability of assembler + // between different object file formats. + if (getContext().getAsmInfo()->hasSingleParameterDotFile()) + getStreamer().EmitFileDirective(Filename); } else { // In case there is a -g option as well as debug info from directive .file, // we turn off the -g option, directly use the existing debug info instead. diff --git a/lib/MC/WasmObjectWriter.cpp b/lib/MC/WasmObjectWriter.cpp index 0cca3757be90..333748db9190 100644 --- a/lib/MC/WasmObjectWriter.cpp +++ b/lib/MC/WasmObjectWriter.cpp @@ -982,7 +982,8 @@ void WasmObjectWriter::writeLinkingMetaDataSection( case wasm::WASM_SYMBOL_TYPE_GLOBAL: case wasm::WASM_SYMBOL_TYPE_EVENT: encodeULEB128(Sym.ElementIndex, W.OS); - if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0) + if ((Sym.Flags & wasm::WASM_SYMBOL_UNDEFINED) == 0 || + (Sym.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) writeString(Sym.Name); break; case wasm::WASM_SYMBOL_TYPE_DATA: @@ -1162,8 +1163,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, MCSymbolWasm *MemorySym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__linear_memory")); wasm::WasmImport MemImport; - MemImport.Module = MemorySym->getModuleName(); - MemImport.Field = MemorySym->getName(); + MemImport.Module = MemorySym->getImportModule(); + MemImport.Field = MemorySym->getImportName(); MemImport.Kind = wasm::WASM_EXTERNAL_MEMORY; Imports.push_back(MemImport); @@ -1173,8 +1174,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, MCSymbolWasm *TableSym = cast<MCSymbolWasm>(Ctx.getOrCreateSymbol("__indirect_function_table")); wasm::WasmImport TableImport; - TableImport.Module = TableSym->getModuleName(); - TableImport.Field = TableSym->getName(); + TableImport.Module = TableSym->getImportModule(); + TableImport.Field = TableSym->getImportName(); TableImport.Kind = wasm::WASM_EXTERNAL_TABLE; TableImport.Table.ElemType = wasm::WASM_TYPE_FUNCREF; Imports.push_back(TableImport); @@ -1200,8 +1201,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, if (!WS.isDefined() && !WS.isComdat()) { if (WS.isFunction()) { wasm::WasmImport Import; - Import.Module = WS.getModuleName(); - Import.Field = WS.getName(); + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_FUNCTION; Import.SigIndex = getFunctionType(WS); Imports.push_back(Import); @@ -1211,8 +1212,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, report_fatal_error("undefined global symbol cannot be weak"); wasm::WasmImport Import; - Import.Module = WS.getModuleName(); - Import.Field = WS.getName(); + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_GLOBAL; Import.Global = WS.getGlobalType(); Imports.push_back(Import); @@ -1222,8 +1223,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, report_fatal_error("undefined event symbol cannot be weak"); wasm::WasmImport Import; - Import.Module = WS.getModuleName(); - Import.Field = WS.getName(); + Import.Module = WS.getImportModule(); + Import.Field = WS.getImportName(); Import.Kind = wasm::WASM_EXTERNAL_EVENT; Import.Event.Attribute = wasm::WASM_EVENT_ATTRIBUTE_EXCEPTION; Import.Event.SigIndex = getEventType(WS); @@ -1448,6 +1449,8 @@ uint64_t WasmObjectWriter::writeObject(MCAssembler &Asm, Flags |= wasm::WASM_SYMBOL_BINDING_LOCAL; if (WS.isUndefined()) Flags |= wasm::WASM_SYMBOL_UNDEFINED; + if (WS.getName() != WS.getImportName()) + Flags |= wasm::WASM_SYMBOL_EXPLICIT_NAME; wasm::WasmSymbolInfo Info; Info.Name = WS.getName(); diff --git a/lib/Object/WasmObjectFile.cpp b/lib/Object/WasmObjectFile.cpp index d84cb48c9fbd..66a53becbb05 100644 --- a/lib/Object/WasmObjectFile.cpp +++ b/lib/Object/WasmObjectFile.cpp @@ -505,9 +505,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Function.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedFunctions[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; Signature = &Signatures[Import.SigIndex]; - Info.Name = Import.Field; - Info.Module = Import.Module; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; @@ -530,8 +534,13 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { Global.SymbolName = Info.Name; } else { wasm::WasmImport &Import = *ImportedGlobals[Info.ElementIndex]; - Info.Name = Import.Field; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; GlobalType = &Import.Global; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; @@ -585,9 +594,14 @@ Error WasmObjectFile::parseLinkingSectionSymtab(ReadContext &Ctx) { } else { wasm::WasmImport &Import = *ImportedEvents[Info.ElementIndex]; + if ((Info.Flags & wasm::WASM_SYMBOL_EXPLICIT_NAME) != 0) + Info.Name = readString(Ctx); + else + Info.Name = Import.Field; EventType = &Import.Event; Signature = &Signatures[EventType->SigIndex]; - Info.Name = Import.Field; + Info.ImportName = Import.Field; + Info.ImportModule = Import.Module; } break; } diff --git a/lib/Support/Unix/Threading.inc b/lib/Support/Unix/Threading.inc index 2d49ce1ad747..92bec36d6a2d 100644 --- a/lib/Support/Unix/Threading.inc +++ b/lib/Support/Unix/Threading.inc @@ -203,6 +203,12 @@ void llvm::get_thread_name(SmallVectorImpl<char> &Name) { ::pthread_getname_np(::pthread_self(), buf, len); Name.append(buf, buf + strlen(buf)); +#elif defined(__OpenBSD__) + constexpr uint32_t len = get_max_thread_name_length_impl(); + char buf[len]; + ::pthread_get_name_np(::pthread_self(), buf, len); + + Name.append(buf, buf + strlen(buf)); #elif defined(__linux__) #if HAVE_PTHREAD_GETNAME_NP constexpr uint32_t len = get_max_thread_name_length_impl(); diff --git a/lib/Target/AArch64/AArch64InstrInfo.cpp b/lib/Target/AArch64/AArch64InstrInfo.cpp index ada067888572..50316ebe218b 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.cpp +++ b/lib/Target/AArch64/AArch64InstrInfo.cpp @@ -2292,6 +2292,31 @@ void AArch64InstrInfo::copyPhysRegTuple(MachineBasicBlock &MBB, } } +void AArch64InstrInfo::copyGPRRegTuple(MachineBasicBlock &MBB, + MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, + unsigned SrcReg, bool KillSrc, + unsigned Opcode, unsigned ZeroReg, + llvm::ArrayRef<unsigned> Indices) const { + const TargetRegisterInfo *TRI = &getRegisterInfo(); + unsigned NumRegs = Indices.size(); + +#ifndef NDEBUG + uint16_t DestEncoding = TRI->getEncodingValue(DestReg); + uint16_t SrcEncoding = TRI->getEncodingValue(SrcReg); + assert(DestEncoding % NumRegs == 0 && SrcEncoding % NumRegs == 0 && + "GPR reg sequences should not be able to overlap"); +#endif + + for (unsigned SubReg = 0; SubReg != NumRegs; ++SubReg) { + const MachineInstrBuilder MIB = BuildMI(MBB, I, DL, get(Opcode)); + AddSubReg(MIB, DestReg, Indices[SubReg], RegState::Define, TRI); + MIB.addReg(ZeroReg); + AddSubReg(MIB, SrcReg, Indices[SubReg], getKillRegState(KillSrc), TRI); + MIB.addImm(0); + } +} + void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, @@ -2431,6 +2456,22 @@ void AArch64InstrInfo::copyPhysReg(MachineBasicBlock &MBB, return; } + if (AArch64::XSeqPairsClassRegClass.contains(DestReg) && + AArch64::XSeqPairsClassRegClass.contains(SrcReg)) { + static const unsigned Indices[] = {AArch64::sube64, AArch64::subo64}; + copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRXrs, + AArch64::XZR, Indices); + return; + } + + if (AArch64::WSeqPairsClassRegClass.contains(DestReg) && + AArch64::WSeqPairsClassRegClass.contains(SrcReg)) { + static const unsigned Indices[] = {AArch64::sube32, AArch64::subo32}; + copyGPRRegTuple(MBB, I, DL, DestReg, SrcReg, KillSrc, AArch64::ORRWrs, + AArch64::WZR, Indices); + return; + } + if (AArch64::FPR128RegClass.contains(DestReg) && AArch64::FPR128RegClass.contains(SrcReg)) { if (Subtarget.hasNEON()) { diff --git a/lib/Target/AArch64/AArch64InstrInfo.h b/lib/Target/AArch64/AArch64InstrInfo.h index 9954669d5675..e48c26d4a84a 100644 --- a/lib/Target/AArch64/AArch64InstrInfo.h +++ b/lib/Target/AArch64/AArch64InstrInfo.h @@ -122,6 +122,10 @@ public: const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc, unsigned Opcode, llvm::ArrayRef<unsigned> Indices) const; + void copyGPRRegTuple(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, + DebugLoc DL, unsigned DestReg, unsigned SrcReg, + bool KillSrc, unsigned Opcode, unsigned ZeroReg, + llvm::ArrayRef<unsigned> Indices) const; void copyPhysReg(MachineBasicBlock &MBB, MachineBasicBlock::iterator I, const DebugLoc &DL, unsigned DestReg, unsigned SrcReg, bool KillSrc) const override; diff --git a/lib/Target/AArch64/AArch64RegisterInfo.td b/lib/Target/AArch64/AArch64RegisterInfo.td index d3710cea0687..8e6aa69eae85 100644 --- a/lib/Target/AArch64/AArch64RegisterInfo.td +++ b/lib/Target/AArch64/AArch64RegisterInfo.td @@ -649,10 +649,12 @@ def FPR128Op : RegisterOperand<FPR128, "printOperand"> { // ARMv8.1a atomic CASP register operands -def WSeqPairs : RegisterTuples<[sube32, subo32], - [(rotl GPR32, 0), (rotl GPR32, 1)]>; -def XSeqPairs : RegisterTuples<[sube64, subo64], - [(rotl GPR64, 0), (rotl GPR64, 1)]>; +def WSeqPairs : RegisterTuples<[sube32, subo32], + [(decimate (rotl GPR32, 0), 2), + (decimate (rotl GPR32, 1), 2)]>; +def XSeqPairs : RegisterTuples<[sube64, subo64], + [(decimate (rotl GPR64, 0), 2), + (decimate (rotl GPR64, 1), 2)]>; def WSeqPairsClass : RegisterClass<"AArch64", [untyped], 32, (add WSeqPairs)>{ diff --git a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 4102f1eb5cc1..64afabd450c1 100644 --- a/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -1779,8 +1779,8 @@ static DecodeStatus DecodeGPRSeqPairsClassRegisterClass(MCInst &Inst, if (RegNo & 0x1) return Fail; - unsigned Register = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo); - Inst.addOperand(MCOperand::createReg(Register)); + unsigned Reg = AArch64MCRegisterClasses[RegClassID].getRegister(RegNo / 2); + Inst.addOperand(MCOperand::createReg(Reg)); return Success; } diff --git a/lib/Target/SystemZ/SystemZISelLowering.cpp b/lib/Target/SystemZ/SystemZISelLowering.cpp index 2a825c1316f3..607e55bf71c8 100644 --- a/lib/Target/SystemZ/SystemZISelLowering.cpp +++ b/lib/Target/SystemZ/SystemZISelLowering.cpp @@ -5618,55 +5618,96 @@ SDValue SystemZTargetLowering::combineBSWAP( static bool combineCCMask(SDValue &CCReg, int &CCValid, int &CCMask) { // We have a SELECT_CCMASK or BR_CCMASK comparing the condition code // set by the CCReg instruction using the CCValid / CCMask masks, - // If the CCReg instruction is itself a (ICMP (SELECT_CCMASK)) testing - // the condition code set by some other instruction, see whether we - // can directly use that condition code. - bool Invert = false; + // If the CCReg instruction is itself a ICMP testing the condition + // code set by some other instruction, see whether we can directly + // use that condition code. - // Verify that we have an appropriate mask for a EQ or NE comparison. + // Verify that we have an ICMP against some constant. if (CCValid != SystemZ::CCMASK_ICMP) return false; - if (CCMask == SystemZ::CCMASK_CMP_NE) - Invert = !Invert; - else if (CCMask != SystemZ::CCMASK_CMP_EQ) - return false; - - // Verify that we have an ICMP that is the user of a SELECT_CCMASK. - SDNode *ICmp = CCReg.getNode(); + auto *ICmp = CCReg.getNode(); if (ICmp->getOpcode() != SystemZISD::ICMP) return false; - SDNode *Select = ICmp->getOperand(0).getNode(); - if (Select->getOpcode() != SystemZISD::SELECT_CCMASK) + auto *CompareLHS = ICmp->getOperand(0).getNode(); + auto *CompareRHS = dyn_cast<ConstantSDNode>(ICmp->getOperand(1)); + if (!CompareRHS) return false; - // Verify that the ICMP compares against one of select values. - auto *CompareVal = dyn_cast<ConstantSDNode>(ICmp->getOperand(1)); - if (!CompareVal) - return false; - auto *TrueVal = dyn_cast<ConstantSDNode>(Select->getOperand(0)); - if (!TrueVal) - return false; - auto *FalseVal = dyn_cast<ConstantSDNode>(Select->getOperand(1)); - if (!FalseVal) - return false; - if (CompareVal->getZExtValue() == FalseVal->getZExtValue()) - Invert = !Invert; - else if (CompareVal->getZExtValue() != TrueVal->getZExtValue()) - return false; + // Optimize the case where CompareLHS is a SELECT_CCMASK. + if (CompareLHS->getOpcode() == SystemZISD::SELECT_CCMASK) { + // Verify that we have an appropriate mask for a EQ or NE comparison. + bool Invert = false; + if (CCMask == SystemZ::CCMASK_CMP_NE) + Invert = !Invert; + else if (CCMask != SystemZ::CCMASK_CMP_EQ) + return false; - // Compute the effective CC mask for the new branch or select. - auto *NewCCValid = dyn_cast<ConstantSDNode>(Select->getOperand(2)); - auto *NewCCMask = dyn_cast<ConstantSDNode>(Select->getOperand(3)); - if (!NewCCValid || !NewCCMask) - return false; - CCValid = NewCCValid->getZExtValue(); - CCMask = NewCCMask->getZExtValue(); - if (Invert) - CCMask ^= CCValid; + // Verify that the ICMP compares against one of select values. + auto *TrueVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(0)); + if (!TrueVal) + return false; + auto *FalseVal = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1)); + if (!FalseVal) + return false; + if (CompareRHS->getZExtValue() == FalseVal->getZExtValue()) + Invert = !Invert; + else if (CompareRHS->getZExtValue() != TrueVal->getZExtValue()) + return false; - // Return the updated CCReg link. - CCReg = Select->getOperand(4); - return true; + // Compute the effective CC mask for the new branch or select. + auto *NewCCValid = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(2)); + auto *NewCCMask = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(3)); + if (!NewCCValid || !NewCCMask) + return false; + CCValid = NewCCValid->getZExtValue(); + CCMask = NewCCMask->getZExtValue(); + if (Invert) + CCMask ^= CCValid; + + // Return the updated CCReg link. + CCReg = CompareLHS->getOperand(4); + return true; + } + + // Optimize the case where CompareRHS is (SRA (SHL (IPM))). + if (CompareLHS->getOpcode() == ISD::SRA) { + auto *SRACount = dyn_cast<ConstantSDNode>(CompareLHS->getOperand(1)); + if (!SRACount || SRACount->getZExtValue() != 30) + return false; + auto *SHL = CompareLHS->getOperand(0).getNode(); + if (SHL->getOpcode() != ISD::SHL) + return false; + auto *SHLCount = dyn_cast<ConstantSDNode>(SHL->getOperand(1)); + if (!SHLCount || SHLCount->getZExtValue() != 30 - SystemZ::IPM_CC) + return false; + auto *IPM = SHL->getOperand(0).getNode(); + if (IPM->getOpcode() != SystemZISD::IPM) + return false; + + // Avoid introducing CC spills (because SRA would clobber CC). + if (!CompareLHS->hasOneUse()) + return false; + // Verify that the ICMP compares against zero. + if (CompareRHS->getZExtValue() != 0) + return false; + + // Compute the effective CC mask for the new branch or select. + switch (CCMask) { + case SystemZ::CCMASK_CMP_EQ: break; + case SystemZ::CCMASK_CMP_NE: break; + case SystemZ::CCMASK_CMP_LT: CCMask = SystemZ::CCMASK_CMP_GT; break; + case SystemZ::CCMASK_CMP_GT: CCMask = SystemZ::CCMASK_CMP_LT; break; + case SystemZ::CCMASK_CMP_LE: CCMask = SystemZ::CCMASK_CMP_GE; break; + case SystemZ::CCMASK_CMP_GE: CCMask = SystemZ::CCMASK_CMP_LE; break; + default: return false; + } + + // Return the updated CCReg link. + CCReg = IPM->getOperand(0); + return true; + } + + return false; } SDValue SystemZTargetLowering::combineBR_CCMASK( diff --git a/lib/Target/SystemZ/SystemZInstrInfo.cpp b/lib/Target/SystemZ/SystemZInstrInfo.cpp index b03b4edaa4ab..8aab5c2c4999 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.cpp +++ b/lib/Target/SystemZ/SystemZInstrInfo.cpp @@ -557,80 +557,6 @@ bool SystemZInstrInfo::analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, return false; } -// If Reg is a virtual register, return its definition, otherwise return null. -static MachineInstr *getDef(unsigned Reg, - const MachineRegisterInfo *MRI) { - if (TargetRegisterInfo::isPhysicalRegister(Reg)) - return nullptr; - return MRI->getUniqueVRegDef(Reg); -} - -// Return true if MI is a shift of type Opcode by Imm bits. -static bool isShift(MachineInstr *MI, unsigned Opcode, int64_t Imm) { - return (MI->getOpcode() == Opcode && - !MI->getOperand(2).getReg() && - MI->getOperand(3).getImm() == Imm); -} - -// If the destination of MI has no uses, delete it as dead. -static void eraseIfDead(MachineInstr *MI, const MachineRegisterInfo *MRI) { - if (MRI->use_nodbg_empty(MI->getOperand(0).getReg())) - MI->eraseFromParent(); -} - -// Compare compares SrcReg against zero. Check whether SrcReg contains -// the result of an IPM sequence whose input CC survives until Compare, -// and whether Compare is therefore redundant. Delete it and return -// true if so. -static bool removeIPMBasedCompare(MachineInstr &Compare, unsigned SrcReg, - const MachineRegisterInfo *MRI, - const TargetRegisterInfo *TRI) { - MachineInstr *LGFR = nullptr; - MachineInstr *RLL = getDef(SrcReg, MRI); - if (RLL && RLL->getOpcode() == SystemZ::LGFR) { - LGFR = RLL; - RLL = getDef(LGFR->getOperand(1).getReg(), MRI); - } - if (!RLL || !isShift(RLL, SystemZ::RLL, 31)) - return false; - - MachineInstr *SRL = getDef(RLL->getOperand(1).getReg(), MRI); - if (!SRL || !isShift(SRL, SystemZ::SRL, SystemZ::IPM_CC)) - return false; - - MachineInstr *IPM = getDef(SRL->getOperand(1).getReg(), MRI); - if (!IPM || IPM->getOpcode() != SystemZ::IPM) - return false; - - // Check that there are no assignments to CC between the IPM and Compare, - if (IPM->getParent() != Compare.getParent()) - return false; - MachineBasicBlock::iterator MBBI = IPM, MBBE = Compare.getIterator(); - for (++MBBI; MBBI != MBBE; ++MBBI) { - MachineInstr &MI = *MBBI; - if (MI.modifiesRegister(SystemZ::CC, TRI)) - return false; - } - - Compare.eraseFromParent(); - if (LGFR) - eraseIfDead(LGFR, MRI); - eraseIfDead(RLL, MRI); - eraseIfDead(SRL, MRI); - eraseIfDead(IPM, MRI); - - return true; -} - -bool SystemZInstrInfo::optimizeCompareInstr( - MachineInstr &Compare, unsigned SrcReg, unsigned SrcReg2, int Mask, - int Value, const MachineRegisterInfo *MRI) const { - assert(!SrcReg2 && "Only optimizing constant comparisons so far"); - bool IsLogical = (Compare.getDesc().TSFlags & SystemZII::IsLogical) != 0; - return Value == 0 && !IsLogical && - removeIPMBasedCompare(Compare, SrcReg, MRI, &RI); -} - bool SystemZInstrInfo::canInsertSelect(const MachineBasicBlock &MBB, ArrayRef<MachineOperand> Pred, unsigned TrueReg, unsigned FalseReg, diff --git a/lib/Target/SystemZ/SystemZInstrInfo.h b/lib/Target/SystemZ/SystemZInstrInfo.h index 216139eb7c79..0392430ed872 100644 --- a/lib/Target/SystemZ/SystemZInstrInfo.h +++ b/lib/Target/SystemZ/SystemZInstrInfo.h @@ -208,9 +208,6 @@ public: int *BytesAdded = nullptr) const override; bool analyzeCompare(const MachineInstr &MI, unsigned &SrcReg, unsigned &SrcReg2, int &Mask, int &Value) const override; - bool optimizeCompareInstr(MachineInstr &CmpInstr, unsigned SrcReg, - unsigned SrcReg2, int Mask, int Value, - const MachineRegisterInfo *MRI) const override; bool canInsertSelect(const MachineBasicBlock&, ArrayRef<MachineOperand> Cond, unsigned, unsigned, int&, int&, int&) const override; void insertSelect(MachineBasicBlock &MBB, MachineBasicBlock::iterator MI, diff --git a/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp b/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp index e0d7bca9a94b..4592e82eea71 100644 --- a/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp +++ b/lib/Target/SystemZ/SystemZSelectionDAGInfo.cpp @@ -164,17 +164,17 @@ static SDValue emitCLC(SelectionDAG &DAG, const SDLoc &DL, SDValue Chain, } // Convert the current CC value into an integer that is 0 if CC == 0, -// less than zero if CC == 1 and greater than zero if CC >= 2. +// greater than zero if CC == 1 and less than zero if CC >= 2. // The sequence starts with IPM, which puts CC into bits 29 and 28 // of an integer and clears bits 30 and 31. static SDValue addIPMSequence(const SDLoc &DL, SDValue CCReg, SelectionDAG &DAG) { SDValue IPM = DAG.getNode(SystemZISD::IPM, DL, MVT::i32, CCReg); - SDValue SRL = DAG.getNode(ISD::SRL, DL, MVT::i32, IPM, - DAG.getConstant(SystemZ::IPM_CC, DL, MVT::i32)); - SDValue ROTL = DAG.getNode(ISD::ROTL, DL, MVT::i32, SRL, - DAG.getConstant(31, DL, MVT::i32)); - return ROTL; + SDValue SHL = DAG.getNode(ISD::SHL, DL, MVT::i32, IPM, + DAG.getConstant(30 - SystemZ::IPM_CC, DL, MVT::i32)); + SDValue SRA = DAG.getNode(ISD::SRA, DL, MVT::i32, SHL, + DAG.getConstant(30, DL, MVT::i32)); + return SRA; } std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp( @@ -184,7 +184,8 @@ std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForMemcmp( if (auto *CSize = dyn_cast<ConstantSDNode>(Size)) { uint64_t Bytes = CSize->getZExtValue(); assert(Bytes > 0 && "Caller should have handled 0-size case"); - SDValue CCReg = emitCLC(DAG, DL, Chain, Src1, Src2, Bytes); + // Swap operands to invert CC == 1 vs. CC == 2 cases. + SDValue CCReg = emitCLC(DAG, DL, Chain, Src2, Src1, Bytes); Chain = CCReg.getValue(1); return std::make_pair(addIPMSequence(DL, CCReg, DAG), Chain); } @@ -232,7 +233,8 @@ std::pair<SDValue, SDValue> SystemZSelectionDAGInfo::EmitTargetCodeForStrcmp( SDValue Src2, MachinePointerInfo Op1PtrInfo, MachinePointerInfo Op2PtrInfo) const { SDVTList VTs = DAG.getVTList(Src1.getValueType(), MVT::i32, MVT::Other); - SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src1, Src2, + // Swap operands to invert CC == 1 vs. CC == 2 cases. + SDValue Unused = DAG.getNode(SystemZISD::STRCMP, DL, VTs, Chain, Src2, Src1, DAG.getConstant(0, DL, MVT::i32)); SDValue CCReg = Unused.getValue(1); Chain = Unused.getValue(2); diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp index 50143fb0ece3..7caeebb1a9aa 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.cpp @@ -113,8 +113,15 @@ void WebAssemblyTargetAsmStreamer::emitEventType(const MCSymbolWasm *Sym) { } void WebAssemblyTargetAsmStreamer::emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) { - OS << "\t.import_module\t" << Sym->getName() << ", " << ModuleName << '\n'; + StringRef ImportModule) { + OS << "\t.import_module\t" << Sym->getName() << ", " + << ImportModule << '\n'; +} + +void WebAssemblyTargetAsmStreamer::emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) { + OS << "\t.import_name\t" << Sym->getName() << ", " + << ImportName << '\n'; } void WebAssemblyTargetAsmStreamer::emitIndIdx(const MCExpr *Value) { diff --git a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h index 3073938118b4..2ee9956c8e38 100644 --- a/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h +++ b/lib/Target/WebAssembly/MCTargetDesc/WebAssemblyTargetStreamer.h @@ -45,7 +45,10 @@ public: virtual void emitEventType(const MCSymbolWasm *Sym) = 0; /// .import_module virtual void emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) = 0; + StringRef ImportModule) = 0; + /// .import_name + virtual void emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) = 0; protected: void emitValueType(wasm::ValType Type); @@ -67,7 +70,8 @@ public: void emitIndIdx(const MCExpr *Value) override; void emitGlobalType(const MCSymbolWasm *Sym) override; void emitEventType(const MCSymbolWasm *Sym) override; - void emitImportModule(const MCSymbolWasm *Sym, StringRef ModuleName) override; + void emitImportModule(const MCSymbolWasm *Sym, StringRef ImportModule) override; + void emitImportName(const MCSymbolWasm *Sym, StringRef ImportName) override; }; /// This part is for Wasm object output @@ -82,7 +86,9 @@ public: void emitGlobalType(const MCSymbolWasm *Sym) override {} void emitEventType(const MCSymbolWasm *Sym) override {} void emitImportModule(const MCSymbolWasm *Sym, - StringRef ModuleName) override {} + StringRef ImportModule) override {} + void emitImportName(const MCSymbolWasm *Sym, + StringRef ImportName) override {} }; /// This part is for null output @@ -98,6 +104,7 @@ public: void emitGlobalType(const MCSymbolWasm *) override {} void emitEventType(const MCSymbolWasm *) override {} void emitImportModule(const MCSymbolWasm *, StringRef) override {} + void emitImportName(const MCSymbolWasm *, StringRef) override {} }; } // end namespace llvm diff --git a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp index c4f03dfa7f9e..b492d1146950 100644 --- a/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp +++ b/lib/Target/WebAssembly/WebAssemblyAsmPrinter.cpp @@ -111,9 +111,16 @@ void WebAssemblyAsmPrinter::EmitEndOfAsmFile(Module &M) { F.hasFnAttribute("wasm-import-module")) { StringRef Name = F.getFnAttribute("wasm-import-module").getValueAsString(); - Sym->setModuleName(Name); + Sym->setImportModule(Name); getTargetStreamer()->emitImportModule(Sym, Name); } + if (TM.getTargetTriple().isOSBinFormatWasm() && + F.hasFnAttribute("wasm-import-name")) { + StringRef Name = + F.getFnAttribute("wasm-import-name").getValueAsString(); + Sym->setImportName(Name); + getTargetStreamer()->emitImportName(Sym, Name); + } } } diff --git a/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp b/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp index 1a416520f97d..13f37f611ed0 100644 --- a/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp +++ b/lib/Target/WebAssembly/WebAssemblyFixFunctionBitcasts.cpp @@ -36,11 +36,6 @@ using namespace llvm; #define DEBUG_TYPE "wasm-fix-function-bitcasts" -static cl::opt<bool> - TemporaryWorkarounds("wasm-temporary-workarounds", - cl::desc("Apply certain temporary workarounds"), - cl::init(true), cl::Hidden); - namespace { class FixFunctionBitcasts final : public ModulePass { StringRef getPassName() const override { @@ -227,6 +222,17 @@ static Function *CreateWrapper(Function *F, FunctionType *Ty) { return Wrapper; } +// Test whether a main function with type FuncTy should be rewritten to have +// type MainTy. +bool shouldFixMainFunction(FunctionType *FuncTy, FunctionType *MainTy) { + // Only fix the main function if it's the standard zero-arg form. That way, + // the standard cases will work as expected, and users will see signature + // mismatches from the linker for non-standard cases. + return FuncTy->getReturnType() == MainTy->getReturnType() && + FuncTy->getNumParams() == 0 && + !FuncTy->isVarArg(); +} + bool FixFunctionBitcasts::runOnModule(Module &M) { LLVM_DEBUG(dbgs() << "********** Fix Function Bitcasts **********\n"); @@ -243,14 +249,14 @@ bool FixFunctionBitcasts::runOnModule(Module &M) { // "int main(int argc, char *argv[])", create an artificial call with it // bitcasted to that type so that we generate a wrapper for it, so that // the C runtime can call it. - if (!TemporaryWorkarounds && !F.isDeclaration() && F.getName() == "main") { + if (F.getName() == "main") { Main = &F; LLVMContext &C = M.getContext(); Type *MainArgTys[] = {Type::getInt32Ty(C), PointerType::get(Type::getInt8PtrTy(C), 0)}; FunctionType *MainTy = FunctionType::get(Type::getInt32Ty(C), MainArgTys, /*isVarArg=*/false); - if (F.getFunctionType() != MainTy) { + if (shouldFixMainFunction(F.getFunctionType(), MainTy)) { LLVM_DEBUG(dbgs() << "Found `main` function with incorrect type: " << *F.getFunctionType() << "\n"); Value *Args[] = {UndefValue::get(MainArgTys[0]), @@ -298,12 +304,18 @@ bool FixFunctionBitcasts::runOnModule(Module &M) { Main->setName("__original_main"); Function *MainWrapper = cast<Function>(CallMain->getCalledValue()->stripPointerCasts()); - MainWrapper->setName("main"); - MainWrapper->setLinkage(Main->getLinkage()); - MainWrapper->setVisibility(Main->getVisibility()); - Main->setLinkage(Function::PrivateLinkage); - Main->setVisibility(Function::DefaultVisibility); delete CallMain; + if (Main->isDeclaration()) { + // The wrapper is not needed in this case as we don't need to export + // it to anyone else. + MainWrapper->eraseFromParent(); + } else { + // Otherwise give the wrapper the same linkage as the original main + // function, so that it can be called from the same places. + MainWrapper->setName("main"); + MainWrapper->setLinkage(Main->getLinkage()); + MainWrapper->setVisibility(Main->getVisibility()); + } } return true; diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 899b50d0f78f..81391b96d126 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -1115,8 +1115,7 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo, } // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens. - if (RegNo == 0 && (Tok.getString() == "st" || Tok.getString() == "ST")) { - RegNo = X86::ST0; + if (RegNo == X86::ST0) { Parser.Lex(); // Eat 'st' // Check to see if we have '(4)' after %st. diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp index 0e861d5ddbc9..3a074818c762 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.cpp @@ -200,3 +200,14 @@ void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, O << markup("<imm:") << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff) << markup(">"); } + +void X86ATTInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &OS) { + const MCOperand &Op = MI->getOperand(OpNo); + unsigned Reg = Op.getReg(); + // Override the default printing to print st(0) instead st. + if (Reg == X86::ST0) + OS << markup("<reg:") << "%st(0)" << markup(">"); + else + printRegName(OS, Reg); +} diff --git a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h index 57422bc9a0b2..584dc9c286e6 100644 --- a/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h +++ b/lib/Target/X86/InstPrinter/X86ATTInstPrinter.h @@ -44,6 +44,7 @@ public: void printSrcIdx(const MCInst *MI, unsigned Op, raw_ostream &O); void printDstIdx(const MCInst *MI, unsigned Op, raw_ostream &O); void printU8Imm(const MCInst *MI, unsigned Op, raw_ostream &OS); + void printSTiRegOperand(const MCInst *MI, unsigned OpNo, raw_ostream &OS); void printanymem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printMemReference(MI, OpNo, O); diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp index 044b71564152..b31f8ab80838 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.cpp @@ -160,3 +160,14 @@ void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op, O << formatImm(MI->getOperand(Op).getImm() & 0xff); } + +void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo, + raw_ostream &OS) { + const MCOperand &Op = MI->getOperand(OpNo); + unsigned Reg = Op.getReg(); + // Override the default printing to print st(0) instead st. + if (Reg == X86::ST0) + OS << "st(0)"; + else + printRegName(OS, Reg); +} diff --git a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h index 3b34a8052bec..fe52bd482a26 100644 --- a/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h +++ b/lib/Target/X86/InstPrinter/X86IntelInstPrinter.h @@ -39,6 +39,7 @@ public: void printSrcIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printDstIdx(const MCInst *MI, unsigned OpNo, raw_ostream &O); void printU8Imm(const MCInst *MI, unsigned Op, raw_ostream &O); + void printSTiRegOperand(const MCInst *MI, unsigned OpNo, raw_ostream &OS); void printanymem(const MCInst *MI, unsigned OpNo, raw_ostream &O) { printMemReference(MI, OpNo, O); diff --git a/lib/Target/X86/X86ISelLowering.cpp b/lib/Target/X86/X86ISelLowering.cpp index 3637562c8ec3..f4f37a894620 100644 --- a/lib/Target/X86/X86ISelLowering.cpp +++ b/lib/Target/X86/X86ISelLowering.cpp @@ -42507,6 +42507,14 @@ X86TargetLowering::getRegForInlineAsmConstraint(const TargetRegisterInfo *TRI, if (StringRef("{flags}").equals_lower(Constraint)) return std::make_pair(X86::EFLAGS, &X86::CCRRegClass); + // dirflag -> DF + if (StringRef("{dirflag}").equals_lower(Constraint)) + return std::make_pair(X86::DF, &X86::DFCCRRegClass); + + // fpsr -> FPSW + if (StringRef("{fpsr}").equals_lower(Constraint)) + return std::make_pair(X86::FPSW, &X86::FPCCRRegClass); + // 'A' means [ER]AX + [ER]DX. if (Constraint == "A") { if (Subtarget.is64Bit()) diff --git a/lib/Target/X86/X86InstrFPStack.td b/lib/Target/X86/X86InstrFPStack.td index 5912a3199613..8e12efff77ea 100644 --- a/lib/Target/X86/X86InstrFPStack.td +++ b/lib/Target/X86/X86InstrFPStack.td @@ -230,7 +230,7 @@ def _FI32m : FPI<0xDA, fp, (outs), (ins i32mem:$src), } // mayLoad = 1, hasSideEffects = 1 } -let Defs = [FPSW] in { +let Defs = [FPSW], Uses = [FPCW] in { // FPBinary_rr just defines pseudo-instructions, no need to set a scheduling // resources. let hasNoSchedulingInfo = 1 in { @@ -258,42 +258,42 @@ defm DIVR: FPBinary<fdiv, MRM7m, "divr", 0>; } // Defs = [FPSW] class FPST0rInst<Format fp, string asm> - : FPI<0xD8, fp, (outs), (ins RST:$op), asm>; + : FPI<0xD8, fp, (outs), (ins RSTi:$op), asm>; class FPrST0Inst<Format fp, string asm> - : FPI<0xDC, fp, (outs), (ins RST:$op), asm>; + : FPI<0xDC, fp, (outs), (ins RSTi:$op), asm>; class FPrST0PInst<Format fp, string asm> - : FPI<0xDE, fp, (outs), (ins RST:$op), asm>; + : FPI<0xDE, fp, (outs), (ins RSTi:$op), asm>; // NOTE: GAS and apparently all other AT&T style assemblers have a broken notion // of some of the 'reverse' forms of the fsub and fdiv instructions. As such, // we have to put some 'r's in and take them out of weird places. -let SchedRW = [WriteFAdd] in { -def ADD_FST0r : FPST0rInst <MRM0r, "fadd\t$op">; -def ADD_FrST0 : FPrST0Inst <MRM0r, "fadd\t{%st(0), $op|$op, st(0)}">; -def ADD_FPrST0 : FPrST0PInst<MRM0r, "faddp\t$op">; -def SUBR_FST0r : FPST0rInst <MRM5r, "fsubr\t$op">; -def SUB_FrST0 : FPrST0Inst <MRM5r, "fsub{r}\t{%st(0), $op|$op, st(0)}">; -def SUB_FPrST0 : FPrST0PInst<MRM5r, "fsub{r}p\t$op">; -def SUB_FST0r : FPST0rInst <MRM4r, "fsub\t$op">; -def SUBR_FrST0 : FPrST0Inst <MRM4r, "fsub{|r}\t{%st(0), $op|$op, st(0)}">; -def SUBR_FPrST0 : FPrST0PInst<MRM4r, "fsub{|r}p\t$op">; +let SchedRW = [WriteFAdd], Defs = [FPSW], Uses = [FPCW] in { +def ADD_FST0r : FPST0rInst <MRM0r, "fadd\t{$op, %st|st, $op}">; +def ADD_FrST0 : FPrST0Inst <MRM0r, "fadd\t{%st, $op|$op, st}">; +def ADD_FPrST0 : FPrST0PInst<MRM0r, "faddp\t{%st, $op|$op, st}">; +def SUBR_FST0r : FPST0rInst <MRM5r, "fsubr\t{$op, %st|st, $op}">; +def SUB_FrST0 : FPrST0Inst <MRM5r, "fsub{r}\t{%st, $op|$op, st}">; +def SUB_FPrST0 : FPrST0PInst<MRM5r, "fsub{r}p\t{%st, $op|$op, st}">; +def SUB_FST0r : FPST0rInst <MRM4r, "fsub\t{$op, %st|st, $op}">; +def SUBR_FrST0 : FPrST0Inst <MRM4r, "fsub{|r}\t{%st, $op|$op, st}">; +def SUBR_FPrST0 : FPrST0PInst<MRM4r, "fsub{|r}p\t{%st, $op|$op, st}">; } // SchedRW -let SchedRW = [WriteFCom] in { +let SchedRW = [WriteFCom], Defs = [FPSW], Uses = [FPCW] in { def COM_FST0r : FPST0rInst <MRM2r, "fcom\t$op">; def COMP_FST0r : FPST0rInst <MRM3r, "fcomp\t$op">; } // SchedRW -let SchedRW = [WriteFMul] in { -def MUL_FST0r : FPST0rInst <MRM1r, "fmul\t$op">; -def MUL_FrST0 : FPrST0Inst <MRM1r, "fmul\t{%st(0), $op|$op, st(0)}">; -def MUL_FPrST0 : FPrST0PInst<MRM1r, "fmulp\t$op">; +let SchedRW = [WriteFMul], Defs = [FPSW], Uses = [FPCW] in { +def MUL_FST0r : FPST0rInst <MRM1r, "fmul\t{$op, %st|st, $op}">; +def MUL_FrST0 : FPrST0Inst <MRM1r, "fmul\t{%st, $op|$op, st}">; +def MUL_FPrST0 : FPrST0PInst<MRM1r, "fmulp\t{%st, $op|$op, st}">; } // SchedRW -let SchedRW = [WriteFDiv] in { -def DIVR_FST0r : FPST0rInst <MRM7r, "fdivr\t$op">; -def DIV_FrST0 : FPrST0Inst <MRM7r, "fdiv{r}\t{%st(0), $op|$op, st(0)}">; -def DIV_FPrST0 : FPrST0PInst<MRM7r, "fdiv{r}p\t$op">; -def DIV_FST0r : FPST0rInst <MRM6r, "fdiv\t$op">; -def DIVR_FrST0 : FPrST0Inst <MRM6r, "fdiv{|r}\t{%st(0), $op|$op, st(0)}">; -def DIVR_FPrST0 : FPrST0PInst<MRM6r, "fdiv{|r}p\t$op">; +let SchedRW = [WriteFDiv], Defs = [FPSW], Uses = [FPCW] in { +def DIVR_FST0r : FPST0rInst <MRM7r, "fdivr\t{$op, %st|st, $op}">; +def DIV_FrST0 : FPrST0Inst <MRM7r, "fdiv{r}\t{%st, $op|$op, st}">; +def DIV_FPrST0 : FPrST0PInst<MRM7r, "fdiv{r}p\t{%st, $op|$op, st}">; +def DIV_FST0r : FPST0rInst <MRM6r, "fdiv\t{$op, %st|st, $op}">; +def DIVR_FrST0 : FPrST0Inst <MRM6r, "fdiv{|r}\t{%st, $op|$op, st}">; +def DIVR_FPrST0 : FPrST0PInst<MRM6r, "fdiv{|r}p\t{%st, $op|$op, st}">; } // SchedRW // Unary operations. @@ -307,7 +307,7 @@ def _Fp80 : FpI_<(outs RFP80:$dst), (ins RFP80:$src), OneArgFPRW, def _F : FPI<0xD9, fp, (outs), (ins), asmstring>; } -let Defs = [FPSW] in { +let Defs = [FPSW], Uses = [FPCW] in { let SchedRW = [WriteFSign] in { defm CHS : FPUnary<fneg, MRM_E0, "fchs">; @@ -335,7 +335,7 @@ def TST_F : FPI<0xD9, MRM_E4, (outs), (ins), "ftst">; // Versions of FP instructions that take a single memory operand. Added for the // disassembler; remove as they are included with patterns elsewhere. -let SchedRW = [WriteFComLd] in { +let SchedRW = [WriteFComLd], Defs = [FPSW], Uses = [FPCW] in { def FCOM32m : FPI<0xD8, MRM2m, (outs), (ins f32mem:$src), "fcom{s}\t$src">; def FCOMP32m : FPI<0xD8, MRM3m, (outs), (ins f32mem:$src), "fcomp{s}\t$src">; @@ -398,22 +398,22 @@ defm CMOVNP : FPCMov<X86_COND_NP>; let Predicates = [HasCMov] in { // These are not factored because there's no clean way to pass DA/DB. -def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RST:$op), - "fcmovb\t{$op, %st(0)|st(0), $op}">; -def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RST:$op), - "fcmovbe\t{$op, %st(0)|st(0), $op}">; -def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RST:$op), - "fcmove\t{$op, %st(0)|st(0), $op}">; -def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RST:$op), - "fcmovu\t{$op, %st(0)|st(0), $op}">; -def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RST:$op), - "fcmovnb\t{$op, %st(0)|st(0), $op}">; -def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RST:$op), - "fcmovnbe\t{$op, %st(0)|st(0), $op}">; -def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RST:$op), - "fcmovne\t{$op, %st(0)|st(0), $op}">; -def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RST:$op), - "fcmovnu\t{$op, %st(0)|st(0), $op}">; +def CMOVB_F : FPI<0xDA, MRM0r, (outs), (ins RSTi:$op), + "fcmovb\t{$op, %st|st, $op}">; +def CMOVBE_F : FPI<0xDA, MRM2r, (outs), (ins RSTi:$op), + "fcmovbe\t{$op, %st|st, $op}">; +def CMOVE_F : FPI<0xDA, MRM1r, (outs), (ins RSTi:$op), + "fcmove\t{$op, %st|st, $op}">; +def CMOVP_F : FPI<0xDA, MRM3r, (outs), (ins RSTi:$op), + "fcmovu\t{$op, %st|st, $op}">; +def CMOVNB_F : FPI<0xDB, MRM0r, (outs), (ins RSTi:$op), + "fcmovnb\t{$op, %st|st, $op}">; +def CMOVNBE_F: FPI<0xDB, MRM2r, (outs), (ins RSTi:$op), + "fcmovnbe\t{$op, %st|st, $op}">; +def CMOVNE_F : FPI<0xDB, MRM1r, (outs), (ins RSTi:$op), + "fcmovne\t{$op, %st|st, $op}">; +def CMOVNP_F : FPI<0xDB, MRM3r, (outs), (ins RSTi:$op), + "fcmovnu\t{$op, %st|st, $op}">; } // Predicates = [HasCMov] } // SchedRW @@ -454,7 +454,7 @@ def ILD_Fp64m80: FpI_<(outs RFP80:$dst), (ins i64mem:$src), ZeroArgFP, [(set RFP80:$dst, (X86fild addr:$src, i64))]>; } // SchedRW -let SchedRW = [WriteStore] in { +let SchedRW = [WriteStore], Uses = [FPCW] in { def ST_Fp32m : FpIf32<(outs), (ins f32mem:$op, RFP32:$src), OneArgFP, [(store RFP32:$src, addr:$op)]>; def ST_Fp64m32 : FpIf64<(outs), (ins f32mem:$op, RFP64:$src), OneArgFP, @@ -489,7 +489,7 @@ def IST_Fp16m80 : FpI_<(outs), (ins i16mem:$op, RFP80:$src), OneArgFP, []>; def IST_Fp32m80 : FpI_<(outs), (ins i32mem:$op, RFP80:$src), OneArgFP, []>; def IST_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, []>; } // mayStore -} // SchedRW +} // SchedRW, Uses = [FPCW] let mayLoad = 1, SchedRW = [WriteLoad] in { def LD_F32m : FPI<0xD9, MRM0m, (outs), (ins f32mem:$src), "fld{s}\t$src">; @@ -499,7 +499,7 @@ def ILD_F16m : FPI<0xDF, MRM0m, (outs), (ins i16mem:$src), "fild{s}\t$src">; def ILD_F32m : FPI<0xDB, MRM0m, (outs), (ins i32mem:$src), "fild{l}\t$src">; def ILD_F64m : FPI<0xDF, MRM5m, (outs), (ins i64mem:$src), "fild{ll}\t$src">; } -let mayStore = 1, SchedRW = [WriteStore] in { +let mayStore = 1, SchedRW = [WriteStore], Uses = [FPCW] in { def ST_F32m : FPI<0xD9, MRM2m, (outs), (ins f32mem:$dst), "fst{s}\t$dst">; def ST_F64m : FPI<0xDD, MRM2m, (outs), (ins f64mem:$dst), "fst{l}\t$dst">; def ST_FP32m : FPI<0xD9, MRM3m, (outs), (ins f32mem:$dst), "fstp{s}\t$dst">; @@ -513,7 +513,7 @@ def IST_FP64m : FPI<0xDF, MRM7m, (outs), (ins i64mem:$dst), "fistp{ll}\t$dst">; } // FISTTP requires SSE3 even though it's a FPStack op. -let Predicates = [HasSSE3], SchedRW = [WriteStore] in { +let Predicates = [HasSSE3], SchedRW = [WriteStore], Uses = [FPCW] in { def ISTT_Fp16m32 : FpI_<(outs), (ins i16mem:$op, RFP32:$src), OneArgFP, [(X86fp_to_i16mem RFP32:$src, addr:$op)]>; def ISTT_Fp32m32 : FpI_<(outs), (ins i32mem:$op, RFP32:$src), OneArgFP, @@ -534,7 +534,7 @@ def ISTT_Fp64m80 : FpI_<(outs), (ins i64mem:$op, RFP80:$src), OneArgFP, [(X86fp_to_i64mem RFP80:$src, addr:$op)]>; } // Predicates = [HasSSE3] -let mayStore = 1, SchedRW = [WriteStore] in { +let mayStore = 1, SchedRW = [WriteStore], Uses = [FPCW] in { def ISTT_FP16m : FPI<0xDF, MRM1m, (outs), (ins i16mem:$dst), "fisttp{s}\t$dst">; def ISTT_FP32m : FPI<0xDB, MRM1m, (outs), (ins i32mem:$dst), "fisttp{l}\t$dst">; def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst">; @@ -542,10 +542,10 @@ def ISTT_FP64m : FPI<0xDD, MRM1m, (outs), (ins i64mem:$dst), "fisttp{ll}\t$dst"> // FP Stack manipulation instructions. let SchedRW = [WriteMove] in { -def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RST:$op), "fld\t$op">; -def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RST:$op), "fst\t$op">; -def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RST:$op), "fstp\t$op">; -def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RST:$op), "fxch\t$op">; +def LD_Frr : FPI<0xD9, MRM0r, (outs), (ins RSTi:$op), "fld\t$op">; +def ST_Frr : FPI<0xDD, MRM2r, (outs), (ins RSTi:$op), "fst\t$op">; +def ST_FPrr : FPI<0xDD, MRM3r, (outs), (ins RSTi:$op), "fstp\t$op">; +def XCH_F : FPI<0xD9, MRM1r, (outs), (ins RSTi:$op), "fxch\t$op">; } // Floating point constant loads. @@ -570,7 +570,7 @@ def LD_F0 : FPI<0xD9, MRM_EE, (outs), (ins), "fldz">; let SchedRW = [WriteFLD1] in def LD_F1 : FPI<0xD9, MRM_E8, (outs), (ins), "fld1">; -let SchedRW = [WriteFLDC], Defs = [FPSW] in { +let SchedRW = [WriteFLDC] in { def FLDL2T : I<0xD9, MRM_E9, (outs), (ins), "fldl2t", []>; def FLDL2E : I<0xD9, MRM_EA, (outs), (ins), "fldl2e", []>; def FLDPI : I<0xD9, MRM_EB, (outs), (ins), "fldpi", []>; @@ -579,7 +579,7 @@ def FLDLN2 : I<0xD9, MRM_ED, (outs), (ins), "fldln2", []>; } // SchedRW // Floating point compares. -let SchedRW = [WriteFCom] in { +let SchedRW = [WriteFCom], Uses = [FPCW] in { def UCOM_Fpr32 : FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, [(set FPSW, (trunc (X86cmp RFP32:$lhs, RFP32:$rhs)))]>; def UCOM_Fpr64 : FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, @@ -591,37 +591,37 @@ def UCOM_Fpr80 : FpI_ <(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, let SchedRW = [WriteFCom] in { // CC = ST(0) cmp ST(i) -let Defs = [EFLAGS, FPSW] in { -let Predicates = [FPStackf32, HasCMov] in -def UCOM_FpIr32: FpIf32<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>; -let Predicates = [FPStackf64, HasCMov] in -def UCOM_FpIr64: FpIf64<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>; -let Predicates = [HasCMov] in +let Defs = [EFLAGS, FPSW], Uses = [FPCW] in { +def UCOM_FpIr32: FpI_<(outs), (ins RFP32:$lhs, RFP32:$rhs), CompareFP, + [(set EFLAGS, (X86cmp RFP32:$lhs, RFP32:$rhs))]>, + Requires<[FPStackf32, HasCMov]>; +def UCOM_FpIr64: FpI_<(outs), (ins RFP64:$lhs, RFP64:$rhs), CompareFP, + [(set EFLAGS, (X86cmp RFP64:$lhs, RFP64:$rhs))]>, + Requires<[FPStackf64, HasCMov]>; def UCOM_FpIr80: FpI_<(outs), (ins RFP80:$lhs, RFP80:$rhs), CompareFP, - [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>; + [(set EFLAGS, (X86cmp RFP80:$lhs, RFP80:$rhs))]>, + Requires<[HasCMov]>; } -let Defs = [FPSW], Uses = [ST0] in { +let Defs = [FPSW], Uses = [ST0, FPCW] in { def UCOM_Fr : FPI<0xDD, MRM4r, // FPSW = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucom\t$reg">; + (outs), (ins RSTi:$reg), "fucom\t$reg">; def UCOM_FPr : FPI<0xDD, MRM5r, // FPSW = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucomp\t$reg">; + (outs), (ins RSTi:$reg), "fucomp\t$reg">; def UCOM_FPPr : FPI<0xDA, MRM_E9, // cmp ST(0) with ST(1), pop, pop (outs), (ins), "fucompp">; } -let Defs = [EFLAGS, FPSW], Uses = [ST0] in { +let Defs = [EFLAGS, FPSW], Uses = [ST0, FPCW] in { def UCOM_FIr : FPI<0xDB, MRM5r, // CC = cmp ST(0) with ST(i) - (outs), (ins RST:$reg), "fucomi\t$reg">; + (outs), (ins RSTi:$reg), "fucomi\t{$reg, %st|st, $reg}">; def UCOM_FIPr : FPI<0xDF, MRM5r, // CC = cmp ST(0) with ST(i), pop - (outs), (ins RST:$reg), "fucompi\t$reg">; -} + (outs), (ins RSTi:$reg), "fucompi\t{$reg, %st|st, $reg}">; -let Defs = [EFLAGS, FPSW] in { -def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RST:$reg), "fcomi\t$reg">; -def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RST:$reg), "fcompi\t$reg">; +def COM_FIr : FPI<0xDB, MRM6r, (outs), (ins RSTi:$reg), + "fcomi\t{$reg, %st|st, $reg}">; +def COM_FIPr : FPI<0xDF, MRM6r, (outs), (ins RSTi:$reg), + "fcompi\t{$reg, %st|st, $reg}">; } } // SchedRW @@ -631,12 +631,12 @@ let Defs = [AX], Uses = [FPSW] in def FNSTSW16r : I<0xDF, MRM_E0, // AX = fp flags (outs), (ins), "fnstsw\t{%ax|ax}", [(set AX, (X86fp_stsw FPSW))]>; -let Defs = [FPSW] in +let Defs = [FPSW], Uses = [FPCW] in def FNSTCW16m : I<0xD9, MRM7m, // [mem16] = X87 control world (outs), (ins i16mem:$dst), "fnstcw\t$dst", [(X86fp_cwd_get16 addr:$dst)]>; } // SchedRW -let Defs = [FPSW], mayLoad = 1 in +let Defs = [FPSW,FPCW], mayLoad = 1 in def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] (outs), (ins i16mem:$dst), "fldcw\t$dst", []>, Sched<[WriteLoad]>; @@ -645,8 +645,8 @@ def FLDCW16m : I<0xD9, MRM5m, // X87 control world = [mem16] let SchedRW = [WriteMicrocoded] in { let Defs = [FPSW] in { def FNINIT : I<0xDB, MRM_E3, (outs), (ins), "fninit", []>; -def FFREE : FPI<0xDD, MRM0r, (outs), (ins RST:$reg), "ffree\t$reg">; -def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RST:$reg), "ffreep\t$reg">; +def FFREE : FPI<0xDD, MRM0r, (outs), (ins RSTi:$reg), "ffree\t$reg">; +def FFREEP : FPI<0xDF, MRM0r, (outs), (ins RSTi:$reg), "ffreep\t$reg">; // Clear exceptions def FNCLEX : I<0xDB, MRM_E2, (outs), (ins), "fnclex", []>; diff --git a/lib/Target/X86/X86InstrInfo.td b/lib/Target/X86/X86InstrInfo.td index e53f83baa3c6..4ec4d566ca99 100644 --- a/lib/Target/X86/X86InstrInfo.td +++ b/lib/Target/X86/X86InstrInfo.td @@ -3231,39 +3231,39 @@ def : InstAlias<"fucompi", (UCOM_FIPr ST1), 0>; // instructions like "fadd %st(0), %st(0)" as "fadd %st(0)" for consistency with // gas. multiclass FpUnaryAlias<string Mnemonic, Instruction Inst, bit EmitAlias = 1> { - def : InstAlias<!strconcat(Mnemonic, "\t{$op, %st(0)|st(0), $op}"), - (Inst RST:$op), EmitAlias>; - def : InstAlias<!strconcat(Mnemonic, "\t{%st(0), %st(0)|st(0), st(0)}"), + def : InstAlias<!strconcat(Mnemonic, "\t$op"), + (Inst RSTi:$op), EmitAlias>; + def : InstAlias<!strconcat(Mnemonic, "\t{%st, %st|st, st}"), (Inst ST0), EmitAlias>; } -defm : FpUnaryAlias<"fadd", ADD_FST0r>; +defm : FpUnaryAlias<"fadd", ADD_FST0r, 0>; defm : FpUnaryAlias<"faddp", ADD_FPrST0, 0>; -defm : FpUnaryAlias<"fsub", SUB_FST0r>; -defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0>; -defm : FpUnaryAlias<"fsubr", SUBR_FST0r>; -defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0>; -defm : FpUnaryAlias<"fmul", MUL_FST0r>; -defm : FpUnaryAlias<"fmulp", MUL_FPrST0>; -defm : FpUnaryAlias<"fdiv", DIV_FST0r>; -defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0>; -defm : FpUnaryAlias<"fdivr", DIVR_FST0r>; -defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0>; +defm : FpUnaryAlias<"fsub", SUB_FST0r, 0>; +defm : FpUnaryAlias<"fsub{|r}p", SUBR_FPrST0, 0>; +defm : FpUnaryAlias<"fsubr", SUBR_FST0r, 0>; +defm : FpUnaryAlias<"fsub{r|}p", SUB_FPrST0, 0>; +defm : FpUnaryAlias<"fmul", MUL_FST0r, 0>; +defm : FpUnaryAlias<"fmulp", MUL_FPrST0, 0>; +defm : FpUnaryAlias<"fdiv", DIV_FST0r, 0>; +defm : FpUnaryAlias<"fdiv{|r}p", DIVR_FPrST0, 0>; +defm : FpUnaryAlias<"fdivr", DIVR_FST0r, 0>; +defm : FpUnaryAlias<"fdiv{r|}p", DIV_FPrST0, 0>; defm : FpUnaryAlias<"fcomi", COM_FIr, 0>; defm : FpUnaryAlias<"fucomi", UCOM_FIr, 0>; -defm : FpUnaryAlias<"fcompi", COM_FIPr>; -defm : FpUnaryAlias<"fucompi", UCOM_FIPr>; +defm : FpUnaryAlias<"fcompi", COM_FIPr, 0>; +defm : FpUnaryAlias<"fucompi", UCOM_FIPr, 0>; -// Handle "f{mulp,addp} st(0), $op" the same as "f{mulp,addp} $op", since they +// Handle "f{mulp,addp} $op, %st(0)" the same as "f{mulp,addp} $op", since they // commute. We also allow fdiv[r]p/fsubrp even though they don't commute, // solely because gas supports it. -def : InstAlias<"faddp\t{%st(0), $op|$op, st(0)}", (ADD_FPrST0 RST:$op), 0>; -def : InstAlias<"fmulp\t{%st(0), $op|$op, st(0)}", (MUL_FPrST0 RST:$op)>; -def : InstAlias<"fsub{|r}p\t{%st(0), $op|$op, st(0)}", (SUBR_FPrST0 RST:$op)>; -def : InstAlias<"fsub{r|}p\t{%st(0), $op|$op, st(0)}", (SUB_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{|r}p\t{%st(0), $op|$op, st(0)}", (DIVR_FPrST0 RST:$op)>; -def : InstAlias<"fdiv{r|}p\t{%st(0), $op|$op, st(0)}", (DIV_FPrST0 RST:$op)>; +def : InstAlias<"faddp\t{$op, %st|st, $op}", (ADD_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fmulp\t{$op, %st|st, $op}", (MUL_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fsub{|r}p\t{$op, %st|st, $op}", (SUBR_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fsub{r|}p\t{$op, %st|st, $op}", (SUB_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fdiv{|r}p\t{$op, %st|st, $op}", (DIVR_FPrST0 RSTi:$op), 0>; +def : InstAlias<"fdiv{r|}p\t{$op, %st|st, $op}", (DIV_FPrST0 RSTi:$op), 0>; def : InstAlias<"fnstsw" , (FNSTSW16r), 0>; diff --git a/lib/Target/X86/X86RegisterInfo.cpp b/lib/Target/X86/X86RegisterInfo.cpp index 55842a4a2091..bc39cee34c4a 100644 --- a/lib/Target/X86/X86RegisterInfo.cpp +++ b/lib/Target/X86/X86RegisterInfo.cpp @@ -497,6 +497,9 @@ BitVector X86RegisterInfo::getReservedRegs(const MachineFunction &MF) const { BitVector Reserved(getNumRegs()); const X86FrameLowering *TFI = getFrameLowering(MF); + // Set the floating point control register as reserved. + Reserved.set(X86::FPCW); + // Set the stack-pointer register and its aliases as reserved. for (MCSubRegIterator I(X86::RSP, this, /*IncludeSelf=*/true); I.isValid(); ++I) diff --git a/lib/Target/X86/X86RegisterInfo.td b/lib/Target/X86/X86RegisterInfo.td index aa20273f89ab..6a0538138528 100644 --- a/lib/Target/X86/X86RegisterInfo.td +++ b/lib/Target/X86/X86RegisterInfo.td @@ -278,7 +278,7 @@ def K7 : X86Reg<"k7", 7>, DwarfRegNum<[125, 100, 100]>; // pseudo registers, but we still mark them as aliasing FP registers. That // way both kinds can be live without exceeding the stack depth. ST registers // are only live around inline assembly. -def ST0 : X86Reg<"st(0)", 0>, DwarfRegNum<[33, 12, 11]>; +def ST0 : X86Reg<"st", 0>, DwarfRegNum<[33, 12, 11]>; def ST1 : X86Reg<"st(1)", 1>, DwarfRegNum<[34, 13, 12]>; def ST2 : X86Reg<"st(2)", 2>, DwarfRegNum<[35, 14, 13]>; def ST3 : X86Reg<"st(3)", 3>, DwarfRegNum<[36, 15, 14]>; @@ -288,7 +288,10 @@ def ST6 : X86Reg<"st(6)", 6>, DwarfRegNum<[39, 18, 17]>; def ST7 : X86Reg<"st(7)", 7>, DwarfRegNum<[40, 19, 18]>; // Floating-point status word -def FPSW : X86Reg<"fpsw", 0>; +def FPSW : X86Reg<"fpsr", 0>; + +// Floating-point control word +def FPCW : X86Reg<"fpcr", 0>; // Status flags register. // @@ -539,6 +542,9 @@ def RST : RegisterClass<"X86", [f80, f64, f32], 32, (sequence "ST%u", 0, 7)> { let isAllocatable = 0; } +// Helper to allow %st to print as %st(0) when its encoded in the instruction. +def RSTi : RegisterOperand<RST, "printSTiRegOperand">; + // Generic vector registers: VR64 and VR128. // Ensure that float types are declared first - only float is legal on SSE1. def VR64: RegisterClass<"X86", [x86mmx], 64, (sequence "MM%u", 0, 7)>; diff --git a/lib/Transforms/Instrumentation/MemorySanitizer.cpp b/lib/Transforms/Instrumentation/MemorySanitizer.cpp index e6573af2077d..b2230afa13d8 100644 --- a/lib/Transforms/Instrumentation/MemorySanitizer.cpp +++ b/lib/Transforms/Instrumentation/MemorySanitizer.cpp @@ -321,6 +321,7 @@ static cl::opt<unsigned long long> ClOriginBase("msan-origin-base", cl::desc("Define custom MSan OriginBase"), cl::Hidden, cl::init(0)); +static const char *const kMsanModuleCtorName = "msan.module_ctor"; static const char *const kMsanInitName = "__msan_init"; namespace { @@ -586,6 +587,8 @@ private: /// An empty volatile inline asm that prevents callback merge. InlineAsm *EmptyAsm; + + Function *MsanCtorFunction; }; /// A legacy function pass for msan instrumentation. @@ -839,6 +842,8 @@ Value *MemorySanitizer::getKmsanShadowOriginAccessFn(bool isStore, int size) { } /// Module-level initialization. +/// +/// inserts a call to __msan_init to the module's constructor list. void MemorySanitizer::initializeModule(Module &M) { auto &DL = M.getDataLayout(); @@ -913,7 +918,22 @@ void MemorySanitizer::initializeModule(Module &M) { OriginStoreWeights = MDBuilder(*C).createBranchWeights(1, 1000); if (!CompileKernel) { - getOrCreateInitFunction(M, kMsanInitName); + std::tie(MsanCtorFunction, std::ignore) = + getOrCreateSanitizerCtorAndInitFunctions( + M, kMsanModuleCtorName, kMsanInitName, + /*InitArgTypes=*/{}, + /*InitArgs=*/{}, + // This callback is invoked when the functions are created the first + // time. Hook them into the global ctors list in that case: + [&](Function *Ctor, Function *) { + if (!ClWithComdat) { + appendToGlobalCtors(M, Ctor, 0); + return; + } + Comdat *MsanCtorComdat = M.getOrInsertComdat(kMsanModuleCtorName); + Ctor->setComdat(MsanCtorComdat); + appendToGlobalCtors(M, Ctor, 0, Ctor); + }); if (TrackOrigins) M.getOrInsertGlobal("__msan_track_origins", IRB.getInt32Ty(), [&] { @@ -4458,6 +4478,8 @@ static VarArgHelper *CreateVarArgHelper(Function &Func, MemorySanitizer &Msan, } bool MemorySanitizer::sanitizeFunction(Function &F, TargetLibraryInfo &TLI) { + if (!CompileKernel && (&F == MsanCtorFunction)) + return false; MemorySanitizerVisitor Visitor(F, *this, TLI); // Clear out readonly/readnone attributes. |